From 64a7739a52bc6d1d464ef1152823f3a58c184a74 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 17 Jun 2013 18:17:46 +0200 Subject: [PATCH] Issue #1998582 by damiankloip, brantwynn, dawehner: Auto-generate machine_name() for Views Blocks using [viewname]_[displayname] rather than forcing manual entry. --- .../block/Tests/Views/DisplayBlockTest.php | 19 ++++ .../Drupal/views/Plugin/Block/ViewsBlock.php | 31 +++++++ .../views/Tests/Plugin/ViewsBlockTest.php | 86 +++++++++++++++++++ core/modules/views/views.module | 23 +++++ 4 files changed, 159 insertions(+) create mode 100644 core/modules/views/lib/Drupal/views/Tests/Plugin/ViewsBlockTest.php 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 9f53bdfd51c..aba702faee7 100644 --- a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php @@ -108,6 +108,25 @@ class DisplayBlockTest extends ViewTestBase { $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 = $this->container->get('plugin.manager.entity')->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')); + $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 e9af634ef66..2c0481ea262 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 @@ namespace Drupal\views\Plugin\Block; use Drupal\block\BlockBase; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Provides a generic Views block. @@ -112,4 +113,34 @@ class ViewsBlock extends BlockBase { } } + /** + * 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) { + $this->view->setDisplay($this->displayID); + $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())); + + // Iterate through potential IDs until we get a new one. E.g. + // 'views_block__MYVIEW_PAGE_1_2' + $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 00000000000..759351a2c1b --- /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 c1ff37976f3..0bf5687a79c 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -1729,3 +1729,26 @@ function views_cache_get($cid, $use_language = FALSE) { return cache('views_info')->get($cid); } + +/** + * Implements hook_form_FORM_ID_alter for block_form(). + * + * Views overrides block configuration form elements during + * \Drupal\views\Plugin\Block\ViewsBlock::form() but machine_name assignment is + * added later by \Drupal\block\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['controller']->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-generated block machine_name. + $form['machine_name']['#access'] = FALSE; + } +}