diff --git a/config/schema/gatsby_endpoints_test.entity_type.schema.yml b/config/schema/gatsby_endpoints_test.entity_type.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..29a8f69459edf3ffe1a9a8303b87ba7d6841aea4 --- /dev/null +++ b/config/schema/gatsby_endpoints_test.entity_type.schema.yml @@ -0,0 +1,12 @@ +gatsby_endpoints.gatsby_endpoint_type.*: + type: config_entity + label: 'Gatsby Endpoint type config' + mapping: + id: + type: string + label: 'ID' + label: + type: label + label: 'Label' + uuid: + type: string diff --git a/gatsby_endpoints.info.yml b/gatsby_endpoints.info.yml index 4ebe9c85bce93b0a6014891495e841c3ecad84bf..7816f8dc9e08c0c02b4bf2264c19fee48c315bfd 100644 --- a/gatsby_endpoints.info.yml +++ b/gatsby_endpoints.info.yml @@ -1,10 +1,9 @@ -name: 'Gatsby JSON:API Endpoints (experimental)' +name: Gatsby Endpoints type: module -description: 'Create multiple endpoints that can be used to source content into Gatsby sites (under active development and should be considered experimental).' +description: 'Create and manage Gatsby Endpoints.' +package: Gatsby core: 8.x core_version_requirement: ^8 || ^9 -package: 'Gatsby' dependencies: - - gatsby:gatsby_instantpreview - - drupal:jsonapi - - jsonapi_extras:jsonapi_extras + - drupal:text +configure: entity.gatsby_endpoint_type.collection diff --git a/gatsby_endpoints.links.action.yml b/gatsby_endpoints.links.action.yml index 63e66fb87d3999115da15882852b125334e6597f..30c1b44b472b25a124fc69daa08f15826eb8416c 100644 --- a/gatsby_endpoints.links.action.yml +++ b/gatsby_endpoints.links.action.yml @@ -1,5 +1,11 @@ -entity.gatsby_endpoint.add_form: - route_name: gatsby_endpoints.gatsby_endpoint_plugin_types +gatsby_endpoint.type_add: + route_name: entity.gatsby_endpoint_type.add_form + title: 'Add Gatsby Endpoint type' + appears_on: + - entity.gatsby_endpoint_type.collection + +gatsby_endpoint.add_page: + route_name: entity.gatsby_endpoint.add_page title: 'Add Gatsby Endpoint' appears_on: - - gatsby_endpoints.gatsby_endpoints_collection + - entity.gatsby_endpoint.collection diff --git a/gatsby_endpoints.links.menu.yml b/gatsby_endpoints.links.menu.yml new file mode 100644 index 0000000000000000000000000000000000000000..26df7e55531ac8870cbfa6c61f0411866a7b528e --- /dev/null +++ b/gatsby_endpoints.links.menu.yml @@ -0,0 +1,5 @@ +entity.gatsby_endpoint_type.collection: + title: 'Gatsby Endpoint types' + parent: system.admin_structure + description: 'Create and manage your Gatsby Endpoint types.' + route_name: entity.gatsby_endpoint_type.collection diff --git a/gatsby_endpoints.links.task.yml b/gatsby_endpoints.links.task.yml index 7073672387e57cde690e41218eac6be441a07140..54bc262650300763644b5d03e25f834ced1467c3 100644 --- a/gatsby_endpoints.links.task.yml +++ b/gatsby_endpoints.links.task.yml @@ -1,12 +1,26 @@ -gatsby_endpoints.gatsby_endpoint_plugin_types: - title: 'Endpoint Types' - route_name: gatsby_endpoints.gatsby_endpoint_plugin_types - description: 'Manage list of Gatsby endpoint types.' - base_route: gatsby.gatsby_admin_form - weight: 30 -gatsby_endpoints.gatsby_endpoints_collection: - title: 'Endpoints' - route_name: gatsby_endpoints.gatsby_endpoints_collection - description: 'Manage list of Gatsby endpoints.' - base_route: gatsby.gatsby_admin_form - weight: 40 +entity.gatsby_endpoint.view: + title: Site Dashboard + route_name: entity.gatsby_endpoint.canonical + base_route: entity.gatsby_endpoint.canonical +entity.gatsby_endpoint.edit_form: + title: Site Settings + route_name: entity.gatsby_endpoint.edit_form + base_route: entity.gatsby_endpoint.canonical +entity.gatsby_endpoint.delete_form: + title: Delete + route_name: entity.gatsby_endpoint.delete_form + base_route: entity.gatsby_endpoint.canonical + weight: 10 +entity.gatsby_endpoint.collection: + title: Gatsby Endpoints + route_name: entity.gatsby_endpoint.collection + base_route: system.admin_content + weight: 10 +entity.gatsby_endpoint_type.edit_form: + title: Edit + route_name: entity.gatsby_endpoint_type.edit_form + base_route: entity.gatsby_endpoint_type.edit_form +entity.gatsby_endpoint_type.collection: + title: List + route_name: entity.gatsby_endpoint_type.collection + base_route: entity.gatsby_endpoint_type.collection diff --git a/gatsby_endpoints.module b/gatsby_endpoints.module index 645bf06acb09dc6983aaf8c61846fa58b4d67775..327e77b0460a227bbb53a5f17b59a6fdc43a396e 100644 --- a/gatsby_endpoints.module +++ b/gatsby_endpoints.module @@ -2,15 +2,117 @@ /** * @file - * Contains gatsby_endpoints.module. + * Provides a gatsby endpoint entity type. */ -use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Render\Element; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Entity\EntityFormInterface; use Drupal\Core\Url; -use Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface; -use Drupal\node\Entity\NodeType; +use Drupal\Core\Link; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityInterface; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; + +/** + * Implements hook_theme(). + */ +function gatsby_endpoints_theme() { + return [ + 'gatsby_endpoint' => [ + 'render element' => 'elements', + ] + ]; +} + +/** + * Override the node add list if adding content to a Gatsby Endpoint. + * + * @param array $variables + * An associative array containing: + * - content: An array of content types + * - types: An array or types created in template_preprocess_node_add_list() + */ +function gatsby_endpoints_preprocess_node_add_list(&$variables) { + $current_path = \Drupal::service('path.current')->getPath(); + $path_args = explode('/', $current_path); + + if (count($path_args) >= 3 && $path_args[1] === 'gatsby_endpoint' && is_numeric($path_args[2])) { + foreach ($variables['types'] as $key => $value) { + $type = $variables['content'][$key]; + $url = Url::fromRoute('node.add', ['node_type' => $type->id()], [ + 'query' => [ + 'gatsby_endpoint' => $path_args[2], + ], + ]); + $variables['types'][$key]['add_link'] = Link::fromTextAndUrl($type->label(), $url)->toString(); + } + } +} + +/** + * Prepares variables for gatsby endpoint templates. + * + * Default template: gatsby-endpoint.html.twig. + * + * @param array $variables + * An associative array containing: + * - elements: An associative array containing the gatsby endpoint information and any + * fields attached to the entity. + * - attributes: HTML attributes for the containing element. + */ +function template_preprocess_gatsby_endpoint(array &$variables) { + foreach (Element::children($variables['elements']) as $key) { + $variables['content'][$key] = $variables['elements'][$key]; + } +} + +/** + * Implements hook_form_alter(). + */ +function gatsby_endpoints_form_alter(&$form, FormStateInterface $form_state, $form_id) { + if (!isset($form['field_gatsby_endpoint'])) { + return; + } + + $gatsby_endpoint = \Drupal::request()->query->get('gatsby_endpoint'); + + if ($gatsby_endpoint) { + $form['field_gatsby_endpoint']['widget']['#default_value'] = intval($gatsby_endpoint); + $form['field_gatsby_endpoint']['widget']['#value'] = intval($gatsby_endpoint); + $form['field_gatsby_endpoint']['widget']['#type'] = 'hidden'; + } + + // If this form is editing an entity, then hide the gatsby endpoint field. + $form_object = $form_state->getFormObject(); + if ($form_object instanceof EntityFormInterface && $form_object->getEntity()->id()) { + $form['field_gatsby_endpoint']['widget']['#value'] = $form['field_gatsby_endpoint']['widget']['#default_value']; + $form['field_gatsby_endpoint']['widget']['#type'] = 'hidden'; + } +} + +/** + * Implements hook_form_ID_alter(). + */ +function gatsby_endpoints_form_gatsby_admin_form_alter(&$form, FormStateInterface $form_state) { + foreach ($form as $key => $form_item) { + if (!empty($form_item['#type'])) { + unset($form[$key]); + } + } + + $form['endpoints_message'] = [ + '#markup' => '<p><strong>' . t('This form is overridden by functionality + provided by the Gatsby Endpoints module.') . '</strong></p>', + ]; + + $url = Url::fromRoute('entity.gatsby_endpoint.collection'); + $form['endpoints_link'] = [ + '#type' => 'link', + '#url' => $url, + '#title' => t('Manage your Gatsby Endpoints'), + ]; +} /** * Implements hook_entity_insert(). @@ -89,139 +191,4 @@ function _gatsby_endpoints_process_entity(GatsbyEndpointInterface $endpoint, Con function _gatsby_endpoints_update() { $gatsbyEndpointTrigger = \Drupal::service('gatsby.gatsby_endpoint_trigger'); $gatsbyEndpointTrigger->gatsbyUpdate(); -} - -/** - * Implements hook_form_alter(). - */ -function gatsby_endpoints_form_alter(&$form, FormStateInterface $form_state, $form_id) { - if (preg_match('/node_(\w*)_edit_form/', $form_id, $matches) && $form_id !== 'node_type_edit_form') { - - // Get Preview & iFrame settings. - $node = $form_state->getFormObject()->getEntity(); - $node_type = NodeType::load($node->bundle()); - $preview_settings = $node_type->getThirdPartySetting('gatsby', 'preview'); - $target_settings = $node_type->getThirdPartySetting('gatsby', 'target'); - - $preview_url = \Drupal::service('gatsby.gatsby_endpoint_manager')->getPreviewUrlForEntity($node); - - // Override node edit form. - if (!empty($preview_settings) && $preview_url) { - $alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $node->id()); - - // If this is the front-page we don't want to pass the alias - // (as Gatsby will likely 404). - if (\Drupal::service('path.matcher')->isFrontPage()) { - $alias = ''; - } - - // Add Gatsby Preview button. - $form['actions']['gatsby_preview'] = [ - '#type' => 'button', - '#weight' => 5, - ]; - $form['actions']['gatsby_preview']['#value'] = 'Open Gatsby Preview'; - $form['actions']['gatsby_preview']['#attributes']['class'] = ['gatsby-preview']; - - // Implement "Open Preview" action. - $form['actions']['gatsby_preview']['#attached'] = [ - 'drupalSettings' => [ - 'gatsby_preview_url' => $preview_url, - 'gatsby_path' => $alias, - 'gatsby_preview_target' => !empty($target_settings) ? $target_settings : 'window', - ], - 'library' => [ - 'gatsby/open_preview', - ], - ]; - } - } -} - -/** - * Implements hook_form_ID_alter(). - */ -function gatsby_endpoints_form_gatsby_admin_form_alter(&$form, FormStateInterface $form_state) { - foreach ($form as $key => $form_item) { - if (!empty($form_item['#type'])) { - unset($form[$key]); - } - } - - $form['endpoints_message'] = [ - '#markup' => '<p><strong>' . t('This form is overridden by functionality - provided by the Gatsby Endpoints module.') . '</strong></p>', - ]; - - $url = Url::fromRoute('gatsby_endpoints.gatsby_endpoints_collection'); - $form['endpoints_link'] = [ - '#type' => 'link', - '#url' => $url, - '#title' => t('Manage your Gatsby Endpoints'), - ]; -} - -/** - * Implements hook_node_view(). - */ -function gatsby_endpoints_node_view(array &$build, $entity, $display, $view_mode) { - // Override node view page with iframe to Gatsby site. - if (!empty($build['#node']) && $view_mode == 'full') { - $node = $build['#node']; - $iframe_settings = NodeType::load($entity->bundle())->getThirdPartySetting('gatsby', 'iframe'); - - // We are wanting to render preview for this content type. - if (!empty($iframe_settings)) { - $preview_url = \Drupal::service('gatsby.gatsby_endpoint_manager')->getPreviewUrlForEntity($node); - - if (!$preview_url) { - return; - } - - $alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $node->id()); - - // If this is the front-page we don't want to pass the alias - // (as Gatsby will likely 404). - if (\Drupal::service('path.matcher')->isFrontPage()) { - $alias = ''; - } - - $gatsby_url = preg_replace('/\/$/', '', $preview_url) . $alias; - - // Render an iframe to the preview URL. - $build['gatsby_preview'] = [ - '#type' => 'inline_template', - '#template' => '<div class="gatsby-iframe-container"><iframe class="gatsby-iframe" src="{{ url }}" /></div>', - '#context' => [ - 'url' => $gatsby_url, - ], - '#attached' => [ - 'library' => [ - 'gatsby/iframe_preview', - ], - ], - ]; - } - } -} - -/** - * Implements hook_cron(). - */ -function gatsby_endpoints_cron() { - $gatsbyEndpointManager = \Drupal::service('gatsby.gatsby_endpoint_manager'); - $endpoints = $gatsbyEndpointManager->getEndpoints(); - foreach ($endpoints as $endpoint) { - _gatsby_endpoints_trigger_cron_builds($endpoint); - } -} - -/** - * Triggers Endpoint build if the build_trigger is set to trigger on cron. - */ -function _gatsby_endpoints_trigger_cron_builds(GatsbyEndpointInterface $endpoint) { - if ($endpoint->getBuildTrigger() === 'cron') { - $gatsbyEndpointTrigger = \Drupal::service('gatsby.gatsby_endpoint_trigger'); - $gatsbyEndpointTrigger->triggerBuildUrls($endpoint); - } -} +} \ No newline at end of file diff --git a/gatsby_endpoints.permissions.yml b/gatsby_endpoints.permissions.yml index ed4abb1e8f0bbc560f62668d688bbf0918294308..511ee08ba1414bb1e8de08f20fa0686152a43174 100644 --- a/gatsby_endpoints.permissions.yml +++ b/gatsby_endpoints.permissions.yml @@ -1,6 +1,16 @@ -access gatsby endpoints: - title: 'Access Gatsby endpoints.' - -manage gatsby endpoints: - title: 'Create and manage Gatsby endpoints.' +administer gatsby endpoint types: + title: 'Administer gatsby endpoint types' + description: 'Maintain the types of gatsby endpoint entity.' restrict access: true +access gatsby endpoint overview: + title: 'Access gatsby endpoint overview page' +delete gatsby endpoint: + title: Delete gatsby endpoint +create gatsby endpoint: + title: Create gatsby endpoint +view gatsby endpoint: + title: View gatsby endpoint +edit gatsby endpoint: + title: Edit gatsby endpoint +create gatsby endpoint content: + title: Create gatsby endpoint content diff --git a/gatsby_endpoints.routing.yml b/gatsby_endpoints.routing.yml index fa6b52d477e056e88fef361f8294a6c6f3806488..429e5cc529805279cc331cb5d7d0f06948e383d0 100644 --- a/gatsby_endpoints.routing.yml +++ b/gatsby_endpoints.routing.yml @@ -1,35 +1,23 @@ -gatsby_endpoints.gatsby_endpoint_plugin_types: - path: '/admin/config/services/gatsby/endpoint/endpoint_types' - defaults: - _controller: '\Drupal\gatsby_endpoints\Controller\GatsbyEndpointLibraryController::listGatsbyEndpoints' - _title: 'Gatsby Endpoint types' - requirements: - _permission: 'manage gatsby endpoints' - options: - _admin_route: TRUE -gatsby_endpoints.admin_add: - path: '/admin/config/services/gatsby/endpoint/add/{plugin_id}' - defaults: - _controller: '\Drupal\gatsby_endpoints\Controller\GatsbyEndpointAddController::gatsbyEndpointAddConfigureForm' - theme: null - _title: 'Add new Gatsby endpoint' - requirements: - _permission: 'manage gatsby endpoints' -gatsby_endpoints.gatsby_endpoints_collection: - path: '/admin/config/services/gatsby/endpoint' - defaults: - _entity_list: 'gatsby_endpoint' - _title: 'Gatsby Endpoints' - requirements: - _permission: 'manage gatsby endpoints' - options: - _admin_route: TRUE gatsby_endpoints.gatsby_endpoints_controller_sync: - path: '/gatsby/{endpoint_id}' + path: '/gatsby/{gatsby_endpoint}' defaults: _controller: '\Drupal\gatsby_endpoints\Controller\GatsbyEndpointController::sync' _title: 'Gatsby Endpoint' options: _auth: ['basic_auth', 'cookie'] + parameters: + gatsby_endpoint: + type: entity:gatsby_endpoint requirements: - _permission: 'access gatsby endpoints' + _permission: 'access gatsby endpoint overview' +gatsby_endpoints.add_content: + path: '/gatsby_endpoint/{gatsby_endpoint}/content/add' + defaults: + _controller: '\Drupal\gatsby_endpoints\Controller\ContentController::addPage' + _title_callback: '\Drupal\gatsby_endpoints\Controller\ContentController::getTitle' + requirements: + _permission: 'create gatsby endpoint content' + options: + parameters: + gatsby_endpoint: + type: entity:gatsby_endpoint diff --git a/gatsby_endpoints.services.yml b/gatsby_endpoints.services.yml index ba57cfa8eeb0ace71d24ed140be1ab4dcc3f16c6..d7d2e17814cd7ea2abeba4c4d127ad26bd5e0db1 100644 --- a/gatsby_endpoints.services.yml +++ b/gatsby_endpoints.services.yml @@ -1,13 +1,10 @@ services: - plugin.manager.gatsby_endpoint: - class: Drupal\gatsby_endpoints\Plugin\GatsbyEndpointManager - parent: default_plugin_manager gatsby.gatsby_endpoint_generator: class: Drupal\gatsby_endpoints\GatsbyEndpointGenerator arguments: ['@entity_type.manager', '@entity_field.manager'] gatsby.gatsby_endpoint_trigger: class: Drupal\gatsby_endpoints\GatsbyEndpointTrigger - arguments: ['@http_client', '@entity_type.manager', '@logger.factory', '@entity.repository', '@gatsby.gatsby_instantpreview'] + arguments: ['@http_client', '@entity_type.manager', '@logger.factory', '@entity.repository', '@gatsby.preview'] gatsby.gatsby_endpoint_manager: class: Drupal\gatsby_endpoints\GatsbyEndpointManager arguments: ['@entity_type.manager', '@entity_field.manager'] diff --git a/src/Controller/ContentController.php b/src/Controller/ContentController.php new file mode 100644 index 0000000000000000000000000000000000000000..4bc969b84dce87cfef8e065b07f0083aedf30f0c --- /dev/null +++ b/src/Controller/ContentController.php @@ -0,0 +1,92 @@ +<?php + +namespace Drupal\gatsby_endpoints\Controller; + +use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Render\RendererInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; + +/** + * Returns responses for Gatsby Endpoint Content routes. + */ +class ContentController extends ControllerBase implements ContainerInjectionInterface { + + /** + * The renderer service. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** + * Constructs a NodeController object. + * + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer service. + */ + public function __construct(RendererInterface $renderer) { + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('renderer') + ); + } + + /** + * Displays add content links for available content types. + * + * Redirects to node/add/[type] if only one content type is available. + * + * @return array|\Symfony\Component\HttpFoundation\RedirectResponse + * A render array for a list of the node types that can be added; however, + * if there is only one node type defined for the site, the function + * will return a RedirectResponse to the node add page for that one node + * type. + */ + public function addPage(GatsbyEndpointInterface $gatsby_endpoint) { + $definition = $this->entityTypeManager()->getDefinition('node_type'); + $build = [ + '#theme' => 'node_add_list', + '#cache' => [ + 'tags' => $this->entityTypeManager()->getDefinition('node_type')->getListCacheTags(), + ], + ]; + + $content = []; + + $types = $this->entityTypeManager()->getStorage('node_type')->loadMultiple(); + uasort($types, [$definition->getClass(), 'sort']); + // Only use node types the user has access to. + foreach ($types as $type) { + $access = $this->entityTypeManager()->getAccessControlHandler('node')->createAccess($type->id(), NULL, [], TRUE); + if ($access->isAllowed() && $gatsby_endpoint->isBuildEntitySelected('node', $type->id())) { + $content[$type->id()] = $type; + } + $this->renderer->addCacheableDependency($build, $access); + } + + $build['#content'] = $content; + + return $build; + } + + /** + * The _title_callback for the node.add route. + * + * @param \Drupal\gatsby_endpoint_test\GatsbyEndpointInterface $gatsby_endpoint + * The current Gatsby Endpoint. + * + * @return string + * The page title. + */ + public function getTitle(GatsbyEndpointInterface $gatsby_endpoint) { + return $this->t('Add content to @name', ['@name' => $gatsby_endpoint->label()]); + } +} diff --git a/src/Controller/GatsbyEndpointController.php b/src/Controller/GatsbyEndpointController.php index 11384f007517f8efa6b4b2536b347999cdf29b58..700a23c4c2ad790b122f64bc7c5b117930cf9d98 100644 --- a/src/Controller/GatsbyEndpointController.php +++ b/src/Controller/GatsbyEndpointController.php @@ -6,6 +6,7 @@ use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; /** * Defines a class for serving Gatsby endpoint routes. @@ -51,7 +52,7 @@ class GatsbyEndpointController extends ControllerBase { * @return Symfony\Component\HttpFoundation\JsonResponse * Returns a JsonResponse with all of the content changes since last fetch. */ - public function sync(string $endpoint_id, Request $request) { + public function sync(GatsbyEndpointInterface $gatsby_endpoint, Request $request) { $sync_data = [ 'timestamp' => time(), ]; @@ -59,16 +60,11 @@ class GatsbyEndpointController extends ControllerBase { $base_url = $request->getSchemeAndHttpHost(); $path_prefix = $this->jsonApiConfig->get('path_prefix'); - $endpoint = $this->entityTypeManager->getStorage('gatsby_endpoint')->load($endpoint_id); - - if ($endpoint) { - $links = $this->gatsbyEndpointGenerator->getEndpointLinks($endpoint); - foreach ($links as $key => $link) { - $sync_data['links'][$key]['href'] = $base_url . '/' . $path_prefix . '/' . $link; - } + $links = $this->gatsbyEndpointGenerator->getEndpointLinks($gatsby_endpoint); + foreach ($links as $key => $link) { + $sync_data['links'][$key]['href'] = $base_url . '/' . $path_prefix . '/' . $link; } return new JsonResponse($sync_data); } - } diff --git a/src/Entity/GatsbyEndpoint.php b/src/Entity/GatsbyEndpoint.php index 16e4250a3bc55a570c86e7a90fd583fccdb4646e..1db5536bdb405124ede9d9dfc96342fb2af91da9 100644 --- a/src/Entity/GatsbyEndpoint.php +++ b/src/Entity/GatsbyEndpoint.php @@ -2,152 +2,171 @@ namespace Drupal\gatsby_endpoints\Entity; -use Drupal\gatsby_endpoints\GatsbyEndpointPluginCollection; -use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Entity\EntityWithPluginCollectionInterface; +use Drupal\Core\Entity\ContentEntityBase; +use Drupal\Core\Entity\EntityChangedTrait; +use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; +use Drupal\user\UserInterface; /** - * Defines the Gatsby Endpoint entity. + * Defines the gatsby endpoint entity class. * - * @ConfigEntityType( + * @ContentEntityType( * id = "gatsby_endpoint", - * label = @Translation("Gatsby endpoint"), + * label = @Translation("Gatsby Endpoint"), + * label_collection = @Translation("Gatsby Endpoints"), + * bundle_label = @Translation("Gatsby Endpoint type"), * handlers = { * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", * "list_builder" = "Drupal\gatsby_endpoints\GatsbyEndpointListBuilder", + * "views_data" = "Drupal\views\EntityViewsData", + * "access" = "Drupal\gatsby_endpoints\GatsbyEndpointAccessControlHandler", * "form" = { - * "default" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointForm", + * "add" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointForm", * "edit" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointForm", - * "delete" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointDeleteForm" + * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm" * }, * "route_provider" = { - * "html" = "Drupal\gatsby_endpoints\GatsbyEndpointHtmlRouteProvider", - * }, + * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", + * } * }, - * config_prefix = "gatsby_endpoint", - * admin_permission = "manage gatsby endpoints", + * base_table = "gatsby_endpoint", + * admin_permission = "administer gatsby endpoint types", * entity_keys = { * "id" = "id", - * "label" = "label", + * "bundle" = "bundle", + * "label" = "title", * "uuid" = "uuid" * }, * links = { - * "canonical" = "/admin/config/services/gatsby/endpoint/{gatsby_endpoint}", - * "add-form" = "/admin/config/services/gatsby/endpoint/add", - * "edit-form" = "/admin/config/services/gatsby/endpoint/{gatsby_endpoint}/edit", - * "delete-form" = "/admin/config/services/gatsby/endpoint/{gatsby_endpoint}/delete" - * }, - * config_export = { - * "id", - * "label", - * "weight", - * "provider", - * "plugin", - * "settings", - * "build_entity_types", - * "included_entity_types", - * "preview_urls", - * "build_urls", - * "build_trigger" + * "add-form" = "/admin/content/gatsby-endpoint/add/{gatsby_endpoint_type}", + * "add-page" = "/admin/content/gatsby-endpoint/add", + * "canonical" = "/gatsby_endpoint/{gatsby_endpoint}", + * "edit-form" = "/admin/content/gatsby-endpoint/{gatsby_endpoint}/edit", + * "delete-form" = "/admin/content/gatsby-endpoint/{gatsby_endpoint}/delete", + * "collection" = "/admin/content/gatsby-endpoint" * }, + * bundle_entity_type = "gatsby_endpoint_type", + * field_ui_base_route = "entity.gatsby_endpoint_type.edit_form" * ) */ -class GatsbyEndpoint extends ConfigEntityBase implements GatsbyEndpointInterface, EntityWithPluginCollectionInterface { +class GatsbyEndpoint extends ContentEntityBase implements GatsbyEndpointInterface { - /** - * The Gatsby Endpoint ID. - * - * @var string - */ - protected $id; + use EntityChangedTrait; /** - * The plugin collection that holds the endpoint plugin for this entity. + * {@inheritdoc} * - * @var \Drupal\gatsby_endpoints\GatsbyEndpointPluginCollection + * When a new gatsby endpoint entity is created, set the uid entity reference + * to the current user as the creator of the entity. */ - protected $pluginCollection; + public static function preCreate(EntityStorageInterface $storage_controller, array &$values) { + parent::preCreate($storage_controller, $values); + $values += ['uid' => \Drupal::currentUser()->id()]; + } /** - * The plugin instance ID. - * - * @var string + * {@inheritdoc} */ - protected $plugin; + public function getTitle() { + return $this->get('title')->value; + } /** - * The Gatsby endpoint label. - * - * @var string + * {@inheritdoc} */ - protected $label; + public function setTitle($title) { + $this->set('title', $title); + return $this; + } /** - * The Gatsby endpoint build entity types. - * - * @var array + * {@inheritdoc} */ - protected $build_entity_types; - + public function getBuildTrigger() { + return $this->get('build_trigger')->value; + } /** - * The Gatsby endpoint preview Urls. - * - * @var array + * {@inheritdoc} */ - protected $preview_urls; + public function setBuildTrigger($build_trigger) { + $this->set('build_trigger', $build_trigger); + return $this; + } /** - * The Gatsby endpoint build Urls. - * - * @var array + * {@inheritdoc} */ - protected $build_urls; + public function getCreatedTime() { + return $this->get('created')->value; + } /** - * The Gatsby endpoint build trigger. - * - * @var string + * {@inheritdoc} */ - protected $build_trigger; + public function setCreatedTime($timestamp) { + $this->set('created', $timestamp); + return $this; + } /** - * The weight of the endpoint. - * - * @var string + * {@inheritdoc} */ - protected $weight; + public function getOwner() { + return $this->get('uid')->entity; + } /** - * The plugin instance settings. - * - * @var array + * {@inheritdoc} */ - protected $settings = []; + public function getOwnerId() { + return $this->get('uid')->target_id; + } /** * {@inheritdoc} */ - public function getEntityTypes($key) { - if ($key === 'build') { - return $this->build_entity_types; - } - - return []; + public function setOwnerId($uid) { + $this->set('uid', $uid); + return $this; } /** * {@inheritdoc} */ - public function getBuildEntityTypes() { - return $this->build_entity_types; + public function setOwner(UserInterface $account) { + $this->set('uid', $account->id()); + return $this; } + // /** + // * {@inheritdoc} + // */ + // public function getEntityTypes($key) + // { + // if ($key === 'build') { + // return $this->build_entity_types; + // } + + // return []; + // } + + // /** + // * {@inheritdoc} + // */ + // public function getBuildEntityTypes() + // { + // return $this->build_entity_types; + // } + /** * {@inheritDoc} */ public function getBuildEntityType($entity_type) { - foreach ($this->build_entity_types as $build_type) { + foreach ($this->getBuildEntities() as $build_type) { if (!empty($build_type['entity_type']) && $build_type['entity_type'] === $entity_type) { return $build_type; } @@ -156,12 +175,13 @@ class GatsbyEndpoint extends ConfigEntityBase implements GatsbyEndpointInterface return FALSE; } - /** - * {@inheritdoc} - */ - public function setBuildEntityTypes($build_entity_types) { - $this->build_entity_types = $build_entity_types; - } + // /** + // * {@inheritdoc} + // */ + // public function setBuildEntityTypes($build_entity_types) + // { + // $this->build_entity_types = $build_entity_types; + // } /** * {@inheritDoc} @@ -185,10 +205,9 @@ class GatsbyEndpoint extends ConfigEntityBase implements GatsbyEndpointInterface */ public function getUrls($key) { if ($key === 'preview') { - return $this->preview_urls; - } - elseif ($key === 'build') { - return $this->build_urls; + return $this->getPreviewUrls(); + } elseif ($key === 'build') { + return $this->getBuildUrls(); } return []; @@ -198,87 +217,267 @@ class GatsbyEndpoint extends ConfigEntityBase implements GatsbyEndpointInterface * {@inheritdoc} */ public function getPreviewUrls() { - return $this->preview_urls; + return $this->get('preview_urls')->value; } /** * {@inheritdoc} */ public function setPreviewUrls($preview_urls) { - $this->preview_urls = $preview_urls; + $this->set('preview_urls', $preview_urls); + return $this; } /** * {@inheritdoc} */ public function getBuildUrls() { - return $this->build_urls; + return $this->get('build_urls')->value; } /** * {@inheritdoc} */ public function setBuildUrls($build_urls) { - $this->build_urls = $build_urls; + $this->set('build_urls', $build_urls); + return $this; } /** * {@inheritdoc} */ - public function getWeight() { - return $this->weight; + public function getContentSyncUrl() { + return $this->get('contentsync_url')->value; } /** * {@inheritdoc} */ - public function getBuildTrigger() { - return $this->build_trigger; + public function setContentSyncUrl($contentsync_url) { + $this->set('contentsync_url', $contentsync_url); + return $this; } /** * {@inheritdoc} */ - public function setBuildTrigger($build_trigger) { - $this->build_trigger = $build_trigger; - } - - /** - * Encapsulates creation of the Gatsby endpoint's LazyPluginCollection. - * - * @return \Drupal\Component\Plugin\LazyPluginCollection - * The Gatsby endpoint's plugin collection. - */ - protected function getPluginCollection() { - if (!$this->pluginCollection) { - $this->pluginCollection = new GatsbyEndpointPluginCollection( - \Drupal::service('plugin.manager.gatsby_endpoint'), $this->plugin, $this->get('settings'), $this->id() - ); - } - return $this->pluginCollection; + public function getBuildEntities() { + return $this->get('build_entities')->getValue(); } /** * {@inheritdoc} */ - public function getPlugin() { - return $this->getPluginCollection()->get($this->plugin); + public function setBuildEntities($build_entities) { + $this->set('build_entities', $build_entities); + return $this; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getPluginCollections() { - return [ - 'settings' => $this->getPluginCollection(), - ]; + public function isBuildEntitySelected($entity_type, $entity_bundle) { + $build_entities = $this->getBuildEntities(); + + foreach ($build_entities as $build_entity) { + if ($build_entity['entity_type'] == $entity_type) { + foreach ($build_entity['entity_bundles'] as $bundle_name) { + if ($bundle_name === $entity_bundle) { + return TRUE; + } + } + } + } + return FALSE; } /** * {@inheritdoc} */ - public function getSettings() { - return $this->settings; + public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { + + $fields = parent::baseFieldDefinitions($entity_type); + + $fields['title'] = BaseFieldDefinition::create('string') + ->setLabel(t('Title')) + ->setDescription(t('The title of the Gatsby Endpoint.')) + ->setRequired(TRUE) + ->setSetting('max_length', 255) + ->setDisplayOptions('form', [ + 'type' => 'string_textfield', + 'weight' => -10, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'hidden', + 'type' => 'string', + 'weight' => -10, + ]) + ->setDisplayConfigurable('view', TRUE); + + $fields['build_trigger'] = BaseFieldDefinition::create('list_string') + ->setLabel(t('Build Trigger')) + ->setDescription(t( + 'Select how Gatsby build URLs should be + triggered. Incremental builds require a + <a href="@gatsby-link">Gatsby Cloud Account</a>. This setting has no + effect if there are no build URLs entered above.', + [ + '@gatsby-link' => 'https://gatsbyjs.com', + ] + )) + ->setRequired(TRUE) + ->setDisplayOptions('form', [ + 'type' => 'options_select', + 'weight' => -9, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'string', + 'weight' => -9, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setSettings([ + 'allowed_values' => [ + 'incremental' => t("Trigger builds incrementally (requires Gatsby Cloud)"), + 'cron' => t("Trigger builds on cron runs"), + 'manual' => t("Trigger builds manually with the built in drush command"), + ], + ]) + ->setDefaultValue([['value' => 'incremental']]) + ->setInternal(TRUE); + + $fields['public_url'] = BaseFieldDefinition::create('uri') + ->setLabel(t('Public URL')) + ->setDescription(t('The Public URL for this Gatsby website')) + ->setRequired(FALSE) + ->setDisplayOptions('form', [ + 'type' => 'string_textfield', + 'weight' => -8, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'uri_link', + 'weight' => -8, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setInternal(TRUE); + + $fields['preview_urls'] = BaseFieldDefinition::create('uri') + ->setLabel(t('Preview Hooks')) + ->setDescription(t('Enter any Gatsby Preview URLs to trigger for this endpoint')) + ->setRequired(FALSE) + ->setCardinality(-1) + ->setDisplayOptions('form', [ + 'type' => 'string_textfield', + 'weight' => -7, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'string', + 'weight' => -7, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setInternal(TRUE); + + $fields['build_urls'] = BaseFieldDefinition::create('uri') + ->setLabel(t('Build Hooks')) + ->setDescription(t('Enter any Gatsby Build URLs to trigger for this endpoint')) + ->setRequired(FALSE) + ->setCardinality(-1) + ->setDisplayOptions('form', [ + 'type' => 'string_textfield', + 'weight' => -6, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'string', + 'weight' => -6, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setInternal(TRUE); + + $fields['contentsync_url'] = BaseFieldDefinition::create('uri') + ->setLabel(t('Content Sync URL')) + ->setDescription(t('The Content Sync Preview URL provided by Gatsby Cloud')) + ->setRequired(FALSE) + ->setDisplayOptions('form', [ + 'type' => 'string_textfield', + 'weight' => -5, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'string', + 'weight' => -5, + ]) + ->setDisplayConfigurable('view', TRUE) + ->setInternal(TRUE); + + $fields['build_entities'] = BaseFieldDefinition::create('map') + ->setLabel(t('Build Entities Data')) + ->setInternal(TRUE); + + $fields['description'] = BaseFieldDefinition::create('text_long') + ->setLabel(t('Description')) + ->setDescription(t('A description of the Gatsby Endpoint.')) + ->setDisplayOptions('form', [ + 'type' => 'text_textarea', + 'weight' => 10, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'type' => 'text_default', + 'label' => 'above', + 'weight' => 10, + ]) + ->setDisplayConfigurable('view', TRUE); + + $fields['uid'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(t('Author')) + ->setDescription(t('The user ID of the Gatsby Endpoint author.')) + ->setSetting('target_type', 'user') + ->setDisplayOptions('form', [ + 'type' => 'entity_reference_autocomplete', + 'settings' => [ + 'match_operator' => 'CONTAINS', + 'size' => 60, + 'placeholder' => '', + ], + 'weight' => 15, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'author', + 'weight' => 15, + ]) + ->setDisplayConfigurable('view', TRUE); + + $fields['created'] = BaseFieldDefinition::create('created') + ->setLabel(t('Authored on')) + ->setDescription(t('The time that the Gatsby Endpoint was created.')) + ->setDisplayOptions('view', [ + 'label' => 'above', + 'type' => 'timestamp', + 'weight' => 20, + ]) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayOptions('form', [ + 'type' => 'datetime_timestamp', + 'weight' => 20, + ]) + ->setDisplayConfigurable('view', TRUE); + + $fields['changed'] = BaseFieldDefinition::create('changed') + ->setLabel(t('Changed')) + ->setDescription(t('The time that the Gatsby Endpoint was last edited.')); + + return $fields; } } diff --git a/src/Entity/GatsbyEndpointType.php b/src/Entity/GatsbyEndpointType.php new file mode 100644 index 0000000000000000000000000000000000000000..fda8ded60d19010d4e91f62f6fff0a17b82c4a21 --- /dev/null +++ b/src/Entity/GatsbyEndpointType.php @@ -0,0 +1,85 @@ +<?php + +namespace Drupal\gatsby_endpoints\Entity; + +use Drupal\Core\Config\Entity\ConfigEntityBundleBase; + +/** + * Defines the Gatsby Endpoint type configuration entity. + * + * @ConfigEntityType( + * id = "gatsby_endpoint_type", + * label = @Translation("Gatsby Endpoint type"), + * handlers = { + * "form" = { + * "add" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointTypeForm", + * "edit" = "Drupal\gatsby_endpoints\Form\GatsbyEndpointTypeForm", + * "delete" = "Drupal\Core\Entity\EntityDeleteForm", + * }, + * "list_builder" = "Drupal\gatsby_endpoints\GatsbyEndpointTypeListBuilder", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", + * } + * }, + * admin_permission = "administer gatsby endpoint types", + * bundle_of = "gatsby_endpoint", + * config_prefix = "gatsby_endpoint_type", + * entity_keys = { + * "id" = "id", + * "label" = "label", + * "uuid" = "uuid" + * }, + * links = { + * "add-form" = "/admin/structure/gatsby_endpoint_types/add", + * "edit-form" = "/admin/structure/gatsby_endpoint_types/manage/{gatsby_endpoint_type}", + * "delete-form" = "/admin/structure/gatsby_endpoint_types/manage/{gatsby_endpoint_type}/delete", + * "collection" = "/admin/structure/gatsby_endpoint_types" + * }, + * config_export = { + * "id", + * "label", + * "uuid", + * } + * ) + */ +class GatsbyEndpointType extends ConfigEntityBundleBase { + + /** + * The machine name of this gatsby endpoint type. + * + * @var string + */ + protected $id; + + /** + * The human-readable name of the gatsby endpoint type. + * + * @var string + */ + protected $label; + + /** + * The build entitites. + * + * @var array + */ + protected $build_entities; + + /** + * {@inheritdoc} + */ + public function getBuildEntities() { + if ($this->get('build_entities')) { + return $this->get('build_entities')->getValue(); + } + return []; + } + + /** + * {@inheritdoc} + */ + public function setBuildEntities($build_entities) { + $this->set('build_entities', $build_entities); + return $this; + } +} diff --git a/src/Form/GatsbyEndpointForm.php b/src/Form/GatsbyEndpointForm.php index 335470bb37a33620ddef80aad71639011b5f3f84..54a5fab745f5edfcd3ceb22d85e36e9d873a84b5 100644 --- a/src/Form/GatsbyEndpointForm.php +++ b/src/Form/GatsbyEndpointForm.php @@ -2,524 +2,50 @@ namespace Drupal\gatsby_endpoints\Form; -use Drupal\gatsby_endpoints\Plugin\GatsbyEndpointInterface; -use Drupal\Core\Entity\ContentEntityTypeInterface; -use Drupal\Core\Entity\EntityForm; -use Drupal\Core\Entity\EntityTypeBundleInfo; +use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\SubformState; -use Drupal\Core\Plugin\PluginFormFactoryInterface; -use Drupal\Core\Plugin\PluginWithFormsInterface; -use Drupal\Core\Url; -use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Provides a form for editing Gatsby Endpoint entities. + * Form controller for the gatsby endpoint entity edit forms. */ -class GatsbyEndpointForm extends EntityForm { - - /** - * The plugin form manager. - * - * @var \Drupal\Core\Plugin\PluginFormFactoryInterface - */ - protected $pluginFormFactory; - - /** - * The entity bundle service. - * - * @var \Drupal\Core\Entity\EntityTypeBundleInfo - */ - protected $entityTypeBundleInfo; - - /** - * GatsbyEndpointForm constructor. - * - * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_manager - * The plugin form manager. - * @param \Drupal\Core\Entity\EntityTypeBundleInfo $entity_type_bundle_info - * The entity type bundle info service. - */ - public function __construct(PluginFormFactoryInterface $plugin_form_manager, - EntityTypeBundleInfo $entity_type_bundle_info) { - - $this->pluginFormFactory = $plugin_form_manager; - $this->entityTypeBundleInfo = $entity_type_bundle_info; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin_form.factory'), - $container->get('entity_type.bundle.info') - ); - } +class GatsbyEndpointForm extends ContentEntityForm { /** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); - - /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface $entity */ - $entity = $this->entity; - - $form['label'] = [ - '#type' => 'textfield', - '#title' => $this->t('Label'), - '#maxlength' => 255, - '#default_value' => $entity->label(), - '#description' => $this->t("Label for the Gatsby endpoint."), - '#required' => TRUE, - ]; - - $form['id'] = [ - '#type' => 'machine_name', - '#default_value' => $entity->id(), - '#machine_name' => [ - 'exists' => '\Drupal\gatsby_endpoints\Entity\GatsbyEndpoint::load', - ], - '#disabled' => !$entity->isNew(), - ]; - - // Render the Preview URLs AJAX enabled fieldset. - $preview_description = $this->t("Enter any Gatsby Live Preview URLs to trigger for this endpoint."); - $this->addAjaxFieldset($form, $form_state, 'preview', $preview_description); - - // Render the Build URLs AJAX enabled fieldset. - $build_description = $this->t("Enter any Gatsby Build Hooks or Build URLs to trigger for this endpoint."); - $this->addAjaxFieldset($form, $form_state, 'build', $build_description); - - $build_entities_description = $this->t("Select which entities should trigger builds/previews for this endpoint."); - $this->addEntityAjaxFieldset($form, $form_state, 'build', $build_entities_description); - - $form['build_trigger'] = [ - '#type' => 'select', - '#options' => [ - 'incremental' => $this->t("Trigger builds incrementally (requires Gatsby Cloud)"), - 'cron' => $this->t("Trigger builds on cron runs"), - 'manual' => $this->t("Trigger builds manually with the built in drush command"), - ], - '#title' => $this->t("Build Trigger"), - '#default_value' => $entity->getBuildTrigger() ? $entity->getBuildTrigger() : 'incremental', - '#description' => $this->t('Select how Gatsby build URLs should be - triggered. Incremental builds require a - <a href="@gatsby-link">Gatsby Cloud Account</a>. This setting has no - effect if there are no build URLs entered above.', - [ - '@gatsby-link' => 'https://gatsbyjs.com', - ] - ), - '#required' => TRUE, - ]; - - $form['weight'] = [ - '#type' => 'number', - '#title' => $this->t('Weight'), - '#max' => 100, - '#min' => -100, - '#size' => 3, - '#default_value' => $entity->getWeight() ? $entity->getWeight() : 0, - '#description' => $this->t("Set the weight, lighter endpoints will be rendered first."), - '#required' => TRUE, - ]; - $form['#tree'] = TRUE; - $form['settings'] = []; - $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state); - $form['settings'] = $this->getPluginForm($entity->getPlugin()) - ->buildConfigurationForm($form['settings'], $subform_state); - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Remove empty Build and Preview URLs. - $this->removeEmptyUrls($form_state, 'preview'); - $this->removeEmptyUrls($form_state, 'build'); - parent::submitForm($form, $form_state); - - /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface $entity */ - $entity = $this->entity; - - $sub_form_state = SubformState::createForSubform($form['settings'], $form, $form_state); - - // Call the plugin submit handler. - $this->getPluginForm($entity->getPlugin()) - ->submitConfigurationForm($form, $sub_form_state); - - $entity->save(); - - $this->messenger()->addStatus($this->t('The Gatsby endpoint configuration has been saved.')); - $form_state->setRedirectUrl(Url::fromRoute('gatsby_endpoints.gatsby_endpoints_collection')); + return $form; } /** * {@inheritdoc} */ - protected function getPluginForm(GatsbyEndpointInterface $gatsbyEndpoint) { - if ($gatsbyEndpoint instanceof PluginWithFormsInterface) { - return $this->pluginFormFactory->createInstance($gatsbyEndpoint, 'configure'); - } - return $gatsbyEndpoint; - } - - /** - * Adds a Form Element to an AJAX Fieldset. - */ - public function addFormElement(array &$form, FormStateInterface $form_state, $key, $element) { - $cnt = $form_state->get($key . '_' . $element . '_cnt'); - $form_state->set($key . '_' . $element . '_cnt', $cnt + 1); - $form_state->setRebuild(); - } - - /** - * Removes a Form Element from an AJAX Fieldset. - */ - public function removeFormElement(array &$form, FormStateInterface $form_state, $key, $element) { - $cnt = $form_state->get($key . '_' . $element . '_cnt'); - if ($cnt > 1) { - $form_state->set($key . '_' . $element . '_cnt', $cnt - 1); - } - $form_state->setRebuild(); - } - - /** - * Adds a Build Url. - */ - public function addBuildUrl(array &$form, FormStateInterface $form_state) { - $this->addFormElement($form, $form_state, 'build', 'url'); - } - - /** - * Removes a Build Url. - */ - public function removeBuildUrl(array &$form, FormStateInterface $form_state) { - $this->removeFormElement($form, $form_state, 'build', 'url'); - } - - /** - * Ajax callback for Build Urls that returns the correct fieldset. - */ - public function buildUrlCallback(array &$form, FormStateInterface $form_state) { - return $form['build_urls']; - } - - /** - * Adds a Preview Url. - */ - public function addPreviewUrl(array &$form, FormStateInterface $form_state) { - $this->addFormElement($form, $form_state, 'preview', 'url'); - } - - /** - * Removes a Preview Url. - */ - public function removePreviewUrl(array &$form, FormStateInterface $form_state) { - $this->removeFormElement($form, $form_state, 'preview', 'url'); - } - - /** - * Ajax callback for Preview Urls that returns the correct fieldset. - */ - public function previewUrlCallback(array &$form, FormStateInterface $form_state) { - return $form['preview_urls']; - } - - /** - * Renders AJAX fieldsets for Build and Preview URLs. - */ - public function addAjaxFieldset(array &$form, FormStateInterface $form_state, $key, $description) { - $label = ucfirst($key); - $url_cnt = $form_state->get($key . '_url_cnt'); - + public function save(array $form, FormStateInterface $form_state) { /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface $entity */ - $entity = $this->entity; - - // If there is no count yet, then this is the first time rendering. - if ($url_cnt === NULL) { - $urls = $entity->getUrls($key); - $url_cnt = !empty($urls) && !empty($urls[$key . '_url']) ? count($urls[$key . '_url']) : 0; - if ($url_cnt === 0) { - $url_cnt = 1; - } - $form_state->set($key . '_url_cnt', $url_cnt); - } + $entity = $this->getEntity(); - $form[$key . '_urls'] = [ - '#type' => 'fieldset', - '#title' => $this->t("Gatsby @label URLs", ['@label' => $label]), - '#prefix' => '<div id="' . $key . '-urls-fieldset-wrapper">', - '#suffix' => '</div>', - ]; - $form[$key . '_urls']['description'] = [ - '#markup' => $description, - '#weight' => -100, - ]; - - for ($i = 0; $i < $url_cnt; $i++) { - $form[$key . '_urls'][$key . '_url'][$i] = [ - '#type' => 'url', - '#title' => $this->t('Gatsby @label URL #@cnt', [ - '@label' => $label, - '@cnt' => $i + 1, - ]), - '#maxlength' => 255, - '#default_value' => !empty($urls[$key . '_url'][$i]) ? $urls[$key . '_url'][$i] : "", - '#required' => FALSE, - ]; - } - $form[$key . '_urls']['actions'] = [ - '#type' => 'actions', - ]; - $form[$key . '_urls']['actions']['add_' . $key . '_url'] = [ - '#type' => 'submit', - '#value' => $this->t('Add Additional @label URL', ['@label' => $label]), - '#submit' => ['::add' . $label . 'Url'], - '#ajax' => [ - 'callback' => '::' . $key . 'UrlCallback', - 'wrapper' => $key . '-urls-fieldset-wrapper', - ], - ]; - if ($url_cnt > 1) { - $form[$key . '_urls']['actions']['remove_' . $key . '_url'] = [ - '#type' => 'submit', - '#value' => $this->t('Remove @label URL', ['@label' => $label]), - '#submit' => ['::remove' . $label . 'Url'], - '#ajax' => [ - 'callback' => '::' . $key . 'UrlCallback', - 'wrapper' => $key . '-urls-fieldset-wrapper', - ], - ]; + if (isset($form_state->getValues()['build_entity_types'])) { + $entity->setBuildEntities($form_state->getValues()['build_entity_types']); } - } - - /** - * Removes empty URLs from preview and build fieldsets. - */ - public function removeEmptyUrls(FormStateInterface $form_state, $key) { - $values = $form_state->getValue($key . '_urls'); - $values[$key . '_url'] = array_values(array_filter($values[$key . '_url'])); - $form_state->setValue($key . '_urls', $values); - } - /** - * Adds a Build Entity Fieldset. - */ - public function addBuildEntityFieldset(array &$form, FormStateInterface $form_state) { - $this->addFormElement($form, $form_state, 'build', 'entity'); - } - - /** - * Removes a Build Entity Fieldset Url. - */ - public function removeBuildEntityFieldset(array &$form, FormStateInterface $form_state) { - $this->removeFormElement($form, $form_state, 'build', 'entity'); - } - - /** - * Ajax callback for Build Entity Fieldsets that returns the correct fieldset. - */ - public function buildEntityCallback(array &$form, FormStateInterface $form_state) { - return $form['build_entity_types']; - } - - /** - * Ajax callback for build entities that returns the correct bundles. - */ - public function buildEntityBundleCallback(array &$form, FormStateInterface $form_state) { - // Determine what element triggered this callback. - $triggering_element = $form_state->getTriggeringElement(); - $wrapper_elements = explode('-', $triggering_element['#ajax']['wrapper']); - $element_id = intval(array_pop($wrapper_elements)); + $result = $entity->save(); + $link = $entity->toLink($this->t('View'))->toRenderable(); - $form['build_entity_types'][$element_id]['#open'] = TRUE; - return $form['build_entity_types'][$element_id]; - } - - /** - * Renders AJAX fieldsets for Entity selection. - */ - public function addEntityAjaxFieldset(array &$form, FormStateInterface $form_state, $key, $description) { - $label = ucfirst($key); - $entity_cnt = $form_state->get($key . '_entity_cnt'); - - /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface $entity */ - $entity = $this->entity; - - // If there is no count yet, then this is the first time rendering. - if ($entity_cnt === NULL) { - $entities = $entity->getEntityTypes($key); - $entity_cnt = !empty($entities) ? count($entities) - 1 : 0; - if ($entity_cnt === 0) { - $entity_cnt = 1; - } - $form_state->set($key . '_entity_cnt', $entity_cnt); - } - - $form[$key . '_entity_types'] = [ - '#type' => 'fieldset', - '#title' => $this->t("Gatsby @label Entities", ['@label' => $label]), - '#prefix' => '<div id="' . $key . '-entity-fieldset-wrapper">', - '#suffix' => '</div>', - ]; - $form[$key . '_entity_types']['description'] = [ - '#markup' => $description, - '#weight' => -100, - ]; - - for ($i = 0; $i < $entity_cnt; $i++) { - // Get the default entity type. - $entity_type = !empty($entities[$i]['entity_type']) ? - $entities[$i]['entity_type'] : ""; - - // Check if there was an entity type set in the form state. - $form_values = $form_state->getValues(); - if (!empty($form_values[$key . '_entity_types'][$i]['entity_type'])) { - $entity_type = $form_values[$key . '_entity_types'][$i]['entity_type']; - } - - $content_entity_types = $this->getContentEntityTypes(); - - $form[$key . '_entity_types'][$i] = [ - '#type' => 'details', - '#title' => $this->t("Gatsby @label Entity #@cnt @entity", [ - '@label' => $label, - '@cnt' => $i + 1, - '@entity' => !empty($entity_type) ? "(" . $content_entity_types[$entity_type] . ")" : "", - ]), - '#prefix' => '<div id="' . $key . '-entity-fieldset-' . $i . '">', - '#suffix' => '</div>', - '#open' => empty($entity_type) ? TRUE : FALSE, - ]; - - $entity_types = ['' => $this->t("-- Select Entity Type --")] + $content_entity_types; - - $form[$key . '_entity_types'][$i]['entity_type'] = [ - '#type' => 'select', - '#options' => $entity_types, - '#title' => $this->t("Entity Type"), - '#default_value' => $entity_type, - ]; - - $form[$key . '_entity_types'][$i]['entity_type']['#ajax'] = [ - 'callback' => '::' . $key . 'EntityBundleCallback', - 'wrapper' => $key . '-entity-fieldset-' . $i, - 'event' => 'change', - 'progress' => [ - 'type' => 'throbber', - 'message' => $this->t('Loading bundles...'), - ], - ]; - - if ($entity_type) { - $entity_bundles = !empty($entities[$i]['entity_bundles']) ? - $entities[$i]['entity_bundles'] : []; - $include_entities = !empty($entities[$i]['include_entities']) ? - $entities[$i]['include_entities'] : []; - - $form[$key . '_entity_types'][$i]['entity_bundles'] = [ - '#type' => 'checkboxes', - '#options' => $this->getContentEntityBundles($entity_type), - '#title' => $this->t("Entity Bundle(s)"), - '#default_value' => $entity_bundles, - ]; - - if ($entity_type == 'node') { - $build_published = !empty($entities[$i]['build_published']) ? - $entities[$i]['build_published'] : FALSE; - $form[$key . '_entity_types'][$i]['build_published'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Only trigger builds for published content'), - '#description' => $this->t('Depending on your content workflow, you may only - want builds to be triggered for published content. By checking this box - only published content will trigger a build.'), - '#default_value' => $build_published, - '#weight' => 3, - ]; - } - - $included_entities_description = $this->t("Select which entities should not trigger builds/previews but should be - included in builds/previews. This is commonly used for entities such as media, files, or paragraphs where you don't - want these items to trigger a new build, but you do want to make sure they are sent to Gatsby if they are - attached to an entity that triggers a build."); - $form[$key . '_entity_types'][$i]['include_entities'] = [ - '#type' => 'checkboxes', - '#options' => $content_entity_types, - '#title' => $this->t("Include Entities"), - '#description' => $included_entities_description, - '#default_value' => $include_entities, - '#weight' => 4, - ]; - } - } - $form[$key . '_entity_types']['actions'] = [ - '#type' => 'actions', - ]; - $form[$key . '_entity_types']['actions']['add_' . $key . '_entity'] = [ - '#type' => 'submit', - '#value' => $this->t('Add Additional @label Entity', ['@label' => $label]), - '#submit' => ['::add' . $label . 'EntityFieldset'], - '#ajax' => [ - 'callback' => '::' . $key . 'EntityCallback', - 'wrapper' => $key . '-entity-fieldset-wrapper', - ], - ]; - if ($entity_cnt > 1) { - $form[$key . '_entity_types']['actions']['remove_' . $key . '_entity'] = [ - '#type' => 'submit', - '#value' => $this->t('Remove @label Entity', ['@label' => $label]), - '#submit' => ['::remove' . $label . 'EntityFieldset'], - '#ajax' => [ - 'callback' => '::' . $key . 'EntityCallback', - 'wrapper' => $key . '-entity-fieldset-wrapper', - ], - ]; - } - } - - /** - * Gets a list of all the defined content entities in the system. - * - * @return array - * An array of content entities definitions. - */ - private function getContentEntityTypes() { - $content_entity_types = []; - $allEntityTypes = $this->entityTypeManager->getDefinitions(); - - foreach ($allEntityTypes as $entity_type_id => $entity_type) { - // Add all content entity types but not the gatsby log entity provided - // by the gatsby_fastbuilds module (if it exists). - if ($entity_type instanceof ContentEntityTypeInterface && - $entity_type_id !== 'gatsby_log_entity') { - - $content_entity_types[$entity_type_id] = $entity_type->getLabel(); - } - } - return $content_entity_types; - } - - /** - * Gets a list of all the defined bundles for a content entity type. - * - * @return array - * An array of bundles for a specific content entity type. - */ - private function getContentEntityBundles($entity_type) { - $bundle_definitions = $this->entityTypeBundleInfo->getBundleInfo($entity_type); + $message_arguments = ['%label' => $this->entity->label()]; + $logger_arguments = $message_arguments + ['link' => render($link)]; - $bundles = []; - foreach ($bundle_definitions as $bundle => $bundle_definition) { - $bundles[$bundle] = $bundle_definition['label']; + if ($result == SAVED_NEW) { + $this->messenger()->addStatus($this->t('New Gatsby Endpoint %label has been created.', $message_arguments)); + $this->logger('gatsby_endpoints')->notice('Created new Gatsby Endpoint %label', $logger_arguments); + } else { + $this->messenger()->addStatus($this->t('The Gatsby Endpoint %label has been updated.', $message_arguments)); + $this->logger('gatsby_endpoints')->notice('Updated new Gatsby Endpoint %label.', $logger_arguments); } - return $bundles; + $form_state->setRedirect('entity.gatsby_endpoint.canonical', ['gatsby_endpoint' => $entity->id()]); } } diff --git a/src/Form/GatsbyEndpointTypeForm.php b/src/Form/GatsbyEndpointTypeForm.php new file mode 100644 index 0000000000000000000000000000000000000000..924069aa20b3d487df1563aa4e62cfe2ed28d36b --- /dev/null +++ b/src/Form/GatsbyEndpointTypeForm.php @@ -0,0 +1,328 @@ +<?php + +namespace Drupal\gatsby_endpoints\Form; + +use Drupal\Core\Entity\BundleEntityFormBase; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\ContentEntityTypeInterface; +use Drupal\Core\Form\FormStateInterface; + +/** + * Form handler for gatsby endpoint type forms. + */ +class GatsbyEndpointTypeForm extends BundleEntityFormBase { + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + + $entity_type = $this->entity; + if ($this->operation == 'add') { + $form['#title'] = $this->t('Add gatsby endpoint type'); + } else { + $form['#title'] = $this->t( + 'Edit %label gatsby endpoint type', + ['%label' => $entity_type->label()] + ); + } + + $form['label'] = [ + '#title' => $this->t('Label'), + '#type' => 'textfield', + '#default_value' => $entity_type->label(), + '#description' => $this->t('The human-readable name of this gatsby endpoint type.'), + '#required' => TRUE, + '#size' => 30, + ]; + + $form['id'] = [ + '#type' => 'machine_name', + '#default_value' => $entity_type->id(), + '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, + '#machine_name' => [ + 'exists' => ['Drupal\gatsby_endpoints\Entity\GatsbyEndpointType', 'load'], + 'source' => ['label'], + ], + '#description' => $this->t('A unique machine-readable name for this gatsby endpoint type. It must only contain lowercase letters, numbers, and underscores.'), + ]; + + $this->addEntityAjaxFieldset($form, $form_state); + $form['#tree'] = TRUE; + + return $this->protectBundleIdElement($form); + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, FormStateInterface $form_state) { + $actions = parent::actions($form, $form_state); + $actions['submit']['#value'] = $this->t('Save gatsby endpoint type'); + $actions['delete']['#value'] = $this->t('Delete gatsby endpoint type'); + return $actions; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointType $entity_type */ + $entity_type = $this->entity; + + if (isset($form_state->getValues()['build_entity_types'])) { + $entity_type->setBuildEntities($form_state->getValues()['build_entity_types']); + } + + $entity_type->set('id', trim($entity_type->id())); + $entity_type->set('label', trim($entity_type->label())); + + $status = $entity_type->save(); + + $t_args = ['%name' => $entity_type->label()]; + if ($status == SAVED_UPDATED) { + $message = $this->t('The gatsby endpoint type %name has been updated.', $t_args); + } elseif ($status == SAVED_NEW) { + $message = $this->t('The gatsby endpoint type %name has been added.', $t_args); + } + $this->messenger()->addStatus($message); + + $form_state->setRedirectUrl($entity_type->toUrl('collection')); + } + + /** + * Adds a Form Element to an AJAX Fieldset. + */ + public function addFormElement(array &$form, FormStateInterface $form_state, $key, $element) { + $cnt = $form_state->get($key . '_' . $element . '_cnt'); + $form_state->set($key . '_' . $element . '_cnt', $cnt + 1); + $form_state->setRebuild(); + } + + /** + * Removes a Form Element from an AJAX Fieldset. + */ + public function removeFormElement(array &$form, FormStateInterface $form_state, $key, $element) { + $cnt = $form_state->get($key . '_' . $element . '_cnt'); + if ($cnt > 1) { + $form_state->set($key . '_' . $element . '_cnt', $cnt - 1); + } + $form_state->setRebuild(); + } + + /** + * Adds a Build Entity Fieldset. + */ + public function addBuildEntityFieldset(array &$form, FormStateInterface $form_state) { + $this->addFormElement($form, $form_state, 'build', 'entity'); + } + + /** + * Removes a Build Entity Fieldset Url. + */ + public function removeBuildEntityFieldset(array &$form, FormStateInterface $form_state) { + $this->removeFormElement($form, $form_state, 'build', 'entity'); + } + + /** + * Ajax callback for Build Entity Fieldsets that returns the correct fieldset. + */ + public function buildEntityCallback(array &$form, FormStateInterface $form_state) { + return $form['build_entity_types']; + } + + /** + * Ajax callback for build entities that returns the correct bundles. + */ + public function buildEntityBundleCallback(array &$form, FormStateInterface $form_state) { + // Determine what element triggered this callback. + $triggering_element = $form_state->getTriggeringElement(); + $wrapper_elements = explode('-', $triggering_element['#ajax']['wrapper']); + $element_id = intval(array_pop($wrapper_elements)); + + $form['build_entity_types'][$element_id]['#open'] = TRUE; + return $form['build_entity_types'][$element_id]; + } + + /** + * Renders AJAX fieldsets for Entity selection. + */ + public function addEntityAjaxFieldset(array &$form, FormStateInterface $form_state) { + $entity_cnt = $form_state->get('build_entity_cnt'); + + /** @var \Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface $entity */ + $entity = $this->entity; + + // If there is no count yet, then this is the first time rendering. + if ($entity_cnt === NULL) { + $entities = $entity->getBuildEntities(); + $entity_cnt = !empty($entities) ? count($entities) - 1 : 0; + if ($entity_cnt === 0) { + $entity_cnt = 1; + } + $form_state->set('build_entity_cnt', $entity_cnt); + } + + $form['build_entity_types'] = [ + '#type' => 'fieldset', + '#title' => $this->t("Gatsby Build Entities"), + '#prefix' => '<div id="build-entity-fieldset-wrapper">', + '#suffix' => '</div>', + ]; + $form['build_entity_types']['description'] = [ + '#markup' => $this->t("Select which entities should trigger builds/previews for this endpoint."), + '#weight' => -100, + ]; + + for ($i = 0; $i < $entity_cnt; $i++) { + // Get the default entity type. + $entity_type = !empty($entities[$i]['entity_type']) ? + $entities[$i]['entity_type'] : ""; + + // Check if there was an entity type set in the form state. + $form_values = $form_state->getValues(); + if (!empty($form_values['build_entity_types'][$i]['entity_type'])) { + $entity_type = $form_values['build_entity_types'][$i]['entity_type']; + } + + $content_entity_types = $this->getContentEntityTypes(); + + $form['build_entity_types'][$i] = [ + '#type' => 'details', + '#title' => $this->t("Gatsby Build Entity #@cnt @entity", [ + '@cnt' => $i + 1, + '@entity' => !empty($entity_type) ? "(" . $content_entity_types[$entity_type] . ")" : "", + ]), + '#prefix' => '<div id="build-entity-fieldset-' . $i . '">', + '#suffix' => '</div>', + '#open' => empty($entity_type) ? TRUE : FALSE, + ]; + + $entity_types = ['' => $this->t("-- Select Entity Type --")] + $content_entity_types; + + $form['build_entity_types'][$i]['entity_type'] = [ + '#type' => 'select', + '#options' => $entity_types, + '#title' => $this->t("Entity Type"), + '#default_value' => $entity_type, + ]; + + $form['build_entity_types'][$i]['entity_type']['#ajax'] = [ + 'callback' => '::buildEntityBundleCallback', + 'wrapper' => 'build-entity-fieldset-' . $i, + 'event' => 'change', + 'progress' => [ + 'type' => 'throbber', + 'message' => $this->t('Loading bundles...'), + ], + ]; + + if ($entity_type) { + $entity_bundles = !empty($entities[$i]['entity_bundles']) ? + $entities[$i]['entity_bundles'] : []; + $include_entities = !empty($entities[$i]['include_entities']) ? + $entities[$i]['include_entities'] : []; + + $form['build_entity_types'][$i]['entity_bundles'] = [ + '#type' => 'checkboxes', + '#options' => $this->getContentEntityBundles($entity_type), + '#title' => $this->t("Entity Bundle(s)"), + '#default_value' => $entity_bundles, + ]; + + if ($entity_type == 'node') { + $build_published = !empty($entities[$i]['build_published']) ? + $entities[$i]['build_published'] : FALSE; + $form['build_entity_types'][$i]['build_published'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Only trigger builds for published content'), + '#description' => $this->t('Depending on your content workflow, you may only + want builds to be triggered for published content. By checking this box + only published content will trigger a build.'), + '#default_value' => $build_published, + '#weight' => 3, + ]; + } + + $included_entities_description = $this->t("Select which entities should not trigger builds/previews but should be + included in builds/previews. This is commonly used for entities such as media, files, or paragraphs where you don't + want these items to trigger a new build, but you do want to make sure they are sent to Gatsby if they are + attached to an entity that triggers a build."); + $form['build_entity_types'][$i]['include_entities'] = [ + '#type' => 'checkboxes', + '#options' => $content_entity_types, + '#title' => $this->t("Include Entities"), + '#description' => $included_entities_description, + '#default_value' => $include_entities, + '#weight' => 4, + ]; + } + } + $form['build_entity_types']['actions'] = [ + '#type' => 'actions', + ]; + $form['build_entity_types']['actions']['add_build_entity'] = [ + '#type' => 'submit', + '#value' => $this->t('Add Additional Build Entity'), + '#submit' => ['::addBuildEntityFieldset'], + '#ajax' => [ + 'callback' => '::buildEntityCallback', + 'wrapper' => 'build-entity-fieldset-wrapper', + ], + ]; + if ($entity_cnt > 1) { + $form['build_entity_types']['actions']['remove_build_entity'] = [ + '#type' => 'submit', + '#value' => $this->t('Remove Build Entity'), + '#submit' => ['::removeBuildEntityFieldset'], + '#ajax' => [ + 'callback' => '::buildEntityCallback', + 'wrapper' => 'build-entity-fieldset-wrapper', + ], + ]; + } + } + + /** + * Gets a list of all the defined content entities in the system. + * + * @return array + * An array of content entities definitions. + */ + private function getContentEntityTypes() { + $content_entity_types = []; + $allEntityTypes = $this->entityTypeManager->getDefinitions(); + + foreach ($allEntityTypes as $entity_type_id => $entity_type) { + // Add all content entity types but not the gatsby log entity provided + // by the gatsby_fastbuilds module or the gatsby_endpoint entity provided + // by this module. + if ( + $entity_type instanceof ContentEntityTypeInterface && + !in_array($entity_type_id, ['gatsby_log_entity', 'gatsby_endpoint']) + ) { + + $content_entity_types[$entity_type_id] = $entity_type->getLabel(); + } + } + return $content_entity_types; + } + + /** + * Gets a list of all the defined bundles for a content entity type. + * + * @return array + * An array of bundles for a specific content entity type. + */ + private function getContentEntityBundles($entity_type) { + $bundle_definitions = $this->entityTypeBundleInfo->getBundleInfo($entity_type); + + $bundles = []; + foreach ($bundle_definitions as $bundle => $bundle_definition) { + $bundles[$bundle] = $bundle_definition['label']; + } + + return $bundles; + } +} diff --git a/src/GatsbyEndpointAccessControlHandler.php b/src/GatsbyEndpointAccessControlHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..275c2463441710d7974cdacf255bec6e8c744433 --- /dev/null +++ b/src/GatsbyEndpointAccessControlHandler.php @@ -0,0 +1,42 @@ +<?php + +namespace Drupal\gatsby_endpoints; + +use Drupal\Core\Access\AccessResult; +use Drupal\Core\Entity\EntityAccessControlHandler; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Session\AccountInterface; + +/** + * Defines the access control handler for the gatsby endpoint entity type. + */ +class GatsbyEndpointAccessControlHandler extends EntityAccessControlHandler { + + /** + * {@inheritdoc} + */ + protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { + + switch ($operation) { + case 'view': + return AccessResult::allowedIfHasPermission($account, 'view gatsby endpoint'); + + case 'update': + return AccessResult::allowedIfHasPermissions($account, ['edit gatsby endpoint', 'administer gatsby endpoint'], 'OR'); + + case 'delete': + return AccessResult::allowedIfHasPermissions($account, ['delete gatsby endpoint', 'administer gatsby endpoint'], 'OR'); + + default: + // No opinion. + return AccessResult::neutral(); + } + } + + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return AccessResult::allowedIfHasPermissions($account, ['create gatsby endpoint', 'administer gatsby endpoint'], 'OR'); + } +} diff --git a/src/GatsbyEndpointGenerator.php b/src/GatsbyEndpointGenerator.php index 9ba54384dbd5da04f2bb316beffd70119e89d854..029c3999592a2c13dd6e48be4c603e579e0ae437 100644 --- a/src/GatsbyEndpointGenerator.php +++ b/src/GatsbyEndpointGenerator.php @@ -5,7 +5,7 @@ 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; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; /** * Class GatsbyEndpointGenerator. @@ -31,8 +31,10 @@ class GatsbyEndpointGenerator { /** * Constructs a new GatsbyEndpointManager object. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, - EntityFieldManagerInterface $entity_field_manager) { + public function __construct( + EntityTypeManagerInterface $entity_type_manager, + EntityFieldManagerInterface $entity_field_manager + ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; } @@ -41,7 +43,7 @@ class GatsbyEndpointGenerator { * Generates JSON:API links for a specific Gatsby Endpoint. */ public function getEndpointLinks(GatsbyEndpointInterface $endpoint) { - $build_types = $endpoint->getBuildEntityTypes(); + $build_types = $endpoint->getBuildEntities(); $links = []; foreach ($build_types as $build_type) { @@ -53,13 +55,15 @@ class GatsbyEndpointGenerator { // Check if this has bundles. foreach ($build_type['entity_bundles'] as $bundle_id => $bundle_label) { - if ($bundle_label === $bundle_id) { + if ($bundle_label === $bundle_id && $this->hasGatsbyEndpointReferenceField($build_type['entity_type'], $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; } } + // Add the link to get the info for the Gatsby Endpoint entity. + $links['gatsby_endpoint'] = 'gatsby_endpoint/' . $endpoint->bundle() . '?filter[drupal_internal__id]=' . $endpoint->id(); } return $links; @@ -69,8 +73,12 @@ class GatsbyEndpointGenerator { * 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); + $url_params = $this->loadUrlFiltersAndIncludes( + $entity_type, + $bundle, + $endpoint, + $include_types + ); $param_string = ''; @@ -86,6 +94,21 @@ class GatsbyEndpointGenerator { return $param_string ? '?' . $param_string : $param_string; } + /** + * Determines if this entity type and bundle have a Gatsby Reference field. + */ + private function hasGatsbyEndpointReferenceField($entity_type, $bundle) { + $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle); + + foreach ($definitions as $field) { + $field_type = $field->getType(); + if ($field_type == 'gatsby_endpoint_reference') { + return TRUE; + } + } + return FALSE; + } + /** * Gets the includes and filter parameters for a JSON:API url. */ @@ -112,8 +135,7 @@ class GatsbyEndpointGenerator { $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)) { + } elseif (in_array($field_type, $core_reference_fields)) { // Check if this field references an included entity type. if (in_array($field_type, $include_types)) { @@ -122,8 +144,7 @@ class GatsbyEndpointGenerator { } $params['include'][] = $field_name; } - } - elseif (in_array($field_type, [ + } elseif (in_array($field_type, [ 'entity_reference', 'entity_reference_revisions', ])) { @@ -142,11 +163,13 @@ class GatsbyEndpointGenerator { $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], + $reference_params = $this->loadUrlFiltersAndIncludes( + $reference_type[1], $target_bundle, $endpoint, $include_types, - $field_name); + $field_name + ); if (!empty($reference_params['include'])) { $params['include'] = array_merge($params['include'], $reference_params['include']); @@ -159,5 +182,4 @@ class GatsbyEndpointGenerator { return $params; } - } diff --git a/src/GatsbyEndpointInterface.php b/src/GatsbyEndpointInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..511934a78e2a76466d01b90c7b361805dbc28883 --- /dev/null +++ b/src/GatsbyEndpointInterface.php @@ -0,0 +1,231 @@ +<?php + +namespace Drupal\gatsby_endpoints; + +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\user\EntityOwnerInterface; +use Drupal\Core\Entity\EntityChangedInterface; +use Drupal\user\UserInterface; + +/** + * Provides an interface defining a gatsby endpoint entity type. + */ +interface GatsbyEndpointInterface extends ContentEntityInterface, EntityOwnerInterface, EntityChangedInterface { + + /** + * Gets the Gatsby Endpoint title. + * + * @return string + * Title of the Gatsby Endpoint. + */ + public function getTitle(); + + /** + * Sets the Gatsby Endpoint title. + * + * @param string $title + * The Gatsby Endpoint title. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called Gatsby Endpoint entity. + */ + public function setTitle($title); + + /** + * Gets the build trigger for the Gatsby Endpoint. + * + * @return string + * Build trigger of the Gatsby Endpoint. + */ + public function getBuildTrigger(); + + /** + * Sets the build trigger for the Gatsby Endpoint. + * + * @param string $build_trigger + * The Build Trigger option for the Gatsby Endpoint. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called Gatsby Endpoint entity. + */ + public function setBuildTrigger($build_trigger); + + /** + * Gets the gatsby endpoint creation timestamp. + * + * @return int + * Creation timestamp of the gatsby endpoint. + */ + public function getCreatedTime(); + + /** + * Sets the gatsby endpoint creation timestamp. + * + * @param int $timestamp + * The gatsby endpoint creation timestamp. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setCreatedTime($timestamp); + + /** + * Gets the owner of the user that owns Gatsby Endpoint. + * + * @return \Drupal\user\UserInterface + * The user entity. + */ + public function getOwner(); + + /** + * Sets the owner of the user that will own the Gatsby Endpoint. + * + * @param \Drupal\user\UserInterface $account + * The user entity. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setOwner(UserInterface $account); + + /** + * Gets the owner id of the user that owns the Gatsby Endpoint. + * + * @return int + * The user id. + */ + public function getOwnerId(); + + /** + * Sets the owner id for the user that will own the Gatsby Endpoint. + * + * @param int $uid + * The user id. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setOwnerId($uid); + + /** + * Gets the urls for a specific build type for the Gatsby Endpoint. + * + * @param string $key + * The build type key (preview or build). + * + * @return array + * The corresponding build type urls. + */ + public function getUrls($key); + + /** + * Gets the preview urls for the Gatsby Endpoint. + * + * @return array + * The preview urls. + */ + public function getPreviewUrls(); + + /** + * Sets the preview urls for the Gatsby Endpoint. + * + * @param array $preview_urls + * The preview urls. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setPreviewUrls(array $preview_urls); + + /** + * Gets the build urls for the Gatsby Endpoint. + * + * @return array + * The build urls. + */ + public function getBuildUrls(); + + /** + * Sets the build urls for the Gatsby Endpoint. + * + * @param array $build_urls + * The build urls. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setBuildUrls(array $build_urls); + + /** + * Gets the Content Sync url for the Gatsby Endpoint. + * + * @return string + * The content sync url. + */ + public function getContentSyncUrl(); + + /** + * Sets the content sync url for the Gatsby Endpoint. + * + * @param string $contentsync_url + * The content sync url. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setContentSyncUrl($contentsync_url); + + /** + * Gets the build entities for the Gatsby Endpoint. + * + * @return object + * An array containing the build entity configuration. + */ + public function getBuildEntities(); + + /** + * Sets the build entities for the Gatsby Endpoint. + * + * @param array $build_entities + * The build entities configuration. + * + * @return \Drupal\gatsby_endpoints\GatsbyEndpointInterface + * The called gatsby endpoint entity. + */ + public function setBuildEntities(array $build_entities); + + /** + * Determines if a entity type and bundle will trigger Gatsby webhooks. + * + * @param string $entity_type + * The entity type to check for. + * @param string $entity_bundle + * The bundle to check for. + * + * @return bool + * Whether the entity type and bundle is selected as a build entity. + */ + public function isBuildEntitySelected($entity_type, $entity_bundle); + + /** + * Gets the build entity type. + * + * @param string $entity_type + * The entity type to search for. + * + * @return array + * An array containing the included build config for this entity type. + */ + public function getBuildEntityType($entity_type); + + /** + * Gets the included entity for a build type. + * + * @param array $build_type + * The build type. + * + * @return array + * An array containing the included entity types. + */ + public function getIncludedEntityTypes($build_type); +} diff --git a/src/GatsbyEndpointListBuilder.php b/src/GatsbyEndpointListBuilder.php index 437ffe6c4cf722087117c31e521a62f2f561376e..cba3870917d49a34e24517a963d48c4ee59f7e6d 100644 --- a/src/GatsbyEndpointListBuilder.php +++ b/src/GatsbyEndpointListBuilder.php @@ -2,27 +2,32 @@ namespace Drupal\gatsby_endpoints; -use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\EntityListBuilder; +use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\Core\Link; -use Drupal\Core\Url; -use Drupal\gatsby_endpoints\Entity\GatsbyEndpoint; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Routing\RedirectDestinationInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; /** - * Provides a listing of Gatsby endpoint entities. + * Provides a list controller for the gatsby endpoint entity type. */ -class GatsbyEndpointListBuilder extends ConfigEntityListBuilder { +class GatsbyEndpointListBuilder extends EntityListBuilder { + + /** + * The date formatter service. + * + * @var \Drupal\Core\Datetime\DateFormatterInterface + */ + protected $dateFormatter; /** - * The current request object. + * The redirect destination service. * - * @var \Symfony\Component\HttpFoundation\Request + * @var \Drupal\Core\Routing\RedirectDestinationInterface */ - protected $request; + protected $redirectDestination; /** * Constructs a new GatsbyEndpointListBuilder object. @@ -31,12 +36,15 @@ class GatsbyEndpointListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. - * @param \Symfony\Component\HttpFoundation\Request $request - * Current request object. + * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter + * The date formatter service. + * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination + * The redirect destination service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, Request $request) { + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) { parent::__construct($entity_type, $storage); - $this->request = $request; + $this->dateFormatter = $date_formatter; + $this->redirectDestination = $redirect_destination; } /** @@ -46,18 +54,35 @@ class GatsbyEndpointListBuilder extends ConfigEntityListBuilder { return new static( $entity_type, $container->get('entity_type.manager')->getStorage($entity_type->id()), - $container->get('request_stack')->getCurrentRequest() + $container->get('date.formatter'), + $container->get('redirect.destination') ); } + /** + * {@inheritdoc} + */ + public function render() { + $build['table'] = parent::render(); + + $total = $this->getStorage() + ->getQuery() + ->count() + ->execute(); + + $build['summary']['#markup'] = $this->t('Total Gatsby Endpoints: @total', ['@total' => $total]); + return $build; + } + /** * {@inheritdoc} */ public function buildHeader() { - $header['label'] = $this->t('Endpoint Name'); - $header['plugin'] = $this->t('Type'); - $header['id'] = $this->t('Machine name'); - $header['url'] = $this->t('Endpoint URL'); + $header['id'] = $this->t('ID'); + $header['title'] = $this->t('Title'); + $header['uid'] = $this->t('Author'); + $header['created'] = $this->t('Created'); + $header['changed'] = $this->t('Updated'); return $header + parent::buildHeader(); } @@ -65,17 +90,27 @@ class GatsbyEndpointListBuilder extends ConfigEntityListBuilder { * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { - if (!($entity instanceof GatsbyEndpoint)) { - return parent::buildRow($entity); - } - - $url = $this->request->getSchemeAndHttpHost() . '/gatsby/' . $entity->id(); - - $row['label'] = $entity->label(); - $row['plugin'] = $entity->getPlugin()->getPluginDefinition()['label']; + /* @var $entity \Drupal\gatsby_endpoints\GatsbyEndpointInterface */ $row['id'] = $entity->id(); - $row['url'] = Link::fromTextAndUrl($url, Url::fromUri($url))->toString(); + $row['title'] = $entity->toLink(); + $row['uid']['data'] = [ + '#theme' => 'username', + '#account' => $entity->getOwner(), + ]; + $row['created'] = $this->dateFormatter->format($entity->getCreatedTime()); + $row['changed'] = $this->dateFormatter->format($entity->getChangedTime()); return $row + parent::buildRow($entity); } + /** + * {@inheritdoc} + */ + protected function getDefaultOperations(EntityInterface $entity) { + $operations = parent::getDefaultOperations($entity); + $destination = $this->redirectDestination->getAsArray(); + foreach ($operations as $key => $operation) { + $operations[$key]['query'] = $destination; + } + return $operations; + } } diff --git a/src/GatsbyEndpointManager.php b/src/GatsbyEndpointManager.php index 12593bbd4edb9b11bc676b267d547e4fbdbcf572..f6663406b186364e643b0af2c0d711570d1c7c27 100644 --- a/src/GatsbyEndpointManager.php +++ b/src/GatsbyEndpointManager.php @@ -5,7 +5,6 @@ namespace Drupal\gatsby_endpoints; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; -use Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface; /** * Provides a service to manage Gatsby endpoints. @@ -29,8 +28,10 @@ class GatsbyEndpointManager { /** * Constructs a new GatsbyEndpointManager object. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, - EntityFieldManagerInterface $entity_field_manager) { + public function __construct( + EntityTypeManagerInterface $entity_type_manager, + EntityFieldManagerInterface $entity_field_manager + ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; } @@ -50,7 +51,6 @@ class GatsbyEndpointManager { public function getEndpoints() { $query = $this->entityTypeManager->getStorage('gatsby_endpoint'); $endpoint_ids = $query->getQuery() - ->sort('weight') ->execute(); $endpoints = []; @@ -68,7 +68,7 @@ class GatsbyEndpointManager { */ public function checkEntity(GatsbyEndpointInterface $endpoint, ContentEntityInterface $entity, $op) { // Check if this entity is selected in the build types. - if (!$this->checkBuildEntityTypeAndBundle($endpoint->getBuildEntityTypes(), $entity->getEntityTypeId(), $entity->bundle())) { + if (!$this->checkBuildEntityTypeAndBundle($endpoint->getBuildEntities(), $entity->getEntityTypeId(), $entity->bundle())) { return FALSE; } @@ -82,7 +82,7 @@ class GatsbyEndpointManager { // If this entity is selected, the endpoint needs to track the entity. $in_selected = $this->checkEndpointValues( $entity->get($reference_field)->getValue(), - $endpoint->id() + (int) $endpoint->id() ); if ($in_selected) { return $op; @@ -93,7 +93,7 @@ class GatsbyEndpointManager { if ($op == 'update') { $in_original = $this->checkEndpointValues( $entity->original->get($reference_field)->getValue(), - $endpoint->id() + (int) $endpoint->id() ); if ($in_original) { @@ -118,7 +118,6 @@ class GatsbyEndpointManager { if ($field_type == 'gatsby_endpoint_reference' && !empty($field_name)) { return $field_name; } - } return FALSE; @@ -140,8 +139,7 @@ class GatsbyEndpointManager { if ($ref_field && !$entity->get($ref_field)->isEmpty() && $endpoint = $entity->{$ref_field}->entity) { return $this->getFirstPreviewUrl($endpoint); - } - else { + } else { $endpoints = $this->getEndpoints(); foreach ($endpoints as $endpoint) { diff --git a/src/GatsbyEndpointTrigger.php b/src/GatsbyEndpointTrigger.php index aebfafec4bcc8e746aeca0a5e7e6edeb886ff99c..feb5f72f4ca7eae2386cd26b4f7de24d22e410ab 100644 --- a/src/GatsbyEndpointTrigger.php +++ b/src/GatsbyEndpointTrigger.php @@ -8,8 +8,8 @@ use Drupal\node\NodeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityRepository; use Drupal\Core\Logger\LoggerChannelFactoryInterface; -use Drupal\gatsby_endpoints\Entity\GatsbyEndpointInterface; -use Drupal\gatsby_instantpreview\GatsbyInstantPreview; +use Drupal\gatsby_endpoints\GatsbyEndpointInterface; +use Drupal\gatsby\GatsbyPreview; /** * Class GatsbyEndpointTrigger. @@ -47,25 +47,27 @@ class GatsbyEndpointTrigger { private $entityRepository; /** - * Drupal\gatsby_instantpreview\GatsbyInstantPreview definition. + * Drupal\gatsby\GatsbyPreview definition. * - * @var \Drupal\gatsby_instantpreview\GatsbyInstantPreview + * @var \Drupal\gatsby\GatsbyPreview */ - private $gatsbyInstantPreview; + private $gatsbyPreview; /** * Constructs a new GatsbyPreview object. */ - public function __construct(ClientInterface $http_client, - EntityTypeManagerInterface $entity_type_manager, - LoggerChannelFactoryInterface $logger, - EntityRepository $entity_repository, - GatsbyInstantPreview $gatsby_instant_preview) { + public function __construct( + ClientInterface $http_client, + EntityTypeManagerInterface $entity_type_manager, + LoggerChannelFactoryInterface $logger, + EntityRepository $entity_repository, + GatsbyPreview $gatsby_preview + ) { $this->httpClient = $http_client; $this->entityTypeManager = $entity_type_manager; $this->logger = $logger->get('gatsby'); $this->entityRepository = $entity_repository; - $this->gatsbyInstantPreview = $gatsby_instant_preview; + $this->gatsbyPreview = $gatsby_preview; } /** @@ -75,48 +77,18 @@ class GatsbyEndpointTrigger { * being sent to the preview or incremental builds servers if mulutiple * Drupal entities are update/inserted/deleted in a single request. */ - public function gatsbyPrepareData(GatsbyEndpointInterface $endpoint, + public function gatsbyPrepareData( + GatsbyEndpointInterface $endpoint, ContentEntityInterface $entity = NULL, string $action = 'update' ) { - $json = $this->gatsbyInstantPreview->getJson($entity); - if (!$json) { - return; - } - $json['id'] = $entity->uuid(); - $json['action'] = $action; $build_type = $endpoint->getBuildEntityType($entity->getEntityTypeId()); - // If there is a secret key we add it to the JSON. - $secret = $this->getSecretKey($endpoint); - if ($secret) { - $json['secret'] = $secret; - } - - // Build the entity relationships to send along with the data. - if (!empty($json['data']['relationships'])) { - // Generate JSON for all related entities to send to Gatsby. - $entity_data = []; - $included_types = $endpoint->getIncludedEntityTypes($build_type); - $this->gatsbyInstantPreview->buildRelationshipJson($json['data']['relationships'], $entity_data, $included_types); - - if (!empty($entity_data)) { - // Remove the uuid keys from the array. - $entity_data = array_values($entity_data); - - $original_data = $json['data']; - $entity_data[] = $original_data; - $json['data'] = $entity_data; - } - } - - $preview_path = "/__refresh"; $preview_urls = $endpoint->getPreviewUrls(); if (!empty($preview_urls) && !empty($preview_urls['preview_url'])) { foreach ($preview_urls['preview_url'] as $preview_url) { - $preview_json = $this->gatsbyInstantPreview->bundleData('preview', $preview_url, $json); - $this->gatsbyInstantPreview->updateData('preview', $preview_url, $preview_json, $preview_path); + $this->gatsbyPreview->updateData('preview', $preview_url); } } @@ -127,7 +99,7 @@ class GatsbyEndpointTrigger { // Verify build URLs are set. $build_urls = $endpoint->getBuildUrls(); - if (empty($build_urls) || empty($build_urls['build_url'])) { + if (empty($build_urls)) { return; } @@ -139,16 +111,16 @@ class GatsbyEndpointTrigger { } } - foreach ($build_urls['build_url'] as $build_url) { - $build_json = $this->gatsbyInstantPreview->bundleData('incrementalbuild', $build_url, $json); - $this->gatsbyInstantPreview->updateData('incrementalbuild', $build_url, $build_json); - } + //foreach ($build_urls['build_url'] as $build_url) { + $this->gatsbyPreview->updateData('incrementalbuild', $build_urls); + //} } /** * Triggers the refreshing of Gatsby preview and incremental builds. */ - public function gatsbyPrepareDelete(GatsbyEndpointInterface $endpoint, + public function gatsbyPrepareDelete( + GatsbyEndpointInterface $endpoint, ContentEntityInterface $entity = NULL ) { @@ -157,24 +129,17 @@ class GatsbyEndpointTrigger { 'action' => 'delete', ]; - // If there is a secret key we add it to the JSON. - $secret = $this->getSecretKey($endpoint); - if ($secret) { - $json['secret'] = $secret; - } - - $preview_path = "/__refresh"; $preview_urls = $endpoint->getPreviewUrls(); if (!empty($preview_urls) && !empty($preview_urls['preview_url'])) { foreach ($preview_urls['preview_url'] as $preview_url) { - $this->gatsbyInstantPreview->updateData('preview', $preview_url, $json, $preview_path); + $this->gatsbyPreview->updateData('preview', $preview_url, $json); } } $build_urls = $endpoint->getBuildUrls(); if (!empty($build_urls) && !empty($build_urls['build_url'])) { foreach ($build_urls['build_url'] as $build_url) { - $this->gatsbyInstantPreview->updateData('incrementalbuild', $build_url, $json); + $this->gatsbyPreview->updateData('incrementalbuild', $build_url, $json); } } } @@ -183,7 +148,7 @@ class GatsbyEndpointTrigger { * Triggers the refreshing of Gatsby preview and incremental builds. */ public function gatsbyUpdate() { - $this->gatsbyInstantPreview->gatsbyUpdate(); + $this->gatsbyPreview->gatsbyUpdate(); } /** @@ -193,22 +158,9 @@ class GatsbyEndpointTrigger { $build_urls = $endpoint->getBuildUrls(); if (!empty($build_urls) && !empty($build_urls['build_url'])) { foreach ($build_urls['build_url'] as $build_url) { - $this->gatsbyInstantPreview->triggerRefresh($build_url); + $this->gatsbyPreview->triggerRefresh($build_url); } } } - /** - * Tries to get the secret key for a Gatsby Endpoint if it exists. - */ - private function getSecretKey(GatsbyEndpointInterface $endpoint) { - $settings = $endpoint->getSettings(); - - if (!empty($settings['secret_key'])) { - return $settings['secret_key']; - } - - return FALSE; - } - } diff --git a/src/GatsbyEndpointTypeListBuilder.php b/src/GatsbyEndpointTypeListBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..a851930609f02c2cf272ac18d2533adbad617726 --- /dev/null +++ b/src/GatsbyEndpointTypeListBuilder.php @@ -0,0 +1,50 @@ +<?php + +namespace Drupal\gatsby_endpoints; + +use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Url; + +/** + * Defines a class to build a listing of gatsby endpoint type entities. + * + * @see \Drupal\gatsby_endpoints\Entity\GatsbyEndpointType + */ +class GatsbyEndpointTypeListBuilder extends ConfigEntityListBuilder { + + /** + * {@inheritdoc} + */ + public function buildHeader() { + $header['title'] = $this->t('Label'); + + return $header + parent::buildHeader(); + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity) { + $row['title'] = [ + 'data' => $entity->label(), + 'class' => ['menu-label'], + ]; + + return $row + parent::buildRow($entity); + } + + /** + * {@inheritdoc} + */ + public function render() { + $build = parent::render(); + + $build['table']['#empty'] = $this->t( + 'No Gatsby Endpoint types available. <a href=":link">Add Gatsby Endpoint type</a>.', + [':link' => Url::fromRoute('entity.gatsby_endpoint_type.add_form')->toString()] + ); + + return $build; + } +} diff --git a/src/Plugin/Field/FieldFormatter/GatsbyEndpointsFormatter.php b/src/Plugin/Field/FieldFormatter/GatsbyEndpointsFormatter.php index f56752c372981d3a5213d700aa27dc772c3065a5..01ebd2d9c4450a0a1177de6b73c8787309e443d4 100644 --- a/src/Plugin/Field/FieldFormatter/GatsbyEndpointsFormatter.php +++ b/src/Plugin/Field/FieldFormatter/GatsbyEndpointsFormatter.php @@ -17,5 +17,4 @@ use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceLabelFormatter; * ) */ class GatsbyEndpointsFormatter extends EntityReferenceLabelFormatter { - } diff --git a/src/Plugin/Field/FieldType/GatsbyEndpointsReferenceField.php b/src/Plugin/Field/FieldType/GatsbyEndpointsReferenceField.php index 768e206ce82eb1c168333fa71456a309b8c1ed97..7cd340733347086c99ac05311765aadc335891e9 100644 --- a/src/Plugin/Field/FieldType/GatsbyEndpointsReferenceField.php +++ b/src/Plugin/Field/FieldType/GatsbyEndpointsReferenceField.php @@ -49,5 +49,4 @@ class GatsbyEndpointsReferenceField extends EntityReferenceItem { public function fieldSettingsForm(array $form, FormStateInterface $form_state) { return []; } - } diff --git a/src/Plugin/Field/FieldWidget/GatsbyEndpointsAutocompleteWidget.php b/src/Plugin/Field/FieldWidget/GatsbyEndpointsAutocompleteWidget.php index 30f1fa467b7e2164ce26751e87eaf60f604c1019..3c25a1e7c38ade6a555377c3f1b199adc63f5cf8 100644 --- a/src/Plugin/Field/FieldWidget/GatsbyEndpointsAutocompleteWidget.php +++ b/src/Plugin/Field/FieldWidget/GatsbyEndpointsAutocompleteWidget.php @@ -17,5 +17,4 @@ use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget * ) */ class GatsbyEndpointsAutocompleteWidget extends EntityReferenceAutocompleteWidget { - } diff --git a/src/Plugin/Field/FieldWidget/GatsbyEndpointsSelectWidget.php b/src/Plugin/Field/FieldWidget/GatsbyEndpointsSelectWidget.php index 36c2c2cad5107fda6ab2a762a88c00829fef11de..8c950dd5bac9bad50ed5d7a08c4a198602ffcd9a 100644 --- a/src/Plugin/Field/FieldWidget/GatsbyEndpointsSelectWidget.php +++ b/src/Plugin/Field/FieldWidget/GatsbyEndpointsSelectWidget.php @@ -18,5 +18,4 @@ use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget; * ) */ class GatsbyEndpointsSelectWidget extends OptionsSelectWidget { - } diff --git a/templates/gatsby-endpoint.html.twig b/templates/gatsby-endpoint.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..4176689de58b09288e5d5471df86f76dc06f90ed --- /dev/null +++ b/templates/gatsby-endpoint.html.twig @@ -0,0 +1,28 @@ +{# +/** + * @file + * Default theme implementation to present a gatsby endpoint entity. + * + * This template is used when viewing a registered gatsby endpoint's page, + * e.g., /admin/content/gatsby-endpoint)/123. 123 being the gatsby endpoint's ID. + * + * Available variables: + * - content: A list of content items. Use 'content' to print all content, or + * print a subset such as 'content.title'. + * - attributes: HTML attributes for the container element. + * + * @see template_preprocess_gatsby_endpoint() + */ +#} +<article{{ attributes }}> + <h2>Create your Gatsby Site</h2> + <a target="blank" class="button button--action button--primary" href="https://www.gatsbyjs.com/dashboard/deploynow?url=https://github.com/smthomas/siteforge-example">Connect to Gatsby Cloud</a> + <p> + Click here to create your Gatsby site on Gatsby Cloud. For now you will + need to manually enter your environment variables and then copy your + build/preview hooks from Gatsby Cloud. + </p> + {% if content %} + {{- content -}} + {% endif %} +</article>