File

advagg_js_minify/src/Asset/JsOptimizer.php, line 141

Class

JsOptimizer
Optimizes a JavaScript asset.

Namespace

Drupal\advagg_js_minify\Asset

Code

public function optimize(array $js_asset) {
    if ($js_asset['type'] !== 'file') {
        throw new \Exception('Only file JavaScript assets can be optimized.');
    }
    if ($js_asset['type'] === 'file' && !$js_asset['preprocess']) {
        throw new \Exception('Only file JavaScript assets with preprocessing enabled can be optimized.');
    }
    // If a BOM is found, convert the file to UTF-8, then use substr() to
    // remove the BOM from the result.
    $data = file_get_contents($js_asset['data']);
    if ($encoding = Unicode::encodingFromBOM($data)) {
        $data = Unicode::substr(Unicode::convertToUtf8($data, $encoding), 1);
    }
    elseif (isset($js_asset['attributes']['charset'])) {
        $data = Unicode::convertToUtf8($data, $js_asset['attributes']['charset']);
    }
    $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[$js_asset['data']])) {
            $minifier = $file_settings[$js_asset['data']];
        }
    }
    // Do nothing if js file minification is disabled.
    if (empty($minifier) || $this->advaggConfig
        ->get('cache_level') < 0) {
        return $data;
    }
    // Do not re-minify if the file is already minified.
    $semicolon_count = substr_count($data, ';');
    if ($minifier != 2 && $semicolon_count > 10 && $semicolon_count > substr_count($data, "\n", strpos($data, ';')) * 5) {
        if ($this->config
            ->get('add_license')) {
            $url = file_create_url($js_asset['data']);
            $data = "/* Source and licensing information for the line(s) below can be found at {$url}. */\n" . $data . "\n/* Source and licensing information for the above line(s) can be found at {$url}. */";
        }
        return $data;
    }
    $data_original = $data;
    $before = strlen($data);
    $info = $this->advaggFiles
        ->get($js_asset['data']);
    $cid = 'js_minify:' . $minifier . ':' . $info['filename_hash'];
    $cid .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
    $cached_data = $this->cache
        ->get($cid);
    if (!empty($cached_data->data)) {
        $data = $cached_data->data;
    }
    else {
        // Use the minifier.
        list(, , , $functions) = $this->getConfiguration();
        if (isset($functions[$minifier])) {
            $run = $functions[$minifier];
            if (is_callable($run)) {
                call_user_func_array($run, [
                    &$data,
                    $js_asset,
                ]);
            }
        }
        else {
            return $data;
        }
        // Ensure that $data ends with ; or }.
        if (strpbrk(substr(trim($data), -1), ';})') === FALSE) {
            $data = trim($data) . ';';
        }
        // Cache minified data for at least 1 week.
        $this->cache
            ->set($cid, $data, REQUEST_TIME + 86400 * 7, [
            'advagg_js',
            $info['filename_hash'],
        ]);
        // Make sure minification ratios are good.
        $after = strlen($data);
        $ratio = 0;
        if ($before != 0) {
            $ratio = ($before - $after) / $before;
        }
        // Make sure the returned string is not empty or has a VERY high
        // minification ratio.
        if (empty($data) || empty($ratio) || $ratio < 0 || $ratio > $this->config
            ->get('ratio_max')) {
            $data = $data_original;
        }
        elseif ($this->config
            ->get('add_license')) {
            $url = file_create_url($js_asset['data']);
            $data = "/* Source and licensing information for the line(s) below can be found at {$url}. */\n" . $data . "\n/* Source and licensing information for the above line(s) can be found at {$url}. */";
        }
    }
    return $data;
}