From c6cd9ac7f9a5bc1f035ae3a6cce04c0d2be61292 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sat, 19 Jul 2014 11:28:17 +0100
Subject: [PATCH] Issue #1288442 by jhodgdon | Wolfflow: Added search index
 status to the Status Report page.

---
 core/modules/search/search.install            | 32 +++++++++
 .../search/src/SearchPageListBuilder.php      |  6 +-
 .../Tests/SearchMultilingualEntityTest.php    | 67 ++++++++++++++++---
 3 files changed, 93 insertions(+), 12 deletions(-)

diff --git a/core/modules/search/search.install b/core/modules/search/search.install
index 4d65a57ce321..a298f2f93164 100644
--- a/core/modules/search/search.install
+++ b/core/modules/search/search.install
@@ -122,3 +122,35 @@ function search_schema() {
 
   return $schema;
 }
+
+/**
+ * Implements hook_requirements().
+ *
+ * For the Status Report, return information about search index status.
+ */
+function search_requirements($phase) {
+  $requirements = array();
+
+  if ($phase == 'runtime') {
+    $remaining = 0;
+    $total = 0;
+    $search_page_repository = \Drupal::service('search.search_page_repository');
+    foreach ($search_page_repository->getIndexableSearchPages() as $entity) {
+      $status = $entity->getPlugin()->indexStatus();
+      $remaining += $status['remaining'];
+      $total += $status['total'];
+    }
+
+    $done = $total - $remaining;
+    // Use floor() to calculate the percentage, so if it is not quite 100%, it
+    // will show as 99%, to indicate "almost done".
+    $percent = ($total > 0 ? floor(100 * $done / $total) : 100);
+    $requirements['search_status'] = array(
+      'title' => t('Search index progress'),
+      'value' => t('@percent% (@remaining remaining)', array('@percent' => $percent, '@remaining' => $remaining)),
+      'severity' => REQUIREMENT_INFO,
+    );
+  }
+
+  return $requirements;
+}
diff --git a/core/modules/search/src/SearchPageListBuilder.php b/core/modules/search/src/SearchPageListBuilder.php
index 044ee648b004..d6a837a580f9 100644
--- a/core/modules/search/src/SearchPageListBuilder.php
+++ b/core/modules/search/src/SearchPageListBuilder.php
@@ -169,7 +169,11 @@ public function buildForm(array $form, array &$form_state) {
 
     $this->moduleHandler->loadAllIncludes('admin.inc');
     $count = format_plural($remaining, 'There is 1 item left to index.', 'There are @count items left to index.');
-    $percentage = ((int) min(100, 100 * ($total - $remaining) / max(1, $total))) . '%';
+    $done = $total - $remaining;
+    // Use floor() to calculate the percentage, so if it is not quite 100%, it
+    // will show as 99%, to indicate "almost done".
+    $percentage = $total > 0 ? floor(100 * $done / $total) : 100;
+    $percentage .= '%';
     $status = '<p><strong>' . $this->t('%percentage of the site has been indexed.', array('%percentage' => $percentage)) . ' ' . $count . '</strong></p>';
     $form['status'] = array(
       '#type' => 'details',
diff --git a/core/modules/search/src/Tests/SearchMultilingualEntityTest.php b/core/modules/search/src/Tests/SearchMultilingualEntityTest.php
index 48607bd39330..f35494045c9f 100644
--- a/core/modules/search/src/Tests/SearchMultilingualEntityTest.php
+++ b/core/modules/search/src/Tests/SearchMultilingualEntityTest.php
@@ -36,6 +36,20 @@ class SearchMultilingualEntityTest extends SearchTestBase {
   function setUp() {
     parent::setUp();
 
+    // Create a user who can administer search, do searches, see the status
+    // report, and administer cron. Log in.
+    $user = $this->drupalCreateUser(array('administer search', 'search content', 'use advanced search', 'access content', 'access site reports', 'administer site configuration'));
+    $this->drupalLogin($user);
+
+    // Make sure that auto-cron is disabled.
+    \Drupal::config('system.cron')->set('threshold.autorun', 0)->save();
+
+    // Set up the search plugin.
+    $this->plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
+
+    // Check indexing counts before adding any nodes.
+    $this->assertIndexCounts(0, 0, 'before adding nodes');
+
     // Add two new languages.
     $language = new Language(array(
       'id' => 'hu',
@@ -77,6 +91,19 @@ function setUp() {
         'body' => array(array('value' => $this->randomName(32), 'format' => $default_format)),
         'langcode' => 'en',
       ),
+      // After the third node, we don't care what the settings are. But we
+      // need to have at least 5 to make sure the throttling is working
+      // correctly. So, let's make 8 total.
+      array(
+      ),
+      array(
+      ),
+      array(
+      ),
+      array(
+      ),
+      array(
+      ),
     );
     $this->searchable_nodes = array();
     foreach ($nodes as $setting) {
@@ -95,11 +122,8 @@ function setUp() {
     $translation->body->value = $this->randomName(32);
     $this->searchable_nodes[2]->save();
 
-    // Create a user who can administer search and do searches.
-    $user = $this->drupalCreateUser(array('administer search', 'search content', 'use advanced search', 'access content'));
-    $this->drupalLogin($user);
-
-    $this->plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
+    // Verify that we have 8 nodes left to do.
+    $this->assertIndexCounts(8, 8, 'before updating the search index');
   }
 
   /**
@@ -109,7 +133,8 @@ function testMultilingualSearch() {
     // Index only 2 nodes per cron run. We cannot do this setting in the UI,
     // because it doesn't go this low.
     \Drupal::config('search.settings')->set('index.cron_limit', 2)->save();
-    $this->assertIndexCounts(3, 3, 'before updating the search index');
+    // Get a new search plugin, to make sure it has this setting.
+    $this->plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
 
     // Update the index. This does the initial processing.
     $this->plugin->updateIndex();
@@ -117,16 +142,18 @@ function testMultilingualSearch() {
     // and searching has to happen in the same request, so running the shutdown
     // function manually is needed to finish the indexing process.
     search_update_totals();
-    $this->assertIndexCounts(1, 3, 'after updating partially');
+    $this->assertIndexCounts(6, 8, 'after updating partially');
 
     // Now index the rest of the nodes.
     // Make sure index throttle is high enough, via the UI.
     $this->drupalPostForm('admin/config/search/pages', array('cron_limit' => 20), t('Save configuration'));
     $this->assertEqual(20, \Drupal::config('search.settings')->get('index.cron_limit', 100), 'Config setting was saved correctly');
+    // Get a new search plugin, to make sure it has this setting.
+    $this->plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
 
     $this->plugin->updateIndex();
     search_update_totals();
-    $this->assertIndexCounts(0, 3, 'after updating fully');
+    $this->assertIndexCounts(0, 8, 'after updating fully');
 
     // Test search results.
 
@@ -167,17 +194,17 @@ function testMultilingualSearch() {
     // Mark one of the nodes for reindexing, using the API function, and
     // verify indexing status.
     search_reindex($this->searchable_nodes[0]->id(), 'node_search');
-    $this->assertIndexCounts(1, 3, 'after marking one node to reindex via API function');
+    $this->assertIndexCounts(1, 8, 'after marking one node to reindex via API function');
 
     // Update the index and verify the totals again.
     $this->plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
     $this->plugin->updateIndex();
     search_update_totals();
-    $this->assertIndexCounts(0, 3, 'after indexing again');
+    $this->assertIndexCounts(0, 8, 'after indexing again');
 
     // Mark one node for reindexing by saving it, and verify indexing status.
     $this->searchable_nodes[1]->save();
-    $this->assertIndexCounts(1, 3, 'after marking one node to reindex via save');
+    $this->assertIndexCounts(1, 8, 'after marking one node to reindex via save');
 
     // The request time is always the same throughout test runs. Update the
     // request time to a previous time, to simulate it having been marked
@@ -211,8 +238,26 @@ function testMultilingualSearch() {
    *   Message to use, something like "after updating the search index".
    */
   protected function assertIndexCounts($remaining, $total, $message) {
+    // Check status via plugin method call.
     $status = $this->plugin->indexStatus();
     $this->assertEqual($status['remaining'], $remaining, 'Remaining items ' . $message . ' is ' . $remaining);
     $this->assertEqual($status['total'], $total, 'Total items ' . $message . ' is ' . $total);
+
+    // Check text in progress section of Search settings page. Note that this
+    // test avoids using format_plural(), so it tests for fragments of text.
+    $indexed = $total - $remaining;
+    $percent = ($total > 0) ? floor(100 * $indexed / $total) : 100;
+    $this->drupalGet('admin/config/search/pages');
+    $this->assertText($percent . '% of the site has been indexed.', 'Progress percent text at top of Search settings page is correct at: ' . $message);
+    $this->assertText($remaining . ' item', 'Remaining text at top of Search settings page is correct at: ' . $message);
+
+    // Check text in pages section of Search settings page.
+    $this->assertText($indexed . ' of ' . $total . ' indexed', 'Progress text in pages section of Search settings page is correct at: ' . $message);
+
+    // Check text on status report page.
+    $this->drupalGet('admin/reports/status');
+    $this->assertText('Search index progress', 'Search status section header is present on status report page');
+    $this->assertText($percent . '%', 'Correct percentage is shown on status report page at: ' . $message);
+    $this->assertText('(' . $remaining . ' remaining)', 'Correct remaining value is shown on status report page at: ' . $message);
   }
 }
-- 
GitLab