From 1606a9f82ad58d43755c5e9debec317a9638468c Mon Sep 17 00:00:00 2001 From: tuutti Date: Wed, 9 Aug 2023 09:59:46 +0300 Subject: [PATCH 1/3] UHF-8636: Debug page item for search api index --- .../helfi_react_search.info.yml | 1 + .../helfi_react_search.module | 16 +++ .../Plugin/DebugDataItem/SearchApiIndex.php | 103 +++++++++++++++ .../debug-item--search-api.html.twig | 45 +++++++ .../tests/src/Unit/SearchApiIndexItemTest.php | 122 ++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php create mode 100644 modules/helfi_react_search/templates/debug-item--search-api.html.twig create mode 100644 modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php diff --git a/modules/helfi_react_search/helfi_react_search.info.yml b/modules/helfi_react_search/helfi_react_search.info.yml index 5034c45a7..a4891f465 100644 --- a/modules/helfi_react_search/helfi_react_search.info.yml +++ b/modules/helfi_react_search/helfi_react_search.info.yml @@ -11,6 +11,7 @@ dependencies: - 'drupal:text' - 'helfi_platform_config:helfi_platform_config' - 'paragraphs:paragraphs' + - 'search_api:search_api' package: HELfi 'interface translation project': helfi_react_search 'interface translation server pattern': modules/contrib/helfi_platform_config/helfi_features/helfi_react_search/translations/%language.po diff --git a/modules/helfi_react_search/helfi_react_search.module b/modules/helfi_react_search/helfi_react_search.module index 1d5df6ca1..2079621f7 100644 --- a/modules/helfi_react_search/helfi_react_search.module +++ b/modules/helfi_react_search/helfi_react_search.module @@ -37,3 +37,19 @@ function helfi_react_search_preprocess_paragraph(array &$variables) : void { $variables['#attached']['drupalSettings']['helfi_react_search']['elastic_proxy_url'] = $proxyUrl; } } + +/** + * Implements hook_theme(). + */ +function helfi_react_search_theme() : array { + return [ + 'debug_item__search_api' => [ + 'variables' => [ + 'id' => NULL, + 'label' => NULL, + 'data' => [], + ], + 'template' => 'debug-item--search-api', + ], + ]; +} diff --git a/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php b/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php new file mode 100644 index 000000000..485a586d8 --- /dev/null +++ b/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php @@ -0,0 +1,103 @@ +entityTypeManager = $container->get('entity_type.manager'); + + return $instance; + } + + /** + * {@inheritdoc} + */ + public function collect(): array { + $data = []; + + $indexes = $this->entityTypeManager + ->getStorage('search_api_index') + ->loadMultiple(); + + if (!$indexes) { + return []; + } + /** @var \Drupal\search_api\IndexInterface $index */ + foreach ($indexes as $index) { + $result = $status = NULL; + + try { + $status = $index->getServerInstance()?->isAvailable(); + $tracker = $index->getTrackerInstance(); + + $result = $this->resolveResult( + $tracker->getIndexedItemsCount(), + $tracker->getTotalItemsCount() + ); + + } + catch (SearchApiException) { + } + $data[] = [ + 'id' => $index->getOriginalId(), + 'result' => $result, + 'status' => $status, + ]; + } + + return $data; + } + + /** + * Resolve return value based on index status. + * + * @param int $indexed + * Amount of up-to-date items in index. + * @param int $total + * Maximum number of items in index. + * + * @return string + * Status. + */ + private function resolveResult(int $indexed, int $total): string { + if ($indexed == 0 || $total == 0) { + return 'indexing or index rebuild required'; + } + + if ($indexed === $total) { + return 'Index up to date'; + } + + return "$indexed/$total"; + } + +} diff --git a/modules/helfi_react_search/templates/debug-item--search-api.html.twig b/modules/helfi_react_search/templates/debug-item--search-api.html.twig new file mode 100644 index 000000000..2f50f3989 --- /dev/null +++ b/modules/helfi_react_search/templates/debug-item--search-api.html.twig @@ -0,0 +1,45 @@ +{# +/** + * To actually show any data from a custom plugin, you *MUST* override this template + * with a template called 'debug-item--{{ id }}.html.twig'. + * + * For example: debug-item--composer.html.twig, where 'composer' is your plugin's ID. + * + * You can then loop your data with something like this: + * {% for item in data.packages %} + * {{ item.name }} + * {{ item.version }} + * {% endfor %} + * + * Available variables: + * - id: The ID of your plugin + * - label The label of your plugin + * - data: An array of data returned by your plugin's collect() method. + */ +#} + +

{{ 'Search API indexes'|t }}

+ + + + + + + + + + {% for value in data %} + + + + + + {% endfor %} + +
IndexStatusResult
+ {{ value.id }} + + {{ value.status ? 'Online'|t : 'Offline'|t }} + + {{ value.result }} +
diff --git a/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php b/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php new file mode 100644 index 000000000..82ffc256c --- /dev/null +++ b/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php @@ -0,0 +1,122 @@ +prophesize(SearchApiConfigEntityStorage::class); + $indexStorage->loadMultiple()->willReturn([]); + $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $entityTypeManager->getStorage('search_api_index') + ->willReturn($indexStorage->reveal()); + $container = new ContainerBuilder(); + $container->set('entity_type.manager', $entityTypeManager->reveal()); + + $sut = SearchApiIndex::create($container, [], '', []); + $this->assertEmpty($sut->collect()); + } + + /** + * @covers ::create + * @covers ::collect + * @covers ::resolveResult + */ + public function testCollect() : void { + $index1 = $this->prophesize(IndexInterface::class); + $index1->getOriginalId()->willReturn('index1'); + $index1->getServerInstance()->willThrow(new SearchApiException()); + + $server = $this->prophesize(ServerInterface::class); + $server->isAvailable()->willReturn(TRUE); + + $tracker2 = $this->prophesize(TrackerInterface::class); + $tracker2->getIndexedItemsCount()->willReturn(0); + $tracker2->getTotalItemsCount()->willReturn(0); + + $index2 = $this->prophesize(IndexInterface::class); + $index2->getOriginalId()->willReturn('index2'); + $index2->getServerInstance()->willReturn($server->reveal()); + $index2->getTrackerInstance()->willReturn($tracker2->reveal()); + + $tracker3 = $this->prophesize(TrackerInterface::class); + $tracker3->getIndexedItemsCount()->willReturn(20); + $tracker3->getTotalItemsCount()->willReturn(20); + + $index3 = $this->prophesize(IndexInterface::class); + $index3->getOriginalId()->willReturn('index3'); + $index3->getServerInstance()->willReturn($server->reveal()); + $index3->getTrackerInstance()->willReturn($tracker3->reveal()); + + $tracker4 = $this->prophesize(TrackerInterface::class); + $tracker4->getIndexedItemsCount()->willReturn(10); + $tracker4->getTotalItemsCount()->willReturn(20); + $index4 = $this->prophesize(IndexInterface::class); + $index4->getOriginalId()->willReturn('index4'); + $index4->getServerInstance()->willReturn($server->reveal()); + $index4->getTrackerInstance()->willReturn($tracker4->reveal()); + + $indexStorage = $this->prophesize(SearchApiConfigEntityStorage::class); + $indexStorage->loadMultiple()->willReturn([ + $index1->reveal(), + $index2->reveal(), + $index3->reveal(), + $index4->reveal(), + ]); + $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $entityTypeManager->getStorage('search_api_index') + ->willReturn($indexStorage->reveal()); + $container = new ContainerBuilder(); + $container->set('entity_type.manager', $entityTypeManager->reveal()); + + $sut = SearchApiIndex::create($container, [], '', []); + $this->assertEquals([ + [ + 'id' => 'index1', + 'result' => NULL, + 'status' => NULL, + ], + [ + 'id' => 'index2', + 'result' => 'indexing or index rebuild required', + 'status' => TRUE, + ], + [ + 'id' => 'index3', + 'result' => 'Index up to date', + 'status' => TRUE, + ], + [ + 'id' => 'index4', + 'result' => '10/20', + 'status' => TRUE, + ], + ], $sut->collect()); + } + +} From 8598e02b6150962e46db550bb22b8eb2614ebb68 Mon Sep 17 00:00:00 2001 From: tuutti Date: Wed, 9 Aug 2023 10:03:14 +0300 Subject: [PATCH 2/3] UHF-8636: Added aria label --- .../templates/debug-item--search-api.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/helfi_react_search/templates/debug-item--search-api.html.twig b/modules/helfi_react_search/templates/debug-item--search-api.html.twig index 2f50f3989..d3fa9fccf 100644 --- a/modules/helfi_react_search/templates/debug-item--search-api.html.twig +++ b/modules/helfi_react_search/templates/debug-item--search-api.html.twig @@ -19,7 +19,7 @@ #}

