From f9aeb5f4f521ee5f59acb83d507e6606cb702e07 Mon Sep 17 00:00:00 2001
From: Stuart Rowlands <stuart@firecannon.com>
Date: Tue, 6 Oct 2020 20:32:36 +1300
Subject: [PATCH] Added rough pagination support for D8.

---
 .../src/EventSubscriber/QuantApi.php          | 37 +++++++++++++++++++
 modules/quant_cron/quant_cron.module          |  6 ++-
 src/EventSubscriber/CollectionSubscriber.php  | 10 ++++-
 src/Form/SeedForm.php                         | 14 ++-----
 4 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/modules/quant_api/src/EventSubscriber/QuantApi.php b/modules/quant_api/src/EventSubscriber/QuantApi.php
index c819732d..df2de5d3 100644
--- a/modules/quant_api/src/EventSubscriber/QuantApi.php
+++ b/modules/quant_api/src/EventSubscriber/QuantApi.php
@@ -180,6 +180,43 @@ public function onOutput(QuantEvent $event) {
       }
     }
 
+    // Pagination support.
+    // @todo: Determine when we need to run this.
+    $document = new \DOMDocument();
+    @$document->loadHTML($content);
+    $xpath = new \DOMXPath($document);
+
+    /** @var \DOMElement $node */
+    $pager_operations = [];
+    // @todo: Make this xpath configurable.
+    // @todo: Check this xpath works for core taxonomy listing (and elsewhere pagination appears).
+    // This supports the use case for core views output (mini and standard pager).
+    foreach ($xpath->query('//a[contains(@href,"page=") and (./span[contains(text(), "Next")])]') as $node) {
+      $original_href = $node->getAttribute('href');
+      if ($original_href[0] === '?') {
+        $new_href = strtok($path, '?') . $original_href;
+      }
+      else {
+        $new_href = $original_href;
+      }
+
+      $pager_operations[] = ['\Drupal\quant\Seed::exportRoute', [$new_href]];
+    }
+
+    if (!empty($pager_operations)) {
+      $batch = [
+        'title' => t('Exporting pagination page...'),
+        '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',
+        'operations' => $pager_operations,
+      ];
+
+      batch_set($batch);
+    }
+
+
     // @todo: Report on forms that need proxying (attachments.forms).
   }
 
diff --git a/modules/quant_cron/quant_cron.module b/modules/quant_cron/quant_cron.module
index 54e0f785..31c5d33e 100644
--- a/modules/quant_cron/quant_cron.module
+++ b/modules/quant_cron/quant_cron.module
@@ -10,13 +10,17 @@ use Drupal\quant\Event\QuantCollectionEvents;
 
 function quant_cron_cron() {
 
+  // Quant cron only supported via CLI.
+  if (PHP_SAPI != 'cli') {
+    return;
+  }
+
   // Load the settings form.
   $form_state = new FormState();
   $form_state->setRebuild();
   \Drupal::formBuilder()->buildForm('Drupal\quant_cron\Form\CronSettingsForm', $form_state);
   $event_dispatcher = \Drupal::service('event_dispatcher');
 
-
   $batch = [
     'title' => t('Exporting to Quant...'),
     'operations' => [],
diff --git a/src/EventSubscriber/CollectionSubscriber.php b/src/EventSubscriber/CollectionSubscriber.php
index 0743559e..1e1c9300 100644
--- a/src/EventSubscriber/CollectionSubscriber.php
+++ b/src/EventSubscriber/CollectionSubscriber.php
@@ -205,7 +205,7 @@ public function collectRoutes(CollectRoutesEvent $event) {
       }
     }
 
-    if ($event->getFormState()->getValue('routes_textarea')) {
+    if ($event->getFormState()->getValue('routes')) {
       foreach (explode(PHP_EOL, $event->getFormState()->getValue('routes_textarea')) as $route) {
         if (strpos((trim($route)), '/') !== 0) {
           continue;
@@ -218,12 +218,15 @@ public function collectRoutes(CollectRoutesEvent $event) {
       $event->addRoute('/robots.txt');
     }
 
+    $routes = [];
     if ($event->getFormState()->getValue('views_pages')) {
       $views_storage = $this->entityTypeManager->getStorage('view');
       $anon = User::getAnonymousUser();
 
       foreach ($views_storage->loadMultiple() as $view) {
         $view = Views::getView($view->get('id'));
+
+        $paths = [];
         $displays = array_keys($view->storage->get('display'));
         foreach ($displays as $display) {
           $view->setDisplay($display);
@@ -233,6 +236,11 @@ public function collectRoutes(CollectRoutesEvent $event) {
               continue;
             }
 
+            if (in_array($path, $paths)) {
+              continue;
+            }
+
+            $paths[] = $path;
             $event->addRoute("/{$path}");
 
             // Languge negotiation may also provide path prefixes.
diff --git a/src/Form/SeedForm.php b/src/Form/SeedForm.php
index 4d2cbab4..7b660db5 100644
--- a/src/Form/SeedForm.php
+++ b/src/Form/SeedForm.php
@@ -184,7 +184,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'checkbox',
       '#title' => $this->t('Custom routes'),
       '#description' => $this->t('Exports custom list of routes.'),
-      '#default_value' => !empty($config->get('routes_export', '')),
+      '#default_value' => $config->get('routes'),
     ];
 
     $form['routes_textarea'] = [
@@ -196,7 +196,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           ':input[name="routes"]' => ['checked' => TRUE],
         ],
       ],
-      '#default_value' => $config->get('routes_export', ''),
+      '#default_value' => $config->get('routes_export'),
     ];
 
     $form['robots'] = [
@@ -256,15 +256,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     }
 
     $config->set('routes_export', $form_state->getValue('routes_textarea'))->save();
-    if ($form_state->getValue('routes_textarea')) {
-      foreach (explode(PHP_EOL, $form_state->getValue('routes_textarea')) as $route) {
-        if (strpos((trim($route)), '/') !== 0) {
-          continue;
-        }
-
-        $routes[] = trim($route);
-      }
-    }
+    $config->set('routes', $form_state->getValue('routes'))->save();
 
     $batch = [
       'title' => t('Exporting to Quant...'),