diff --git a/modules/quant_api/quant_api.routing.yml b/modules/quant_api/quant_api.routing.yml index 9c1390ec..94dcb8bd 100644 --- a/modules/quant_api/quant_api.routing.yml +++ b/modules/quant_api/quant_api.routing.yml @@ -4,6 +4,6 @@ quant_api.settings_form: _form: '\Drupal\quant_api\Form\SettingsForm' _title: 'Quant API Configuration' requirements: - _permission: 'access administration pages' + _permission: 'configure quant' options: _admin_route: TRUE diff --git a/modules/quant_cron/quant_cron.info.yml b/modules/quant_cron/quant_cron.info.yml new file mode 100644 index 00000000..6bb6ab98 --- /dev/null +++ b/modules/quant_cron/quant_cron.info.yml @@ -0,0 +1,10 @@ +name: Quant Cron +description: Support running Quant processes during cron runs +package: Quant + +type: module +core_version_requirement: ^8 || ^9 +core: 8.x + +dependencies: + - drupal:quant diff --git a/modules/quant_cron/quant_cron.links.task.yml b/modules/quant_cron/quant_cron.links.task.yml new file mode 100644 index 00000000..9e7afbc5 --- /dev/null +++ b/modules/quant_cron/quant_cron.links.task.yml @@ -0,0 +1,4 @@ +quant_cron.settings_form: + route_name: quant_cron.settings_form + title: 'Cron' + base_route: quant.config diff --git a/modules/quant_cron/quant_cron.module b/modules/quant_cron/quant_cron.module new file mode 100644 index 00000000..54e0f785 --- /dev/null +++ b/modules/quant_cron/quant_cron.module @@ -0,0 +1,82 @@ +setRebuild(); + \Drupal::formBuilder()->buildForm('Drupal\quant_cron\Form\CronSettingsForm', $form_state); + $event_dispatcher = \Drupal::service('event_dispatcher'); + + + $batch = [ + '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', + ]; + + $assets = []; + $routes = []; + $redirects = []; + + // Lunr. + if ($form_state->getValue('lunr')) { + $assets = array_merge($assets, Seed::findLunrAssets()); + $routes = array_merge($routes, Seed::findLunrRoutes()); + } + + // Custom routes. + if ($form_state->getValue('routes_export')) { + foreach (explode(PHP_EOL, $cron_config->get('routes_export')) as $route) { + if (strpos((trim($route)), '/') !== 0) { + continue; + } + $routes[] = trim($route); + } + } + + if ($form_state->getValue('redirects')) { + // Collect the redirects for the seed. + $event = new CollectRedirectsEvent([], $form_state); + $event_dispatcher->dispatch(QuantCollectionEvents::REDIRECTS, $event); + while ($redirect = $event->getEntity()) { + $batch['operations'][] = ['\Drupal\quant\Seed::exportRedirect', [$redirect]]; + } + } + + if ($form_state->getValue('entity_node')) { + $revisions = $form_state->getValue('entity_node_revisions'); + $event = new CollectEntitiesEvent([], $revisions, $form_state); + $event_dispatcher->dispatch(QuantCollectionEvents::ENTITIES, $event); + while ($entity = $event->getEntity()) { + $batch['operations'][] = ['\Drupal\quant\Seed::exportNode', [$entity]]; + } + } + + $event = new CollectRoutesEvent($routes, $form_state); + $event_dispatcher->dispatch(QuantCollectionEvents::ROUTES, $event); + while ($route = $event->getRoute()) { + $batch['operations'][] = ['\Drupal\quant\Seed::exportRoute', [$route]]; + } + + $event = new CollectFilesEvent($assets, $form_state); + $event_dispatcher->dispatch(QuantCollectionEvents::FILES, $event); + while ($file = $event->getFilePath()) { + $batch['operations'][] = ['\Drupal\quant\Seed::exportFile', [$file]]; + } + + batch_set($batch); + drush_backend_batch_process(); + +} diff --git a/modules/quant_cron/quant_cron.routing.yml b/modules/quant_cron/quant_cron.routing.yml new file mode 100644 index 00000000..72992861 --- /dev/null +++ b/modules/quant_cron/quant_cron.routing.yml @@ -0,0 +1,9 @@ +quant_cron.settings_form: + path: '/admin/config/development/quant/cron' + defaults: + _form: '\Drupal\quant_cron\Form\CronSettingsForm' + _title: 'Quant Cron Configuration' + requirements: + _permission: 'configure quant' + options: + _admin_route: TRUE diff --git a/modules/quant_cron/src/Form/CronSettingsForm.php b/modules/quant_cron/src/Form/CronSettingsForm.php new file mode 100644 index 00000000..bb06c95e --- /dev/null +++ b/modules/quant_cron/src/Form/CronSettingsForm.php @@ -0,0 +1,202 @@ +getWarnings(); + $config = $this->config('quant_cron.settings'); + $moduleHandler = \Drupal::moduleHandler(); + + 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('Nodes'), + '#description' => $this->t('Exports the latest revision of each node.'), + '#default_value' => !empty($config->get('entity_node', '')), + ]; + + // Seed by language. + // Only active if there are more than one active languages. + $languages = \Drupal::languageManager()->getLanguages(); + + if (count($languages) > 1) { + $defaultLanguage = \Drupal::languageManager()->getDefaultLanguage(); + $language_codes = []; + + foreach ($languages as $langcode => $language) { + $default = ($defaultLanguage->getId() == $langcode) ? ' (Default)' : ''; + $language_codes[$langcode] = $language->getName() . $default; + } + + $form['entity_node_languages'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Languages'), + '#description' => $this->t('Optionally restrict to these languages. If no options are selected all languages will be exported.'), + '#options' => $language_codes, + '#states' => [ + 'visible' => [ + ':input[name="entity_node"]' => ['checked' => TRUE], + ], + ], + '#default_value' => $config->get('entity_node_languages'), + ]; + } + + // Seed by bundle. + $types = \Drupal::entityTypeManager() + ->getStorage('node_type') + ->loadMultiple(); + + $content_types = []; + foreach($types as $type) { + $content_types[$type->id()] = $type->label(); + } + + $form['entity_node_bundles'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Enabled bundles'), + '#description' => $this->t('Optionally restrict to these content types.'), + '#options' => $content_types, + '#states' => [ + 'visible' => [ + ':input[name="entity_node"]' => ['checked' => TRUE], + ], + ], + '#default_value' => $config->get('entity_node_bundles'), + ]; + + $form['entity_taxonomy_term'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Taxonomy terms'), + '#description' => $this->t('Exports taxonomy term pages.'), + '#default_value' => $config->get('entity_taxonomy_term'), + ]; + + // @todo: Implement these as plugins. + $form['theme_assets'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Theme assets'), + '#description' => $this->t('Images, fonts and favicon in the public theme.'), + '#default_value' => $config->get('theme_assets'), + ]; + + $form['views_pages'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Views (Pages)'), + '#description' => $this->t('Exports all views with a Page display accessible to anonymous users.'), + '#default_value' => $config->get('views_pages'), + ]; + + $form['routes'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Custom routes'), + '#description' => $this->t('Exports custom list of routes.'), + '#default_value' => !empty($config->get('routes_export')), + ]; + + $form['routes_textarea'] = [ + '#type' => 'textarea', + '#title' => $this->t('Routes'), + '#description' => $this->t('Add routes to export, each on a new line.'), + '#states' => [ + 'visible' => [ + ':input[name="routes"]' => ['checked' => TRUE], + ], + ], + '#default_value' => $config->get('routes_export'), + ]; + + $form['robots'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Robots.txt'), + '#description' => $this->t('Export robots.txt to Quant.'), + '#default_value' => $config->get('robots'), + ]; + + if ($moduleHandler->moduleExists('lunr')) { + $form['lunr'] = [ + '#type' => 'checkbox', + '#title' => 'Lunr search assets', + '#description' => $this->t('Exports required lunr javascript libraries and all search indexes for decoupled search.'), + '#default_value' => $config->get('lunr'), + ]; + } + + $form['actions'] = [ + '#type' => 'actions', + ]; + + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Save cron settings'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $config = $this->configFactory->getEditable('quant_cron.settings'); + $config->set('routes_export', $form_state->getValue('routes_textarea'))->save(); + $config->set('entity_node', $form_state->getValue('entity_node'))->save(); + $config->set('entity_node_languages', $form_state->getValue('entity_node_languages'))->save(); + $config->set('entity_node_bundles', $form_state->getValue('entity_node_bundles'))->save(); + $config->set('entity_taxonomy_term', $form_state->getValue('entity_taxonomy_term'))->save(); + $config->set('theme_assets', $form_state->getValue('theme_assets'))->save(); + $config->set('views_pages', $form_state->getValue('views_pages'))->save(); + $config->set('robots', $form_state->getValue('robots'))->save(); + $config->set('lunr', $form_state->getValue('lunr'))->save(); + } + +} diff --git a/src/EventSubscriber/CollectionSubscriber.php b/src/EventSubscriber/CollectionSubscriber.php index 8bd5a048..0743559e 100644 --- a/src/EventSubscriber/CollectionSubscriber.php +++ b/src/EventSubscriber/CollectionSubscriber.php @@ -150,7 +150,7 @@ public function collectFiles(CollectFilesEvent $event) { die; } - $directoryIterator = new \RecursiveDirectoryIterator($themePath, RecursiveDirectoryIterator::SKIP_DOTS); + $directoryIterator = new \RecursiveDirectoryIterator($themePath, \RecursiveDirectoryIterator::SKIP_DOTS); $iterator = new \RecursiveIteratorIterator($directoryIterator); $regex = new \RegexIterator($iterator, '/^.+(.jpe?g|.png|.svg|.ttf|.woff|.woff2|.otf|.ico)$/i', \RecursiveRegexIterator::GET_MATCH); @@ -163,12 +163,12 @@ public function collectFiles(CollectFilesEvent $event) { $iterator = new \AppendIterator(); if (is_dir($filesPath . '/css')) { - $directoryIteratorCss = new \RecursiveDirectoryIterator($filesPath . '/css', RecursiveDirectoryIterator::SKIP_DOTS); + $directoryIteratorCss = new \RecursiveDirectoryIterator($filesPath . '/css', \RecursiveDirectoryIterator::SKIP_DOTS); $iterator->append(new \RecursiveIteratorIterator($directoryIteratorCss)); } if (is_dir($filesPath . '/js')) { - $directoryIteratorJs = new \RecursiveDirectoryIterator($filesPath . '/js', RecursiveDirectoryIterator::SKIP_DOTS); + $directoryIteratorJs = new \RecursiveDirectoryIterator($filesPath . '/js', \RecursiveDirectoryIterator::SKIP_DOTS); $iterator->append(new \RecursiveIteratorIterator($directoryIteratorJs)); }