You are here

class ContentHubEntityRequestHandler in Acquia Content Hub 8

Decorates the REST module's RequestHandler.

Because the Acquia Content Hub module needs to expose REST access:

  • for certain entity types,
  • but always only GET,
  • but always only its own special format,
  • but always only its own special authentication,
  • but always only its own special authorization (access checking),

it doesn't make sense to rely on the REST module's default pattern of having a RestResourceConfig configuration entity. That configuration entity is what determines which methods/formats/authentication are enabled for a given REST resource. But this module has the need to fully control that.

So, we still rely on these to benefit from improvements/bugfixes:

But we decorate RequestHandler to make it not rely on configuration entities, and to make it instead fully depend on the information in the route. This unfortunately requires some duplication.

@todo Remove this when https://www.drupal.org/node/2822201 lands, and this module is able to require Drupal 8.3.x.

Hierarchy

Expanded class hierarchy of ContentHubEntityRequestHandler

File

src/Controller/ContentHubEntityRequestHandler.php, line 40

Namespace

Drupal\acquia_contenthub\Controller
View source
class ContentHubEntityRequestHandler extends RequestHandler {

  /**
   * The resource plugin manager.
   *
   * @var \Drupal\Component\Plugin\PluginManagerInterface
   */
  protected $resourcePluginManager;

  /**
   * The Content Hub Entity Manager.
   *
   * @var \Drupal\acquia_contenthub\EntityManager
   */
  protected $entityManager;

  /**
   * The serializer.
   *
   * @var \Symfony\Component\Serializer\SerializerInterface|\Symfony\Component\Serializer\Encoder\DecoderInterface
   */
  protected $serializer;

  /**
   * The Renderer Service.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * Creates a new RequestHandler instance.
   *
   * @param \Drupal\Component\Plugin\PluginManagerInterface $resource_plugin_manager
   *   The resource plugin manager.
   * @param \Drupal\acquia_contenthub\EntityManager $entity_manager
   *   The Content Hub Entity Manager.
   * @param \Symfony\Component\Serializer\SerializerInterface|\Symfony\Component\Serializer\Encoder\DecoderInterface $serializer
   *   The serializer.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer service.
   */
  public function __construct(PluginManagerInterface $resource_plugin_manager, EntityManager $entity_manager, SerializerInterface $serializer, RendererInterface $renderer) {
    $this->resourcePluginManager = $resource_plugin_manager;
    $this->entityManager = $entity_manager;
    $this->serializer = $serializer;
    $this->renderer = $renderer;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('plugin.manager.rest'), $container
      ->get('acquia_contenthub.entity_manager'), $container
      ->get('serializer'), $container
      ->get('renderer'));
  }

  /**
   * {@inheritdoc}
   */
  public function handle(RouteMatchInterface $route_match, Request $request, RestResourceConfigInterface $_rest_resource_config = NULL) {

    // We only support one method, one format, and use one of the derivatives of
    // only one resource plugin. (We receive the exact plugin ID via the route
    // defaults).
    $method = 'GET';
    $format = 'acquia_contenthub_cdf';

    // Force the acquia_contenthub_cdf format.
    if ($request
      ->getRequestFormat() !== $format) {
      $request
        ->setRequestFormat($format);
    }
    $resource = $this->resourcePluginManager
      ->createInstance($route_match
      ->getRouteObject()
      ->getDefault('_acquia_content_hub_rest_resource_plugin_id'));

    // EVERYTHING BELOW THIS IS MERE DUPLICATION OF THE DECORATED CLASS IN THE
    // MOST MINIMAL WAY POSSIBLE AND REMOVING THE DEPENDENCY ON CONFIG ENTITIES.
    // Determine the request parameters that should be passed to the resource
    // plugin.
    $route_parameters = $route_match
      ->getParameters();
    $parameters = [];

    // Filter out all internal parameters starting with "_".
    foreach ($route_parameters as $key => $parameter) {
      if ($key[0] !== '_') {
        $parameters[] = $parameter;
      }
    }

    // Invoke the operation on the resource plugin.
    $response = call_user_func_array([
      $resource,
      $method,
    ], array_merge($parameters, [
      $request,
    ]));

    // Render response.
    $data = $response
      ->getResponseData();
    $context = new RenderContext();
    if (!$context
      ->isEmpty()) {
      $response
        ->addCacheableDependency($context
        ->pop());
    }

    // Adding cacheable dependency on the config entity for this particular
    // entity type.
    // All requests served by this route will have the cache tag of the config
    // entity that provided the response so if that config entity changes, then
    // this will automatically invalidate the caches of all responses
    // associated with it.
    $entity_type_id = $data
      ->getEntityTypeId();
    if ($content_hub_config_entity = $this->entityManager
      ->getContentHubEntityTypeConfigurationEntity($entity_type_id)) {
      $response
        ->addCacheableDependency($content_hub_config_entity);
    }
    $response->headers
      ->set('Content-Type', $request
      ->getMimeType($format));
    return $response;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ContentHubEntityRequestHandler::$entityManager protected property The Content Hub Entity Manager.
ContentHubEntityRequestHandler::$renderer protected property The Renderer Service.
ContentHubEntityRequestHandler::$resourcePluginManager protected property The resource plugin manager.
ContentHubEntityRequestHandler::$serializer protected property The serializer. Overrides RequestHandler::$serializer
ContentHubEntityRequestHandler::create public static function Instantiates a new instance of this class. Overrides RequestHandler::create
ContentHubEntityRequestHandler::handle public function Handles a REST API request. Overrides RequestHandler::handle
ContentHubEntityRequestHandler::__construct public function Creates a new RequestHandler instance. Overrides RequestHandler::__construct
RequestHandler::$configFactory protected property The config factory.
RequestHandler::createArgumentResolver protected function Creates an argument resolver, containing all REST parameters.
RequestHandler::delegateToRestResourcePlugin protected function Delegates an incoming request to the appropriate REST resource plugin.
RequestHandler::deserialize protected function Deserializes request body, if any.
RequestHandler::getLegacyParameters Deprecated protected function Provides the parameter usable without an argument resolver.
RequestHandler::getNormalizedRequestMethod protected static function Gets the normalized HTTP request method of the matched route.
RequestHandler::handleRaw public function Handles a REST API request without deserializing the request body.
RequestHandler::prepareResponse protected function Prepares the REST resource response.