You are here

class PreviewLinkCanonicalRerouteAccessCheck in Preview Link 2.x

Same name and namespace in other branches
  1. 2.0.x src/Access/PreviewLinkCanonicalRerouteAccessCheck.php \Drupal\preview_link\Access\PreviewLinkCanonicalRerouteAccessCheck

Reroutes users from a canonical route to preview link route.

Does not actually grant access, access checkers are in the right place to interrupt routing and send the user agent elsewhere.

Hierarchy

Expanded class hierarchy of PreviewLinkCanonicalRerouteAccessCheck

1 string reference to 'PreviewLinkCanonicalRerouteAccessCheck'
preview_link.services.yml in ./preview_link.services.yml
preview_link.services.yml
1 service uses PreviewLinkCanonicalRerouteAccessCheck
access_check.preview_link.canonical_rerouter in ./preview_link.services.yml
Drupal\preview_link\Access\PreviewLinkCanonicalRerouteAccessCheck

File

src/Access/PreviewLinkCanonicalRerouteAccessCheck.php, line 24

Namespace

Drupal\preview_link\Access
View source
class PreviewLinkCanonicalRerouteAccessCheck implements AccessInterface {

  /**
   * Private temp store factory.
   *
   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
   */
  protected $privateTempStoreFactory;

  /**
   * Preview link host service.
   *
   * @var \Drupal\preview_link\PreviewLinkHostInterface
   */
  protected $previewLinkHost;

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch
   */
  protected $routeMatch;

  /**
   * PreviewLinkCanonicalRerouteAccessCheck constructor.
   *
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $privateTempStoreFactory
   *   Private temp store factory.
   * @param \Drupal\preview_link\PreviewLinkHostInterface $previewLinkHost
   *   Preview link host service.
   * @param \Drupal\Core\Routing\CurrentRouteMatch $routeMatch
   *   The current route match.
   */
  public function __construct(PrivateTempStoreFactory $privateTempStoreFactory, PreviewLinkHostInterface $previewLinkHost, CurrentRouteMatch $routeMatch) {
    $this->privateTempStoreFactory = $privateTempStoreFactory;
    $this->previewLinkHost = $previewLinkHost;
    $this->routeMatch = $routeMatch;
  }

  /**
   * Checks if an activated preview link token is associated with this entity.
   *
   * @param \Symfony\Component\HttpFoundation\Request|null $request
   *   The request.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   A \Drupal\Core\Access\AccessInterface value.
   *
   * @throws \Drupal\preview_link\Exception\PreviewLinkRerouteException
   *   When a claimed token grants access to entity for this route match.
   */
  public function access(Request $request = NULL) : AccessResultInterface {
    $cacheability = (new CacheableMetadata())
      ->addCacheContexts([
      'session',
      'route',
    ]);

    // Dont use argument resolved route match or route, get the real route match
    // from the master request.
    $routeMatch = $this->routeMatch
      ->getMasterRouteMatch();
    $route = $routeMatch
      ->getRouteObject();
    $entityParameterName = $route ? $route
      ->getRequirement('_access_preview_link_canonical_rerouter') : NULL;
    if (!isset($entityParameterName)) {

      // If the requirement doesnt exist then the master request isn't the
      // canonical route, its probably simulated from something like menu or
      // breadcrumb.
      return AccessResult::allowed()
        ->addCacheableDependency($cacheability);
    }
    $cacheability = (new CacheableMetadata())
      ->addCacheContexts([
      'session',
      'route',
    ]);
    if (!$request) {
      return AccessResult::allowed()
        ->addCacheableDependency($cacheability);
    }
    $entity = $routeMatch
      ->getParameter($entityParameterName);
    if (!$entity instanceof EntityInterface) {

      // Entity was not upcast for preview link reroute access check.
      return AccessResult::allowed()
        ->addCacheableDependency($cacheability);
    }
    $collection = $this->privateTempStoreFactory
      ->get('preview_link');
    $claimedTokens = $collection
      ->get('keys') ?? [];
    if (!$claimedTokens) {

      // Session has no claimed tokens.
      return AccessResult::allowed()
        ->addCacheableDependency($cacheability);
    }
    if (!$this->previewLinkHost
      ->isToken($entity, $claimedTokens)) {

      // This session doesnt have an activated preview link tokens matching this
      // entity.
      return AccessResult::allowed()
        ->addCacheableDependency($cacheability);
    }

    // Check if any keys in this session unlock this entity.
    $previewLinks = $this->previewLinkHost
      ->getPreviewLinks($entity);

    // Get the first token that matches this entity.
    foreach ($previewLinks as $previewLink) {
      if (in_array($previewLink
        ->getToken(), $claimedTokens, TRUE)) {
        throw new PreviewLinkRerouteException('', 0, NULL, $entity, $previewLink);
      }
    }
    throw new \LogicException('Shouldnt get here unless there are implementation differences between isToken and getPreviewLinks.');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PreviewLinkCanonicalRerouteAccessCheck::$previewLinkHost protected property Preview link host service.
PreviewLinkCanonicalRerouteAccessCheck::$privateTempStoreFactory protected property Private temp store factory.
PreviewLinkCanonicalRerouteAccessCheck::$routeMatch protected property The current route match.
PreviewLinkCanonicalRerouteAccessCheck::access public function Checks if an activated preview link token is associated with this entity.
PreviewLinkCanonicalRerouteAccessCheck::__construct public function PreviewLinkCanonicalRerouteAccessCheck constructor.