From da51533e09939eb02264d7a5650e118ac1c9bc27 Mon Sep 17 00:00:00 2001 From: Andy Broomfield Date: Mon, 22 May 2023 10:03:30 +0100 Subject: [PATCH] Check that type of alert field exists before using as a sort for current banners During import, and in times where the type_of_alert field has been deleted, the getCurrentBanners method will try to perform an entity query, but it needs to check the field is present before adding a sort. --- src/Plugin/Block/AlertBannerBlock.php | 19 ++++++- .../src/Kernel/AlertBannerBlockOrderTest.php | 55 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/Plugin/Block/AlertBannerBlock.php b/src/Plugin/Block/AlertBannerBlock.php index aaa8f82c..837a6e78 100644 --- a/src/Plugin/Block/AlertBannerBlock.php +++ b/src/Plugin/Block/AlertBannerBlock.php @@ -7,6 +7,7 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Block\BlockBase; @@ -168,14 +169,26 @@ protected function getCurrentAlertBanners() { $types = $this->mapTypesConfigToQuery(); $published_alert_banner_query = $this->entityTypeManager->getStorage('localgov_alert_banner') ->getQuery() - ->condition('status', 1) - ->sort('type_of_alert', 'DESC') - ->sort('changed', 'DESC') + ->condition('status', 1); + + // Only order by type of alert if the field is present. + $alert_banner_has_type_of_alert = FieldStorageConfig::loadByName('localgov_alert_banner', 'type_of_alert'); + if (!empty($alert_banner_has_type_of_alert)) { + $published_alert_banner_query->sort('type_of_alert', 'DESC'); + } + + // Continue alert banner query. + $published_alert_banner_query->sort('changed', 'DESC') ->accessCheck(TRUE); + + // If types (bunldes) are selected, add filter condition. if (!empty($types)) { $published_alert_banner_query->condition('type', $types, 'IN'); } + + // Execute alert banner query. $published_alert_banners = $published_alert_banner_query->execute(); + // Load alert banners and add all. // Visibility check happens in build, so we get cache contexts on all. foreach ($published_alert_banners as $alert_banner_id) { diff --git a/tests/src/Kernel/AlertBannerBlockOrderTest.php b/tests/src/Kernel/AlertBannerBlockOrderTest.php index e4729763..ca2224cd 100644 --- a/tests/src/Kernel/AlertBannerBlockOrderTest.php +++ b/tests/src/Kernel/AlertBannerBlockOrderTest.php @@ -160,4 +160,59 @@ public function testAlertBannerBlockOrder() { } + /** + * Test alert banner block order without type of alert. + */ + public function testAlertBannerBlockOrderWithoutTypeOfAlert() { + + // Delete type of alert field. + // This is so we are testing the case where :- + // - Alerts don't have a type, so are in date order. + // - Querying for current banners without the type field is possible. + $this->container + ->get('entity_type.manager') + ->getStorage('field_storage_config') + ->load('localgov_alert_banner.type_of_alert') + ->delete(); + + // Alert times. + $alert_times = [ + (new DrupalDateTime('-4 hours'))->getTimestamp(), + (new DrupalDateTime('-2 hours'))->getTimestamp(), + (new DrupalDateTime('-3 hours'))->getTimestamp(), + (new DrupalDateTime('now'))->getTimestamp(), + ]; + + // Set up alert banners. + foreach ($alert_times as $changed) { + $alert_entity = $this->container->get('entity_type.manager')->getStorage('localgov_alert_banner') + ->create([ + 'type' => 'localgov_alert_banner', + 'title' => $this->randomMachineName(8), + 'moderation_state' => 'published', + 'changed' => $changed, + ]); + $alert_entity->save(); + $alert[] = $alert_entity->id(); + } + + // Create and render the block and get the alert banner IDs as an array. + $block_manager = $this->container->get('plugin.manager.block'); + $config = []; + $plugin_block = $block_manager->createInstance('localgov_alert_banner_block', $config); + $render = $plugin_block->build(); + foreach ($render as $render_value) { + $result[] = $render_value['#localgov_alert_banner']->id(); + } + + // Set expected order, which will be date changed order. + $expected = [ + $alert[3], + $alert[1], + $alert[2], + $alert[0], + ]; + $this->assertEquals($expected, $result); + } + }