refreshless-8.x-1.x-dev/modules/refreshless_turbo/src/Service/AssetResolver.php

modules/refreshless_turbo/src/Service/AssetResolver.php
<?php

declare(strict_types=1);

namespace Drupal\refreshless_turbo\Service;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Asset\AssetResolverInterface;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\refreshless\Service\RefreshlessKillSwitchInterface;
use Drupal\refreshless_turbo\Value\RefreshlessAsset;
use function array_keys;
use function array_search;
use function array_splice;
use function is_int;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;

/**
 * Decorated asset resolver service.
 *
 * @see \Drupal\Core\Asset\AssetResolver
 *   Drupal core implementation.
 *
 * @see \Drupal\Core\Asset\AssetResolverInterface
 *
 * @see https://www.drupal.org/project/refreshless/issues/3397370
 *   Explains the rationale for including drupalSettings in the <body>.
 */
class AssetResolver implements AssetResolverInterface {

  /**
   * Service constructor; saves dependencies.
   *
   * @param \Drupal\Core\Asset\AssetResolverInterface $decorated
   *   The asset resolver service that we decorate.
   *
   * @param \Drupal\refreshless\Service\RefreshlessKillSwitchInterface $killSwitch
   *   The RefreshLess kill switch service.
   */
  public function __construct(
    #[AutowireDecorated]
    protected readonly AssetResolverInterface $decorated,
    protected readonly RefreshlessKillSwitchInterface $killSwitch,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function getCssAssets(
    AttachedAssetsInterface $assets,
    $optimize,
    ?LanguageInterface $language = null,
  ) {

    if ($this->killSwitch->triggered()) {
      return $this->decorated->getCssAssets($assets, $optimize, $language);
    }

    // Save already loaded libraries to restore after building CSS.
    $alreadyLoaded = $assets->getAlreadyLoadedLibraries();

    // Force building of CSS assets as if no libraries have already been marked
    // as loaded. This is necessary to work around our additive JavaScript
    // aggregation which will mark libraries as already loaded, which can then
    // result in cases where a library that contains both JavaScript and CSS
    // attaching neither; unfortunately, this means we wouldn't have access to
    // the full list of ordered CSS files to generate the weight attributes,
    // resulting in incorrect specificity issues during Turbo navigation if CSS
    // aggregation is disabled.
    //
    // @todo Can we handle this instead in a custom attachments processor to
    //   avoid doing this?
    $assets->setAlreadyLoadedLibraries([]);

    $css = $this->decorated->getCssAssets($assets, $optimize, $language);

    // Now restore the already loaded libraries to avoid unintended problems.
    $assets->setAlreadyLoadedLibraries($alreadyLoaded);

    // Output a data attribute for the front-end to sort the stylesheets into
    // the correct order as Turbo currently only appends new stylesheets
    // without preserving their source order.
    //
    // @see https://www.drupal.org/project/refreshless/issues/3399314
    foreach (array_keys($css) as $index => $key) {

      $css[$key]['attributes'][
        RefreshlessAsset::getStylesheetOrderAttributeName()
      ] = $index;

    }

    return $css;

  }

  /**
   * {@inheritdoc}
   */
  public function getJsAssets(
    AttachedAssetsInterface $assets,
    $optimize,
    ?LanguageInterface $language = null,
  ) {

    if ($this->killSwitch->triggered()) {
      return $this->decorated->getJsAssets($assets, $optimize, $language);
    }

    $alreadyLoaded = $assets->getAlreadyLoadedLibraries();

    /** @var int|false */
    $index = array_search('refreshless_turbo/refreshless', $alreadyLoaded);

    if (is_int($index)) {

      // Remove the 'refreshless_turbo/refreshless' library from the already
      // loaded array to ensure it remains attached.
      array_splice($alreadyLoaded, $index, 1);

      // Mark Turbo itself as already loaded. While Turbo is currently set to
      // preprocess: false and thus should not get evaluated more than once,
      // not marking it as already loaded seems to introduce some multiple
      // evaluation of our own JavaScript when aggregation is enabled in some
      // cases.
      //
      // @todo Remove when we've resolved the above issue.
      $alreadyLoaded[] = 'refreshless_turbo/turbo';

      $assets->setAlreadyLoadedLibraries($alreadyLoaded);

    }

    return $this->decorated->getJsAssets($assets, $optimize, $language);

  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc