diff --git a/core/modules/block_content/block_content.post_update.php b/core/modules/block_content/block_content.post_update.php index 592b3ee9714733913767241e7503c5f0ce1c44f2..280d2ba59f4287f3c767db8b6374827eb267d543 100644 --- a/core/modules/block_content/block_content.post_update.php +++ b/core/modules/block_content/block_content.post_update.php @@ -5,6 +5,9 @@ * Post update functions for Content Block. */ +use Drupal\Core\Config\Entity\ConfigEntityUpdater; +use Drupal\views\ViewEntityInterface; + /** * Implements hook_removed_post_updates(). */ @@ -18,3 +21,27 @@ function block_content_removed_post_updates(): array { 'block_content_post_update_revision_type' => '11.0.0', ]; } + +/** + * Removes the "area_text_custom" plugin from block content view configuration. + */ +function block_content_post_update_10301(?array &$sandbox = NULL): int { + \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function (ViewEntityInterface $view): bool { + $changed = FALSE; + + foreach ($view->get('display') as $display_id => $display) { + if ( + isset($display['display_options']['empty']['area_text_custom']) && + $display['display_options']['empty']['area_text_custom']['content'] === 'There are no content blocks available.' + ) { + unset($display['display_options']['empty']['area_text_custom']); + $view->set('display.' . $display_id . '.display_options.empty.area_text_custom', NULL); + $changed = TRUE; + } + } + + return $changed; + }); + + return 0; +} diff --git a/core/modules/block_content/config/optional/views.view.block_content.yml b/core/modules/block_content/config/optional/views.view.block_content.yml index 1bccbb4464672d02b4e50c44dbd90e2437b265c0..f0f47f48b7a78ab5118a0a9676c3d4eb51724664 100644 --- a/core/modules/block_content/config/optional/views.view.block_content.yml +++ b/core/modules/block_content/config/optional/views.view.block_content.yml @@ -303,17 +303,6 @@ display: type: tag options: { } empty: - area_text_custom: - id: area_text_custom - table: views - field: area_text_custom - relationship: none - group_type: group - admin_label: '' - plugin_id: text_custom - empty: true - content: 'There are no content blocks available.' - tokenize: false block_content_listing_empty: id: block_content_listing_empty table: block_content diff --git a/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php index b4ee4737e19bf8511a10f5b63c8cd7a3d26e9f66..c65f9cbc0e00e40cf04b893f169c0c7ec16a3215 100644 --- a/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php +++ b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php @@ -70,19 +70,32 @@ public static function create(ContainerInterface $container, array $configuratio */ public function render($empty = FALSE) { if (!$empty || !empty($this->options['empty'])) { - /** @var \Drupal\Core\Access\AccessResultInterface|\Drupal\Core\Cache\CacheableDependencyInterface $access_result */ + $message = $this->t('There are no content blocks available.'); + + // Construct the "Add a content block" link + // only if the user has the proper access. $access_result = $this->accessManager->checkNamedRoute('block_content.add_page', [], $this->currentUser, TRUE); + if ($access_result->isAllowed()) { + // Only show the link if the user has permission. + $add_link = $this->t('Add a <a href=":url">content block</a>.', [ + ':url' => Url::fromRoute('block_content.add_page')->toString(), + ]); + // Combine the message and the link. + $message .= ' ' . $add_link; + } + $element = [ - '#markup' => $this->t('Add a <a href=":url">content block</a>.', [':url' => Url::fromRoute('block_content.add_page')->toString()]), - '#access' => $access_result->isAllowed(), + '#markup' => $message, '#cache' => [ 'contexts' => $access_result->getCacheContexts(), 'tags' => $access_result->getCacheTags(), 'max-age' => $access_result->getCacheMaxAge(), ], ]; + return $element; } + return []; } diff --git a/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php b/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0c080706b93fcdb2592b9af25ef236307e0d9faf --- /dev/null +++ b/core/modules/block_content/tests/src/Kernel/BlockContentUpdateTest.php @@ -0,0 +1,142 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\block_content\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\views\Entity\View; + +/** + * Tests the block content update hook. + * + * @group block_content + */ +class BlockContentUpdateTest extends KernelTestBase { + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'block_content', + 'views', + 'user', + 'system', + 'config', + ]; + + /** + * The test view. + * + * @var \Drupal\views\Entity\View + */ + protected $view; + + /** + * Setup test environment. + */ + protected function setUp(): void { + parent::setUp(); + + $this->installEntitySchema('view'); + $this->installEntitySchema('block_content'); + $this->installEntitySchema('user'); + $this->installConfig(['block_content', 'views']); + + // Create a test view configuration with "area_text_custom". + $this->view = View::create([ + 'id' => 'block_content', + 'label' => 'Block Content Test View', + 'module' => 'views', + 'status' => TRUE, + 'display' => [ + 'default' => [ + 'display_options' => [ + 'empty' => [ + 'area_text_custom' => [ + 'id' => 'text_custom', + 'content' => 'There are no content blocks available.', + ], + ], + ], + ], + ], + ]); + $this->view->save(); + } + + /** + * Tests the update function. + */ + public function testUpdateHook(): void { + // Ensure the plugin exists before the update. + $this->assertTrue(isset($this->view->get('display')['default']['display_options']['empty']['area_text_custom'])); + + // Run the update function with sandbox. + $sandbox = []; + block_content_post_update_10301($sandbox); + + $updated_view = View::load('block_content'); + + // Verify the plugin is removed if it contains the default text. + $this->assertFalse(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom'])); + } + + /** + * Tests that a customized text area is NOT removed. + */ + public function testUpdateHookPreservesCustomText(): void { + $this->view->set('display.default.display_options.empty.area_text_custom.content', 'My custom message.'); + $this->view->save(); + + $sandbox = []; + block_content_post_update_10301($sandbox); + + $updated_view = View::load('block_content'); + + $this->assertTrue(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom'])); + } + + /** + * Tests batch processing of multiple views. + */ + public function testBatchProcessing(): void { + // Create additional views for batch testing. + for ($i = 1; $i <= 15; $i++) { + $view = View::create([ + 'id' => "block_content_$i", + 'label' => "Block Content Test View $i", + 'module' => 'views', + 'status' => TRUE, + 'display' => [ + 'default' => [ + 'display_options' => [ + 'empty' => [ + 'area_text_custom' => [ + 'id' => 'text_custom', + 'content' => 'There are no content blocks available.', + ], + ], + ], + ], + ], + ]); + $view->save(); + } + + // Run the update in batches. + $sandbox = []; + do { + block_content_post_update_10301($sandbox); + } while (!empty($sandbox)); + + // Verify that all views have been processed. + for ($i = 1; $i <= 15; $i++) { + $updated_view = View::load("block_content_$i"); + $this->assertFalse(isset($updated_view->get('display')['default']['display_options']['empty']['area_text_custom'])); + } + } + +}