Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
4 / 6
CRAP
37.21% covered (danger)
37.21%
16 / 43
PathValidator
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
4 / 6
119.03
37.21% covered (danger)
37.21%
16 / 43
 __construct
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 5
 isValid
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getUrlIfValid
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getUrlIfValidWithoutAccessCheck
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getUrl
0.00% covered (danger)
0.00%
0 / 1
90
0.00% covered (danger)
0.00%
0 / 22
 getPathAttributes
100.00% covered (success)
100.00%
1 / 1
7
100.00% covered (success)
100.00%
13 / 13
<?php
/**
 * @file
 * Contains \Drupal\Core\Path\PathValidator.
 */
namespace Drupal\Core\Path;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\ParamConverter\ParamNotConvertedException;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\Routing\AccessAwareRouterInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
 * Provides a default path validator and access checker.
 */
class PathValidator implements PathValidatorInterface {
  /**
   * The access aware router.
   *
   * @var \Drupal\Core\Routing\AccessAwareRouterInterface
   */
  protected $accessAwareRouter;
  /**
   * A router implementation which does not check access.
   *
   * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
   */
  protected $accessUnawareRouter;
  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;
  /**
   * The path processor.
   *
   * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
   */
  protected $pathProcessor;
  /**
   * Creates a new PathValidator.
   *
   * @param \Drupal\Core\Routing\AccessAwareRouterInterface $access_aware_router
   *   The access aware router.
   * @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $access_unaware_router
   *   A router implementation which does not check access.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $path_processor
   *   The path processor;
   */
  public function __construct(AccessAwareRouterInterface $access_aware_router, UrlMatcherInterface $access_unaware_router, AccountInterface $account, InboundPathProcessorInterface $path_processor) {
    $this->accessAwareRouter = $access_aware_router;
    $this->accessUnawareRouter = $access_unaware_router;
    $this->account = $account;
    $this->pathProcessor = $path_processor;
  }
  /**
   * {@inheritdoc}
   */
  public function isValid($path) {
    return (bool) $this->getUrlIfValid($path);
  }
  /**
   * {@inheritdoc}
   */
  public function getUrlIfValid($path) {
    return $this->getUrl($path, TRUE);
  }
  /**
   * {@inheritdoc}
   */
  public function getUrlIfValidWithoutAccessCheck($path) {
    return $this->getUrl($path, FALSE);
  }
  /**
   * Helper for getUrlIfValid() and getUrlIfValidWithoutAccessCheck().
   */
  protected function getUrl($path, $access_check) {
    $path = ltrim($path, '/');
    $parsed_url = UrlHelper::parse($path);
    $options = [];
    if (!empty($parsed_url['query'])) {
      $options['query'] = $parsed_url['query'];
    }
    if (!empty($parsed_url['fragment'])) {
      $options['fragment'] = $parsed_url['fragment'];
    }
    if ($parsed_url['path'] == '<front>') {
      return new Url('<front>', [], $options);
    }
    elseif ($parsed_url['path'] == '<none>') {
      return new Url('<none>', [], $options);
    }
    elseif (UrlHelper::isExternal($path) && UrlHelper::isValid($path)) {
      if (empty($parsed_url['path'])) {
        return FALSE;
      }
      return Url::fromUri($path);
    }
    $request = Request::create('/' . $path);
    $attributes = $this->getPathAttributes($path, $request, $access_check);
    if (!$attributes) {
      return FALSE;
    }
    $route_name = $attributes[RouteObjectInterface::ROUTE_NAME];
    $route_parameters = $attributes['_raw_variables']->all();
    return new Url($route_name, $route_parameters, $options + ['query' => $request->query->all()]);
  }
  /**
   * Gets the matched attributes for a given path.
   *
   * @param string $path
   *   The path to check.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   A request object with the given path.
   * @param bool $access_check
   *   If FALSE then skip access check and check only whether the path is
   *   valid.
   *
   * @return array|bool
   *   An array of request attributes of FALSE if an exception was thrown.
   */
  protected function getPathAttributes($path, Request $request, $access_check) {
    if (!$access_check || $this->account->hasPermission('link to any page')) {
      $router = $this->accessUnawareRouter;
    }
    else {
      $router = $this->accessAwareRouter;
    }
    $path = $this->pathProcessor->processInbound('/' . $path, $request);
    try {
      return $router->match($path);
    }
    catch (ResourceNotFoundException $e) {
      return FALSE;
    }
    catch (ParamNotConvertedException $e) {
      return FALSE;
    }
    catch (AccessDeniedHttpException $e) {
      return FALSE;
    }
    catch (MethodNotAllowedException $e) {
      return FALSE;
    }
  }
}