Get the replacements array for the css.

Paramètres

string $css_string: String of CSS.

Return value

array An array containing the replacemnts and the font class name.

4 calls to advagg_font_get_replacements_array()
advagg_css_alter dans advagg_font/advagg_font.module
Implements hook_css_alter().
advagg_font_admin_settings_form dans advagg_font/advagg_font.admin.inc
Form builder; Configure advagg settings.
advagg_font_advagg_get_css_file_contents_alter dans advagg_font/advagg_font.advagg.inc
Implements hook_advagg_get_css_file_contents_alter().
advagg_font_advagg_get_info_on_files_alter dans advagg_font/advagg_font.advagg.inc
Implements hook_advagg_get_info_on_files_alter().

Fichier

advagg_font/advagg_font.module, line 319

Code

function advagg_font_get_replacements_array($css_string) {
    // Get the CSS that contains a font-family rule.
    $length = strlen($css_string);
    $property_position = 0;
    $property = 'font';
    $property_alt = 'font-family';
    $replacements = array();
    $fonts_with_no_replacements = array();
    $lower = strtolower($css_string);
    $safe_fonts_list = array(
        'georgia' => TRUE,
        'palatino' => TRUE,
        'times new roman' => TRUE,
        'times' => TRUE,
        'arial' => TRUE,
        'helvetica' => TRUE,
        'gadget' => TRUE,
        'verdana' => TRUE,
        'geneva' => TRUE,
        'tahoma' => TRUE,
        'garamond' => TRUE,
        'bookman' => TRUE,
        'comic sans ms' => TRUE,
        'cursive' => TRUE,
        'trebuchet ms' => TRUE,
        'arial black' => TRUE,
        'impact' => TRUE,
        'charcoal' => TRUE,
        'courier new' => TRUE,
        'courier' => TRUE,
        'monaco' => TRUE,
        'system' => TRUE,
    );
    while (($property_position = strpos($lower, $property, $property_position)) !== FALSE) {
        // Find the start of the values for the property.
        $start_of_values = strpos($css_string, ':', $property_position);
        // Get the property at this location of the css.
        $property_in_loop = trim(substr($css_string, $property_position, $start_of_values - $property_position));
        // Make sure this property is one of the ones we're looking for.
        if ($property_in_loop !== $property && $property_in_loop !== $property_alt) {
            $property_position += strlen($property);
            continue;
        }
        // Get position of the last closing bracket plus 1 (start of this section).
        $start = strrpos($css_string, '}', -($length - $property_position));
        if ($start === FALSE) {
            // Property is in the first selector and a declaration block (full rule
            // set).
            $start = 0;
        }
        else {
            // Add one to start after the }.
            $start++;
        }
        // Get closing bracket (end of this section).
        $end = strpos($css_string, '}', $property_position);
        if ($end === FALSE) {
            // The end is the end of this file.
            $end = $length;
        }
        // Get closing ; in order to get the end of the declaration of the property.
        $declaration_end_a = strpos($css_string, ';', $property_position);
        $declaration_end_b = strpos($css_string, '}', $property_position);
        if ($declaration_end_a === FALSE) {
            $declaration_end = $declaration_end_b;
        }
        else {
            $declaration_end = min($declaration_end_a, $declaration_end_b);
        }
        if ($declaration_end > $end) {
            $declaration_end = $end;
        }
        // Add one in order to capture the } when we ge the full rule set.
        $end++;
        // Advance position for the next run of the while loop.
        $property_position = $end;
        // Get values assigned to this property.
        $values_string = substr($css_string, $start_of_values + 1, $declaration_end - ($start_of_values + 1));
        // Parse values string into an array of values.
        $values_array = explode(',', $values_string);
        if (empty($values_array)) {
            continue;
        }
        // Values array, first element is a quoted string.
        $dq = strpos($values_array[0], '"');
        $sq = strpos($values_array[0], "'");
        $quote_pos = $sq !== FALSE ? $sq : $dq;
        // Skip if the first font is not quoted.
        if ($quote_pos === FALSE) {
            continue;
        }
        $values_array[0] = trim($values_array[0]);
        // Skip if only one font is listed.
        if (count($values_array) === 1) {
            $fonts_with_no_replacements[$values_array[0]] = '';
            continue;
        }
        // Save the first value to a variable; starting at the quote.
        $removed_value_original = substr($values_array[0], max($quote_pos - 1, 0));
        // Resave first value.
        if ($quote_pos > 1) {
            $values_array[0] = trim(substr($values_array[0], 0, $quote_pos - 1));
        }
        // Get value as a classname. Remove quotes, trim, lowercase, and replace
        // spaces with dashes.
        $removed_value_classname = strtolower(trim(str_replace(array(
            '"',
            "'",
        ), '', $removed_value_original)));
        $removed_value_classname = str_replace(' ', '-', $removed_value_classname);
        // Remove value if it contains a quote.
        $values_array_copy = $values_array;
        foreach ($values_array as $key => $value) {
            if (strpos($value, '"') !== FALSE || strpos($value, "'") !== FALSE) {
                unset($values_array[$key]);
            }
            elseif ($key !== 0) {
                break;
            }
        }
        if (empty($values_array)) {
            // See if there's a "safe" fallback that is quoted.
            $values_array = $values_array_copy;
            foreach ($values_array as $key => $value) {
                if (strpos($value, '"') !== FALSE || strpos($value, "'") !== FALSE) {
                    if ($key !== 0) {
                        $lower_key = trim(trim(strtolower(trim($value)), '"'), "'");
                        if (!empty($safe_fonts_list[$lower_key])) {
                            break;
                        }
                    }
                    unset($values_array[$key]);
                }
                elseif ($key !== 0) {
                    break;
                }
            }
            if (empty($values_array)) {
                // No unquoted values left; do not modify the css.
                $key = array_shift($values_array_copy);
                $fonts_with_no_replacements[$key] = implode(',', $values_array_copy);
                continue;
            }
        }
        $extra = '';
        if (isset($values_array[0])) {
            $extra = $values_array[0] . ' ';
            unset($values_array[0]);
        }
        // Rezero the keys.
        $values_array = array_values($values_array);
        // Save next value.
        $next_value_original = trim($values_array[0]);
        // Create the values string.
        $new_values_string = $extra . implode(',', $values_array);
        // Get all selectors.
        $end_of_selectors = strpos($css_string, '{', $start);
        $selectors = substr($css_string, $start, $end_of_selectors - $start);
        // Ensure selectors is not a media query.
        if (stripos($selectors, "@media") !== FALSE) {
            // Move the start to the end of the media query.
            $start = $end_of_selectors + 1;
            // Get the selectors again.
            $end_of_selectors = strpos($css_string, '{', $start);
            $selectors = substr($css_string, $start, $end_of_selectors - $start);
        }
        // From advagg_load_stylesheet_content().
        // Perform some safe CSS optimizations.
        // Regexp to match comment blocks.
        // Regexp to match double quoted strings.
        // Regexp to match single quoted strings.
        $comment = '/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/';
        $double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
        $single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";
        // Strip all comment blocks, but keep double/single quoted strings.
        $selectors_stripped = preg_replace("<({$double_quot}|{$single_quot})|{$comment}>Ss", "\$1", $selectors);
        // Add css class to all the selectors.
        $selectors_array = explode(',', $selectors_stripped);
        foreach ($selectors_array as &$selector) {
            // Remove extra whitespace.
            $selector = trim($selector);
            $selector = " .{$removed_value_classname} {$selector}";
        }
        $new_selectors = implode(',', $selectors_array);
        // Get full rule set.
        $full_rule_set = substr($css_string, $start, $end - $start);
        // Replace values.
        $new_values_full_rule_set = str_replace($values_string, $new_values_string, $full_rule_set);
        // Add in old rule set with new selectors.
        $new_selectors_full_rule_set = $new_selectors . '{' . $property_in_loop . ': ' . $values_string . ';}';
        // Record info.
        $replacements[] = array(
            $full_rule_set,
            $new_values_full_rule_set,
            $new_selectors_full_rule_set,
            $removed_value_original,
            $removed_value_classname,
            $next_value_original,
        );
    }
    return array(
        $replacements,
        $fonts_with_no_replacements,
    );
}