You are here

function advagg_css_js_file_builder in Advanced CSS/JS Aggregation 7

Same name and namespace in other branches
  1. 6 advagg.module \advagg_css_js_file_builder()

Aggregate CSS/JS files, putting them in the files directory.

Parameters

$type: js or css

$files: An array of JS files to aggregate and compress into one file.

$query_string: (optional) Query string to add on to the file if bundle isn't ready.

$counter: (optional) Counter value.

$force: (optional) Rebuild even if file already exists.

$md5: (optional) Bundle's machine name.

Return value

array with the filepath as the key and prefix and suffix in another array.

See also

drupal_build_js_cache()

drupal_build_css_cache()

3 calls to advagg_css_js_file_builder()
advagg_process_css in includes/css.inc
Returns a themed representation of all stylesheets that should be attached to the page.
advagg_process_js in ./advagg.module
Returns a themed presentation of all JavaScript code for the current page.
advagg_rebuild_bundle in ./advagg.module
Rebuild a bundle.

File

./advagg.module, line 2155
Advanced CSS/JS aggregation module

Code

function advagg_css_js_file_builder($type, $files, $query_string = '', $counter = FALSE, $force = FALSE, $md5 = '') {
  global $_advagg, $base_path;
  $data = '';

  // Try cache first. When ever the counter changes this cache gets reset.
  $schema = advagg_get_server_schema();
  $cached_data_key = 'advagg_file_builder_' . md5($schema . implode('', array_filter(array_unique($files))));
  if (!$force) {

    // Try cache first; cache table is cache_advagg_bundle_reuse.
    $cached_data = advagg_cached_bundle_get($cached_data_key, 'file_builder_cache_object');
    if (!empty($cached_data)) {
      foreach ($cached_data as $filepath => $values) {

        // Ping cache.
        advagg_bundle_built($filepath);
      }
      return $cached_data;
    }
  }
  list($css_path, $js_path) = advagg_get_root_files_dir();
  if ($type == 'js') {
    $file_type_path = $js_path[0];
  }
  if ($type == 'css') {
    $file_type_path = $css_path[0];
  }

  // Send $files, get filename back
  $filenames = advagg_get_filename($files, $type, $counter, $md5);
  if (empty($filenames)) {
    return FALSE;
  }

  // Debugging.
  if (variable_get('advagg_debug', ADVAGG_DEBUG)) {
    $_advagg['debug']['file_builder_get_filenames'][] = array(
      'key' => $cached_data_key,
      'filenames' => $filenames,
    );
  }
  $output = array();
  $locks = array();
  $cacheable = TRUE;
  $files_used = array();
  foreach ($filenames as $info) {
    $filename = $info['filename'];
    $files = $info['files'];
    $bundle_md5 = $info['bundle_md5'];
    $prefix = '';
    $suffix = '';
    $filepath = $file_type_path . '/' . $filename;

    // Invoke hook_advagg_js_extra_alter() or hook_advagg_css_extra_alter to
    // give installed modules a chance to modify the prefix or suffix for a
    // given filename.
    $values = array(
      $filename,
      $bundle_md5,
      $prefix,
      $suffix,
    );
    drupal_alter('advagg_' . $type . '_extra', $values);
    list($filename, $bundle_md5, $prefix, $suffix) = $values;

    // Check that the file exists & filesize is not zero
    $built = advagg_bundle_built($filepath);
    if (!$built || $force) {

      // Generate on request?
      if (variable_get('advagg_async_generation', ADVAGG_ASYNC_GENERATION) && !$force && empty($_GET['generator'])) {

        // Build request.
        $redirect_counter = isset($_GET['redirect_counter']) ? intval($_GET['redirect_counter']) : 0;
        $url = _advagg_build_url($filepath . '?generator=1&redirect_counter=' . $redirect_counter);
        $headers = array(
          'Host' => $_SERVER['HTTP_HOST'],
          'Connection' => 'close',
        );

        // Request file.
        if (function_exists('stream_socket_client') && function_exists('stream_select')) {
          advagg_async_connect_http_request($url, array(
            'headers' => $headers,
          ));
        }
        else {

          // Set timeout.
          $socket_timeout = ini_set('default_socket_timeout', variable_get('advagg_socket_timeout', ADVAGG_SOCKET_TIMEOUT));
          drupal_http_request($url, array(
            'headers' => $headers,
          ));
          ini_set('default_socket_timeout', $socket_timeout);
        }

        // Return filepath if we are going to wait for the bundle to be
        // generated or if the bundle already exists.
        if (variable_get('advagg_aggregate_mode', ADVAGG_AGGREGATE_MODE) < 2 || advagg_bundle_built($filepath)) {
          $output[$filepath] = array(
            'prefix' => $prefix,
            'suffix' => $suffix,
            'files' => array_map('advagg_return_true', array_flip($files)),
          );
        }
        else {

          // Aggregate isn't built yet, send back the files that where going to
          // be in it.
          foreach ($files as $file) {
            $output[$file . $query_string] = array(
              'prefix' => '',
              'suffix' => '',
              'files' => array(
                $file . $query_string => TRUE,
              ),
            );
          }
          $cacheable = FALSE;
          advagg_disable_page_cache();
        }
        continue;
      }

      // Only generate once.
      $lock_name = 'advagg_' . $filename;
      if (!lock_acquire($lock_name)) {
        if (variable_get('advagg_aggregate_mode', ADVAGG_AGGREGATE_MODE) == 0) {
          $locks[] = array(
            $lock_name => $filepath,
          );
          $output[$filepath] = array(
            'prefix' => $prefix,
            'suffix' => $suffix,
            'files' => array_map('advagg_return_true', array_flip($files)),
          );
        }
        else {

          // Aggregate isn't built yet, send back the files that where going
          // to be in it.
          foreach ($files as $file) {
            $output[$file . $query_string] = array(
              'prefix' => '',
              'suffix' => '',
              'files' => array(
                $file . $query_string => TRUE,
              ),
            );
          }
          $cacheable = FALSE;
          advagg_disable_page_cache();
        }
        continue;
      }
      if ($type == 'css') {
        $data = advagg_build_css_bundle($files);
      }
      elseif ($type == 'js') {
        $data = advagg_build_js_bundle($files);
      }

      // Invoke hook_advagg_js_alter() or hook_advagg_css_alter to give
      // installed modules a chance to modify the data in the bundle if
      // necessary.
      drupal_alter('advagg_' . $type, $data, $files, $bundle_md5);
      $files_used = array_merge($files_used, $files);

      // If data is empty then do not include this bundle in the final output.
      if (empty($data) && !$force) {
        lock_release($lock_name);
        continue;
      }

      // Create the advagg_$type/ within the files folder.
      file_prepare_directory($file_type_path, FILE_CREATE_DIRECTORY);

      // Write file. default function called: advagg_file_saver
      $function = variable_get('advagg_file_save_function', ADVAGG_FILE_SAVE_FUNCTION);
      $good = $function($data, $filepath, $force, $type);

      // Release lock.
      lock_release($lock_name);

      // If file save was not good then downgrade to non aggregated mode.
      if (!$good) {
        $output[$filepath] = FALSE;
        $cacheable = FALSE;
        continue;
      }
    }
    else {
      $files_used = array_merge($files_used, $files);
    }
    $output[$filepath] = array(
      'prefix' => $prefix,
      'suffix' => $suffix,
      'files' => array_map('advagg_return_true', array_flip($files)),
    );
  }

  // Wait for all locks before returning.
  if (!empty($locks)) {
    foreach ($locks as $lock_name => $filepath) {
      lock_wait($lock_name);
      if (!advagg_bundle_built($filepath)) {
        $output[$filepath] = FALSE;
      }
    }
  }
  if (empty($output)) {
    $output[] = FALSE;
    return $output;
  }

  // Cache the output
  if (!$force && $cacheable) {
    $new_cached_data_key = 'advagg_file_builder_' . md5($schema . implode('', array_filter(array_unique($files_used))));

    // Verify the files in equals the files out.
    if ($new_cached_data_key == $cached_data_key) {
      cache_set($cached_data_key, $output, 'cache_advagg_bundle_reuse', CACHE_TEMPORARY);
    }
  }
  return $output;
}