You are here

function advagg_get_css_aggregate_contents in Advanced CSS/JS Aggregation 7.2

Given a list of files, grab their contents and glue it into one big string.

Parameters

array $files: Array of filenames.

array $aggregate_settings: Array of settings.

string $aggregate_filename: Filename of the aggregeate.

Return value

string String containing all the files.

2 calls to advagg_get_css_aggregate_contents()
advagg_generate_filesize_processed in ./advagg.inc
Given a filename calculate the processed filesize.
advagg_save_aggregate in ./advagg.missing.inc
Save an aggregate given a filename, the files included in it, and the type.

File

./advagg.missing.inc, line 785
Advanced CSS/JS aggregation module.

Code

function advagg_get_css_aggregate_contents(array $files, array $aggregate_settings, $aggregate_filename = '') {
  $write_aggregate = TRUE;

  // Check if CSS compression is enabled.
  $optimize = TRUE;
  if (!empty($aggregate_settings['settings']['no_alters'])) {
    $optimize = FALSE;
  }
  if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) < 0) {
    $optimize = FALSE;
  }
  module_load_include('inc', 'advagg', 'advagg');
  $info_on_files = advagg_load_files_info_into_static_cache(array_keys($files));
  $data = '';
  if (!empty($files)) {
    $media_changes = FALSE;
    $last_media = NULL;
    foreach ($files as $settings) {
      if (!isset($settings['media'])) {
        continue;
      }
      if (is_null($last_media)) {
        $last_media = $settings['media'];
        continue;
      }
      if ($settings['media'] !== $last_media) {
        $media_changes = TRUE;
        break;
      }
    }
    if ($media_changes) {
      $global_file_media = 'all';
    }
    else {
      $global_file_media = $last_media;
    }

    // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
    $media_types = array(
      'all',
      'aural',
      'braille',
      'handheld',
      'print',
      'projection',
      'screen',
      'tty',
      'tv',
      'embossed',
    );
    $import_statements = array();
    module_load_include('inc', 'advagg', 'advagg');
    $original_settings = array(
      $optimize,
      $aggregate_settings,
    );
    foreach ($files as $file => $settings) {
      $media_changes = FALSE;
      if (!isset($settings['media'])) {
        $settings['media'] = '';
      }
      if ($settings['media'] !== $global_file_media) {
        $media_changes = TRUE;
      }
      list($optimize, $aggregate_settings) = $original_settings;

      // Allow other modules to modify aggregate_settings optimize.
      // Call hook_advagg_get_css_file_contents_pre_alter().
      if (empty($aggregate_settings['settings']['no_alters'])) {
        drupal_alter('advagg_get_css_file_contents_pre', $file, $optimize, $aggregate_settings);
      }
      if (is_readable($file)) {

        // Get the files contents.
        $file_contents = (string) @advagg_file_get_contents($file);

        // Get a hash of the file's contents.
        $file_contents_hash = drupal_hash_base64($file_contents);
        $cid = 'advagg:file:' . advagg_drupal_hash_base64($file);
        if (empty($info_on_files[$cid]['content_hash'])) {

          // If hash was not in the cache, get it from the DB.
          $results = db_select('advagg_files', 'af')
            ->fields('af', array(
            'content_hash',
            'filename_hash',
          ))
            ->condition('filename', $file)
            ->execute();
          foreach ($results as $row) {
            $info_on_files['advagg:file:' . $row->filename_hash]['content_hash'] = $row->content_hash;
          }
        }
        if (isset($info_on_files[$cid]) == FALSE || $info_on_files[$cid]['content_hash'] !== $file_contents_hash) {

          // If the content hash doesn't match don't write the file.
          $write_aggregate = advagg_missing_file_not_readable($file, $aggregate_filename, FALSE);
        }
        $contents = advagg_load_css_stylesheet($file, $optimize, $aggregate_settings, $file_contents);
      }
      else {

        // File is not readable.
        $write_aggregate = advagg_missing_file_not_readable($file, $aggregate_filename, TRUE);
      }

      // Allow other modules to modify this files contents.
      // Call hook_advagg_get_css_file_contents_alter().
      if (empty($aggregate_settings['settings']['no_alters'])) {
        drupal_alter('advagg_get_css_file_contents', $contents, $file, $aggregate_settings);
      }
      if ($media_changes) {
        $media_blocks = advagg_parse_media_blocks($contents);
        $contents = '';
        $file_has_type = FALSE;
        if (!empty($settings['media'])) {
          foreach ($media_types as $media_type) {
            if (stripos($settings['media'], $media_type) !== FALSE) {
              $file_has_type = TRUE;
              break;
            }
          }
        }
        foreach ($media_blocks as $css_rules) {
          if (strpos($css_rules, '@media') !== FALSE) {

            // Get start and end of the rules for this media query block.
            $start = strpos($css_rules, '{');
            if ($start === FALSE) {
              continue;
            }
            $end = strrpos($css_rules, '}');
            if ($end === FALSE) {
              continue;
            }

            // Get current media queries for this media block.
            $media_rules = substr($css_rules, 6, $start - 6);

            // Get everything else besides top level media query.
            $css_selectors_rules = substr($css_rules, $start + 1, $end - ($start + 1));

            // Add in main media rule if needed.
            if (!empty($settings['media']) && strpos($media_rules, $settings['media']) === FALSE && $settings['media'] !== $global_file_media) {
              $rule_has_type = FALSE;
              if ($file_has_type) {
                foreach ($media_types as $media_type) {
                  if (stripos($media_rules, $media_type) !== FALSE) {
                    $rule_has_type = TRUE;
                    break;
                  }
                }
              }
              if (!$rule_has_type) {
                $media_rules = $settings['media'] . ' and ' . $media_rules;
              }
            }
          }
          else {
            $media_rules = $settings['media'];
            $css_selectors_rules = $css_rules;
          }
          $media_rules = trim($media_rules);

          // Pul all @font-face defentions inside the @media declaration above.
          $font_face_string = '';
          $font_blocks = advagg_parse_media_blocks($css_selectors_rules, '@font-face');
          $css_selectors_rules = '';
          foreach ($font_blocks as $rules) {
            if (strpos($rules, '@font-face') !== FALSE) {
              $font_face_string .= "\n {$rules}";
            }
            else {
              $css_selectors_rules .= $rules;
            }
          }
          $css_selectors_rules = str_replace("\n", "\n  ", $css_selectors_rules);
          $font_face_string = str_replace("\n", "\n  ", $font_face_string);

          // Wrap css in dedicated media query if it differs from the global
          // media query and there actually are media rules.
          if (!empty($media_rules) && $media_rules !== $global_file_media) {
            $output = "{$font_face_string} \n@media {$media_rules} {\n {$css_selectors_rules} \n}";
          }
          else {
            $output = "{$font_face_string} \n {$css_selectors_rules}";
          }
          $contents .= trim($output);
        }
      }

      // Per the W3C specification at
      // http://www.w3.org/TR/REC-CSS2/cascade.html#at-import, @import rules
      // must proceed any other style, so we move those to the top.
      $regexp = '/@import[^;]+;/i';
      preg_match_all($regexp, $contents, $matches);
      $contents = preg_replace($regexp, '', $contents);

      // Add the import statements with the media query of the current file.
      $import_media = isset($settings['media']) ? $settings['media'] : '';
      $import_media = trim($import_media);
      $import_statements[] = array(
        $import_media,
        $matches[0],
      );

      // Close any open comment blocks.
      $contents .= "\n/*})'\"*/\n";
      if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) < 0) {
        $contents .= "\n/* Above code came from {$file} */\n\n";
      }
      $data .= $contents;
    }

    // Add import statements to the top of the stylesheet.
    $import_string = '';
    foreach ($import_statements as $values) {
      if ($media_changes) {
        foreach ($values[1] as $statement) {
          $import_string .= str_replace(';', $values[0] . ';', $statement);
        }
      }
      else {
        $import_string .= implode('', $values[1]);
      }
    }
    $data = $import_string . $data;
  }

  // Allow other modules to modify this aggregates contents.
  // Call hook_advagg_get_css_aggregate_contents_alter().
  if (empty($aggregate_settings['settings']['no_alters'])) {
    drupal_alter('advagg_get_css_aggregate_contents', $data, $files, $aggregate_settings);
  }
  return array(
    $data,
    $write_aggregate,
  );
}