From dd7ec6dcb1f70f2e085e8d4a7a3f75e0b636e726 Mon Sep 17 00:00:00 2001 From: Eric Bremner <ebremner@uwaterloo.ca> Date: Tue, 18 Jul 2023 16:33:44 -0400 Subject: [PATCH] ISTWCMS-5954: adding subscriber for better formatting of api --- src/EventSubscriber/UwResponseSubscriber.php | 201 +++++++++++++++++++ uw_cfg_common.services.yml | 7 + 2 files changed, 208 insertions(+) create mode 100644 src/EventSubscriber/UwResponseSubscriber.php diff --git a/src/EventSubscriber/UwResponseSubscriber.php b/src/EventSubscriber/UwResponseSubscriber.php new file mode 100644 index 00000000..2ff741d3 --- /dev/null +++ b/src/EventSubscriber/UwResponseSubscriber.php @@ -0,0 +1,201 @@ +<?php + +namespace Drupal\uw_cfg_common\EventSubscriber; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityTypeManager; +use Drupal\Core\Entity\EntityRepository; +use Drupal\Core\File\FileUrlGeneratorInterface; +use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\jsonapi\Routing\Routes; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Class UwResponseSubscriber. + * + * Implements the alter hook for JSON:API responses. + * + * @package Drupal\uw_cfg_common\EventSubscriber + */ +class UwResponseSubscriber implements EventSubscriberInterface, ContainerInjectionInterface { + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The entity repository. + * + * @var \Drupal\Core\Entity\EntityRepository + */ + protected $entityRepository; + + /** + * The file url generator. + * + * @var \Drupal\Core\File\FileUrlGeneratorInterface + */ + protected $fileUrlGenerator; + + /** + * The route match service. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * ResponseSubscriber constructor. + * + * @param \Drupal\Core\Extension\ModuleHandlerInterface $entityTypeManager + * The entity type manager. + * @param \Drupal\Core\Entity\EntityRepository $entityRepository + * The entity repository. + * @param \Drupal\Core\Routing\RouteMatchInterface $fileUrlGenerator + * The file url generator. + */ + public function __construct( + EntityTypeManager $entityTypeManager, + EntityRepository $entityRepository, + FileUrlGeneratorInterface $fileUrlGenerator + ) { + + $this->entityTypeManager = $entityTypeManager; + $this->entityRepository = $entityRepository; + $this->fileUrlGenerator = $fileUrlGenerator; + } + + /** + * Create a new instance. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The container. + * + * @return \Drupal\jsonapi_response_alter\EventSubscriber\ResponseSubscriber + * The new instance. + */ + public static function create(ContainerInterface $container) { + return new self( + $container->get('entity_type.manager'), + $container->get('entity.repository'), + $container->get('file_url_generator') + ); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[KernelEvents::RESPONSE] = ['onResponse']; + + return $events; + } + + /** + * Set route match service. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + */ + public function setRouteMatch(RouteMatchInterface $route_match) { + $this->routeMatch = $route_match; + } + + /** + * This method is called the KernelEvents::RESPONSE event is dispatched. + * + * @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event + * The filter event. + */ + public function onResponse(ResponseEvent $event) { + + // If there is no route object, i.e. non-routed pages, + // simply return nothing. + if (!$this->routeMatch->getRouteObject()) { + return; + } + + // If this is a jsonapi request, set some values. + if ( + $this->routeMatch->getRouteName() === 'jsonapi.resource_list' || + Routes::isJsonApiRequest($this->routeMatch->getRouteObject() + ->getDefaults()) + ) { + + // Get the response and content. + $response = $event->getResponse(); + $content = $response->getContent(); + + // Get the json response into a readable format. + $jsonapi_response = json_decode($content, TRUE); + + // If there is no json response, simply return. + if (!is_array($jsonapi_response)) { + return; + } + + // If there is a listing image, set it to the + // info we need. + if (isset($jsonapi_response['data'][0]['relationships']['listing_page_image'])) { + $this->setUwListingImage($jsonapi_response); + } + + // Now set the new json response. + $response->setContent(json_encode($jsonapi_response)); + } + } + + /** + * Function to sub in the file info for listing image. + * + * @param array $jsonapi_response + * The json api response. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ + private function setUwListingImage(array &$jsonapi_response): void { + + // Step through each of the data and set the listing image. + for ($i = 0; $i < count($jsonapi_response['data']); $i++) { + + // If there is a uuid for the listing image, then set the data. + if ($uuid = $jsonapi_response['data'][$i]['relationships']['listing_page_image']['data']['id']) { + + // Load the media entity using the uuid. + $entity = $this->entityRepository->loadEntityByUuid('media', $uuid); + + // Get the image field from the media entity. + $image = $entity->field_media_image; + + // Load the file entity using the media target id. + // Need to do this because the mid could be different + // than the fid. + $file = $this->entityTypeManager + ->getStorage('file') + ->load($image->target_id); + + // Set the values for the listing image. + $jsonapi_response['data'][$i]['relationships']['listing_page_image'] = [ + 'fid' => $file->id(), + 'filename' => $file->getFilename(), + 'uri' => $file->getFileUri(), + 'url' => $this->fileUrlGenerator->generateAbsoluteString($file->getFileUri()), + 'filemime' => $file->getMimeType(), + 'filesize' => $file->getSize(), + 'uuid' => $file->uuid(), + 'alt' => $image->alt, + 'width' => $image->width, + 'height' => $image->height, + ]; + } + } + } + +} diff --git a/uw_cfg_common.services.yml b/uw_cfg_common.services.yml index f3b10415..cabbbb8f 100644 --- a/uw_cfg_common.services.yml +++ b/uw_cfg_common.services.yml @@ -49,3 +49,10 @@ services: class: '\Drupal\uw_cfg_common\EventSubscriber\UwWebformEventSubscriber' tags: - { name: 'event_subscriber' } + uw_cfg_common.response_subscriber: + class: Drupal\uw_cfg_common\EventSubscriber\UwResponseSubscriber + arguments: [ '@entity_type.manager', '@entity.repository', '@file_url_generator' ] + tags: + - { name: event_subscriber } + calls: + - [ setRouteMatch, [ '@current_route_match' ] ] -- GitLab