You are here

protected function AjaxResponseAttachmentsProcessor::buildAttachmentsCommands in Content-Security-Policy 8

Prepares the AJAX commands to attach assets.

Parameters

\Drupal\Core\Ajax\AjaxResponse $response: The AJAX response to update.

\Symfony\Component\HttpFoundation\Request $request: The request object that the AJAX is responding to.

Return value

array An array of commands ready to be returned as JSON.

1 call to AjaxResponseAttachmentsProcessor::buildAttachmentsCommands()
AjaxResponseAttachmentsProcessor::processAttachments in csp_extras/src/Ajax/AjaxResponseAttachmentsProcessor.php
Processes the attachments of a response that has attachments.

File

csp_extras/src/Ajax/AjaxResponseAttachmentsProcessor.php, line 117

Class

AjaxResponseAttachmentsProcessor
Processes attachments of AJAX responses.

Namespace

Drupal\csp_extras\Ajax

Code

protected function buildAttachmentsCommands(AjaxResponse $response, Request $request) {
  $ajax_page_state = $request->request
    ->get('ajax_page_state');

  // Aggregate CSS/JS if necessary, but only during normal site operation.
  $optimize_css = !defined('MAINTENANCE_MODE') && $this->config
    ->get('css.preprocess');
  $optimize_js = !defined('MAINTENANCE_MODE') && $this->config
    ->get('js.preprocess');
  $attachments = $response
    ->getAttachments();

  // Resolve the attached libraries into asset collections.
  $assets = new AttachedAssets();
  $assets
    ->setLibraries(isset($attachments['library']) ? $attachments['library'] : [])
    ->setAlreadyLoadedLibraries(isset($ajax_page_state['libraries']) ? explode(',', $ajax_page_state['libraries']) : [])
    ->setSettings(isset($attachments['drupalSettings']) ? $attachments['drupalSettings'] : []);
  $css_assets = $this->assetResolver
    ->getCssAssets($assets, $optimize_css);
  list($js_assets_header, $js_assets_footer) = $this->assetResolver
    ->getJsAssets($assets, $optimize_js);

  // First, AttachedAssets::setLibraries() ensures duplicate libraries are
  // removed: it converts it to a set of libraries if necessary. Second,
  // AssetResolver::getJsSettings() ensures $assets contains the final set of
  // JavaScript settings. AttachmentsResponseProcessorInterface also mandates
  // that the response it processes contains the final attachment values, so
  // update both the 'library' and 'drupalSettings' attachments accordingly.
  $attachments['library'] = $assets
    ->getLibraries();
  $attachments['drupalSettings'] = $assets
    ->getSettings();
  $response
    ->setAttachments($attachments);

  // Render the HTML to load these files, and add AJAX commands to insert this
  // HTML in the page. Settings are handled separately, afterwards.
  $settings = [];
  if (isset($js_assets_header['drupalSettings'])) {
    $settings = $js_assets_header['drupalSettings']['data'];
    unset($js_assets_header['drupalSettings']);
  }
  if (isset($js_assets_footer['drupalSettings'])) {
    $settings = $js_assets_footer['drupalSettings']['data'];
    unset($js_assets_footer['drupalSettings']);
  }

  // Remove assets that are not available to all browsers.
  $css_assets = array_filter($css_assets, [
    $this,
    'filterBrowserAssets',
  ]);
  $js_assets = array_filter(array_merge($js_assets_header, $js_assets_footer), [
    $this,
    'filterBrowserAssets',
  ]);
  if (!empty($css_assets) || !empty($js_assets)) {
    $default_query_string = \Drupal::state()
      ->get('system.css_js_query_string') ?: '0';
    $css_assets = array_map(function ($css_asset) use ($default_query_string) {
      $asset = [
        'type' => 'stylesheet',
        'attributes' => [
          'media' => $css_asset['media'],
          'href' => file_url_transform_relative(file_create_url($css_asset['data'])),
        ],
      ];
      if (isset($css_asset['attributes'])) {
        $asset['attributes'] += $css_asset['attributes'];
      }

      // Only add the cache-busting query string if this isn't an
      // aggregate file.
      if ($css_asset['type'] == 'file' && !isset($css_asset['preprocessed'])) {
        $query_string_separator = strpos($css_asset['data'], '?') !== FALSE ? '&' : '?';
        $asset['attributes']['href'] .= $query_string_separator . $default_query_string;
      }
      return $asset;
    }, $css_assets);
    $js_assets = array_map(function ($js_asset) use ($default_query_string) {
      $asset = [
        'type' => 'script',
        'attributes' => [
          'src' => file_url_transform_relative(file_create_url($js_asset['data'])),
        ],
      ];
      if (isset($js_asset['attributes'])) {
        $asset['attributes'] += $js_asset['attributes'];
      }

      // Only add the cache-busting query string if this isn't an
      // aggregate file.
      if ($js_asset['type'] == 'file' && !isset($js_asset['preprocessed'])) {
        $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version'];
        $query_string_separator = strpos($js_asset['data'], '?') !== FALSE ? '&' : '?';
        $asset['attributes']['src'] .= $query_string_separator . ($js_asset['cache'] ? $query_string : $this->time
          ->getRequestTime());
      }
      return $asset;
    }, $js_assets);
    $response
      ->addCommand(new AddAssetsCommand(array_merge($css_assets, $js_assets)), TRUE);
  }

  // Prepend a command to merge changes and additions to drupalSettings.
  if (!empty($settings)) {

    // During Ajax requests basic path-specific settings are excluded from
    // new drupalSettings values. The original page where this request comes
    // from already has the right values. An Ajax request would update them
    // with values for the Ajax request and incorrectly override the page's
    // values.
    // @see system_js_settings_alter()
    unset($settings['path']);
    $response
      ->addCommand(new SettingsCommand($settings, TRUE), TRUE);
  }
  $commands = $response
    ->getCommands();
  $this->moduleHandler
    ->alter('ajax_render', $commands);
  return $commands;
}