PathProcessorLanguage.php

Same filename in other branches
  1. 9 core/modules/language/src/HttpKernel/PathProcessorLanguage.php
  2. 10 core/modules/language/src/HttpKernel/PathProcessorLanguage.php
  3. 11.x core/modules/language/src/HttpKernel/PathProcessorLanguage.php

Namespace

Drupal\language\HttpKernel

File

core/modules/language/src/HttpKernel/PathProcessorLanguage.php

View source
<?php

namespace Drupal\language\HttpKernel;

use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\language\ConfigurableLanguageManagerInterface;
use Drupal\language\EventSubscriber\ConfigSubscriber;
use Drupal\language\LanguageNegotiatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Session\AccountInterface;

/**
 * Processes the inbound path using path alias lookups.
 */
class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPathProcessorInterface {
    
    /**
     * A config factory for retrieving required config settings.
     *
     * @var \Drupal\Core\Config\ConfigFactoryInterface
     */
    protected $config;
    
    /**
     * Language manager for retrieving the url language type.
     *
     * @var \Drupal\language\ConfigurableLanguageManagerInterface
     */
    protected $languageManager;
    
    /**
     * The language negotiator.
     *
     * @var \Drupal\language\LanguageNegotiatorInterface
     */
    protected $negotiator;
    
    /**
     * Local cache for language path processors.
     *
     * @var array
     */
    protected $processors;
    
    /**
     * Flag indicating whether the site is multilingual.
     *
     * @var bool
     */
    protected $multilingual;
    
    /**
     * The language configuration event subscriber.
     *
     * @var \Drupal\language\EventSubscriber\ConfigSubscriber
     */
    protected $configSubscriber;
    
    /**
     * Constructs a PathProcessorLanguage object.
     *
     * @param \Drupal\Core\Config\ConfigFactoryInterface $config
     *   A config factory object for retrieving configuration settings.
     * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
     *   The configurable language manager.
     * @param \Drupal\language\LanguageNegotiatorInterface $negotiator
     *   The language negotiator.
     * @param \Drupal\Core\Session\AccountInterface $current_user
     *   The current active user.
     * @param \Drupal\language\EventSubscriber\ConfigSubscriber $config_subscriber
     *   The language configuration event subscriber.
     */
    public function __construct(ConfigFactoryInterface $config, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user, ConfigSubscriber $config_subscriber) {
        $this->config = $config;
        $this->languageManager = $language_manager;
        $this->negotiator = $negotiator;
        $this->negotiator
            ->setCurrentUser($current_user);
        $this->configSubscriber = $config_subscriber;
    }
    
    /**
     * {@inheritdoc}
     */
    public function processInbound($path, Request $request) {
        if (!empty($path)) {
            $scope = 'inbound';
            if (!isset($this->processors[$scope])) {
                $this->initProcessors($scope);
            }
            foreach ($this->processors[$scope] as $instance) {
                $path = $instance->processInbound($path, $request);
            }
        }
        return $path;
    }
    
    /**
     * {@inheritdoc}
     */
    public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
        if (!isset($this->multilingual)) {
            $this->multilingual = $this->languageManager
                ->isMultilingual();
        }
        if ($this->multilingual) {
            $this->negotiator
                ->reset();
            $scope = 'outbound';
            if (!isset($this->processors[$scope])) {
                $this->initProcessors($scope);
            }
            foreach ($this->processors[$scope] as $instance) {
                $path = $instance->processOutbound($path, $options, $request, $bubbleable_metadata);
            }
            // No language dependent path allowed in this mode.
            if (empty($this->processors[$scope])) {
                unset($options['language']);
            }
        }
        return $path;
    }
    
    /**
     * Initializes the local cache for language path processors.
     *
     * @param string $scope
     *   The scope of the processors: "inbound" or "outbound".
     */
    protected function initProcessors($scope) {
        $interface = '\\Drupal\\Core\\PathProcessor\\' . Unicode::ucfirst($scope) . 'PathProcessorInterface';
        $this->processors[$scope] = [];
        $weights = [];
        foreach ($this->languageManager
            ->getLanguageTypes() as $type) {
            foreach ($this->negotiator
                ->getNegotiationMethods($type) as $method_id => $method) {
                if (!isset($this->processors[$scope][$method_id])) {
                    $reflector = new \ReflectionClass($method['class']);
                    if ($reflector->implementsInterface($interface)) {
                        $this->processors[$scope][$method_id] = $this->negotiator
                            ->getNegotiationMethodInstance($method_id);
                        $weights[$method_id] = $method['weight'];
                    }
                }
            }
        }
        // Sort the processors list, so that their functions are called in the
        // order specified by the weight of the methods.
        uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use ($weights) {
            $a_weight = $weights[$method_id_a];
            $b_weight = $weights[$method_id_b];
            if ($a_weight == $b_weight) {
                return 0;
            }
            return $a_weight < $b_weight ? -1 : 1;
        });
    }
    
    /**
     * Initializes the injected event subscriber with the language path processor.
     *
     * The language path processor service is registered only on multilingual
     * site configuration, thus we inject it in the event subscriber only when
     * it is initialized.
     */
    public function initConfigSubscriber() {
        $this->configSubscriber
            ->setPathProcessorLanguage($this);
    }
    
    /**
     * Resets the collected processors instances.
     */
    public function reset() {
        $this->processors = [];
    }

}

Classes

Title Deprecated Summary
PathProcessorLanguage Processes the inbound path using path alias lookups.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.