gatsby_endpoints-8.x-1.0-alpha1/src/GatsbyEndpointGenerator.php
src/GatsbyEndpointGenerator.php
<?php namespace Drupal\gatsby_endpoints; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\field\Entity\FieldConfig; use Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface; /** * Class GatsbyEndpointGenerator. * * Generates JSON:API links for a Gatsby Endpoint. */ class GatsbyEndpointGenerator { /** * Drupal\Core\Entity\EntityTypeManagerInterface definition. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * Drupal\Core\Entity\EntityFieldManagerInterface definition. * * @var \Drupal\Core\Entity\EntityFieldManagerInterface */ protected $entityFieldManager; /** * Constructs a new GatsbyEndpointManager object. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; } /** * Generates JSON:API links for a specific Gatsby Endpoint. */ public function getEndpointLinks(GatsbyEndpointInterface $endpoint) { $build_types = $endpoint->getBuildEntityTypes(); $links = []; foreach ($build_types as $build_type) { if (empty($build_type) || empty($build_type['entity_type'])) { continue; } $include_types = $endpoint->getIncludedEntityTypes($build_type); // Check if this has bundles. foreach ($build_type['entity_bundles'] as $bundle_id => $bundle_label) { if ($bundle_label === $bundle_id) { $params = $this->getUrlParameters($build_type['entity_type'], $bundle_id, $endpoint, $include_types); $entity_key = $build_type['entity_type'] . '--' . $bundle_id; $links[$entity_key] = $build_type['entity_type'] . '/' . $bundle_id . $params; } } } return $links; } /** * Gets the correct JSON:API url parameters string. */ private function getUrlParameters($entity_type, $bundle, GatsbyEndpointInterface $endpoint, $include_types) { $url_params = $this->loadUrlFiltersAndIncludes($entity_type, $bundle, $endpoint, $include_types); $param_string = ''; if (!empty($url_params['filter'])) { $param_string .= $url_params['filter'] . '&'; } if (!empty($url_params['include'])) { $param_string .= 'include=' . implode(',', $url_params['include']); } // Add the starting "?" if parameters are needed. return $param_string ? '?' . $param_string : $param_string; } /** * Gets the includes and filter parameters for a JSON:API url. */ private function loadUrlFiltersAndIncludes($entity_type, $bundle, GatsbyEndpointInterface $endpoint, $include_types, $current_field = FALSE) { $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle); $core_reference_fields = ['comments', 'file', 'image']; $params = []; // Images are a special kind of file, so make sure include_types // include images if they have files added. Without this core image fields // will not work. if (in_array('file', $include_types)) { $include_types[] = 'image'; } foreach ($definitions as $field) { $field_name = $field->getName(); // Only check manually created fields. if (empty($field_name) || !$field instanceof FieldConfig) { continue; } $field_type = $field->getType(); if ($field_type == 'gatsby_endpoint_reference') { $params['filter'] = 'filter[' . $field_name . '.meta.drupal_internal__target_id]=' . $endpoint->id(); } elseif (in_array($field_type, $core_reference_fields)) { // Check if this field references an included entity type. if (in_array($field_type, $include_types)) { if ($current_field) { $field_name = $current_field . '.' . $field_name; } $params['include'][] = $field_name; } } elseif (in_array($field_type, [ 'entity_reference', 'entity_reference_revisions', ])) { // Check if this field references an included entity type. $handler = $field->getSetting('handler'); $reference_type = explode(':', $handler); if (!empty($reference_type[1]) && in_array($reference_type[1], $include_types)) { // Continue building out the JSON:API path to this related field. if ($current_field) { $field_name = $current_field . '.' . $field_name; } $params['include'][] = $field_name; // Now we need to recursively traverse this reference field to ensure // to include all the necessary related entity fields. $handler_settings = $field->getSetting('handler_settings'); if (!empty($handler_settings['target_bundles'])) { foreach ($handler_settings['target_bundles'] as $target_bundle) { $reference_params = $this->loadUrlFiltersAndIncludes($reference_type[1], $target_bundle, $endpoint, $include_types, $field_name); if (!empty($reference_params['include'])) { $params['include'] = array_merge($params['include'], $reference_params['include']); } } } } } } return $params; } }