From 8af1b3c612b802c4851c0532c66c320f47c631b9 Mon Sep 17 00:00:00 2001 From: Stuart Rowlands Date: Tue, 10 Mar 2020 08:44:23 +1300 Subject: [PATCH] Repository cleanup. --- config/install/quant.settings.yml | 3 + modules/quant_api/quant_api.info.yml | 9 + modules/quant_api/quant_api.links.menu.yml | 6 + modules/quant_api/quant_api.routing.yml | 9 + modules/quant_api/quant_api.services.yml | 13 + modules/quant_api/src/Client/QuantClient.php | 34 +++ .../src/Client/QuantClientInterface.php | 33 +++ .../src/EventSubscriber/QuantApi.php | 52 ++++ modules/quant_api/src/Form/SettingsForm.php | 80 ++++++ quant.info.yml | 6 + quant.links.menu.yml | 13 + quant.module | 22 ++ quant.permissions.yml | 6 + quant.routing.yml | 15 ++ quant.services.yml | 29 +++ src/Annotation/Metadata.php | 31 +++ src/EntityRenderer.php | 244 ++++++++++++++++++ src/EntityRendererInterface.php | 23 ++ src/Event/NodeInsertEvent.php | 41 +++ src/Event/QuantEvent.php | 95 +++++++ src/EventSubscriber/NodeInsertSubscriber.php | 64 +++++ src/EventSubscriber/QuantFilesystem.php | 43 +++ src/Form/ConfigForm.php | 84 ++++++ src/Form/SeedForm.php | 140 ++++++++++ src/Plugin/MetadataBase.php | 22 ++ src/Plugin/MetadataInterface.php | 29 +++ src/Plugin/Quant/Metadata/Published.php | 56 ++++ .../Quant/Metadata/PublishedRevision.php | 62 +++++ .../Quant/Metadata/TransitionRevision.php | 32 +++ src/Plugin/Quant/Metadata/Transitions.php | 81 ++++++ src/Plugin/QuantMetadataManager.php | 29 +++ src/QuantStaticTrait.php | 50 ++++ src/Seed.php | 37 +++ 33 files changed, 1493 insertions(+) create mode 100644 config/install/quant.settings.yml create mode 100644 modules/quant_api/quant_api.info.yml create mode 100644 modules/quant_api/quant_api.links.menu.yml create mode 100644 modules/quant_api/quant_api.routing.yml create mode 100644 modules/quant_api/quant_api.services.yml create mode 100644 modules/quant_api/src/Client/QuantClient.php create mode 100644 modules/quant_api/src/Client/QuantClientInterface.php create mode 100644 modules/quant_api/src/EventSubscriber/QuantApi.php create mode 100644 modules/quant_api/src/Form/SettingsForm.php create mode 100644 quant.info.yml create mode 100644 quant.links.menu.yml create mode 100644 quant.module create mode 100644 quant.permissions.yml create mode 100644 quant.routing.yml create mode 100644 quant.services.yml create mode 100644 src/Annotation/Metadata.php create mode 100644 src/EntityRenderer.php create mode 100644 src/EntityRendererInterface.php create mode 100644 src/Event/NodeInsertEvent.php create mode 100644 src/Event/QuantEvent.php create mode 100644 src/EventSubscriber/NodeInsertSubscriber.php create mode 100644 src/EventSubscriber/QuantFilesystem.php create mode 100644 src/Form/ConfigForm.php create mode 100644 src/Form/SeedForm.php create mode 100644 src/Plugin/MetadataBase.php create mode 100644 src/Plugin/MetadataInterface.php create mode 100644 src/Plugin/Quant/Metadata/Published.php create mode 100644 src/Plugin/Quant/Metadata/PublishedRevision.php create mode 100644 src/Plugin/Quant/Metadata/TransitionRevision.php create mode 100644 src/Plugin/Quant/Metadata/Transitions.php create mode 100644 src/Plugin/QuantMetadataManager.php create mode 100644 src/QuantStaticTrait.php create mode 100644 src/Seed.php diff --git a/config/install/quant.settings.yml b/config/install/quant.settings.yml new file mode 100644 index 00000000..3bf6697b --- /dev/null +++ b/config/install/quant.settings.yml @@ -0,0 +1,3 @@ +content_revisions: TRUE +asset_revisions: TRUE +storage_location: ../html diff --git a/modules/quant_api/quant_api.info.yml b/modules/quant_api/quant_api.info.yml new file mode 100644 index 00000000..8f33e741 --- /dev/null +++ b/modules/quant_api/quant_api.info.yml @@ -0,0 +1,9 @@ +name: Quant API +description: Connect to the hosted Quant service +package: Quant + +type: module +core: 8.x + +dependencies: + - drupal:quant diff --git a/modules/quant_api/quant_api.links.menu.yml b/modules/quant_api/quant_api.links.menu.yml new file mode 100644 index 00000000..ec4017c9 --- /dev/null +++ b/modules/quant_api/quant_api.links.menu.yml @@ -0,0 +1,6 @@ +quant_api.settings_form: + title: 'Quant API' + route_name: quant_api.settings_form + description: 'API connectivity with the hosted Quant service' + parent: quant + weight: 2 diff --git a/modules/quant_api/quant_api.routing.yml b/modules/quant_api/quant_api.routing.yml new file mode 100644 index 00000000..9c1390ec --- /dev/null +++ b/modules/quant_api/quant_api.routing.yml @@ -0,0 +1,9 @@ +quant_api.settings_form: + path: '/admin/config/development/quant/api' + defaults: + _form: '\Drupal\quant_api\Form\SettingsForm' + _title: 'Quant API Configuration' + requirements: + _permission: 'access administration pages' + options: + _admin_route: TRUE diff --git a/modules/quant_api/quant_api.services.yml b/modules/quant_api/quant_api.services.yml new file mode 100644 index 00000000..304ceb0c --- /dev/null +++ b/modules/quant_api/quant_api.services.yml @@ -0,0 +1,13 @@ +services: + quant_api.client: + class: Drupal\quant_api\Client\QuantClient + arguments: + - '@http_client' + - '@config.factory' + + quant.output.api: + class: Drupal\quant_api\EventSubscriber\QuantApi + arguments: + - '@quant_api.client' + tags: + - { name: 'event_subscriber' } diff --git a/modules/quant_api/src/Client/QuantClient.php b/modules/quant_api/src/Client/QuantClient.php new file mode 100644 index 00000000..fcf4cd1e --- /dev/null +++ b/modules/quant_api/src/Client/QuantClient.php @@ -0,0 +1,34 @@ +get('quant_api.settings'); + $this->client = $client; + // @TODO: Grab API connection details from the config. + } + + /** + * {@inheritdoc} + */ + public function ping() : bool { + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function send(array $data) : bool { + return TRUE; + } + +} diff --git a/modules/quant_api/src/Client/QuantClientInterface.php b/modules/quant_api/src/Client/QuantClientInterface.php new file mode 100644 index 00000000..447a1f72 --- /dev/null +++ b/modules/quant_api/src/Client/QuantClientInterface.php @@ -0,0 +1,33 @@ +client = $client; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[QuantEvent::OUTPUT][] = ['onOutput']; + return $events; + } + + /** + * Trigger an API request with the event data. + * + * @param Drupal\quant\Event\QuantEvent $event + * The event. + */ + public function onOutput(QuantEvent $event) { + + } + +} diff --git a/modules/quant_api/src/Form/SettingsForm.php b/modules/quant_api/src/Form/SettingsForm.php new file mode 100644 index 00000000..a023e6e0 --- /dev/null +++ b/modules/quant_api/src/Form/SettingsForm.php @@ -0,0 +1,80 @@ +client = $client; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('quant_api.client') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'quant_api_settings'; + } + + /** + * {@inheritdoc} + */ + public function getEditableConfigNames() { + return [ + self::SETTINGS, + ]; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $config = $this->config(self::SETTINGS); + + if ($config->get('api_token')) { + if ($this->client->ping()) { + $form['api_status'] = [ + '#markup' => $this->t('Successfully connected to the API'), + ]; + } + else { + $form['api_status'] = [ + '#markup' => $this->t('Cannot connect to the API'), + ]; + } + } + + $form['api_token'] = [ + '#type' => 'textfield', + '#title' => $this->t('API Token'), + ]; + + // @TODO QUANT API CONFIGURATION... + + return parent::buildForm($form, $form_state); + } + +} diff --git a/quant.info.yml b/quant.info.yml new file mode 100644 index 00000000..e17b3d80 --- /dev/null +++ b/quant.info.yml @@ -0,0 +1,6 @@ +name: Quant +description: Quant content export +package: Quant + +type: module +core: 8.x diff --git a/quant.links.menu.yml b/quant.links.menu.yml new file mode 100644 index 00000000..ab3352f3 --- /dev/null +++ b/quant.links.menu.yml @@ -0,0 +1,13 @@ +quant: + title: 'Quant' + route_name: quant.config + description: 'Configuration for the quant static exporter' + parent: system.admin_config + weight: 10 + +quant.config: + title: 'Quant' + route_name: quant.config + description: 'Configuration for the quant static exporter' + parent: quant + weight: 1 diff --git a/quant.module b/quant.module new file mode 100644 index 00000000..5fa6569a --- /dev/null +++ b/quant.module @@ -0,0 +1,22 @@ +dispatch(NodeInsertEvent::NODE_INSERT_EVENT, new NodeInsertEvent($entity)); +} + +function quant_node_update(Drupal\Core\Entity\EntityInterface $entity) { + \Drupal::service('event_dispatcher')->dispatch(NodeInsertEvent::NODE_INSERT_EVENT, new NodeInsertEvent($entity)); +} + +// function quant_node_load($entities) { +// $entity = reset($entities); +// \Drupal::service('event_dispatcher')->dispatch(NodeInsertEvent::NODE_INSERT_EVENT, new NodeInsertEvent($entity)); +// } diff --git a/quant.permissions.yml b/quant.permissions.yml new file mode 100644 index 00000000..53e87a75 --- /dev/null +++ b/quant.permissions.yml @@ -0,0 +1,6 @@ +configure quant: + title: 'Administer Quant configuration' + restrict access: true +bulk quant export: + title: 'Trigger a bulk export/seed via Quant' + restrict access: true diff --git a/quant.routing.yml b/quant.routing.yml new file mode 100644 index 00000000..8798a52b --- /dev/null +++ b/quant.routing.yml @@ -0,0 +1,15 @@ +quant.config: + path: '/admin/config/quant' + defaults: + _form: 'Drupal\quant\Form\ConfigForm' + _title: 'Configure Quant' + requirements: + _permission: 'configure quant' + +quant.seed: + path: '/admin/config/quant/seed' + defaults: + _form: 'Drupal\quant\Form\SeedForm' + _title: 'Generate bulk export/seed of web content' + requirements: + _permission: 'bulk quant export' diff --git a/quant.services.yml b/quant.services.yml new file mode 100644 index 00000000..da2a319a --- /dev/null +++ b/quant.services.yml @@ -0,0 +1,29 @@ +services: + plugin.manager.quant.metadata: + class: Drupal\quant\Plugin\QuantMetadataManager + parent: default_plugin_manager + + quant.entity_renderer: + class: Drupal\quant\EntityRenderer + arguments: + - '@config.factory' + - '@entity.manager' + - '@renderer' + - '@main_content_renderer.html' + - '@plugin.manager.display_variant' + - '@theme.initialization' + - '@theme.manager' + - '@account_switcher' + + quant.node.insert: + class: Drupal\quant\EventSubscriber\NodeInsertSubscriber + arguments: + - '@quant.entity_renderer' + - '@plugin.manager.quant.metadata' + tags: + - { name: 'event_subscriber' } + + quant.output.filesystem: + class: Drupal\quant\EventSubscriber\QuantFilesystem + tags: + - { name: 'event_subscriber' } diff --git a/src/Annotation/Metadata.php b/src/Annotation/Metadata.php new file mode 100644 index 00000000..b7357671 --- /dev/null +++ b/src/Annotation/Metadata.php @@ -0,0 +1,31 @@ +configFactory = $config_factory; + $this->entityManager = $entity_manager; + $this->renderer = $renderer; + $this->htmlRenderer = $html_renderer; + $this->displayVariant = $display_variant; + $this->themeInit = $theme_init; + $this->themeManager = $theme_manager; + $this->accountSwitcher = $account_switcher; + + $this->activeTheme = $theme_manager->getActiveTheme()->getName(); + $this->frontendTheme = $config_factory->get('system.theme')->get('default'); + } + + /** + * Create a render array for the entity. + * + * @see entity_view + * + * @return array + * A renderable array. + */ + protected function entityView(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) { + $render_controller = \Drupal::entityManager() + ->getViewBuilder($entity->getEntityTypeId()); + + // @TODO: Validate cache clear. + // @see entity_view. + + return $render_controller + ->view($entity, $view_mode, $langcode); + } + + /** + * Switch the theme. + */ + protected function switchTheme($first = FALSE) { + $theme_name = $first ? $this->activeTheme : $this->frontendTheme; + $active_theme = $this->themeInit->initTheme($theme_name); + $this->themeManager->setActiveTheme($active_theme); + } + + protected function removeKeyFromArray($key, &$array) { + foreach ($array as $k => $arr) { + if (is_array($arr)) { + if (isset($arr[$key])) { + unset($arr[$key]); + } else { + $this->removeKeyFromArray($key, $arr[$k]); + } + } + } + } + + + /** + * {@inheritdoc} + */ + public function render(EntityInterface $entity) : string { + // Make sure notices and other PHP warnings are not surfaced + // during the static render. + // @TODO: We should probably try and log this. + error_reporting(0); + $main_content = $this->entityView($entity); + + // Switch to the anonymous session. + $this->accountSwitcher->switchTo(new AnonymousUserSession()); + $this->switchTheme(); + + $context = new RenderContext(); + + // @TODO: Variant ID service for this. + $variant_id = 'block_page'; + + \Drupal::messenger()->deleteAll(); + + $this->renderer->executeInRenderContext($context, function () use (&$main_content) { + $this->renderer->render($main_content); + }); + + // Get render cache. + $renderCache = \Drupal::service('render_cache'); + $main_content = $renderCache->getCacheableRenderArray($main_content) + [ + '#title' => isset($main_content['#title']) ? $main_content['#title'] : NULL, + ]; + + // @TODO: Change how to grab the title. + $title = [ + '#markup' => $entity->getTitle(), + ]; + $this->renderer->renderPlain($title); + $title = $title['#markup']; + + $page_display = $this->displayVariant->createInstance($variant_id); + $page_display + ->setMainContent($main_content) + ->setTitle($title); + + $page = [ + '#type' => 'page', + ]; + $page += $page_display->build(); + + // Get regions for the currently active theme. + $regions = $this->themeManager->getActiveTheme()->getRegions(); + + foreach ($regions as $region) { + if (!empty($page[$region])) { + $page[$region]['#theme_wrappers'][] = 'region'; + $page[$region]['#region'] = $region; + } + } + + // @TODO: This should give us attachments (css+js) for the page so we can + // add this to the page attachments. + $this->htmlRenderer->invokePageAttachmentHooks($page); + + // @todo: Determine which approach is better. + // bare_html_page_renderer replaces the placeholders with correct values + $bb = \Drupal::service('bare_html_page_renderer') + ->renderBarePage( + $page, + 'Page label', + 'page', + [] + ); + $this->accountSwitcher->switchBack(); + return $bb->getContent(); + // END: End of bare_html_page_renderer hax. + + $html = [ + 'page' => $page, + '#type' => 'html', + ]; + + // Go back to the logged in session. + + $this->htmlRenderer->buildPageTopAndBottom($html); + system_page_attachments($html['page']); + $output = $this->renderer->renderPlain($html); + $this->accountSwitcher->switchBack(); + + return $output; + } + +} diff --git a/src/EntityRendererInterface.php b/src/EntityRendererInterface.php new file mode 100644 index 00000000..43321ab9 --- /dev/null +++ b/src/EntityRendererInterface.php @@ -0,0 +1,23 @@ +entity = $entity; + } + + /** + * Get the inserted entity. + * + * @return \Drupal\Core\Entity\EntityInterface + * The entity object. + */ + public function getEntity() { + return $this->entity; + } +} diff --git a/src/Event/QuantEvent.php b/src/Event/QuantEvent.php new file mode 100644 index 00000000..7c8f9c70 --- /dev/null +++ b/src/Event/QuantEvent.php @@ -0,0 +1,95 @@ +contents = $contents; + $this->location = $location; + $this->entity = $entity; + } + + /** + * Get the contents string. + * + * @return string + * The contents. + */ + public function getContents() : string { + return $this->contents; + } + + /** + * Get the location string. + * + * @return string + * The location. + */ + public function getLocation() : string { + return $this->location; + } + + /** + * Get the inserted entity. + * + * @return \Drupal\Core\Entity\EntityInterface + * The entity. + */ + public function getEntity() { + return $this->entity; + } + +} diff --git a/src/EventSubscriber/NodeInsertSubscriber.php b/src/EventSubscriber/NodeInsertSubscriber.php new file mode 100644 index 00000000..d4cce197 --- /dev/null +++ b/src/EventSubscriber/NodeInsertSubscriber.php @@ -0,0 +1,64 @@ +renderer = $renderer; + $this->metadataManager = $metadata_manager; + } + + /** + * Log the creation of a new node. + * + * @param \Drupal\quant\Event\NodeInsertEvent $event + */ + public function onNodeInsert(NodeInsertEvent $event) { + + $entity = $event->getEntity(); + $markup = $this->renderer->render($entity); + $rid = $entity->get('vid')->value; + + // This should get the entity alias. + $url = $entity->toUrl()->toString(); + \Drupal::service('event_dispatcher')->dispatch(QuantEvent::OUTPUT, new QuantEvent($markup, "$url/index_$rid.html", $entity)); + + $meta = []; + + foreach ($this->metadataManager->getDefinitions() as $pid => $def) { + $plugin = $this->metadataManager->createInstance($pid); + if ($plugin->applies($entity)) { + $meta = array_merge($meta, $plugin->build($entity)); + } + } + + \Drupal::service('event_dispatcher')->dispatch(QuantEvent::OUTPUT, new QuantEvent(json_encode($meta), "$url/quant.meta", $entity)); + + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[NodeInsertEvent::NODE_INSERT_EVENT][] = ['onNodeInsert']; + return $events; + } +} diff --git a/src/EventSubscriber/QuantFilesystem.php b/src/EventSubscriber/QuantFilesystem.php new file mode 100644 index 00000000..df116b56 --- /dev/null +++ b/src/EventSubscriber/QuantFilesystem.php @@ -0,0 +1,43 @@ +getLocation()); + $file = self::LOC . $event->getLocation(); + // Make sure the output directory exists. + @mkdir($dir, 0755); + file_put_contents($file, $event->getContents()); + } + +} diff --git a/src/Form/ConfigForm.php b/src/Form/ConfigForm.php new file mode 100644 index 00000000..a8f3f7a9 --- /dev/null +++ b/src/Form/ConfigForm.php @@ -0,0 +1,84 @@ +config(static::SETTINGS); + + $form['content_revisions'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable content revisions'), + '#description' => $this->t('Any content change will create a new revision in Quant.'), + '#default_value' => $config->get('content_revisions'), + ]; + + // @todo: Should revisions be configured at the API level? + $form['asset_revisions'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable asset revisions'), + '#description' => $this->t('Media revisions will be tracked when files/images/etc change.'), + '#default_value' => $config->get('asset_revisions'), + ]; + + $form['storage_location'] = [ + '#type' => 'textfield', + '#title' => $this->t('Storage path'), + '#description' => $this->t('Location on disk to store static assets'), + '#default_value' => $config->get('storage_location'), + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + // Retrieve the configuration. + $this->configFactory->getEditable(static::SETTINGS) + ->set('content_revisions', $form_state->getValue('content_revisions')) + ->set('asset_revisions', $form_state->getValue('asset_revisions')) + ->set('storage_location', $form_state->getValue('storage_location')) + ->save(); + + parent::submitForm($form, $form_state); + } + + +} diff --git a/src/Form/SeedForm.php b/src/Form/SeedForm.php new file mode 100644 index 00000000..3a42f736 --- /dev/null +++ b/src/Form/SeedForm.php @@ -0,0 +1,140 @@ +getWarnings(); + + if (!empty($warnings)) { + $form['warnings'] = [ + '#type' => 'container', + 'title' => [ + '#markup' => '' . $this->t('Build warnings') . '', + ], + 'list' => [ + '#theme' => 'item_list', + '#items' => [], + ], + ]; + foreach ($warnings as $warning) { + $form['warnings']['list']['#items'][] = [ + '#markup' => $warning, + ]; + } + } + + $form['entity_node'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Export nodes'), + ]; + + $form['entity_node_revisions'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Export historic node revisions'), + '#states' => [ + 'visible' => [ + ':input[name="entity_node"]' => ['checked' => TRUE], + ], + ], + ]; + + // @todo: Plugins. + $form['entity_user'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Export user profiles'), + '#disabled' => TRUE, + ]; + + $form['entity_media'] = [ + '#type' => 'checkbox', + '#title' => 'Export media', + '#description' => $this->t('Public media paths (e.g /media/123).'), + '#disabled' => TRUE, + ]; + + $form['actions'] = [ + '#type' => 'actions', + ]; + + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Start batch'), + ]; + + return $form; + } + + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + + if (!$form_state->getValue('entity_node')) { + return; + } + + $query = \Drupal::entityQuery('node'); + $nids = $query->execute(); + + $batch = array( + 'title' => t('Exporting to Quant...'), + 'operations' => [], + 'init_message' => t('Commencing'), + 'progress_message' => t('Processed @current out of @total.'), + 'error_message' => t('An error occurred during processing'), + 'finished' => '\Drupal\quant\Seed::finishedSeedCallback', + ); + foreach ($nids as $key => $value) { + $node = \Drupal\node\Entity\Node::load($value); + + // Export all node revisions. + if ($form_state->getValue('entity_node_revisions')) { + $vids = \Drupal::entityManager()->getStorage('node')->revisionIds($node); + + foreach ($vids as $vid) { + $nr = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($vid); + $batch['operations'][] = ['\Drupal\quant\Seed::exportNode',[$nr]]; + } + + } + + // Export current node revision. + $batch['operations'][] = ['\Drupal\quant\Seed::exportNode',[$node]]; + } + + batch_set($batch); + + } +} diff --git a/src/Plugin/MetadataBase.php b/src/Plugin/MetadataBase.php new file mode 100644 index 00000000..37866dc3 --- /dev/null +++ b/src/Plugin/MetadataBase.php @@ -0,0 +1,22 @@ +entityManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function build(EntityInterface $entity) : array { + $default = $this->entityManager->getStorage($entity->getEntityTypeId())->load($entity->id()); + return ['published' => $default->isPublished()]; + } + +} diff --git a/src/Plugin/Quant/Metadata/PublishedRevision.php b/src/Plugin/Quant/Metadata/PublishedRevision.php new file mode 100644 index 00000000..bc5a7d13 --- /dev/null +++ b/src/Plugin/Quant/Metadata/PublishedRevision.php @@ -0,0 +1,62 @@ +entityManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function applies(EntityInterface $entity) : bool { + return $entity->getEntityType()->isRevisionable(); + } + + /** + * {@inheritdoc} + */ + public function build(EntityInterface $entity) : array { + $default = $this->entityManager->getStorage($entity->getEntityTypeId())->load($entity->id()); + return ['published_revision' => $default->get('vid')->value]; + } + +} diff --git a/src/Plugin/Quant/Metadata/TransitionRevision.php b/src/Plugin/Quant/Metadata/TransitionRevision.php new file mode 100644 index 00000000..00adbf92 --- /dev/null +++ b/src/Plugin/Quant/Metadata/TransitionRevision.php @@ -0,0 +1,32 @@ +getEntityType()->isRevisionable(); + } + + /** + * {@inheritdoc} + */ + public function build(EntityInterface $entity): array { + return ['transition_revision' => $entity->get('vid')->value]; + } +} diff --git a/src/Plugin/Quant/Metadata/Transitions.php b/src/Plugin/Quant/Metadata/Transitions.php new file mode 100644 index 00000000..7a06839f --- /dev/null +++ b/src/Plugin/Quant/Metadata/Transitions.php @@ -0,0 +1,81 @@ +configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('config.factory') + ); + } + + /** + * {@inheritdoc} + */ + public function build(EntityInterface $entity) : array { + $timezone = $this->configFactory->get('system.date')->get('timezone.default'); + $meta = ['transitions' => []]; + + try { + $date = $entity->get('scheduled_transition_date')->getValue(); + $state = $entity->get('scheduled_transition_state')->getValue(); + } + catch (\Exception $error) { + return $meta; + } + + if (empty($date) || empty($state)) { + return $meta; + } + + foreach ($state as $delta => $d) { + $dt = new \DateTime($date[$delta]['value'], new \DateTimeZone('UTC')); + $dt->setTimeZone(new \DateTimeZone($timezone)); + $meta['transitions'][] = [ + 'date_time_utc' => $date[$delta]['value'], + 'date_timestamp' => $dt->getTimestamp(), + 'state' => $state[$delta]['value'], + ]; + } + + return $meta; + } + +} diff --git a/src/Plugin/QuantMetadataManager.php b/src/Plugin/QuantMetadataManager.php new file mode 100644 index 00000000..fa78bb75 --- /dev/null +++ b/src/Plugin/QuantMetadataManager.php @@ -0,0 +1,29 @@ +alterInfo('quant_metadata_info'); + $this->setCacheBackend($cache_backend, 'quant_metadata_plugins'); + } + +} diff --git a/src/QuantStaticTrait.php b/src/QuantStaticTrait.php new file mode 100644 index 00000000..f99a6383 --- /dev/null +++ b/src/QuantStaticTrait.php @@ -0,0 +1,50 @@ +get('css.preprocess') || !$performance_config->get('js.preprocess')) { + if (!$performance_config->get('css.preprocess') && !$performance_config->get('js.preprocess')) { + $message = $this->t('CSS and JS preprocessing is disabled.'); + } + elseif (!$performance_config->get('css.preprocess')) { + $message = $this->t('CSS preprocessing is disabled.'); + } + else { + $message = $this->t('JS preprocessing is disabled.'); + } + $warnings[] = $message . ' ' . $this->t('This could lead to performance issues. To resolve, visit /admin/config/development/performance.'); + } + $twig_config = \Drupal::getContainer()->getParameter('twig.config'); + if ($twig_config['debug'] || !$twig_config['cache']) { + if ($twig_config['debug'] && !$twig_config['cache']) { + $message = $this->t('Twig debugging is enabled and caching is disabled.'); + } + elseif ($twig_config['debug']) { + $message = $this->t('Twig debugging is enabled.'); + } + else { + $message = $this->t('Twig caching is disabled.'); + } + $warnings[] = $message . ' ' . $this->t('This could lead to performance issues. To resolve, edit the "twig.config" parameter in the "sites/*/services.yml" file, then rebuild cache.'); + } + return $warnings; + } + +} diff --git a/src/Seed.php b/src/Seed.php new file mode 100644 index 00000000..e2aaddc6 --- /dev/null +++ b/src/Seed.php @@ -0,0 +1,37 @@ +get('vid')->value; + $message = "Processing {$node->title->value} (Revision: {$vid})"; + + // Export via event dispatcher. + \Drupal::service('event_dispatcher')->dispatch(NodeInsertEvent::NODE_INSERT_EVENT, new NodeInsertEvent($node)); + + $results = [$node->nid->value]; + $context['message'] = $message; + $context['results'][] = $results; + } + + public static function finishedSeedCallback($success, $results, $operations) { + // The 'success' parameter means no fatal PHP errors were detected. All + // other error management should be handled using 'results'. + if ($success) { + $message = \Drupal::translation()->formatPlural( + count($results), + 'One item processed.', '@count items processed.' + ); + } + else { + $message = t('Finished with an error.'); + } + drupal_set_message($message); + } +}