{{ 'Search API indexes'|t }}

- +
From 317f35fc00058285e2d7578ce501c6c43ff17731 Mon Sep 17 00:00:00 2001 From: tuutti Date: Tue, 15 Aug 2023 08:42:49 +0300 Subject: [PATCH 3/3] UHF-8636: Removed search_api dependency --- .../helfi_react_search.info.yml | 1 - .../src/Plugin/DebugDataItem/SearchApiIndex.php | 5 ++++- .../tests/src/Unit/SearchApiIndexItemTest.php | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/modules/helfi_react_search/helfi_react_search.info.yml b/modules/helfi_react_search/helfi_react_search.info.yml index a4891f465..5034c45a7 100644 --- a/modules/helfi_react_search/helfi_react_search.info.yml +++ b/modules/helfi_react_search/helfi_react_search.info.yml @@ -11,7 +11,6 @@ dependencies: - 'drupal:text' - 'helfi_platform_config:helfi_platform_config' - 'paragraphs:paragraphs' - - 'search_api:search_api' package: HELfi 'interface translation project': helfi_react_search 'interface translation server pattern': modules/contrib/helfi_platform_config/helfi_features/helfi_react_search/translations/%language.po diff --git a/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php b/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php index 485a586d8..b6ff0ea9d 100644 --- a/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php +++ b/modules/helfi_react_search/src/Plugin/DebugDataItem/SearchApiIndex.php @@ -31,7 +31,7 @@ final class SearchApiIndex extends DebugDataItemPluginBase implements ContainerF /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) : self { $instance = new self($configuration, $plugin_id, $plugin_definition); $instance->entityTypeManager = $container->get('entity_type.manager'); @@ -44,6 +44,9 @@ public static function create(ContainerInterface $container, array $configuratio public function collect(): array { $data = []; + if (!$this->entityTypeManager->hasDefinition('search_api_index')) { + return []; + } $indexes = $this->entityTypeManager ->getStorage('search_api_index') ->loadMultiple(); diff --git a/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php b/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php index 82ffc256c..3db830ffa 100644 --- a/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php +++ b/modules/helfi_react_search/tests/src/Unit/SearchApiIndexItemTest.php @@ -25,6 +25,19 @@ class SearchApiIndexItemTest extends UnitTestCase { use ProphecyTrait; + /** + * @covers ::create + * @covers ::collect + */ + public function testNoSearchApiStorage() : void { + $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $entityTypeManager->hasDefinition('search_api_index')->willReturn(FALSE); + $container = new ContainerBuilder(); + $container->set('entity_type.manager', $entityTypeManager->reveal()); + $sut = SearchApiIndex::create($container, [], '', []); + $this->assertEmpty($sut->collect()); + } + /** * @covers ::create * @covers ::collect @@ -33,6 +46,8 @@ public function testNoIndex() : void { $indexStorage = $this->prophesize(SearchApiConfigEntityStorage::class); $indexStorage->loadMultiple()->willReturn([]); $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $entityTypeManager->hasDefinition('search_api_index') + ->willReturn(TRUE); $entityTypeManager->getStorage('search_api_index') ->willReturn($indexStorage->reveal()); $container = new ContainerBuilder(); @@ -91,6 +106,8 @@ public function testCollect() : void { $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); $entityTypeManager->getStorage('search_api_index') ->willReturn($indexStorage->reveal()); + $entityTypeManager->hasDefinition('search_api_index') + ->willReturn(TRUE); $container = new ContainerBuilder(); $container->set('entity_type.manager', $entityTypeManager->reveal());
Index