You are here

function _advagg_process_html in Advanced CSS/JS Aggregation 7.2

Replacement for template_process_html().

2 string references to '_advagg_process_html'
advagg_mod_theme_registry_alter in advagg_mod/advagg_mod.module
Implements hook_theme_registry_alter().
advagg_theme_registry_alter in ./advagg.module
Implements hook_theme_registry_alter().

File

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

Code

function _advagg_process_html(&$variables) {

  // Don't fail even if the menu router failed.
  if (drupal_get_http_header('status') === '404 Not Found') {

    // See if the URI contains advagg.
    $uri = request_uri();
    if (stripos($uri, '/advagg_') !== FALSE) {
      $advagg_items = advagg_menu();

      // Check css.
      $css = reset($advagg_items);
      $css_path = key($advagg_items);
      $css_path = substr($css_path, 0, strlen($css_path) - 1);
      $css_start = strpos($uri, $css_path);
      if ($css_start !== FALSE) {
        $filename = substr($uri, $css_start + strlen($css_path));
      }
      else {
        if (variable_get('advagg_weak_file_verification', ADVAGG_WEAK_FILE_VERIFICATION)) {
          $css_start = strpos($uri, '/' . basename($css_path) . '/');
          if ($css_start !== FALSE) {
            $filename = substr($uri, $css_start + strlen('/' . basename($css_path) . '/'));
          }
        }
      }

      // Check js.
      if (empty($filename)) {
        $js = next($advagg_items);
        $js_path = key($advagg_items);
        $js_path = substr($js_path, 0, strlen($js_path) - 1);
        $js_start = strpos($uri, $js_path);
        if ($js_start !== FALSE) {
          $filename = substr($uri, $js_start + strlen($js_path));
        }
        else {
          if (variable_get('advagg_weak_file_verification', ADVAGG_WEAK_FILE_VERIFICATION)) {
            $js_start = strpos($uri, '/' . basename($js_path) . '/');
            if ($js_start !== FALSE) {
              $filename = substr($uri, $js_start + strlen('/' . basename($js_path) . '/'));
            }
          }
        }
      }

      // If we have a filename call the page callback.
      if (!empty($filename)) {
        $router_item = $css;
        if (isset($js)) {
          $router_item = $js;
        }

        // Include the file if needed.
        if ($router_item['file']) {
          $included = module_load_include($router_item['file'], 'advagg');
          if (!$included && !function_exists($router_item['page callback'])) {
            $file = DRUPAL_ROOT . '/' . drupal_get_path('module', 'advagg') . '/' . $router_item['file'];
            if (is_file($file)) {
              require_once $file;
            }
          }
        }

        // Call the function.
        if (function_exists($router_item['page callback'])) {

          // Strip query and fragment form the filename.
          if ($pos = strpos($filename, '?')) {
            $filename = substr($filename, 0, $pos);
          }
          if ($pos = strpos($filename, '#')) {
            $filename = substr($filename, 0, $pos);
          }

          // Generate the file.
          call_user_func_array($router_item['page callback'], array(
            $filename,
          ));
        }
        else {

          // Report the bigger issue to watchdog.
          watchdog('advagg', 'You need to flush your menu cache. This can be done at the top of the <a href="@performance">performance page</a>. The advagg callback failed while trying to generate this file: @uri', array(
            '@performance' => url('admin/config/development/performance'),
            '@uri' => $uri,
          ), WATCHDOG_CRITICAL);
        }
      }
    }
  }
  if (!advagg_enabled()) {
    template_process_html($variables);
    return;
  }

  // Render page_top and page_bottom into top level variables.
  if (isset($variables['page']) && is_array($variables['page']) && isset($variables['page']['page_top'])) {
    $variables['page_top'] = drupal_render($variables['page']['page_top']);
  }
  elseif (!isset($variables['page_top'])) {
    $variables['page_top'] = '';
  }
  if (isset($variables['page']) && is_array($variables['page']) && isset($variables['page']['page_bottom'])) {
    $variables['page_bottom'] = drupal_render($variables['page']['page_bottom']);
  }
  elseif (!isset($variables['page_bottom'])) {
    $variables['page_bottom'] = '';
  }

  // Place the rendered HTML for the page body into a top level variable.
  if (isset($variables['page']) && is_array($variables['page']) && isset($variables['page']['#children'])) {
    $variables['page'] = $variables['page']['#children'];
  }
  $advagg_script_alt_scope_scripts = array();
  if (variable_get('advagg_scripts_scope_anywhere', ADVAGG_SCRIPTS_SCOPE_ANYWHERE)) {
    $prefix = "<!-- AdvAgg page:prefix tag -->";
    $suffix = "<!-- AdvAgg page:suffix tag -->";
    $variables['page'] = $prefix . $variables['page'] . $suffix;
    $prefix = "<!-- AdvAgg page_top:prefix tag -->";
    $suffix = "<!-- AdvAgg page_top:suffix tag -->";
    $variables['page_top'] = $prefix . $variables['page_top'] . $suffix;
    $prefix = "<!-- AdvAgg page_bottom:prefix tag -->";
    $suffix = "<!-- AdvAgg page_bottom:suffix tag -->";
    $variables['page_bottom'] = $prefix . $variables['page_bottom'] . $suffix;
    $matches = array();
    preg_match_all('/<!-- AdvAgg (.*?) tag -->/', $variables['page_top'], $matches);
    $advagg_script_alt_scope_scripts = array_merge($matches[1], $advagg_script_alt_scope_scripts);
    preg_match_all('/<!-- AdvAgg (.*?) tag -->/', $variables['page'], $matches);
    $advagg_script_alt_scope_scripts = array_merge($matches[1], $advagg_script_alt_scope_scripts);
    preg_match_all('/<!-- AdvAgg (.*?) tag -->/', $variables['page_bottom'], $matches);
    $advagg_script_alt_scope_scripts = array_merge($matches[1], $advagg_script_alt_scope_scripts);
  }

  // Parts of drupal_get_html_head().
  $elements = drupal_add_html_head();
  if (is_callable('advagg_mod_html_head_post_alter')) {
    advagg_mod_html_head_post_alter($elements);
  }

  // Get default javascript.
  // @see http://drupal.org/node/1279226
  if (function_exists('drupal_add_js_page_defaults')) {
    drupal_add_js_page_defaults();
  }
  $javascript = array();

  // Try the render cache.
  if (!variable_get('advagg_debug', ADVAGG_DEBUG)) {

    // No Alter.
    if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 5 && !module_exists('advagg_relocate')) {

      // Get all CSS and JS variables needed; running no alters.
      list($variables['css'], $full_css) = _advagg_build_css_arrays_for_rendering(TRUE);
      list($javascript, $js_scope_settings_array, $js_scope_array) = _advagg_build_js_arrays_for_rendering(TRUE);

      // Get the render cache.
      list($css_cache, $js_cache, $css_cache_id_no_alter, $js_cache_id_no_alter) = advagg_get_render_cache($full_css, $js_scope_array);
    }

    // With Alter.
    if ((empty($css_cache->data) || empty($js_cache->data)) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 3) {

      // Get all CSS and JS variables needed; running alters.
      list($variables['css'], $full_css) = _advagg_build_css_arrays_for_rendering();
      list($javascript, $js_scope_settings_array, $js_scope_array) = _advagg_build_js_arrays_for_rendering();

      // Get the render cache.
      list($css_cache, $js_cache, $css_cache_id, $js_cache_id) = advagg_get_render_cache($full_css, $js_scope_array);
    }
  }

  // CSS has nice hooks so we don't need to work around it.
  if (!empty($css_cache->data)) {

    // Use render cache.
    list($variables['styles'], $full_css) = $css_cache->data;
  }
  else {

    // Get the css if we have not done so.
    if (empty($full_css)) {
      list($variables['css'], $full_css) = _advagg_build_css_arrays_for_rendering();
    }

    // Render the CSS; advagg_pre_render_styles() gets called here.
    $variables['styles'] = drupal_render($full_css);
    if (!empty($css_cache_id) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 3) {

      // Save to the cache.
      cache_set($css_cache_id, array(
        $variables['styles'],
        $full_css,
      ), 'cache_advagg_aggregates', CACHE_TEMPORARY);
    }
    if (!empty($css_cache_id_no_alter) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 5) {

      // Save to the cache.
      cache_set($css_cache_id_no_alter, array(
        $variables['styles'],
        $full_css,
      ), 'cache_advagg_aggregates', CACHE_TEMPORARY);
    }
  }
  if (module_exists('advagg_font') && variable_get('advagg_font_fontfaceobserver', ADVAGG_FONT_FONTFACEOBSERVER)) {
    $fonts = array();
    foreach ($full_css['#groups'] as $groups) {
      if (isset($groups['items']['files'])) {
        foreach ($groups['items']['files'] as $file) {
          if (isset($file['advagg_font'])) {
            foreach ($file['advagg_font'] as $class => $name) {
              $fonts[$class] = $name;
            }
          }
        }
      }
    }
    if (!empty($fonts)) {
      if (isset($js_scope_settings_array)) {
        $key = key($js_scope_settings_array);
        $js_scope_settings_array[$key]['settings']['data'][] = array(
          'advagg_font' => $fonts,
        );
      }
      drupal_add_js(array(
        'advagg_font' => $fonts,
      ), array(
        'type' => 'setting',
      ));
    }
  }
  if (variable_get('advagg_resource_hints_preload', ADVAGG_RESOURCE_HINTS_PRELOAD)) {
    foreach ($full_css['#groups'] as $groups) {
      if (empty($groups['data']) || $groups['type'] === 'inline') {
        continue;
      }
      advagg_add_preload_header(advagg_convert_abs_to_rel(file_create_url($groups['data'])), 'style');
    }
  }

  // JS needs hacks.
  // Clear out all old scripts.
  if (variable_get('advagg_clear_scripts', ADVAGG_CLEAR_SCRIPTS)) {
    $variables['scripts'] = '';
  }
  if (!isset($variables['scripts'])) {
    $variables['scripts'] = '';
  }
  if (!isset($variables['page_bottom']) || !is_string($variables['page_bottom'])) {
    $variables['page_bottom'] = '';
  }
  $use_cache = FALSE;
  if (!empty($js_cache->data) && !variable_get('advagg_debug', ADVAGG_DEBUG)) {

    // Use render cache.
    $use_cache = TRUE;
    $add_to_variables = array();

    // Replace cached settings with current ones.
    $js_settings_used = array();
    $js_scope_settings_array_copy = $js_scope_settings_array;
    if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 5) {
      if (!empty($js_scope_settings_array_copy['header']) && empty($js_scope_settings_array_copy['footer'])) {

        // Copy header settings into the footer.
        $js_scope_settings_array_copy['footer'] = $js_scope_settings_array_copy['header'];
      }
    }
    list($js_cache_data, $js_scope_array) = $js_cache->data;
    foreach ($js_cache_data as $scope => $value) {
      $scope_settings = $scope;
      if ($scope_settings === 'scripts') {
        $scope_settings = 'header';
      }
      if ($scope === 'page_bottom') {
        $scope_settings = 'footer';
      }

      // Search $value for Drupal.settings.
      $start = strpos($value, 'jQuery.extend(Drupal.settings,');
      if ($start !== FALSE) {

        // If the cache and current settings scope's do not match; do not use
        // the cached version.
        if (!isset($js_scope_settings_array_copy[$scope_settings]['settings'])) {
          $use_cache = FALSE;
          break;
        }

        // Replace cached Drupal.settings with current Drupal.settings for this
        // page.
        $merged = advagg_cleanup_settings_array(drupal_array_merge_deep_array(array_filter($js_scope_settings_array_copy[$scope_settings]['settings']['data'], 'is_array')));
        $json_data = advagg_json_encode($merged);
        if (!empty($json_data)) {

          // Record that this is being used.
          $js_settings_used[$scope_settings] = TRUE;

          // Replace the drupal settings string.
          $value = advagg_replace_drupal_settings_string($value, $json_data);
        }
      }
      $add_to_variables[$scope] = $value;
    }
    if ($use_cache) {
      $all_used = array_diff(array_keys($js_scope_settings_array_copy), array_keys($js_settings_used));

      // Ignore this check if the cache level is less than 5.
      if (!empty($all_used) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) < 5 && !empty($js_settings_used)) {

        // Some js settings did not make it into the output. Skip cache.
        $use_cache = FALSE;
      }
    }
    if ($use_cache) {

      // Using the cache; write to the $variables array.
      foreach ($add_to_variables as $scope => $value) {

        // Set the scope variable if not set.
        if (!isset($variables[$scope]) || !is_string($variables[$scope])) {
          $variables[$scope] = '';
        }

        // Append the js to the scope.
        $variables[$scope] .= $value;
      }
    }
  }

  // If the cache isn't used.
  if (!$use_cache) {
    if (!empty($js_cache->data) && !empty($css_cache->data) && advagg_css_in_js($css_cache)) {

      // Render the css so it will be added to the js array;
      // advagg_pre_render_styles() gets called here.
      $variables['styles'] = drupal_render($full_css);
    }

    // Check if the js has changed.
    $new_js = drupal_add_js();
    $diff = array_diff(array_keys($new_js), array_keys($javascript));
    if (!empty($diff) || empty($javascript)) {

      // Get all JS variables needed again because js changed; or because we
      // never got them in the first place.
      list($javascript, $js_scope_settings_array, $js_scope_array) = _advagg_build_js_arrays_for_rendering();
    }
    $js_cache = array();
    $js_cache['scripts'] = '';
    if (!empty($js_scope_array)) {

      // Add JS to the header and footer of the page.
      foreach ($js_scope_array as $scope => &$scripts_array) {

        // Add js settings.
        if (!empty($js_scope_settings_array[$scope]['settings'])) {
          $scripts_array['#items']['settings'] = $js_scope_settings_array[$scope]['settings'];
        }

        // Render js; advagg_pre_render_scripts() gets called here.
        $scripts = drupal_render($scripts_array);
        if ($scope === 'header') {

          // Add to the top of this section.
          $variables['scripts'] = $scripts . $variables['scripts'];
          $js_cache['scripts'] = $scripts . $js_cache['scripts'];
        }
        elseif ($scope === 'footer') {

          // Add to the bottom of this section.
          $variables['page_bottom'] .= $scripts;
          $js_cache['page_bottom'] = $scripts;
        }
        elseif ($scope === 'above_css') {

          // Put in this new section.
          $variables['above_css'] = $scripts;
          $js_cache['above_css'] = $scripts;
        }
        elseif (variable_get('advagg_scripts_scope_anywhere', ADVAGG_SCRIPTS_SCOPE_ANYWHERE)) {

          // Scripts in other places.
          if (isset($variables[$scope]) && is_string($variables[$scope]) && array_key_exists($scope, $GLOBALS['theme_info']->info['regions'])) {

            // Add to the bottom of this section.
            $variables[$scope] .= $scripts;
            $js_cache[$scope] = $scripts;
          }
          elseif (array_search($scope, $advagg_script_alt_scope_scripts, TRUE) !== FALSE) {

            // Add to the inline html.
            $pos_page_top = strpos($variables['page_top'], "<!-- AdvAgg {$scope} tag -->");
            $pos_page = strpos($variables['page'], "<!-- AdvAgg {$scope} tag -->");
            $pos_page_bottom = strpos($variables['page_bottom'], "<!-- AdvAgg {$scope} tag -->");
            if ($pos_page_top !== FALSE) {
              $pos_page_top += strlen("<!-- AdvAgg {$scope} tag -->");
              $variables['page_top'] = substr_replace($variables['page_top'], "\n{$scripts}", $pos_page_top, 0);
              $js_cache[$scope] = $scripts;
            }
            elseif ($pos_page !== FALSE) {
              $pos_page += strlen("<!-- AdvAgg {$scope} tag -->");
              $variables['page'] = substr_replace($variables['page'], "\n{$scripts}", $pos_page, 0);
              $js_cache[$scope] = $scripts;
            }
            elseif ($pos_page_bottom !== FALSE) {
              $pos_page_bottom += strlen("<!-- AdvAgg {$scope} tag -->");
              $variables['page_bottom'] = substr_replace($variables['page_bottom'], "\n{$scripts}", $pos_page_bottom, 0);
              $js_cache[$scope] = $scripts;
            }
          }
          elseif (strpos($scope, ':') === FALSE) {

            // Add to the bottom of this section.
            $variables['scripts'] .= $scripts;
            $js_cache['scripts'] .= $scripts;
          }
        }
      }
      unset($scripts_array);

      // Clear drupal settings so cache is smaller.
      foreach ($js_cache as &$string) {
        $string = advagg_replace_drupal_settings_string($string, '{}');
      }
      unset($string);

      // Clear drupal settings and not needed items from render cache.
      $js_scope_array = array_intersect_key($js_scope_array, array_flip(element_children($js_scope_array)));
      foreach ($js_scope_array as $scope => &$scripts_array) {

        // Clear element children.
        $scripts_array = array_diff_key($scripts_array, array_flip(element_children($scripts_array)));
        if (isset($scripts_array['#children'])) {
          unset($scripts_array['#children']);
        }

        // Clear drupal settings.
        if (isset($scripts_array['#items']['settings']['data']) && is_array($scripts_array['#items']['settings']['data'])) {
          $scripts_array['#items']['settings']['data'] = array();
        }

        // Clear printed keys.
        if (isset($scripts_array['#printed'])) {
          unset($scripts_array['#printed']);
        }

        // Clear not used groups.
        foreach ($scripts_array['#groups'] as $key => $groups) {
          if (!isset($groups['items']['files'])) {
            unset($scripts_array['#groups'][$key]);
          }
        }
      }
      unset($scripts_array);
      if (!empty($js_cache_id) && !empty($js_cache) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 3) {
        cache_set($js_cache_id, array(
          $js_cache,
          $js_scope_array,
        ), 'cache_advagg_aggregates', CACHE_TEMPORARY);
      }
      if (!empty($js_cache_id_no_alter) && !empty($js_cache) && variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) >= 5) {
        cache_set($js_cache_id_no_alter, array(
          $js_cache,
          $js_scope_array,
        ), 'cache_advagg_aggregates', CACHE_TEMPORARY);
      }
    }
  }
  if (!empty($variables['above_css'])) {
    $variables['styles'] = $variables['above_css'] . $variables['styles'];
  }
  if (variable_get('advagg_resource_hints_preload', ADVAGG_RESOURCE_HINTS_PRELOAD)) {
    foreach ($js_scope_array as $scope => &$scripts_array) {
      if ($scope !== 'header' && $scope !== 'footer' && $scope !== 'above_css' && !variable_get('advagg_scripts_scope_anywhere', ADVAGG_SCRIPTS_SCOPE_ANYWHERE)) {
        continue;
      }
      foreach ($scripts_array['#groups'] as $groups) {
        if (empty($groups['data']) || $groups['type'] === 'inline') {
          continue;
        }
        advagg_add_preload_header(advagg_convert_abs_to_rel(file_create_url($groups['data'])), 'script');
      }
    }
  }
  $head_elements_before = drupal_add_html_head();
  if (variable_get('advagg_resource_hints_dns_prefetch', ADVAGG_RESOURCE_HINTS_DNS_PREFETCH) || variable_get('advagg_resource_hints_preconnect', ADVAGG_RESOURCE_HINTS_PRECONNECT) || variable_get('advagg_resource_hints_preload', ADVAGG_RESOURCE_HINTS_PRELOAD)) {

    // Prefetch css domains.
    foreach ($full_css['#items'] as $file) {
      advagg_add_resource_hints_array($file);
    }
    foreach ($full_css['#groups'] as $groups) {
      if (isset($groups['items']['files'])) {
        foreach ($groups['items']['files'] as $file) {
          advagg_add_resource_hints_array($file);
        }
      }
    }

    // Prefetch js domains.
    foreach ($js_scope_array as $scope_js) {
      foreach ($scope_js['#items'] as $file) {
        advagg_add_resource_hints_array($file);
      }
      if (isset($scope_js['#groups'])) {
        foreach ($scope_js['#groups'] as $groups) {
          if (isset($groups['items']['files'])) {
            foreach ($groups['items']['files'] as $file) {
              advagg_add_resource_hints_array($file);
            }
          }
        }
      }
    }
  }

  // Add in preload link headers.
  advagg_add_preload_header();

  // Add in the headers added by advagg.
  $head_elements_after = drupal_add_html_head();
  $elements += array_diff_key($head_elements_after, $head_elements_before);

  // Parts of drupal_get_html_head().
  drupal_alter('html_head', $elements);
  $head = drupal_render($elements);
  if (variable_get('advagg_html_head_in_css_location', ADVAGG_HTML_HEAD_IN_CSS_LOCATION)) {
    $variables['styles'] = $head . $variables['styles'];
    $variables['head'] = '';
  }
  else {
    $variables['head'] = $head;
  }

  // Remove AdvAgg comments.
  if (variable_get('advagg_scripts_scope_anywhere', ADVAGG_SCRIPTS_SCOPE_ANYWHERE) && !empty($advagg_script_alt_scope_scripts) && !variable_get('theme_debug', FALSE)) {
    $variables['page_top'] = preg_replace('/<!-- AdvAgg (.*?) tag -->/', '', $variables['page_top']);
    $variables['page'] = preg_replace('/<!-- AdvAgg (.*?) tag -->/', '', $variables['page']);
    $variables['page_bottom'] = preg_replace('/<!-- AdvAgg (.*?) tag -->/', '', $variables['page_bottom']);
  }

  // Output debug info.
  if (variable_get('advagg_debug', ADVAGG_DEBUG)) {
    $debug = $GLOBALS['_advagg']['debug'];
    if (is_callable('httprl_pr')) {
      $output = ' ' . httprl_pr($debug);
    }
    else {
      $output = '<pre>' . str_replace(array(
        '<',
        '>',
      ), array(
        '&lt;',
        '&gt;',
      ), print_r($debug, TRUE)) . '</pre>';
    }
    watchdog('advagg_debug', $output, array(), WATCHDOG_DEBUG);
  }
}