refreshless-8.x-1.x-dev/modules/refreshless_turbo/src/Hooks/Prefetch.php

modules/refreshless_turbo/src/Hooks/Prefetch.php
<?php

declare(strict_types=1);

namespace Drupal\refreshless_turbo\Hooks;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\hux\Attribute\Alter;
use Drupal\hux\Attribute\Hook;
use function array_unique;

/**
 * Prefetch hook implementations.
 */
class Prefetch {

  /**
   * Hook constructor; saves dependencies.
   *
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   *   The current user account proxy service.
   */
  public function __construct(
    protected readonly AccountProxyInterface $currentUser,
  ) {}

  /**
   * Array of route names in link elements to disable Turbo prefetching on.
   *
   * @var string[]
   */
  protected array $excludedRoutesLink = [
    'devel.cache_clear',
    'devel.run_cron',
    'entity.block.disable',
    'entity.block.enable',
    'entity.shortcut.link_delete_inline',
    'shortcut.link_add_inline',
    'system.admin_compact_page',
    'system.batch_page.html',
    'system.cron',
    'system.run_cron',
    'system.theme_install',
    'system.theme_set_default',
    'system.theme_uninstall',
    'update.manual_status',
    'user.logout',
    'user.logout.http',
  ];

  /**
   * Array of route names to disable Turbo prefetching on via drupalSettings.
   *
   * @var string[]
   */
  protected array $excludedRoutesDrupalSettings = [
    'user.logout',
  ];

  #[Alter('link')]
  /**
   * Implements hook_link_alter().
   *
   * This adds the 'data-turbo-prefetch="false"' attribute to various
   * administration links that would perform unexpected actions when prefetched
   * by Turbo.
   *
   * @see \Drupal\Core\Url
   *
   * @see https://www.drupal.org/project/refreshless/issues/3423544
   *   Issue detailing the problem.
   */
  public function alterLink(array &$variables): void {

    if (
      $variables['url']->isExternal() ||
      !$variables['url']->isRouted() ||
      !\in_array(
        $variables['url']->getRouteName(), $this->excludedRoutesLink,
      )
    ) {
      return;
    }

    $variables['options']['attributes']['data-turbo-prefetch'] = 'false';

    // Also prevent preloading on these routes as that causes the same problems
    // as prefetching.
    $variables['options']['attributes'][
      'data-refreshless-lazy-preload'
    ] = 'false';

  }

  #[Hook('js_settings_build')]
  /**
   * Output pretch exclusion path to drupalSettings.
   *
   * @todo Should we cache this or does Drupal handle that? It's unclear if
   *   this will scale well so it may need to be looked at down the line if it
   *   becomes a performance issue.
   */
  public function outputExcludePaths(
    array &$settings, AttachedAssetsInterface $assets,
  ): void {

    $paths = [];

    foreach ($this->excludedRoutesDrupalSettings as $routeName) {

      try {

        $url = Url::fromRoute($routeName);

      } catch (\Exception $exception) {

        continue;

      }

      // Don't output paths the user doesn't have access to so that we don't
      // disclose potentially sensitive information.
      if ($url->access($this->currentUser) === false) {
        continue;
      }

      $generatedPath = $url->toString();

      // We need to parse this to output only the path itself without any query
      // parameters that may be present such as CSRF tokens, etc., as they will
      // prevent matching.
      $parsed = UrlHelper::parse($generatedPath);

      $paths[] = $parsed['path'];

    }

    $settings['refreshless']['prefetchExcludePaths'] = array_unique($paths);

  }

}

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

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