diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index 5b0b0fa..e0ba242 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -314,6 +314,11 @@ block_settings: provider: type: string label: 'Provider' + context_mapping: + type: sequence + label: 'Context assignments' + sequence: + type: string condition.plugin: type: mapping diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php index 8a7fbfa..930d8ab 100644 --- a/core/lib/Drupal/Core/Block/BlockBase.php +++ b/core/lib/Drupal/Core/Block/BlockBase.php @@ -201,7 +201,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#options' => $period, ); - // Add context form elements. + // Add context mapping UI form elements. $contexts = $form_state->getTemporaryValue('gathered_contexts') ?: []; $form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts); // Add plugin-specific settings for this block type. diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php index e3ae261..c2d2dd8 100644 --- a/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php +++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php @@ -65,7 +65,7 @@ protected function addContextAssignmentElement(ContextAwarePluginInterface $plug $assignments = $plugin->getContextMapping(); $element[$context_slot] = [ - '#title' => $definition->getLabel() ?: $context_slot, + '#title' => $definition->getLabel() ?: $this->t('Select a @context value:', ['@context' => $context_slot]), '#type' => 'select', '#options' => $options, '#required' => $definition->isRequired(), diff --git a/core/modules/block/block.services.yml b/core/modules/block/block.services.yml index ff4277d..5b6e521 100644 --- a/core/modules/block/block.services.yml +++ b/core/modules/block/block.services.yml @@ -9,4 +9,4 @@ services: - { name: event_subscriber } block.repository: class: Drupal\block\BlockRepository - arguments: ['@entity.manager', '@theme.manager', '@context.handler', '@context.repository'] + arguments: ['@entity.manager', '@theme.manager'] diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php index e8035f4..605cf40 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -336,6 +336,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Call the plugin submit handler. $block = $entity->getPlugin(); $block->submitConfigurationForm($form, $settings); + // If this block is context-aware, set the context mapping. if ($block instanceof ContextAwarePluginInterface && $block->getContextDefinitions()) { $context_mapping = $settings->getValue('context_mapping', []); $block->setContextMapping($context_mapping); diff --git a/core/modules/block/src/BlockRepository.php b/core/modules/block/src/BlockRepository.php index e9a5eb0..103557b 100644 --- a/core/modules/block/src/BlockRepository.php +++ b/core/modules/block/src/BlockRepository.php @@ -9,9 +9,6 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Plugin\Context\ContextHandlerInterface; -use Drupal\Core\Plugin\Context\ContextRepositoryInterface; -use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Core\Theme\ThemeManagerInterface; /** @@ -34,36 +31,16 @@ class BlockRepository implements BlockRepositoryInterface { protected $themeManager; /** - * The context repository. - * - * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface - */ - protected $contextRepository; - - /** - * The context handler. - * - * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface - */ - protected $contextHandler; - - /** * Constructs a new BlockRepository. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * The theme manager. - * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler - * The plugin context handler. - * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository - * The context repository */ - public function __construct(EntityManagerInterface $entity_manager, ThemeManagerInterface $theme_manager, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository) { + public function __construct(EntityManagerInterface $entity_manager, ThemeManagerInterface $theme_manager) { $this->blockStorage = $entity_manager->getStorage('block'); $this->themeManager = $theme_manager; - $this->contextHandler = $context_handler; - $this->contextRepository = $context_repository; } /** @@ -77,7 +54,6 @@ public function getVisibleBlocksPerRegion(array &$cacheable_metadata = []) { $full = array(); foreach ($this->blockStorage->loadByProperties(array('theme' => $active_theme->getName())) as $block_id => $block) { /** @var \Drupal\block\BlockInterface $block */ - $access = $block->access('view', NULL, TRUE); $region = $block->getRegion(); if (!isset($cacheable_metadata[$region])) { diff --git a/core/modules/block/src/Tests/BlockUiTest.php b/core/modules/block/src/Tests/BlockUiTest.php index 47fea2e..2206158 100644 --- a/core/modules/block/src/Tests/BlockUiTest.php +++ b/core/modules/block/src/Tests/BlockUiTest.php @@ -169,10 +169,16 @@ public function testCandidateBlockList() { * Tests the behavior of context-aware blocks. */ public function testContextAwareBlocks() { + $expected_text = '
' . \Drupal::currentUser()->getUsername() . '
'; + $this->drupalGet(''); + $this->assertNoText('Test context-aware block'); + $this->assertNoRaw($expected_text); + + $block_url = 'admin/structure/block/add/test_context_aware/classy'; $arguments = array( ':title' => 'Test context-aware block', ':category' => 'Block test', - ':href' => 'admin/structure/block/add/test_context_aware/classy', + ':href' => $block_url, ); $pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]'; @@ -182,6 +188,16 @@ public function testContextAwareBlocks() { $this->assertTrue(!empty($elements), 'The context-aware test block appears.'); $definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware'); $this->assertTrue(!empty($definition), 'The context-aware test block exists.'); + + $edit = [ + 'region' => 'content', + 'settings[context_mapping][user]' => '@block_test.multiple_static_context:user2', + ]; + $this->drupalPostForm($block_url, $edit, 'Save block'); + + $this->drupalGet(''); + $this->assertText('Test context-aware block'); + $this->assertRaw($expected_text); } /** diff --git a/core/modules/block/tests/modules/block_test/block_test.services.yml b/core/modules/block/tests/modules/block_test/block_test.services.yml new file mode 100644 index 0000000..f165a02 --- /dev/null +++ b/core/modules/block/tests/modules/block_test/block_test.services.yml @@ -0,0 +1,6 @@ +services: + block_test.multiple_static_context: + class: Drupal\block_test\ContextProvider\MultipleStaticContext + arguments: ['@current_user', '@entity.manager'] + tags: + - { name: 'context_provider' } diff --git a/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php b/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php new file mode 100644 index 0000000..e316e8b --- /dev/null +++ b/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php @@ -0,0 +1,80 @@ +account = $account; + $this->userStorage = $entity_manager->getStorage('user'); + } + + /** + * {@inheritdoc} + */ + public function getRuntimeContexts(array $unqualified_context_ids) { + $current_user = $this->userStorage->load($this->account->id()); + + $context1 = new Context(new ContextDefinition('entity:user', 'User 1')); + $context1->setContextValue($current_user); + + $context2 = new Context(new ContextDefinition('entity:user', 'User 2')); + $context2->setContextValue($current_user); + + $cacheability = new CacheableMetadata(); + $cacheability->setCacheContexts(['user']); + + $context1->addCacheableDependency($cacheability); + $context2->addCacheableDependency($cacheability); + + return [ + 'user1' => $context1, + 'user2' => $context2, + ]; + } + + /** + * {@inheritdoc} + */ + public function getAvailableContexts() { + return $this->getRuntimeContexts([]); + } + +} diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareBlock.php b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareBlock.php index 56b127b..c4223d0 100644 --- a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareBlock.php +++ b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareBlock.php @@ -29,6 +29,8 @@ public function build() { /** @var $user \Drupal\user\UserInterface */ $user = $this->getContextValue('user'); return array( + '#prefix' => '
', + '#suffix' => '
', '#markup' => $user->getUsername(), ); } diff --git a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php index 3fbf0db..83747de 100644 --- a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php +++ b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php @@ -10,7 +10,6 @@ use Drupal\block\BlockRepository; use Drupal\Core\Access\AccessResult; use Drupal\Core\Block\BlockPluginInterface; -use Drupal\Core\Plugin\Context\LazyContextRepository; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Tests\UnitTestCase; @@ -36,16 +35,6 @@ class BlockRepositoryTest extends UnitTestCase { protected $theme; /** - * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextHandler; - - /** - * @var \Drupal\Core\Plugin\Context\LazyContextRepository|\Prophecy\Prophecy\ProphecyInterface - */ - protected $contextRepository; - - /** * {@inheritdoc} */ protected function setUp() { @@ -70,15 +59,13 @@ protected function setUp() { ->method('getActiveTheme') ->will($this->returnValue($active_theme)); - $this->contextHandler = $this->getMock('Drupal\Core\Plugin\Context\ContextHandlerInterface'); - $this->contextRepository = $this->prophesize(LazyContextRepository::class); $this->blockStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface'); $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); $entity_manager->expects($this->any()) ->method('getStorage') ->willReturn($this->blockStorage); - $this->blockRepository = new BlockRepository($entity_manager, $theme_manager, $this->contextHandler, $this->contextRepository->reveal()); + $this->blockRepository = new BlockRepository($entity_manager, $theme_manager); } /**