You are here

function advagg_mod_advagg_modify_css_pre_render_alter in Advanced CSS/JS Aggregation 7.2

Implements hook_advagg_modify_css_pre_render_alter().

Related topics

File

advagg_mod/advagg_mod.module, line 905
Advanced aggregation modifier module.

Code

function advagg_mod_advagg_modify_css_pre_render_alter(&$children, &$elements) {

  // Skip if there is no css.
  if (empty($children)) {
    return;
  }
  if (!module_exists('advagg') || !advagg_enabled()) {
    return;
  }

  // Return early if this setting is disabled.
  list(, , , , , , , , , , $css_defer) = advagg_mod_get_lists(array(), $elements['#items']);
  if (empty($css_defer)) {
    return;
  }
  $critical_css = FALSE;

  // Only check for the critical-css key if configured to do so.
  if (variable_get('advagg_mod_css_defer_visibility', ADVAGG_MOD_VISIBILITY_LISTED) == ADVAGG_MOD_VISIBILITY_FILE_CONTROLLED) {
    foreach ($elements['#items'] as $item) {
      if ($item['type'] === 'inline' && !empty($item['critical-css'])) {
        $critical_css = TRUE;
        break;
      }
    }

    // Return early if there's no critical css for the path and deferring is
    // file controlled.
    if (!$critical_css) {
      return;
    }
  }
  if (!$critical_css) {

    // Return early if we're in a page that is not specified in the settings for
    // specific pages.
    if (!advagg_mod_css_defer_page()) {
      return;
    }

    // Return early if we're in the admin theme and this setting is disabled.
    $css_defer_admin = variable_get('advagg_mod_css_defer_admin', ADVAGG_MOD_CSS_DEFER_ADMIN);
    if (empty($css_defer_admin) && path_is_admin(current_path())) {
      return;
    }
  }

  // Modify css.
  static $added;
  advagg_mod_add_loadcss_js_lib(array(), $elements['#items']);

  // Wrap CSS in noscript tags.
  $defer_skip_first_file = variable_get('advagg_mod_css_defer_skip_first_file', ADVAGG_MOD_CSS_DEFER_SKIP_FIRST_FILE);
  $options = array(
    'type' => 'inline',
    'scope' => $css_defer >= 5 ? 'footer' : 'header',
    'scope_lock' => TRUE,
    'group' => $css_defer == 1 ? JS_LIBRARY - 1 : JS_DEFAULT,
    'weight' => $css_defer == 1 ? -50000 : 0,
    'movable' => $css_defer == 1 ? FALSE : TRUE,
  );

  // Get the key of the last css file that will use loadcss.
  $last_key = NULL;
  foreach ($children as $children_key => $values) {

    // Do not count inline styles.
    if ($values['#tag'] === 'style' || empty($values['#attributes']['href'])) {
      continue;
    }

    // Only use if no browser conditionals.
    if (isset($values['#browsers']['!IE']) && $values['#browsers']['!IE'] === TRUE && isset($values['#browsers']['IE']) && $values['#browsers']['IE'] === TRUE && isset($values['#attributes']['media']) && $values['#attributes']['media'] !== 'print' && $values['#attributes']['media'] !== 'none') {
      $last_key = $children_key;
    }
  }

  // If all css uses a browser conditional, then use the last one to release.
  if ($last_key === NULL) {
    $last_key = $children_key;
  }
  $preload_array = array();
  foreach ($children as $children_key => &$values) {

    // Do not defer inline styles.
    if ($values['#tag'] === 'style' || empty($values['#attributes']['href'])) {
      continue;
    }
    if (empty($preload_array) && $defer_skip_first_file == 2) {
      $preload_array[] = array();
      continue;
    }

    // If this is the last CSS file release the hold on jquery.ready.
    $onload_extra = '';
    if ($last_key === $children_key) {

      // Run holdready once it is defined.
      $holdready_script = 'window.advagg_mod_loadcss = function() {if (window.jQuery) {if (jQuery.isFunction(jQuery.holdReady)){jQuery.holdReady(false);}} else {setTimeout(advagg_mod_loadcss, 100);}};';
      $onload_extra = "{$holdready_script}setTimeout(advagg_mod_loadcss, 200);";
      $GLOBALS['advagg_mod_loadcss_jquery_holdready'] = TRUE;
    }
    $id = "advagg_loadcss_{$children_key}";
    if ($css_defer == 4) {
      $copy = $values;
      $copy['#attributes']['rel'] = 'preload';
      $copy['#attributes']['as'] = 'style';
      $copy['#attributes']['onload'] = "{$onload_extra}this.onload=null;this.rel='stylesheet'";
      $preload_array[$children_key] = $copy;
    }
    else {

      // Add browsers to the js options.
      if (isset($values['#browsers'])) {
        $options['browsers'] = $values['#browsers'];
      }

      // Create loadCSS wrapper code.
      $inline = "loadCSS(\"{$values['#attributes']['href']}\", document.getElementById(\"{$id}\")";
      if ($values['#attributes']['media'] !== 'all') {
        $inline .= ", \"{$values['#attributes']['media']}\"";
      }
      if (!empty($values['#attributes']['crossorigin'])) {
        $inline .= ", \"{$values['#attributes']['crossorigin']}\"";
      }
      $inline .= ')';

      // Create onloadCSS wrapper code.
      if (!empty($values['#attributes']['onloadCSS'])) {
        $inline = "onloadCSS({$inline}, function() {{$onload_extra}{$values['#attributes']['onloadCSS']}});";
      }
      elseif (!empty($onload_extra)) {
        $inline = "onloadCSS({$inline}, function() {{$onload_extra}});";
      }

      // Make code work if loader code is below loadcss calls.
      $matches[2] = $matches[0] = $inline;
      $inline = advagg_mod_wrap_inline_js($matches, "window.loadCSS", 40);

      // Add in script tags to load css via js.
      if (!isset($added[$values['#attributes']['href']])) {
        drupal_add_js($inline, $options);
        $added[$values['#attributes']['href']] = TRUE;
      }
    }

    // Wrap current css in noscript tags.
    $values['#prefix'] = "<noscript id=\"{$id}\">\n";
    $values['#suffix'] = '</noscript>';

    // Reset for next item in loop.
    if (isset($options['browsers'])) {
      unset($options['browsers']);
    }
  }
  unset($values);

  // Add in the element after the noscript element keeping the css order.
  $new_elements = array();
  foreach ($elements as $elements_key => $elements_value) {

    // Build old array.
    if (is_numeric($elements_key)) {
      $new_elements[] = $elements_value;
    }
    else {
      $new_elements[$elements_key] = $elements_value;
    }

    // Splice in new data.
    if (isset($preload_array[$elements_key])) {
      $new_elements[] = $preload_array[$elements_key];
    }
  }
  $elements = $new_elements;
  unset($new_elements);
}