decoupled_router-2.0.1/src/EventSubscriber/RedirectPathTranslatorSubscriber.php

src/EventSubscriber/RedirectPathTranslatorSubscriber.php
<?php

namespace Drupal\decoupled_router\EventSubscriber;

use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\CacheableJsonResponse;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\decoupled_router\PathTranslatorEvent;
use Drupal\path_alias\AliasManagerInterface;
use Drupal\redirect\RedirectRepository;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;

/**
 * Event subscriber that processes a path translation with the redirect info.
 *
 * @see \Drupal\decoupled_router\DecoupledRouterServiceProvider
 */
class RedirectPathTranslatorSubscriber extends RouterPathTranslatorSubscriber {

  public function __construct(
    ContainerInterface $container,
    #[Autowire(service: 'logger.channel.decoupled_router')] LoggerInterface $logger,
    #[Autowire(service: 'router.no_access_checks')] UrlMatcherInterface $router,
    ModuleHandlerInterface $module_handler,
    ConfigFactoryInterface $config_factory,
    AliasManagerInterface $aliasManager,
    protected LanguageManagerInterface $languageManager,
    protected RedirectRepository $redirectRepository,
  ) {
    parent::__construct($container, $logger, $router, $module_handler, $config_factory, $aliasManager);
  }

  /**
   * {@inheritdoc}
   */
  protected const LOG_ENTITY_NOT_FOUND = FALSE;

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // We wanna run before the router-based path translator because redirects
    // naturally act before routing subsystem in Drupal HTTP kernel.
    $events[PathTranslatorEvent::TRANSLATE][] = ['onPathTranslation', 10];
    return $events;
  }

  /**
   * {@inheritdoc}
   */
  public function onPathTranslation(PathTranslatorEvent $event) {
    $response = $event->getResponse();
    if (!$response instanceof CacheableJsonResponse) {
      $this->logger->error('Unable to get the response object for the decoupled router event.');
      return;
    }

    // Find the redirected path. Bear in mind that we need to go through several
    // redirection levels before handing off to the route translator.
    $original_parsed_url = UrlHelper::parse($event->getPath());
    $request_query = $original_parsed_url['query'];
    $source_path = $this->cleanSubdirInPath($original_parsed_url['path'], $event->getRequest());

    $cacheable_metadata = new CacheableMetadata();
    $cacheable_metadata->addCacheableDependency($this->configFactory->get('redirect.settings'));

    $redirect = $this->redirectRepository->findMatchingRedirect(
      $source_path,
      $request_query,
      $this->languageManager->getCurrentLanguage()->getId(),
      $cacheable_metadata
    );
    if (!$redirect) {
      return;
    }

    $response->addCacheableDependency($cacheable_metadata);
    $redirect_url = $redirect->getRedirectUrl();
    if ($this->configFactory->get('redirect.settings')->get('passthrough_querystring')) {
      $redirect_url->setOption('query', (array) $redirect_url->getOption('query') + $request_query);
    }

    $redirect_url_string = $redirect_url->toString();

    // Preserve the fragment as per RFC 7231, see
    // https://www.rfc-editor.org/rfc/rfc7231#section-7.1.2. Only replace the
    // fragment if the redirect does not have a fragment. Redirects store
    // fragments as part of the path so we need to parse the URI.
    if (isset($original_parsed_url['fragment']) && empty(UrlHelper::parse($redirect_url_string)['fragment'])) {
      $redirect_url->setOption('fragment', $original_parsed_url['fragment']);
      $redirect_url_string = $redirect_url->toString();
    }

    $redirects_trace[] = [
      'from' => $event->getPath(),
      'to' => $redirect_url_string,
      'status' => $redirect->getStatusCode(),
    ];

    // At this point we should be pointing to a system route or path alias.
    $event->setPath($redirect_url_string);

    // Now call the route level.
    parent::onPathTranslation($event);

    if ($response->isSuccessful()) {
      $content = Json::decode($response->getContent());
    }
    elseif ($response->getStatusCode() === 404) {
      // We should return the redirect data.
      $response->setStatusCode(200);
      $cacheable_metadata->addCacheableDependency($this->decoupledRouterConfig);
      $content = [
        'resolved' => $redirect_url->setAbsolute($this->decoupledRouterConfig->get('absolute_resolved_urls'))->toString(TRUE)->getGeneratedUrl(),
        'isExternal' => FALSE,
        'isHomePath' => $this->resolvedPathIsHomePath($redirect_url, $cacheable_metadata),
      ];
    }
    else {
      return;
    }

    // Set the content in the response.
    $response->setData(array_merge(
      $content,
      ['redirect' => $redirects_trace]
    ));

    $response->addCacheableDependency($cacheable_metadata);

    $event->stopPropagation();
  }

}

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

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