Version 1
[yaffs-website] / web / modules / contrib / advagg / advagg_css_minify / src / Asset / CssOptimizer.php
diff --git a/web/modules/contrib/advagg/advagg_css_minify/src/Asset/CssOptimizer.php b/web/modules/contrib/advagg/advagg_css_minify/src/Asset/CssOptimizer.php
new file mode 100644 (file)
index 0000000..4c2fdf6
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+
+namespace Drupal\advagg_css_minify\Asset;
+
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Asset\AssetOptimizerInterface;
+use Drupal\Core\Asset\CssOptimizer as CoreCssOptimizer;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\State\StateInterface;
+
+/**
+ * Optimizes a CSS asset.
+ */
+class CssOptimizer extends CoreCssOptimizer implements AssetOptimizerInterface {
+
+  /**
+   * The minify cache.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * A config object for the advagg css minify configuration.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $config;
+
+  /**
+   * A config object for the advagg configuration.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $advaggConfig;
+
+  /**
+   * The AdvAgg file status state information storage service.
+   *
+   * @var \Drupal\Core\State\StateInterface
+   */
+  protected $advaggFiles;
+
+  /**
+   * Module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Construct the optimizer instance.
+   *
+   * @param \Drupal\Core\Cache\CacheBackendInterface $minify_cache
+   *   The minify cache.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   A config factory for retrieving required config objects.
+   * @param \Drupal\Core\State\StateInterface $advagg_files
+   *   The AdvAgg file status state information storage service.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   */
+  public function __construct(CacheBackendInterface $minify_cache, ConfigFactoryInterface $config_factory, StateInterface $advagg_files, ModuleHandlerInterface $module_handler) {
+    $this->cache = $minify_cache;
+    $this->config = $config_factory->get('advagg_css_minify.settings');
+    $this->advaggConfig = $config_factory->get('advagg.settings');
+    $this->advaggFiles = $advagg_files;
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * Generate the css minification configuration.
+   *
+   * @return array
+   *   Array($options, $description, $minifiers, $functions).
+   */
+  public function getConfiguration() {
+    $description = '';
+    $options = [
+      0 => t('Disabled'),
+      1 => t('Core'),
+      2 => t('YUI'),
+    ];
+
+    $minifiers = [NULL, NULL, NULL];
+    $functions = [NULL, NULL, NULL];
+
+    // Allow for other modules to alter this list.
+    $options_desc = [$options, $description];
+    $this->moduleHandler->alter('advagg_css_minify_configuration', $options_desc, $minifiers, $functions);
+    list($options, $description) = $options_desc;
+
+    return [$options, $description, $minifiers, $functions];
+  }
+
+  /**
+   * Loads the stylesheet and resolves all @import commands.
+   *
+   * Loads a stylesheet and replaces @import commands with the contents of the
+   * imported file. Use this instead of file_get_contents when processing
+   * stylesheets.
+   *
+   * The returned contents are compressed removing white space and comments only
+   * when CSS aggregation is enabled. This optimization will not apply for
+   * color.module enabled themes with CSS aggregation turned off.
+   *
+   * Note: the only reason this method is public is so color.module can call it;
+   * it is not on the AssetOptimizerInterface, so future refactorings can make
+   * it protected.
+   *
+   * @param string $file
+   *   Name of the stylesheet to be processed.
+   * @param bool $optimize
+   *   (optional) Defines if CSS contents should be compressed or not. Not used
+   *   in AdvAgg implementation.
+   * @param bool $reset_basepath
+   *   (optional) Used internally to facilitate recursive resolution of @import
+   *   commands.
+   *
+   * @return string
+   *   Contents of the stylesheet, including any resolved @import commands.
+   */
+  public function loadFile($file, $optimize = NULL, $reset_basepath = TRUE) {
+    // These statics are not cache variables, so we don't use drupal_static().
+    static $basepath;
+    if ($reset_basepath) {
+      $basepath = '';
+    }
+
+    // Stylesheets are relative one to each other. Start by adding a base path
+    // prefix provided by the parent stylesheet (if necessary).
+    if ($basepath && !file_uri_scheme($file)) {
+      $file = $basepath . '/' . $file;
+    }
+    // Store the parent base path to restore it later.
+    $parent_base_path = $basepath;
+    // Set the current base path to process possible child imports.
+    $basepath = dirname($file);
+
+    // Load the CSS stylesheet. We suppress errors because themes may specify
+    // stylesheets in their .info.yml file that don't exist in the theme's path,
+    // but are merely there to disable certain module CSS files.
+    $content = '';
+    if ($contents = @file_get_contents($file)) {
+      // If a BOM is found, convert the file to UTF-8, then use substr() to
+      // remove the BOM from the result.
+      if ($encoding = (Unicode::encodingFromBOM($contents))) {
+        $contents = Unicode::substr(Unicode::convertToUtf8($contents, $encoding), 1);
+      }
+      // If no BOM, check for fallback encoding. Per CSS spec the regex is very
+      // strict.
+      elseif (preg_match('/^@charset "([^"]+)";/', $contents, $matches)) {
+        if ($matches[1] !== 'utf-8' && $matches[1] !== 'UTF-8') {
+          $contents = substr($contents, strlen($matches[0]));
+          $contents = Unicode::convertToUtf8($contents, $matches[1]);
+        }
+      }
+
+      $minifier = $this->config->get('minifier');
+      if ($file_settings = $this->config->get('file_settings')) {
+        $file_settings = array_column($file_settings, 'minifier', 'path');
+        if (isset($file_settings[$file])) {
+          $minifier = $file_settings[$file];
+        }
+      }
+
+      $info = $this->advaggFiles->get($file);
+      $cid = 'css_minify:' . $minifier . ':' . $info['filename_hash'];
+      $cid .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
+      $cached_data = $this->cache->get($cid);
+      if (!empty($cached_data->data)) {
+        $content = $cached_data->data;
+      }
+      else {
+        if (!$minifier || $this->advaggConfig->get('cache_level') < 0) {
+          $content = $this->processCss($contents, FALSE);
+        }
+        elseif ($minifier == 1) {
+          $content = $this->processCss($contents, TRUE);
+        }
+        elseif ($minifier == 2) {
+          $content = $this->processCssMin($contents);
+        }
+        else {
+          $content = $this->processCssOther($contents, $minifier);
+        }
+      }
+      // Cache minified data for at least 1 week.
+      $this->cache->set($cid, $content, REQUEST_TIME + (86400 * 7), ['advagg_css', $info['filename_hash']]);
+    }
+
+    // Restore the parent base path as the file and its children are processed.
+    $basepath = $parent_base_path;
+    return $content;
+  }
+
+  /**
+   * Processes the contents of a stylesheet through CSSMin for minification.
+   *
+   * @param string $contents
+   *   The contents of the stylesheet.
+   *
+   * @return string
+   *   Minified contents of the stylesheet including the imported stylesheets.
+   */
+  protected function processCssMin($contents) {
+    $contents = $this->clean($contents);
+    if (!class_exists('CSSmin')) {
+      include drupal_get_path('module', 'advagg_css_minify') . '/yui/CSSMin.inc';
+    }
+    $cssmin = new \CSSmin(TRUE);
+
+    // Minify the CSS splitting lines after 4k of text.
+    $contents = $cssmin->run($contents, 4096);
+
+    // Replaces @import commands with the actual stylesheet content.
+    // This happens recursively but omits external files.
+    $contents = preg_replace_callback('/@import\s*(?:url\(\s*)?[\'"]?(?![a-z]+:)(?!\/\/)([^\'"\()]+)[\'"]?\s*\)?\s*;/', [$this, 'loadNestedFile'], $contents);
+
+    return $contents;
+  }
+
+  /**
+   * Processes the contents of a stylesheet for minification.
+   *
+   * @param string $contents
+   *   The contents of the stylesheet.
+   * @param string $minifier
+   *   The name of the minifier to use.
+   *
+   * @return string
+   *   Minified contents of the stylesheet including the imported stylesheets.
+   */
+  protected function processCssOther($contents, $minifier) {
+    $contents = $this->clean($contents);
+    list(, , , $functions) = $this->getConfiguration();
+    if (isset($functions[$minifier])) {
+      $run = $functions[$minifier];
+      if (function_exists($run)) {
+        $run($contents);
+      }
+    }
+    // Replaces @import commands with the actual stylesheet content.
+    // This happens recursively but omits external files.
+    $contents = preg_replace_callback('/@import\s*(?:url\(\s*)?[\'"]?(?![a-z]+:)(?!\/\/)([^\'"\()]+)[\'"]?\s*\)?\s*;/', [$this, 'loadNestedFile'], $contents);
+
+    return $contents;
+  }
+
+}