You are here

function _css_emimage_process in CSS Embedded Images 7

Same name and namespace in other branches
  1. 6.2 css_emimage.module \_css_emimage_process()
  2. 6 css_emimage.module \_css_emimage_process()

Helper function to replace URLs with data URIs.

1 call to _css_emimage_process()
_css_emimage_process_html in ./css_emimage.module
Replace URLs with data URIs in aggregated CSS if optimization is enabled.

File

./css_emimage.module, line 314
CSS Embedded Images module.

Code

function _css_emimage_process($styles) {
  module_load_include('inc', 'css_emimage', 'css_emimage');
  $files_base_url = file_create_url('public://');
  $files_realpath = drupal_realpath('public://') . '/';
  $pattern = '/<link(.*?)href=".*?' . preg_quote($files_base_url, '/') . '(.*?)(\\?[^"]*)?"(.*?)\\/>/';
  if (preg_match_all($pattern, $styles, $matches) > 0) {
    foreach ($matches[2] as $i => $aggregated_file_name) {
      $emimage_file_name = str_replace('.css', '.emimage.css', $aggregated_file_name);
      $orig_file_name = str_replace('.css', '.orig.css', $aggregated_file_name);
      $emimage_file_realpath = $files_realpath . $emimage_file_name;
      $orig_file_realpath = $files_realpath . $orig_file_name;
      $aggregated_file_realpath = $files_realpath . $aggregated_file_name;

      // Save the processed CSS file if it doesn't exist yet.
      if (!file_exists($emimage_file_realpath) || filemtime($aggregated_file_realpath) > filemtime($emimage_file_realpath)) {
        _css_emimage_collect_static(array(
          array(),
          array(),
        ));

        // Reset the processed declarations.
        $contents = $orig_contents = file_get_contents($aggregated_file_realpath);
        $datauri_css = '';
        $gzip_enabled = variable_get('css_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib');
        $pattern = '/([^{}]+){([^{}]*?(background(?:-image)?|list-style(?:-image)?):[^{};)]*?(?:none|url\\([\'"]?.+?[\'"]?\\))[^{}]*)}/i';
        $contents = preg_replace_callback($pattern, '_css_emimage_replace', $contents);
        $media_blocks = parse_media_blocks($contents);
        if (!is_null($contents)) {
          list($declarations, $file_stats) = _css_emimage_collect_static();

          // Check for duplicate images and exclude those exceeding our duplication limit.
          // Sum the amount of data being embedded.
          $datauri_total_length = 0;
          foreach ($file_stats as $fs) {
            if (count($fs['indices']) > 1 && $fs['total_length'] > variable_get('css_emimage_duplicate_embed_limit', CSS_EMIMAGE_DUPLICATE_EMBED_LIMIT)) {
              foreach ($fs['indices'] as $fsi) {
                $declarations[$fsi]['base64'] = '';
              }
            }
            else {
              $datauri_total_length += $fs['total_length'];
            }
          }

          // Handle media queries.
          if (!empty($media_blocks)) {
            foreach ($declarations as $a => $b) {
              foreach ($media_blocks as $c) {

                // Skip if token is not in the media block.
                if (strpos($c, $b['token']) === FALSE) {
                  continue;
                }
                $declarations[$a]['media_query'] = substr($c, 0, strpos($c, '{'));
                break;
              }
            }
          }
          list($ext_contents, $ext_data) = _css_emimage_build_external($contents, $declarations);

          // If the amount of data being embedded is within the inline limit, inline the data URIs;
          // otherwise, store the data URIs in a separate CSS file.
          if (variable_get('css_emimage_force_inline', 0) || $datauri_total_length && $datauri_total_length <= variable_get('css_emimage_inline_datauri_limit', CSS_EMIMAGE_INLINE_DATAURI_LIMIT)) {
            $inline = _css_emimage_build_inline($contents, $declarations);
            if (strlen($inline) < strlen($ext_contents) + strlen($ext_data)) {
              $datauri_css = $inline;
            }
            else {
              $datauri_css = "{$ext_contents}\n{$ext_data}";
            }
            $contents = '';
          }
          else {
            $contents = $ext_contents;
            $datauri_css = $ext_data;
          }

          // Save the modified aggregated CSS file.
          file_unmanaged_save_data($contents, "public://{$aggregated_file_name}", FILE_EXISTS_REPLACE);

          // Save a copy of the original aggregated CSS for IE < 8 fallback.
          file_unmanaged_save_data($orig_contents, "public://{$orig_file_name}", FILE_EXISTS_REPLACE);
          if ($gzip_enabled) {
            file_unmanaged_save_data(gzencode($contents, 9, FORCE_GZIP), "public://{$aggregated_file_name}.gz", FILE_EXISTS_REPLACE);
            file_unmanaged_save_data(gzencode($orig_contents, 9, FORCE_GZIP), "public://{$orig_file_name}.gz", FILE_EXISTS_REPLACE);
          }
        }
        else {
          $error_code = preg_last_error();
          $error_messages = array(
            PREG_NO_ERROR => 'NO_ERROR',
            PREG_INTERNAL_ERROR => 'INTERNAL_ERROR',
            PREG_BACKTRACK_LIMIT_ERROR => 'BACKTRACK_LIMIT_ERROR',
            PREG_RECURSION_LIMIT_ERROR => 'RECURSION_LIMIT_ERROR',
            PREG_BAD_UTF8_ERROR => 'BAD_UTF8_ERROR',
            PREG_BAD_UTF8_OFFSET_ERROR => 'BAD_UTF8_OFFSET_ERROR',
          );
          watchdog('css_emimage', 'Error while trying to embed images in your CSS, falling back to unmodified CSS. PCRE error was: !error.', array(
            '!error' => array_key_exists($error_code, $error_messages) ? $error_messages[$error_code] : $error_code,
          ), WATCHDOG_ERROR);
        }

        // Save the CSS file containing the embedded images.
        // This may be empty, but we use the file as a flag to prevent
        // processing the CSS on every uncached request.
        file_unmanaged_save_data($datauri_css, "public://{$emimage_file_name}", FILE_EXISTS_REPLACE);
        if ($gzip_enabled) {
          file_unmanaged_save_data(gzencode($datauri_css, 9, FORCE_GZIP), "public://{$emimage_file_name}.gz", FILE_EXISTS_REPLACE);
        }
      }

      // Replace the aggregated file with the processed CSS file.
      if (file_exists($emimage_file_realpath) && filesize($emimage_file_realpath)) {
        $styles = str_replace($matches[0][$i], "<!--[if gte IE 8]><!-->\n" . (filesize($aggregated_file_realpath) ? $matches[0][$i] . "\n" : '') . str_replace($aggregated_file_name, $emimage_file_name, $matches[0][$i]) . "\n<!--<![endif]-->\n" . "<!--[if lt IE 8]>\n" . str_replace($aggregated_file_name, $orig_file_name, $matches[0][$i]) . "\n<![endif]-->", $styles);
      }
    }
  }
  return $styles;
}