function advagg_font_get_replacements_array in Advanced CSS/JS Aggregation 7.2
Get the replacements array for the css.
Parameters
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 in advagg_font/
advagg_font.module - Implements hook_css_alter().
- advagg_font_admin_settings_form in advagg_font/
advagg_font.admin.inc - Form builder; Configure advagg settings.
- advagg_font_advagg_get_css_file_contents_alter in advagg_font/
advagg_font.advagg.inc - Implements hook_advagg_get_css_file_contents_alter().
- advagg_font_advagg_get_info_on_files_alter in advagg_font/
advagg_font.advagg.inc - Implements hook_advagg_get_info_on_files_alter().
File
- advagg_font/
advagg_font.module, line 319 - Advanced aggregation font module.
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,
);
}