You are here

function javascript_aggregator_cache in Javascript Aggregator 5

Main function that finds .js files in $scripts.

File

./javascript_aggregator.module, line 14
Aggregates Javascript files to increase performance.

Code

function javascript_aggregator_cache($scripts) {
  if (variable_get('javascript_aggregator_aggregate_js', 0)) {

    // Compiling exclude pattern.
    if ($exclude_pattern = variable_get('javascript_aggregator_exclude_js', FALSE)) {
      if (trim($exclude_pattern) != '') {
        $exclude_pattern = strtr($exclude_pattern, array(
          '\\' => '/',
          '.' => '\\.',
        ));
        $exclude_pattern = preg_split('/\\r?\\n/', $exclude_pattern, -1, PREG_SPLIT_NO_EMPTY);
        $exclude_pattern = '~' . implode("\$|", $exclude_pattern) . '$~';
      }
    }

    // One regular expression to extract and remove .js paths and filenames from $scripts variable
    $pattern = "!(<script type=\"text\\/javascript\" src=\")(.*?)(\"(.*?)><\\/script>\n)!";

    // Create an array $matches with pieces of $pattern found in $scripts
    preg_match_all($pattern, $scripts, $matches);

    // $matches[2] is where paths and filenames are stored
    // Remove aggregated js files from $scripts using the same $pattern.
    $scripts = preg_replace($pattern, "", $scripts);
    $scripts_js_files = array();
    $scripts_js_links = array();

    // Sort through the files and see what is to be aggregated, and what is to be excluded.
    foreach ($matches[2] as $value) {
      if ($exclude_pattern && preg_match($exclude_pattern, $value)) {
        $scripts_js_links[] = $value;

        // prepares it to add it later after aggregation
      }
      else {
        $scripts_js_files[] = $value;
      }
    }

    // Generate a unique filename from the set of JavaScript files.
    $filename = md5(serialize($scripts_js_files)) . '.js';

    // Create files/js similar to drupal_build_css_cache (common.inc).
    $jspath = file_create_path('js');
    file_check_directory($jspath, FILE_CREATE_DIRECTORY);
    $jsfile = $jspath . '/' . $filename;

    // Create the aggregated file if it doesn't exist.
    if (!file_exists($jsfile)) {
      $contents = '';

      // Obtain all JavaScript.
      foreach ($scripts_js_files as $scripts_js_file) {

        // Retreve the path without Drupal's base path.
        $scripts_js_file = substr($scripts_js_file, strlen(base_path()));

        // Eliminate any query arguments or hash strings from the end of the name.
        // These could happen because some smart modules try to help us version
        // their Javascript files (get browsers reload them when we update the
        // modules, even when the file name stays the same). Since Javascript
        // aggregator users know they need to clear their JS cache on update,
        // they will solve this issue manually.
        $scripts_js_file = preg_replace('!(.+)([\\?#].*)!', '\\1', $scripts_js_file);
        if (file_exists($scripts_js_file)) {
          $data = file_get_contents($scripts_js_file);
          $contents .= ";\n/* AGGREGATED JS FILE: {$scripts_js_file} */\n" . $data . "\n";
        }
      }

      // JSMinify the JavaScript.
      if (variable_get('javascript_aggregator_jsmin', FALSE)) {
        include_once drupal_get_path('module', 'javascript_aggregator') . '/jsmin.php';
        $contents = JSMIN::minify($contents);
      }

      // GZip the JavaScript if required.
      $htaccess = $jspath . '/.htaccess';
      if (variable_get('javascript_aggregator_gzip', FALSE)) {

        // Create the GZip file if it doesn't already exist.
        if (!file_exists($jsfile . '.gz')) {
          file_save_data(gzencode($contents, 9), $jsfile . '.gz', FILE_EXISTS_REPLACE);
        }

        // Make sure the .htaccess file is active to handle GZipped JavaScript files.
        if (!file_exists($htaccess)) {
          $htaccess_contents = <<<EOT
<Files *.js.gz>
  AddEncoding x-gzip .gz
  ForceType text/javascript
</Files>
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTP_USER_AGENT} !".*Safari.*"
  RewriteCond %{HTTP:Accept-encoding} gzip
  RewriteCond %{REQUEST_FILENAME}.gz -f
  RewriteRule ^(.*)\\.js \$1.js.gz [L,QSA]
</IfModule>
EOT;
          file_save_data($htaccess_contents, $htaccess, FILE_EXISTS_REPLACE);
        }
      }
      else {

        // Delete .htaccess file so *.gz files do not get served.
        if (file_exists($htaccess)) {
          file_delete($htaccess);
        }
      }

      // Create the JavaScript file.
      file_save_data($contents, $jsfile, FILE_EXISTS_REPLACE);
    }

    // Adds excluded files again to the $scripts variable, making sure the aggregated file is on top.
    $base_path = variable_get('javascript_aggregator_base_path', NULL);
    $base_path = $base_path ? $base_path : base_path();
    array_unshift($scripts_js_links, $base_path . $jsfile);
    foreach ($scripts_js_links as $add_to_scripts) {
      $script_links .= "<script type=\"text/javascript\" src=\"{$add_to_scripts}\"></script>\n";
    }

    // Reconstruct the scripts variable, making sure to add the aggregated files at the beginning.
    $scripts = trim($script_links . $scripts);
  }
  return $scripts;
}