You are here

WebformRevisionsRequest.php in Config Entity Revisions 8

File

modules/webform_revisions/src/WebformRevisionsRequest.php
View source
<?php

namespace Drupal\webform_revisions;

use Drupal\webform\Entity\Webform;
use Drupal\webform\WebformRequest;
use Drupal\webform\WebformRequestInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Url;
use Drupal\webform\Plugin\WebformSourceEntityManagerInterface;
use Drupal\webform\WebformEntityReferenceManagerInterface;
use Drupal\webform_revisions\Controller\WebformRevisionsController;
use DrupalCodeGenerator\Command\Drupal_8\Test\Web;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\webform\WebformInterface;

/**
 * Handles webform requests.
 */
class WebformRevisionsRequest extends WebformRequest implements WebformRequestInterface {

  /**
   * The route provider.
   *
   * @var \Drupal\Core\Routing\RouteProviderInterface
   */
  protected $routeProvider;

  /**
   * The current request.
   *
   * @var \Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * The route admin context to determine whether a route is an admin one.
   *
   * @var \Drupal\Core\Routing\AdminContext
   */
  protected $adminContext;

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

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity type repository.
   *
   * @var \Drupal\Core\Entity\EntityTypeRepositoryInterface
   */
  protected $entityTypeRepository;

  /**
   * The webform entity reference manager.
   *
   * @var \Drupal\webform\WebformEntityReferenceManagerInterface
   */
  protected $webformEntityReferenceManager;

  /**
   * Webform source entity plugin manager.
   *
   * @var \Drupal\webform\Plugin\WebformSourceEntityManagerInterface
   */
  protected $webformSourceEntityManager;

  /**
   * Track if the current page is a webform admin route.
   *
   * @var bool
   */
  protected $isAdminRoute;

