diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index f44ebc46850f4bece658165fbe81703161a1460e..272b2d65194ee9795a7c4079cbc486b45387f992 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -339,6 +339,14 @@ condition.plugin: sequence: type: string +condition.plugin.entity_bundle:*: + type: condition.plugin + mapping: + bundles: + type: sequence + sequence: + type: string + display_variant.plugin: type: mapping label: 'Display variant' diff --git a/core/lib/Drupal/Core/Entity/Plugin/Condition/Deriver/EntityBundle.php b/core/lib/Drupal/Core/Entity/Plugin/Condition/Deriver/EntityBundle.php new file mode 100644 index 0000000000000000000000000000000000000000..de4c48509937861eb192508dfba849087fac5efe --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Plugin/Condition/Deriver/EntityBundle.php @@ -0,0 +1,59 @@ +<?php + +namespace Drupal\Core\Entity\Plugin\Condition\Deriver; + +use Drupal\Component\Plugin\Derivative\DeriverBase; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Plugin\Context\EntityContextDefinition; +use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Deriver that creates a condition for each entity type with bundles. + */ +class EntityBundle extends DeriverBase implements ContainerDeriverInterface { + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructs a new EntityBundle. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + */ + public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) { + if ($entity_type->hasKey('bundle')) { + $this->derivatives[$entity_type_id] = $base_plugin_definition; + $this->derivatives[$entity_type_id]['label'] = $entity_type->getBundleLabel(); + $this->derivatives[$entity_type_id]['provider'] = $entity_type->getProvider(); + $this->derivatives[$entity_type_id]['context_definitions'] = [ + $entity_type_id => EntityContextDefinition::fromEntityType($entity_type), + ]; + } + } + return $this->derivatives; + } + +} diff --git a/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php b/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php new file mode 100644 index 0000000000000000000000000000000000000000..f073fdbcc12ef16a8eaa2f4a3f233d617fd164da --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php @@ -0,0 +1,144 @@ +<?php + +namespace Drupal\Core\Entity\Plugin\Condition; + +use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Provides the 'Entity Bundle' condition. + * + * @Condition( + * id = "entity_bundle", + * deriver = "\Drupal\Core\Entity\Plugin\Condition\Deriver\EntityBundle", + * ) + */ +class EntityBundle extends ConditionPluginBase implements ContainerFactoryPluginInterface { + + /** + * The entity type bundle info service. + * + * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface + */ + protected $entityTypeBundleInfo; + + /** + * Creates a new EntityBundle instance. + * + * @param array $configuration + * The plugin configuration, i.e. an array with configuration values keyed + * by configuration option name. The special key 'context' may be used to + * initialize the defined contexts by setting it to an array of context + * values keyed by context names. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info + * The entity type bundle info service. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeBundleInfoInterface $entity_type_bundle_info) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->entityTypeBundleInfo = $entity_type_bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $bundles = $this->entityTypeBundleInfo->getBundleInfo($this->getDerivativeId()); + $form['bundles'] = [ + '#title' => $this->pluginDefinition['label'], + '#type' => 'checkboxes', + '#options' => array_combine(array_keys($bundles), array_column($bundles, 'label')), + '#default_value' => $this->configuration['bundles'], + ]; + return parent::buildConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + $this->configuration['bundles'] = array_filter($form_state->getValue('bundles')); + parent::submitConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + // Returns true if no bundles are selected and negate option is disabled. + if (empty($this->configuration['bundles']) && !$this->isNegated()) { + return TRUE; + } + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + $entity = $this->getContextValue($this->getDerivativeId()); + return !empty($this->configuration['bundles'][$entity->bundle()]); + } + + /** + * {@inheritdoc} + */ + public function summary() { + if (count($this->configuration['bundles']) > 1) { + $bundles = $this->configuration['bundles']; + $last = array_pop($bundles); + $bundles = implode(', ', $bundles); + + if (empty($this->configuration['negate'])) { + return $this->t('@bundle_type is @bundles or @last', [ + '@bundle_type' => $this->pluginDefinition['label'], + '@bundles' => $bundles, + '@last' => $last, + ]); + } + else { + return $this->t('@bundle_type is not @bundles or @last', [ + '@bundle_type' => $this->pluginDefinition['label'], + '@bundles' => $bundles, + '@last' => $last, + ]); + } + } + $bundle = reset($this->configuration['bundles']); + + if (empty($this->configuration['negate'])) { + return $this->t('@bundle_type is @bundle', [ + '@bundle_type' => $this->pluginDefinition['label'], + '@bundle' => $bundle, + ]); + } + else { + return $this->t('@bundle_type is not @bundle', [ + '@bundle_type' => $this->pluginDefinition['label'], + '@bundle' => $bundle, + ]); + } + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'bundles' => [], + ] + parent::defaultConfiguration(); + } + +} diff --git a/core/misc/cspell/dictionary.txt b/core/misc/cspell/dictionary.txt index f6328a4e3f1cf06645403afa4ed8fa88eaecac10..53cfc3332a17fd2ac7de7ae70cf13038627dddda 100644 --- a/core/misc/cspell/dictionary.txt +++ b/core/misc/cspell/dictionary.txt @@ -191,6 +191,7 @@ buildtest bundable bundleable bundleless +bundlenode buttonpane buttonset buytaert diff --git a/core/modules/block/block.post_update.php b/core/modules/block/block.post_update.php index 5b4e241d3934c96e739dcd85f445f381edcaf199..6196fad620a9f82b5a20ce8c303fb436f8125ed7 100644 --- a/core/modules/block/block.post_update.php +++ b/core/modules/block/block.post_update.php @@ -15,3 +15,21 @@ function block_removed_post_updates() { 'block_post_update_fix_negate_in_conditions' => '9.0.0', ]; } + +/** + * Updates the node type visibility condition. + */ +function block_post_update_replace_node_type_condition() { + $config_factory = \Drupal::configFactory(); + foreach ($config_factory->listAll('block.block.') as $block_config_name) { + $block = $config_factory->getEditable($block_config_name); + + if ($block->get('visibility.node_type')) { + $configuration = $block->get('visibility.node_type'); + $configuration['id'] = 'entity_bundle:node'; + $block->set('visibility.entity_bundle:node', $configuration); + $block->clear('visibility.node_type'); + $block->save(TRUE); + } + } +} diff --git a/core/modules/block/js/block.es6.js b/core/modules/block/js/block.es6.js index 00a01df227b60f67d81a2267ffb3d9218585b7fe..4d949639d621a3abd4cfb9e94d01d262857e945c 100644 --- a/core/modules/block/js/block.es6.js +++ b/core/modules/block/js/block.es6.js @@ -46,7 +46,7 @@ } $( - '[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"]', + '[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-entity-bundlenode"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"]', ).drupalSetSummary(checkboxesSummary); $( diff --git a/core/modules/block/js/block.js b/core/modules/block/js/block.js index 4a78a8cfdb435708722a27a8762a575a54ac6051..167cd2a1a0b1fd6161353aa1e71096f355b503ce 100644 --- a/core/modules/block/js/block.js +++ b/core/modules/block/js/block.js @@ -28,7 +28,7 @@ return vals.join(', '); } - $('[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"]').drupalSetSummary(checkboxesSummary); + $('[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-entity-bundlenode"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"]').drupalSetSummary(checkboxesSummary); $('[data-drupal-selector="edit-visibility-request-path"]').drupalSetSummary(function (context) { var $pages = $(context).find('textarea[name="visibility[request_path][pages]"]'); diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php index f5d476700b4a97d906af93d870853b7099cab13e..22c35644e66971b640f17747f2fb662bcdbc28b3 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -237,6 +237,16 @@ protected function buildVisibilityInterface(array $form, FormStateInterface $for if ($condition_id == 'language' && !$this->language->isMultilingual()) { continue; } + + // Don't display the deprecated node type condition unless it has existing + // settings. + // @todo Make this more generic in + // https://www.drupal.org/project/drupal/issues/2922451. Also remove + // the node_type specific logic below. + if ($condition_id == 'node_type' && !isset($visibility[$condition_id])) { + continue; + } + /** @var \Drupal\Core\Condition\ConditionInterface $condition */ $condition = $this->manager->createInstance($condition_id, isset($visibility[$condition_id]) ? $visibility[$condition_id] : []); $form_state->set(['conditions', $condition_id], $condition); @@ -248,12 +258,17 @@ protected function buildVisibilityInterface(array $form, FormStateInterface $for } if (isset($form['node_type'])) { - $form['node_type']['#title'] = $this->t('Content types'); + $form['node_type']['#title'] = $this->t('Content types (deprecated)'); $form['node_type']['bundles']['#title'] = $this->t('Content types'); $form['node_type']['negate']['#type'] = 'value'; $form['node_type']['negate']['#title_display'] = 'invisible'; $form['node_type']['negate']['#value'] = $form['node_type']['negate']['#default_value']; } + if (isset($form['entity_bundle:node'])) { + $form['entity_bundle:node']['negate']['#type'] = 'value'; + $form['entity_bundle:node']['negate']['#title_display'] = 'invisible'; + $form['entity_bundle:node']['negate']['#value'] = $form['entity_bundle:node']['negate']['#default_value']; + } if (isset($form['user_role'])) { $form['user_role']['#title'] = $this->t('Roles'); unset($form['user_role']['roles']['#description']); diff --git a/core/modules/block/tests/src/Functional/Update/BlockNodeTypeVisibilityUpdateTest.php b/core/modules/block/tests/src/Functional/Update/BlockNodeTypeVisibilityUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7f44f3acb59313144077424832d3b983aff1bb42 --- /dev/null +++ b/core/modules/block/tests/src/Functional/Update/BlockNodeTypeVisibilityUpdateTest.php @@ -0,0 +1,46 @@ +<?php + +namespace Drupal\Tests\block\Functional\Update; + +use Drupal\FunctionalTests\Update\UpdatePathTestBase; + +/** + * Tests the upgrade path for updating the node type visibility condition. + * + * @group Update + */ +class BlockNodeTypeVisibilityUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-9.0.0.filled.standard.php.gz', + ]; + } + + /** + * Tests that block context mapping is updated properly. + * + * @group legacy + */ + public function testBlock() { + $bundles = [ + 'article' => 'article', + 'test_content_type' => 'test_content_type', + ]; + + $block = \Drupal::config('block.block.stark_testblock'); + $this->assertEquals($bundles, $block->get('visibility.node_type.bundles')); + $this->assertNull($block->get('visibility.entity_bundle:node')); + + $this->runUpdates(); + + $block = \Drupal::config('block.block.stark_testblock'); + $this->assertEquals($bundles, $block->get('visibility.entity_bundle:node.bundles')); + $this->assertEquals('entity_bundle:node', $block->get('visibility.entity_bundle:node.id')); + $this->assertNull($block->get('visibility.node_type')); + } + +} diff --git a/core/modules/node/config/schema/node.schema.yml b/core/modules/node/config/schema/node.schema.yml index 862a39651a28336362235930faddd724492664b7..2c45383a60ac50f591da442a0e7a3377644b141a 100644 --- a/core/modules/node/config/schema/node.schema.yml +++ b/core/modules/node/config/schema/node.schema.yml @@ -91,6 +91,7 @@ block.settings.node_syndicate_block: label: 'Block count' condition.plugin.node_type: + deprecated: "The 'condition.plugin.node_type' config schema is deprecated in drupal:9.3.0 and is removed from drupal 10.0.0. Use the 'entity_bundle:node_type' key instead to define a node type condition. See https://www.drupal.org/node/2983299." type: condition.plugin mapping: bundles: diff --git a/core/modules/node/src/Plugin/Condition/NodeType.php b/core/modules/node/src/Plugin/Condition/NodeType.php index ba8726d5374265b345815ab4b643c26ba329b086..a70b818501b065818acb69b50d44a91b346f4138 100644 --- a/core/modules/node/src/Plugin/Condition/NodeType.php +++ b/core/modules/node/src/Plugin/Condition/NodeType.php @@ -13,11 +13,16 @@ * * @Condition( * id = "node_type", - * label = @Translation("Node Bundle"), + * label = @Translation("Node Bundle (Deprecated)"), * context_definitions = { * "node" = @ContextDefinition("entity:node", label = @Translation("Node")) * } * ) + * + * @deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. + * Use \Drupal\Core\Entity\Plugin\Condition\EntityBundle instead. + * + * @see https://www.drupal.org/node/2983299 */ class NodeType extends ConditionPluginBase implements ContainerFactoryPluginInterface { @@ -45,6 +50,7 @@ class NodeType extends ConditionPluginBase implements ContainerFactoryPluginInte */ public function __construct(EntityStorageInterface $entity_storage, array $configuration, $plugin_id, $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); + @trigger_error('\Drupal\node\Plugin\Condition\NodeType is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use \Drupal\Core\Entity\Plugin\Condition\EntityBundle instead. See https://www.drupal.org/node/2983299', E_USER_DEPRECATED); $this->entityStorage = $entity_storage; } diff --git a/core/modules/node/tests/src/Functional/NodeBlockFunctionalTest.php b/core/modules/node/tests/src/Functional/NodeBlockFunctionalTest.php index 36f38aaa883915eb844f1d74d06fce6d93634ced..5bad6e6d6f19e8a8ac40b034d751ec5e003d5039 100644 --- a/core/modules/node/tests/src/Functional/NodeBlockFunctionalTest.php +++ b/core/modules/node/tests/src/Functional/NodeBlockFunctionalTest.php @@ -141,18 +141,20 @@ public function testRecentNodeBlock() { $this->assertCacheContexts(['languages:language_content', 'languages:language_interface', 'theme', 'url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT, 'url.site', 'user']); // Enable the "Powered by Drupal" block only on article nodes. + $theme = \Drupal::service('theme_handler')->getDefault(); + $this->drupalGet("admin/structure/block/add/system_powered_by_block/{$theme}"); + $this->assertSession()->pageTextContains('Content type'); + $this->assertSession()->pageTextNotContains('Content types (Deprecated)'); $edit = [ 'id' => strtolower($this->randomMachineName()), 'region' => 'sidebar_first', - 'visibility[node_type][bundles][article]' => 'article', + 'visibility[entity_bundle:node][bundles][article]' => 'article', ]; - $theme = \Drupal::service('theme_handler')->getDefault(); - $this->drupalGet("admin/structure/block/add/system_powered_by_block/{$theme}"); $this->submitForm($edit, 'Save block'); $block = Block::load($edit['id']); $visibility = $block->getVisibility(); - $this->assertTrue(isset($visibility['node_type']['bundles']['article']), 'Visibility settings were saved to configuration'); + $this->assertTrue(isset($visibility['entity_bundle:node']['bundles']['article']), 'Visibility settings were saved to configuration'); // Create a page node. $node5 = $this->drupalCreateNode(['uid' => $this->adminUser->id(), 'type' => 'page']); @@ -232,4 +234,33 @@ public function testRecentNodeBlock() { $this->assertSession()->linkByHrefExists($block->toUrl()->toString()); } + /** + * Tests customization of deprecated node type condition. + * + * @group legacy + */ + public function testDeprecatedNodeTypeCondition() { + $this->expectDeprecation('\Drupal\node\Plugin\Condition\NodeType is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use \Drupal\Core\Entity\Plugin\Condition\EntityBundle instead. See https://www.drupal.org/node/2983299'); + $this->expectDeprecation("The 'condition.plugin.node_type' config schema is deprecated in drupal:9.3.0 and is removed from drupal 10.0.0. Use the 'entity_bundle:node_type' key instead to define a node type condition. See https://www.drupal.org/node/2983299."); + $this->drupalLogin($this->adminUser); + $this->drupalPlaceBlock('system_powered_by_block', [ + 'id' => 'powered_by_deprecated', + 'visibility' => [ + 'node_type' => [ + 'bundles' => [ + 'article' => 'article', + ], + ], + ], + 'context_mapping' => ['node' => '@node.node_route_context:node'], + ]); + + // On an existing block with the deprecated plugin, the deprecated + // label is shown. + $this->drupalGet("admin/structure/block/manage/powered_by_deprecated"); + $this->assertSession()->pageTextContains('Content type'); + $this->assertSession()->pageTextContains('Content types (Deprecated)'); + $this->submitForm([], 'Save'); + } + } diff --git a/core/modules/node/tests/src/Kernel/NodeConditionTest.php b/core/modules/node/tests/src/Kernel/NodeConditionTest.php index 6e5aad68caf5150b82a3192bccd325e22b643028..2aa4f0dfb2d7c49988de8d548a1288f4aa34197d 100644 --- a/core/modules/node/tests/src/Kernel/NodeConditionTest.php +++ b/core/modules/node/tests/src/Kernel/NodeConditionTest.php @@ -10,6 +10,7 @@ * Tests that conditions, provided by the node module, are working properly. * * @group node + * @group legacy */ class NodeConditionTest extends EntityKernelTestBase { @@ -31,6 +32,7 @@ protected function setUp(): void { * Tests conditions. */ public function testConditions() { + $this->expectDeprecation('\Drupal\node\Plugin\Condition\NodeType is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use \Drupal\Core\Entity\Plugin\Condition\EntityBundle instead. See https://www.drupal.org/node/2983299'); $manager = $this->container->get('plugin.manager.condition'); $this->createUser(); diff --git a/core/modules/system/tests/modules/condition_test/src/FormController.php b/core/modules/system/tests/modules/condition_test/src/FormController.php index 19dc9505bd288aef8cfee03967641c160895cbb0..04e3eff9a1f2d5adbdd898b9752a8b1edfc13855 100644 --- a/core/modules/system/tests/modules/condition_test/src/FormController.php +++ b/core/modules/system/tests/modules/condition_test/src/FormController.php @@ -31,7 +31,7 @@ public function getFormId() { */ public function __construct() { $manager = new ConditionManager(\Drupal::service('container.namespaces'), \Drupal::cache('discovery'), \Drupal::moduleHandler()); - $this->condition = $manager->createInstance('node_type'); + $this->condition = $manager->createInstance('entity_bundle:node'); } /** diff --git a/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestBaseFilledTest.php b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestBaseFilledTest.php index 56fbfc7d381b6ff9397e9b70570616f7af8d395d..bcb801103c2850379d0b9c490bb6f6afbe861a2d 100644 --- a/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestBaseFilledTest.php +++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathTestBaseFilledTest.php @@ -180,8 +180,8 @@ public function testUpdatedSite() { $this->drupalGet('admin/structure/block/manage/testblock'); $this->assertSession()->checkboxNotChecked('edit-visibility-language-langcodes-es'); $this->assertSession()->checkboxChecked('edit-visibility-language-langcodes-en'); - $this->assertSession()->checkboxNotChecked('edit-visibility-node-type-bundles-book'); - $this->assertSession()->checkboxChecked('edit-visibility-node-type-bundles-test-content-type'); + $this->assertSession()->checkboxNotChecked('edit-visibility-entity-bundlenode-bundles-book'); + $this->assertSession()->checkboxChecked('edit-visibility-entity-bundlenode-bundles-test-content-type'); // Make sure our block is still translated. $this->drupalGet('admin/structure/block/manage/testblock/translate/es/edit'); diff --git a/core/profiles/demo_umami/config/install/block.block.umami_views_block__articles_aside_block_1.yml b/core/profiles/demo_umami/config/install/block.block.umami_views_block__articles_aside_block_1.yml index 83125975a44caf1ad9fa0f270579e9244a054dfc..a6859df75cda3a54d1503954d4b5b737d12517e5 100644 --- a/core/profiles/demo_umami/config/install/block.block.umami_views_block__articles_aside_block_1.yml +++ b/core/profiles/demo_umami/config/install/block.block.umami_views_block__articles_aside_block_1.yml @@ -22,8 +22,8 @@ settings: views_label: '' items_per_page: none visibility: - node_type: - id: node_type + entity_bundle:node: + id: entity_bundle:node bundles: article: article negate: false diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleConditionTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleConditionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8f0296e5f4d97302d78f97e8a2b1aa6731a6d3ee --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleConditionTest.php @@ -0,0 +1,84 @@ +<?php + +namespace Drupal\KernelTests\Core\Entity; + +use Drupal\entity_test\Entity\EntityTestBundle; +use Drupal\entity_test\Entity\EntityTestWithBundle; + +/** + * Tests that entity bundle conditions works properly. + * + * @group Entity + */ +class EntityBundleConditionTest extends EntityKernelTestBase { + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->installEntitySchema('entity_test_with_bundle'); + + // Create the entity bundles required for testing. + $bundle = EntityTestBundle::create(['id' => 'page', 'label' => 'page']); + $bundle->save(); + $bundle = EntityTestBundle::create(['id' => 'article', 'label' => 'article']); + $bundle->save(); + $bundle = EntityTestBundle::create(['id' => 'test', 'label' => 'test']); + $bundle->save(); + } + + /** + * Tests conditions. + */ + public function testConditions() { + $this->createUser(); + // Get some entities of various bundles to check against. + $page = EntityTestWithBundle::create(['type' => 'page', 'name' => $this->randomMachineName()]); + $page->save(); + $article = EntityTestWithBundle::create(['type' => 'article', 'name' => $this->randomMachineName()]); + $article->save(); + $test = EntityTestWithBundle::create(['type' => 'test', 'name' => $this->randomMachineName()]); + $test->save(); + + // Grab the bundle condition and configure it to check against bundle of + // 'article' and set the context to the page type entity. + /** @var \Drupal\Core\Entity\Plugin\Condition\EntityBundle $condition */ + $condition = $this->container->get('plugin.manager.condition')->createInstance('entity_bundle:entity_test_with_bundle') + ->setConfig('bundles', ['article' => 'article']) + ->setContextValue('entity_test_with_bundle', $page); + $this->assertFalse($condition->execute(), 'Page type entities fail bundle checks for articles.'); + // Check for the proper summary. + $this->assertEquals('Test entity bundle is article', $condition->summary()); + $this->assertEquals('entity_test', $condition->getPluginDefinition()['provider']); + + // Set the bundle check to page. + $condition->setConfig('bundles', ['page' => 'page']); + $this->assertTrue($condition->execute(), 'Page type entities pass bundle checks for pages'); + // Check for the proper summary. + $this->assertEquals('Test entity bundle is page', $condition->summary()); + + // Set the bundle check to page or article. + $condition->setConfig('bundles', ['page' => 'page', 'article' => 'article']); + $this->assertTrue($condition->execute(), 'Page type entities pass bundle checks for pages or articles'); + // Check for the proper summary. + $this->assertEquals('Test entity bundle is page or article', $condition->summary()); + + // Set the context to the article entity. + $condition->setContextValue('entity_test_with_bundle', $article); + $this->assertTrue($condition->execute(), 'Article type entities pass bundle checks for pages or articles'); + + // Set the context to the test entity. + $condition->setContextValue('entity_test_with_bundle', $test); + $this->assertFalse($condition->execute(), 'Test type entities pass bundle checks for pages or articles'); + + // Check a greater than 2 bundles summary scenario. + $condition->setConfig('bundles', [ + 'page' => 'page', + 'article' => 'article', + 'test' => 'test', + ]); + $this->assertEquals('Test entity bundle is page, article or test', $condition->summary()); + } + +}