You are here

public function JsOptimizer::optimize in Advanced CSS/JS Aggregation 8.2

Optimizes an asset.

Parameters

array $asset: An asset.

Return value

string The optimized asset's contents.

Overrides AssetOptimizerInterface::optimize

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;
}