  /**
   * Constructs a WebformRevisionsRequest object.
   *
   * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
   *   The route provider.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Routing\AdminContext $admin_context
   *   The route admin context service.
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The current route match.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository
   *   The entity type repository.
   * @param \Drupal\webform\WebformEntityReferenceManagerInterface $webform_entity_reference_manager
   *   The webform entity reference manager.
   * @param \Drupal\webform\Plugin\WebformSourceEntityManagerInterface $webform_source_entity_manager
   *   The webform source entity plugin manager.
   */
  public function __construct(RouteProviderInterface $route_provider, RequestStack $request_stack, AdminContext $admin_context, RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager, EntityTypeRepositoryInterface $entity_type_repository, WebformEntityReferenceManagerInterface $webform_entity_reference_manager, WebformSourceEntityManagerInterface $webform_source_entity_manager) {
    $this->routeProvider = $route_provider;
    $this->request = $request_stack
      ->getCurrentRequest();
    $this->adminContext = $admin_context;
    $this->routeMatch = $route_match;
    $this->entityTypeManager = $entity_type_manager;
    $this->entityTypeRepository = $entity_type_repository;
    $this->webformEntityReferenceManager = $webform_entity_reference_manager;
    $this->webformSourceEntityManager = $webform_source_entity_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function isWebformAdminRoute() {
    if (isset($this->isAdminRoute)) {
      return $this->isAdminRoute;
    }

    // Make sure the current route is an admin route.
    if (!$this->adminContext
      ->isAdminRoute()) {
      $this->isAdminRoute = FALSE;
      return $this->isAdminRoute;
    }
    $route_name = $this->routeMatch
      ->getRouteName();
    if (in_array($route_name, [
      'entity.webform.canonical',
      'entity.webform_submission.edit_form',
    ])) {
      $this->isAdminRoute = FALSE;
    }
    else {
      $this->isAdminRoute = preg_match('/^(webform\\.|^entity\\.([^.]+\\.)?webform)/', $route_name) ? TRUE : FALSE;
    }
    return $this->isAdminRoute;
  }

  /**
   * {@inheritdoc}
   */
  public function getCurrentSourceEntity($ignored_types = NULL) {

    // TODO: Can we refactor this method away altogether and let all its callers
    // work directly with webform source entity manager?
    return $this->webformSourceEntityManager
      ->getSourceEntity(is_null($ignored_types) ? [] : $ignored_types);
  }

  /**
   * {@inheritdoc}
   */
  public function getCurrentWebform() {
    $source_entity = static::getCurrentSourceEntity('webform');
    if ($source_entity && ($webform = $this->webformEntityReferenceManager
      ->getWebform($source_entity))) {
      return $webform;
    }
    $webform = $this->routeMatch
      ->getParameter('webform');
    if (is_string($webform)) {
      $controller = WebformRevisionsController::create(\Drupal::getContainer());
      $revisionId = $source_entity
        ->get('webform_revision')
        ->getValue();
      if ($revisionId) {
        $revisionId = $revisionId[0]['target_id'];
      }
      else {

        // Get the id by getting the default webform's third party settings.
        $webform = $this->entityTypeManager
          ->getStorage('webform')
          ->load($webform);
        $content_entity_id = $webform
          ->getContentEntityID();

        // Get the first revision id.
        $revisionId = \Drupal::database()
          ->query('SELECT MIN(revision) FROM {config_entity_revisions_revision} c WHERE c.id = :id', [
          ':id' => $content_entity_id,
        ])
          ->fetchField();
      }
      $webform = $controller
        ->loadConfigEntityRevision($revisionId);
    }
    return $webform;
  }

  /**
   * {@inheritdoc}
   */
  public function getCurrentWebformSubmission() {
    $webform_submission = $this->routeMatch
      ->getParameter('webform_submission');
    if (is_string($webform_submission)) {
      $webform_submission = $this->entityTypeManager
        ->getStorage('webform_submission')
        ->load($webform_submission);
    }
    return $webform_submission;
  }

  /**
   * {@inheritdoc}
   */
  public function getWebformEntities() {
    $webform = $this
      ->getCurrentWebform();
    $source_entity = $this
      ->getCurrentSourceEntity('webform');
    return [
      $webform,
      $source_entity,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getWebformSubmissionEntities() {
    $webform_submission = $this->routeMatch
      ->getParameter('webform_submission');
    if (is_string($webform_submission)) {
      $webform_submission = $this->entityTypeManager
        ->getStorage('webform_submission')
        ->load($webform_submission);
    }
    $source_entity = $this
      ->getCurrentSourceEntity('webform_submission');
    return [
      $webform_submission,
      $source_entity,
    ];
  }

  /****************************************************************************/

  // Routing helpers

  /****************************************************************************/

  /**
   * {@inheritdoc}
   */
  public function isAjax() {
    return $this->request
      ->get(AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER) ? TRUE : FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getUrl(EntityInterface $webform_entity, EntityInterface $source_entity = NULL, $route_name, array $route_options = []) {
    $route_name = $this
      ->getRouteName($webform_entity, $source_entity, $route_name);
    $route_parameters = $this
      ->getRouteParameters($webform_entity, $source_entity);
    return Url::fromRoute($route_name, $route_parameters, $route_options);
  }

  /**
   * {@inheritdoc}
   */
  public function getRouteName(EntityInterface $webform_entity, EntityInterface $source_entity = NULL, $route_name) {
    if (!$this
      ->hasSourceEntityWebformRoutes($source_entity)) {
      $source_entity = NULL;
    }
    return $this
      ->getBaseRouteName($webform_entity, $source_entity) . '.' . $route_name;
  }

  /**
   * {@inheritdoc}
   */
  public function getRouteParameters(EntityInterface $webform_entity, EntityInterface $source_entity = NULL) {
    if (!$this
      ->hasSourceEntityWebformRoutes($source_entity)) {
      $source_entity = NULL;
    }
    if (static::isValidSourceEntity($webform_entity, $source_entity)) {
      if ($webform_entity instanceof WebformSubmissionInterface) {
        return [
          'webform_submission' => $webform_entity
            ->id(),
          $source_entity
            ->getEntityTypeId() => $source_entity
            ->id(),
        ];
      }
      else {
        return [
          $source_entity
            ->getEntityTypeId() => $source_entity
            ->id(),
        ];
      }
    }
    elseif ($webform_entity instanceof WebformSubmissionInterface) {
      return [
        'webform_submission' => $webform_entity
          ->id(),
        'webform' => $webform_entity
          ->getWebform()
          ->id(),
      ];
    }
    else {
      return [
        $webform_entity
          ->getEntityTypeId() => $webform_entity
          ->id(),
      ];
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getBaseRouteName(EntityInterface $webform_entity, EntityInterface $source_entity = NULL) {
    if ($webform_entity instanceof WebformSubmissionInterface) {
      $webform = $webform_entity
        ->getWebform();
    }
    elseif ($webform_entity instanceof WebformInterface) {
      $webform = $webform_entity;
    }
    else {
      throw new \InvalidArgumentException('Webform entity');
    }
    if (static::isValidSourceEntity($webform, $source_entity)) {
      return 'entity.' . $source_entity
        ->getEntityTypeId();
    }
    else {
      return 'entity';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function hasSourceEntityWebformRoutes(EntityInterface $source_entity = NULL) {
    if ($source_entity && $this
      ->routeExists('entity.' . $source_entity
      ->getEntityTypeId() . '.webform_submission.canonical')) {
      return TRUE;
    }
    else {
      return FALSE;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function isValidSourceEntity(EntityInterface $webform_entity, EntityInterface $source_entity = NULL) {

    // Validate that source entity exists and can be linked to.
    if (!$source_entity || !$source_entity
      ->hasLinkTemplate('canonical')) {
      return FALSE;
    }

    // Get the webform.
    if ($webform_entity instanceof WebformSubmissionInterface) {
      $webform = $webform_entity
        ->getWebform();
    }
    elseif ($webform_entity instanceof WebformInterface) {
      $webform = $webform_entity;
    }
    else {
      throw new \InvalidArgumentException('Webform entity');
    }

    // Validate that source entity's field target id is the correct webform.
    $webform_target = $this->webformEntityReferenceManager
      ->getWebform($source_entity);
    if ($webform_target && $webform_target
      ->id() == $webform
      ->id()) {
      return TRUE;
    }
    else {
      return FALSE;
    }
  }

  /**
   * Check if route exists.
   *
   * @param string $name
   *   Route name.
   *
   * @return bool
   *   TRUE if the route exists.
   *
   * @see http://drupal.stackexchange.com/questions/222591/how-do-i-verify-a-route-exists
   */
  protected function routeExists($name) {
    try {
      $this->routeProvider
        ->getRouteByName($name);
      return TRUE;
    } catch (\Exception $exception) {
      return FALSE;
    }
  }

}

Classes

Namesort descending Description
WebformRevisionsRequest Handles webform requests.