You are here

AgreementSubscriber.php in Agreement 3.0.x

Same filename and directory in other branches
  1. 8.2 src/EventSubscriber/AgreementSubscriber.php

File

src/EventSubscriber/AgreementSubscriber.php
View source
<?php

namespace Drupal\agreement\EventSubscriber;

use Drupal\agreement\AgreementHandlerInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Session\SessionManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

/**
 * Checks if the current user is required to accept an agreement.
 */
class AgreementSubscriber implements EventSubscriberInterface {

  /**
   * Agreement handler.
   *
   * @var \Drupal\agreement\AgreementHandlerInterface
   */
  protected $handler;

  /**
   * Current path getter because paths > routes for users.
   *
   * @var \Drupal\Core\Path\CurrentPathStack
   */
  protected $pathStack;

  /**
   * Session manager.
   *
   * @var \Drupal\Core\Session\SessionManagerInterface
   */
  protected $sessionManager;

  /**
   * Current user account.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $account;

  /**
   * Initialize method.
   *
   * @param \Drupal\agreement\AgreementHandlerInterface $agreementHandler
   *   The agreement handler.
   * @param \Drupal\Core\Path\CurrentPathStack $pathStack
   *   The current path.
   * @param \Drupal\Core\Session\SessionManagerInterface $sessionManager
   *   The session manager service.
   * @param \Drupal\Core\Session\AccountProxyInterface $account
   *   The current user account.
   */
  public function __construct(AgreementHandlerInterface $agreementHandler, CurrentPathStack $pathStack, SessionManagerInterface $sessionManager, AccountProxyInterface $account) {
    $this->handler = $agreementHandler;
    $this->pathStack = $pathStack;
    $this->sessionManager = $sessionManager;
    $this->account = $account;
  }

  /**
   * Check if the user needs to accept an agreement.
   *
   * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent|\Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The response event.
   */
  public function checkForRedirection($event) {

    // Users with the bypass agreement permission are always excluded from any
    // agreement.
    if (!$this->account
      ->hasPermission('bypass agreement')) {
      $path = $this->pathStack
        ->getPath($event
        ->getRequest());
      $info = $this->handler
        ->getAgreementByUserAndPath($this->account, $path);
      if ($info) {

        // Save intended destination.
        // @todo figure out which of this is still necessary.
        if (!isset($_SESSION['agreement_destination'])) {
          if (preg_match('/^user\\/reset/i', $path)) {
            $_SESSION['agreement_destination'] = 'change password';
          }
          else {
            $_SESSION['agreement_destination'] = $path;
          }
        }

        // Redirect to the agreement page.
        $redirect_path = $event
          ->getRequest()
          ->getBasePath() . $info
          ->get('path');
        $event
          ->setResponse(new RedirectResponse($redirect_path));
      }
    }
  }

  /**
   * Performs redirect for access denied exceptions.
   *
   * In case the user has no permission to access a page, the denied exception
   * will be thrown. Therefore the response will be set before executing of
   * the checkForRedirection function, that will lead to an infinite redirect
   * loop.
   *
   * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event
   *   The response exception event.
   */
  public function exceptionRedirect(ExceptionEvent $event) {
    $exception = $event
      ->getThrowable();
    if ($exception instanceof HttpExceptionInterface && $exception
      ->getStatusCode() === 403) {
      $this
        ->checkForRedirection($event);
    }
  }

  /**
   * Executes function to set redirect response if it is required.
   *
   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The response event.
   */
  public function requestForRedirection(RequestEvent $event) {
    $this
      ->checkForRedirection($event);
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [];

    // Dynamic page cache will redirect to a cached page at priority 27.
    $events[KernelEvents::REQUEST][] = [
      'requestForRedirection',
      28,
    ];
    $events[KernelEvents::EXCEPTION][] = [
      'exceptionRedirect',
      1,
    ];
    return $events;
  }

}

Classes

Namesort descending Description
AgreementSubscriber Checks if the current user is required to accept an agreement.