class PathProcessor in Sub-pathauto (Sub-path URL Aliases) 8
Processes the inbound path using path alias lookups.
Hierarchy
- class \Drupal\subpathauto\PathProcessor implements InboundPathProcessorInterface, OutboundPathProcessorInterface
Expanded class hierarchy of PathProcessor
1 file declares its use of PathProcessor
- SubPathautoTest.php in tests/src/ Unit/ SubPathautoTest.php 
1 string reference to 'PathProcessor'
1 service uses PathProcessor
File
- src/PathProcessor.php, line 17 
Namespace
Drupal\subpathautoView source
class PathProcessor implements InboundPathProcessorInterface, OutboundPathProcessorInterface {
  /**
   * The path processor.
   *
   * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
   */
  protected $pathProcessor;
  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;
  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;
  /**
   * The path validator.
   *
   * @var \Drupal\Core\Path\PathValidatorInterface
   */
  protected $pathValidator;
  /**
   * Whether it is recursive call or not.
   *
   * @var bool
   */
  protected $recursiveCall;
  /**
   * Builds PathProcessor object.
   *
   * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $path_processor
   *   The path processor.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   */
  public function __construct(InboundPathProcessorInterface $path_processor, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) {
    $this->pathProcessor = $path_processor;
    $this->languageManager = $language_manager;
    $this->configFactory = $config_factory;
  }
  /**
   * {@inheritdoc}
   */
  public function processInbound($path, Request $request) {
    $request_path = $this
      ->getPath($request
      ->getPathInfo());
    // The path won't be processed if the path has been already modified by
    // a path processor (including this one), or if this is a recursive call
    // caused by ::isValidPath.
    if ($request_path !== $path || $this->recursiveCall) {
      return $path;
    }
    $original_path = $path;
    $max_depth = $this
      ->getMaxDepth();
    $subpath = [];
    $i = 0;
    while (($path_array = explode('/', ltrim($path, '/'))) && ($max_depth === 0 || $i < $max_depth)) {
      $i++;
      $subpath[] = array_pop($path_array);
      if (empty($path_array)) {
        break;
      }
      $path = '/' . implode('/', $path_array);
      $processed_path = $this->pathProcessor
        ->processInbound($path, $request);
      if ($processed_path !== $path) {
        $path = $processed_path . '/' . implode('/', array_reverse($subpath));
        // Ensure that the path generated is valid. Call ::isValidPath to
        // trigger path processors one more time to ensure proposed new path is
        // valid. Since this method has generated the path, it should ignore all
        // recursive calls made for this method.
        $valid_path = $this
          ->isValidPath($path);
        // Use generated path if it's valid, otherwise give up and return
        // original path to give other path processors chance to make their
        // modifications for the path.
        if ($valid_path) {
          return $path;
        }
        break;
      }
    }
    return $original_path;
  }
  /**
   * {@inheritdoc}
   */
  public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleableMetadata = NULL) {
    $original_path = $path;
    $subpath = [];
    $max_depth = $this
      ->getMaxDepth();
    $i = 0;
    while (($path_array = explode('/', ltrim($path, '/'))) && ($max_depth === 0 || $i < $max_depth)) {
      $i++;
      $subpath[] = array_pop($path_array);
      if (empty($path_array)) {
        break;
      }
      $path = '/' . implode('/', $path_array);
      $processed_path = $this->pathProcessor
        ->processOutbound($path, $options, $request);
      if ($processed_path !== $path) {
        $path = $processed_path . '/' . implode('/', array_reverse($subpath));
        return $path;
      }
    }
    return $original_path;
  }
  /**
   * Helper function to handle multilingual paths.
   *
   * @param string $path_info
   *   Path that might contain language prefix.
   *
   * @return string
   *   Path without language prefix.
   */
  protected function getPath($path_info) {
    $language_prefix = '/' . $this->languageManager
      ->getCurrentLanguage(LanguageInterface::TYPE_URL)
      ->getId() . '/';
    if (substr($path_info, 0, strlen($language_prefix)) == $language_prefix) {
      $path_info = '/' . substr($path_info, strlen($language_prefix));
    }
    return $path_info;
  }
  /**
   * Tests if path is valid.
   *
   * This method will call all of the path processors (including this one).
   * Sufficient protection against recursive calls is needed.
   *
   * @param string $path
   *   The path to be checked.
   *
   * @return bool
   *   Whether path is valid or not.
   */
  protected function isValidPath($path) {
    $this->recursiveCall = TRUE;
    $is_valid = (bool) $this
      ->getPathValidator()
      ->getUrlIfValidWithoutAccessCheck($path);
    $this->recursiveCall = FALSE;
    return $is_valid;
  }
  /**
   * Gets the path validator.
   *
   * @return \Drupal\Core\Path\PathValidatorInterface
   *   The path validator.
   */
  protected function getPathValidator() {
    if (!$this->pathValidator) {
      $this
        ->setPathValidator(\Drupal::service('path.validator'));
    }
    return $this->pathValidator;
  }
  /**
   * Sets the path validator.
   *
   * The path validator couldn't be injected to this class properly since it
   * would cause circular dependency.
   *
   * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
   *   The path validator.
   *
   * @return $this
   */
  public function setPathValidator(PathValidatorInterface $path_validator) {
    $this->pathValidator = $path_validator;
    return $this;
  }
  /**
   * Gets the max depth that subpaths should be scanned through.
   *
   * @return int
   *   The maximum depth.
   */
  protected function getMaxDepth() {
    return $this->configFactory
      ->get('subpathauto.settings')
      ->get('depth');
  }
}Members
| Name   | Modifiers | Type | Description | Overrides | 
|---|---|---|---|---|
| PathProcessor:: | protected | property | The config factory. | |
| PathProcessor:: | protected | property | The language manager. | |
| PathProcessor:: | protected | property | The path processor. | |
| PathProcessor:: | protected | property | The path validator. | |
| PathProcessor:: | protected | property | Whether it is recursive call or not. | |
| PathProcessor:: | protected | function | Gets the max depth that subpaths should be scanned through. | |
| PathProcessor:: | protected | function | Helper function to handle multilingual paths. | |
| PathProcessor:: | protected | function | Gets the path validator. | |
| PathProcessor:: | protected | function | Tests if path is valid. | |
| PathProcessor:: | public | function | Processes the inbound path. Overrides InboundPathProcessorInterface:: | |
| PathProcessor:: | public | function | Processes the outbound path. Overrides OutboundPathProcessorInterface:: | |
| PathProcessor:: | public | function | Sets the path validator. | |
| PathProcessor:: | public | function | Builds PathProcessor object. | 
