Same name in other branches
  1. 5.0.x src/Asset/CssOptimizer.php \Drupal\advagg\Asset\CssOptimizer
  2. 6.0.x src/Asset/CssOptimizer.php \Drupal\advagg\Asset\CssOptimizer
  3. 8.x-3.x src/Asset/CssOptimizer.php \Drupal\advagg\Asset\CssOptimizer
  4. 8.x-4.x src/Asset/CssOptimizer.php \Drupal\advagg\Asset\CssOptimizer

Optimizes a CSS asset.

Hierarchy

  • class \Drupal\advagg_css_minify\Asset\CssOptimizer extends \Drupal\Core\Asset\CssOptimizer implements \Drupal\Core\Asset\AssetOptimizerInterface

Expanded class hierarchy of CssOptimizer

1 string reference to 'CssOptimizer'
advagg_css_minify.services.yml in advagg_css_minify/advagg_css_minify.services.yml
advagg_css_minify/advagg_css_minify.services.yml
1 service uses CssOptimizer
asset.css.optimizer in advagg_css_minify/advagg_css_minify.services.yml
Drupal\advagg_css_minify\Asset\CssOptimizer

File

advagg_css_minify/src/Asset/CssOptimizer.php, line 16

Namespace

Drupal\advagg_css_minify\Asset
View source
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);
            }
            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;
    }

}

Members

Title Sort descending Modifiers Object type Summary
CssOptimizer::$advaggConfig protected property A config object for the advagg configuration.
CssOptimizer::$advaggFiles protected property The AdvAgg file status state information storage service.
CssOptimizer::$cache protected property The minify cache.
CssOptimizer::$config protected property A config object for the advagg css minify configuration.
CssOptimizer::$moduleHandler protected property Module handler service.
CssOptimizer::getConfiguration public function Generate the css minification configuration.
CssOptimizer::loadFile public function Loads the stylesheet and resolves all @import commands.
CssOptimizer::processCssMin protected function Processes the contents of a stylesheet through CSSMin for minification.
CssOptimizer::processCssOther protected function Processes the contents of a stylesheet for minification.
CssOptimizer::__construct public function Construct the optimizer instance.