diff --git a/core/lib/Drupal/Component/Plugin/PluginBag.php b/core/lib/Drupal/Component/Plugin/PluginBag.php new file mode 100644 index 0000000..9487d8c --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/PluginBag.php @@ -0,0 +1,176 @@ +pluginInstances. + * + * @param string $instance_id + * The ID of the plugin instance to initialize. + */ + abstract protected function initializePlugin($instance_id); + + /** + * Clears all instantiated plugins. + */ + public function clear() { + $this->pluginInstances = array(); + } + + /** + * Determines if a plugin instance exists. + * + * @param string $instance_id + * The ID of the plugin instance to check. + * + * @return bool + * TRUE if the plugin instance exists, FALSE otherwise. + */ + public function has($instance_id) { + return isset($this->pluginInstances[$instance_id]) || isset($this->instanceIDs[$instance_id]); + } + + /** + * Retrieves a plugin instance, initializing it if necessary. + * + * @param string $instance_id + * The ID of the plugin instance being retrieved. + */ + public function get($instance_id) { + if (!isset($this->pluginInstances[$instance_id])) { + $this->initializePlugin($instance_id); + } + return $this->pluginInstances[$instance_id]; + } + + /** + * Stores an initialized plugin. + * + * @param string $instance_id + * The ID of the plugin instance being stored. + * @param mixed $value + * An instantiated plugin. + */ + public function set($instance_id, $value) { + $this->pluginInstances[$instance_id] = $value; + } + + /** + * Removes an initialized plugin. + * + * The plugin can still be used, it will be reinitialized. + */ + public function remove($instance_id) { + unset($this->pluginInstances[$instance_id]); + } + + /** + * Implements \ArrayAccess::offsetExists(). + * + * This is deprecated, use \Drupal\Component\Plugin\PluginBag::has(). + */ + public function offsetExists($offset) { + return isset($this->pluginInstances[$offset]) || isset($this->instanceIDs[$offset]); + } + + /** + * Implements \ArrayAccess::offsetGet(). + * + * This is deprecated, use \Drupal\Component\Plugin\PluginBag::get(). + */ + public function offsetGet($offset) { + if (!isset($this->pluginInstances[$offset])) { + $this->initializePlugin($offset); + } + return $this->pluginInstances[$offset]; + } + + /** + * Implements \ArrayAccess::offsetSet(). + * + * This is deprecated, use \Drupal\Component\Plugin\PluginBag::set(). + */ + public function offsetSet($offset, $value) { + $this->pluginInstances[$offset] = $value; + } + + /** + * Implements \ArrayAccess::offsetUnset(). + * + * This is deprecated, use \Drupal\Component\Plugin\PluginBag::remove(). + */ + public function offsetUnset($offset) { + unset($this->pluginInstances[$offset]); + } + + /** + * Implements \Iterator::current(). + */ + public function current() { + return $this->offsetGet($this->key()); + } + + /** + * Implements \Iterator::next(). + */ + public function next() { + next($this->instanceIDs); + } + + /** + * Implements \Iterator::key(). + */ + public function key() { + return key($this->instanceIDs); + } + + /** + * Implements \Iterator::valid(). + */ + public function valid() { + $key = key($this->instanceIDs); + return $key !== NULL && $key !== FALSE; + } + + /** + * Implements \Iterator::rewind(). + */ + public function rewind() { + reset($this->instanceIDs); + } + + /** + * Implements \Countable::count(). + */ + public function count() { + return count($this->instanceIDs); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginBagTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginBagTest.php new file mode 100644 index 0000000..207beb8 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginBagTest.php @@ -0,0 +1,64 @@ + 'Plugin Bag', + 'description' => 'Tests the generic plugin bag.', + 'group' => 'Plugin API', + ); + } + + /** + * Tests the generic plugin bag. + */ + protected function testPluginBag() { + // Setup the plugin bag as well as the available plugin definitions. + $plugin_bag = new TestPluginBag($this->mockBlockManager); + $definitions = $this->mockBlockManager->getDefinitions(); + $first_instance_id = key($definitions); + + foreach ($definitions as $instance_id => $definition) { + $this->assertTrue(isset($plugin_bag[$instance_id]), format_string('Plugin instance @instance_id exits on the bag', array('@instance_id' => $instance_id))); + } + + // A non existing instance_id shouldn't exist on the bag. + $random_name = $this->randomName(); + $this->assertFalse(isset($plugin_bag[$random_name]), 'A random instance_id should not exist on the plugin bag.'); + + // Set a new plugin instance to the bag, to test offsetSet. + $plugin_bag[$random_name] = $this->mockBlockManager->createInstance($first_instance_id, array()); + $this->assertTrue(isset($plugin_bag[$random_name]), 'A random instance_id should exist after manual setting on the plugin bag.'); + + // Remove the previous added element and check whether it still exists. + unset($plugin_bag[$random_name]); + $this->assertFalse(isset($plugin_bag[$random_name]), 'A random instance_id should not exist on the plugin bag after removing.'); + + // Test that iterating over the plugins work. + $expected_instance_ids = array_keys($definitions); + $counter = 0; + foreach ($plugin_bag as $instance_id => $plugin) { + $this->assertEqual($expected_instance_ids[$counter], $instance_id, format_string('The iteration works as expected for plugin instance @instance_id', array('@instance_id' => $instance_id))); + $counter++; + } + + $this->assertEqual(count($plugin_bag), count($expected_instance_ids), 'The amount of items in plugin bag is as expected.'); + } + +} diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginBag.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginBag.php new file mode 100644 index 0000000..e72ae5d --- /dev/null +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginBag.php @@ -0,0 +1,49 @@ +manager = $manager; + + $this->instanceIDs = drupal_map_assoc(array_keys($this->manager->getDefinitions())); + } + + /** + * Implements \Drupal\Component\Plugin\PluginBag::initializePlugin(). + */ + protected function initializePlugin($instance_id) { + // If the plugin was initialized before, just return. + if (isset($this->pluginInstances[$instance_id])) { + return; + } + + $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, array()); + } + +} diff --git a/core/modules/views/lib/Drupal/views/DisplayArray.php b/core/modules/views/lib/Drupal/views/DisplayArray.php deleted file mode 100644 index 41b48a2..0000000 --- a/core/modules/views/lib/Drupal/views/DisplayArray.php +++ /dev/null @@ -1,165 +0,0 @@ -view->storage->get('display'). - * - * @var array - */ - protected $displayIDs; - - /** - * Constructs a DisplayArray object. - * - * @param \Drupal\views\ViewExecutable - * The view which has this displays attached. - */ - public function __construct(ViewExecutable $view) { - $this->view = $view; - - $this->initializeDisplay('default'); - - // Store all display IDs to access them easy and fast. - $display = $this->view->storage->get('display'); - $this->displayIDs = drupal_map_assoc(array_keys($display)); - } - - /** - * Destructs a DisplayArray object. - */ - public function __destruct() { - foreach ($this->displayHandlers as $display_id => $display) { - $display->destroy(); - unset($this->displayHandlers[$display_id]); - } - } - - /** - * Initializes a single display and stores the result in $this->displayHandlers. - * - * @param string $display_id - * The name of the display to initialize. - */ - protected function initializeDisplay($display_id) { - // If the display was initialized before, just return. - if (isset($this->displayHandlers[$display_id])) { - return; - } - - // Retrieve and initialize the new display handler with data. - $display = &$this->view->storage->getDisplay($display_id); - $this->displayHandlers[$display_id] = drupal_container()->get("plugin.manager.views.display")->createInstance($display['display_plugin']); - if (empty($this->displayHandlers[$display_id])) { - // Provide a 'default' handler as an emergency. This won't work well but - // it will keep things from crashing. - $this->displayHandlers[$display_id] = drupal_container()->get("plugin.manager.views.display")->createInstance('default'); - } - - $this->displayHandlers[$display_id]->initDisplay($this->view, $display); - // If this is not the default display handler, let it know which is since - // it may well utilize some data from the default. - if ($display_id != 'default') { - $this->displayHandlers[$display_id]->default_display = $this->displayHandlers['default']; - } - } - - /** - * Implements \ArrayAccess::offsetExists(). - */ - public function offsetExists($offset) { - return isset($this->displayHandlers[$offset]) || isset($this->displayIDs[$offset]); - } - - /** - * Implements \ArrayAccess::offsetGet(). - */ - public function offsetGet($offset) { - if (!isset($this->displayHandlers[$offset])) { - $this->initializeDisplay($offset); - } - return $this->displayHandlers[$offset]; - } - - /** - * Implements \ArrayAccess::offsetSet(). - */ - public function offsetSet($offset, $value) { - $this->displayHandlers[$offset] = $value; - } - - /** - * Implements \ArrayAccess::offsetUnset(). - */ - public function offsetUnset($offset) { - unset($this->displayHandlers[$offset]); - } - - /** - * Implements \Iterator::current(). - */ - public function current() { - return $this->offsetGet($this->key()); - } - - /** - * Implements \Iterator::next(). - */ - public function next() { - next($this->displayIDs); - } - - /** - * Implements \Iterator::key(). - */ - public function key() { - return key($this->displayIDs); - } - - /** - * Implements \Iterator::valid(). - */ - public function valid() { - $key = key($this->displayIDs); - return $key !== NULL && $key !== FALSE; - } - - /** - * Implements \Iterator::rewind(). - */ - public function rewind() { - reset($this->displayIDs); - } - - /** - * Implements \Countable::count(). - */ - public function count() { - return count($this->displayIDs); - } - -} diff --git a/core/modules/views/lib/Drupal/views/DisplayBag.php b/core/modules/views/lib/Drupal/views/DisplayBag.php new file mode 100644 index 0000000..b6b9db9 --- /dev/null +++ b/core/modules/views/lib/Drupal/views/DisplayBag.php @@ -0,0 +1,84 @@ +view = $view; + + $this->initializePlugin('default'); + + // Store all display IDs to access them easy and fast. + $display = $this->view->storage->get('display'); + $this->instanceIDs = drupal_map_assoc(array_keys($display)); + } + + /** + * Destructs a DisplayBag object. + */ + public function __destruct() { + $this->clear(); + } + + /** + * Overrides \Drupal\Component\Plugin\PluginBag::clear(). + */ + public function clear() { + foreach ($this->pluginInstances as $display_id => $display) { + $display->destroy(); + } + + parent::clear(); + } + + /** + * Overrides \Drupal\Component\Plugin\PluginBag::initializePlugin(). + */ + protected function initializePlugin($display_id) { + // If the display was initialized before, just return. + if (isset($this->pluginInstances[$display_id])) { + return; + } + + // Retrieve and initialize the new display handler with data. + $display = &$this->view->storage->getDisplay($display_id); + $this->pluginInstances[$display_id] = drupal_container()->get("plugin.manager.views.display")->createInstance($display['display_plugin']); + if (empty($this->pluginInstances[$display_id])) { + // Provide a 'default' handler as an emergency. This won't work well but + // it will keep things from crashing. + $this->pluginInstances[$display_id] = drupal_container()->get("plugin.manager.views.display")->createInstance('default'); + } + + $this->pluginInstances[$display_id]->initDisplay($this->view, $display); + // If this is not the default display handler, let it know which is since + // it may well utilize some data from the default. + if ($display_id != 'default') { + $this->pluginInstances[$display_id]->default_display = $this->pluginInstances['default']; + } + } + +} diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php index 1000b1f..79f4616 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php @@ -9,7 +9,7 @@ use Symfony\Component\HttpFoundation\Response; use Drupal\views\ViewExecutable; -use Drupal\views\DisplayArray; +use Drupal\views\DisplayBag; use Drupal\views\Plugin\views\display\DefaultDisplay; use Drupal\views\Plugin\views\display\Page; use Drupal\views\Plugin\views\style\DefaultStyle; @@ -152,7 +152,7 @@ public function testDisplays() { // Tests Drupal\views\ViewExecutable::initDisplay(). $view->initDisplay(); - $this->assertTrue($view->displayHandlers instanceof DisplayArray, 'The displayHandlers property has the right class.'); + $this->assertTrue($view->displayHandlers instanceof DisplayBag, 'The displayHandlers property has the right class.'); // Tests the classes of the instances. $this->assertTrue($view->displayHandlers['default'] instanceof DefaultDisplay); $this->assertTrue($view->displayHandlers['page_1'] instanceof Page); diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php index 25a47ac..db4f3a2 100644 --- a/core/modules/views/lib/Drupal/views/ViewExecutable.php +++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php @@ -597,7 +597,7 @@ public function initDisplay() { } // Initialize the display cache array. - $this->displayHandlers = new DisplayArray($this); + $this->displayHandlers = new DisplayBag($this); $this->current_display = 'default'; $this->display_handler = $this->displayHandlers['default'];