diff --git a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php index d88894d..3d6fd9b 100644 --- a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php @@ -146,6 +146,26 @@ public function testViewsBlockForm() { $this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme); $elements = $this->xpath('//input[@name="label"]'); $this->assertTrue(empty($elements), 'The label field is not found for Views blocks.'); + // Test that that machine name field is hidden from display and has been + // saved as expected from the default value. + $this->assertNoFieldById('edit-machine-name', 'stark.views_block__test_view_block_1', 'The machine name is hidden on the views block form.'); + // Save the block. + $this->drupalPost(NULL, array(), t('Save block')); + $storage = \Drupal::entityManager()->getStorageController('block'); + $blocks = $storage->load(array('stark.views_block__test_view_block_block_1')); + // This will only return a result if our new block has been created with the + // expected machine name. + $this->assertTrue(!empty($blocks), 'The expected block was loaded.'); + + for ($i = 2; $i <= 3; $i++) { + // Place the same block again and make sure we have a new ID. + $this->drupalPost('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, array(), t('Save block')); + $storage = \Drupal::entityManager()->getStorageController('block'); + $blocks = $storage->load(array('stark.views_block__test_view_block_block_1_' . $i)); + // This will only return a result if our new block has been created with the + // expected machine name. + $this->assertTrue(!empty($blocks), 'The expected block was loaded.'); + } } /** diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php index 1e2bfd5..292b472 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php @@ -10,6 +10,7 @@ use Drupal\block\BlockBase; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Provides a generic Views block. @@ -109,4 +110,40 @@ protected function addContextualLinks(&$output, $block_type = 'block') { } } + /** + * Returns the ViewExecutable instance for this block. + * + * @return \Drupal\views\ViewExecutable + */ + public function getView() { + return $this->view; + } + + /** + * Generates a views block instance ID. + * + * @param \Drupal\Core\Entity\EntityStorageControllerInterface $manager + * The block storage controller. + * + * @return string + * The new block instance ID. + */ + public function generateBlockInstanceID(EntityStorageControllerInterface $manager) { + $original_id = 'views_block__' . $this->view->storage->id() . '_' . $this->view->current_display; + + // Get an array of block IDs without the theme prefix. + $block_ids = array_map(function ($block_id) { + $parts = explode('.', $block_id); + return end($parts); + }, array_keys($manager->load())); + + $count = 1; + $id = $original_id; + while (in_array($id, $block_ids)) { + $id = $original_id . '_' . ++$count; + } + + return $id; + } + } diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/ViewsBlockTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/ViewsBlockTest.php new file mode 100644 index 0000000..759351a --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/ViewsBlockTest.php @@ -0,0 +1,86 @@ + 'Views block', + 'description' => 'Tests the block views plugin.', + 'group' => 'Views Plugins', + ); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + ViewTestData::importTestViews(get_class($this), array('block_test_views')); + } + + /** + * Tests generateBlockInstanceID. + * + * @see \Drupal\views\Plugin\Block::generateBlockInstanceID(). + */ + public function testGenerateBlockInstanceID() { + + $plugin_definition = array( + 'module' => 'views', + ); + $plugin_id = 'views_block:test_view_block-block_1'; + $views_block = new ViewsBlock(array(), $plugin_id, $plugin_definition); + + $storage_controller = $this->container->get('plugin.manager.entity')->getStorageController('block'); + + // Generate a instance ID on a block without any instances. + $this->assertEqual($views_block->generateBlockInstanceID($storage_controller), 'views_block__test_view_block_block_1'); + + $values = array( + 'plugin' => $plugin_id, + 'id' => 'stark.views_block__test_view_block_block_1', + 'module' => 'views', + 'settings' => array( + 'module' => 'views', + ) + ); + $storage_controller->create($values)->save(); + $this->assertEqual($views_block->generateBlockInstanceID($storage_controller), 'views_block__test_view_block_block_1_2'); + + // Add another one block instance and ensure the block instance went up. + $values['id'] = 'stark.views_block__test_view_block_block_1_2'; + $storage_controller->create($values)->save(); + $this->assertEqual($views_block->generateBlockInstanceID($storage_controller), 'views_block__test_view_block_block_1_3'); + } + +} diff --git a/core/modules/views/views.module b/core/modules/views/views.module index 09d8c6e..077b29d 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -1813,3 +1813,25 @@ function views_cache_get($cid, $use_language = FALSE) { return cache('views_info')->get($cid); } + +/** + * Implement hook_form_alter for the views block form. + * + * Views overrides block configuration form elements during ViewsBlock:form() + * but machine_name assignment is added later by BlockFormController:form() + * so we provide an override for the block machine_name here. + */ +function views_form_block_form_alter(&$form, &$form_state) { + // Ensure the block-form being altered is a Views block configuration form. + if (($form['settings']['module']['#value'] == 'views') && empty($form['machine_name']['#default_value'])) { + // Unset the machine_name provided by BlockFormController + unset($form['machine_name']['#machine_name']['source']); + // Load the Views plugin object using form_state array and create a + // block machine_name based on the View ID and View Display ID. + $block_plugin = $form_state['build_info']['callback_object']->getEntity()->getPlugin(); + // Override the Views block's machine_name by providing a default_value. + $form['machine_name']['#default_value'] = $block_plugin->generateBlockInstanceID(Drupal::entityManager()->getStorageController('block')); + // Prevent users from changing the auto-generate block machine_name. + $form['machine_name']['#access'] = FALSE; + } +}