diff --git a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php new file mode 100644 index 0000000..3c500ea --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php @@ -0,0 +1,31 @@ +manager = $manager; + $this->configurations = $configurations; + + if (!empty($configurations)) { + $this->instanceIDs = MapArray::copyValuesToKeys(array_keys($configurations)); + } + } + + /** + * {@inheritdoc} + */ + protected function initializePlugin($instance_id) { + if (!isset($this->pluginInstances[$instance_id])) { + $configuration = $this->configurations[$instance_id]; + if (!isset($configuration[$this->pluginKey])) { + throw new PluginException(String::format("Unknown plugin ID '@instance'.", array('@instance' => $instance_id))); + } + $this->pluginInstances[$instance_id] = $this->manager->createInstance($configuration[$this->pluginKey], $configuration); + $this->addInstanceID($instance_id); + } + } + + /** + * Sorts all plugin instances in this bag. + * + * @return self + * Returns the plugin bag. + */ + public function sort() { + uasort($this->instanceIDs, array($this, 'sortHelper')); + return $this; + } + + /** + * Provides uasort() callback to sort plugins. + */ + public function sortHelper($aID, $bID) { + $a = $this->get($aID); + $b = $this->get($bID); + return strnatcasecmp($a->getPluginId(), $b->getPluginId()); + } + + /** + * Returns the current configuration of all plugins in this bag. + * + * @return array + * An associative array keyed by instance ID, whose values are up-to-date + * plugin configurations. + */ + public function getConfiguration() { + $instances = array(); + $this->rewind(); + foreach ($this as $instance_id => $instance) { + if ($instance instanceof ConfigurablePluginInterface) { + $instances[$instance_id] = $instance->getConfiguration(); + } + else { + $instances[$instance_id] = $this->configurations[$instance_id]; + } + } + return $instances; + } + + /** + * Updates the configuration for a plugin instance. + * + * If there is no plugin instance yet, a new will be instantiated. Otherwise, + * the existing instance is updated with the new configuration. + * + * @param string $instance_id + * The ID of a plugin to set the configuration for. + * @param array $configuration + * The plugin configuration to set. + */ + public function setConfiguration($instance_id, array $configuration) { + $this->configurations[$instance_id] = $configuration; + $instance = $this->get($instance_id); + if ($instance instanceof ConfigurablePluginInterface) { + $instance->setConfiguration($configuration); + } + } + +} diff --git a/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php b/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php new file mode 100644 index 0000000..023ba3e --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php @@ -0,0 +1,62 @@ +manager = $manager; + $this->instanceIDs = MapArray::copyValuesToKeys($instance_ids); + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + protected function initializePlugin($instance_id) { + if (!isset($this->pluginInstances[$instance_id])) { + $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $this->configuration); + } + } + +} diff --git a/core/lib/Drupal/Core/Action/ActionBag.php b/core/lib/Drupal/Core/Action/ActionBag.php index a8210fe..de0e1d7 100644 --- a/core/lib/Drupal/Core/Action/ActionBag.php +++ b/core/lib/Drupal/Core/Action/ActionBag.php @@ -7,46 +7,11 @@ namespace Drupal\Core\Action; -use Drupal\Component\Plugin\PluginBag; -use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Component\Plugin\DefaultSinglePluginBag; /** * Provides a container for lazily loading Action plugins. */ -class ActionBag extends PluginBag { - - /** - * The manager used to instantiate the plugins. - * - * @var \Drupal\Component\Plugin\PluginManagerInterface - */ - protected $manager; - - /** - * Constructs a new ActionBag object. - * - * @param \Drupal\Component\Plugin\PluginManagerInterface $manager - * The manager to be used for instantiating plugins. - * @param array $instance_ids - * The ids of the plugin instances with which we are dealing. - * @param array $configuration - * An array of configuration. - */ - public function __construct(PluginManagerInterface $manager, array $instance_ids, array $configuration) { - $this->manager = $manager; - $this->instanceIDs = drupal_map_assoc($instance_ids); - $this->configuration = $configuration; - } - - /** - * {@inheritdoc} - */ - protected function initializePlugin($instance_id) { - if (isset($this->pluginInstances[$instance_id])) { - return; - } - - $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $this->configuration); - } +class ActionBag extends DefaultSinglePluginBag { } diff --git a/core/lib/Drupal/Core/Action/ConfigurableActionBase.php b/core/lib/Drupal/Core/Action/ConfigurableActionBase.php index 04ca4fe..25fe32f 100644 --- a/core/lib/Drupal/Core/Action/ConfigurableActionBase.php +++ b/core/lib/Drupal/Core/Action/ConfigurableActionBase.php @@ -7,13 +7,14 @@ namespace Drupal\Core\Action; -use Drupal\Core\Action\ConfigurableActionInterface; +use Drupal\Component\Plugin\ConfigurablePluginInterface; use Drupal\Core\Action\ActionBase; +use Drupal\Core\Plugin\PluginFormInterface; /** * Provides a base implementation for a configurable Action plugin. */ -abstract class ConfigurableActionBase extends ActionBase implements ConfigurableActionInterface { +abstract class ConfigurableActionBase extends ActionBase implements ConfigurablePluginInterface, PluginFormInterface { /** * {@inheritdoc} @@ -43,7 +44,14 @@ public function getConfiguration() { /** * {@inheritdoc} */ - public function validate(array &$form, array &$form_state) { + public function setConfiguration(array $configuration) { + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function validateConfigurationForm(array &$form, array &$form_state) { } } diff --git a/core/lib/Drupal/Core/Action/ConfigurableActionInterface.php b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php similarity index 54% rename from core/lib/Drupal/Core/Action/ConfigurableActionInterface.php rename to core/lib/Drupal/Core/Plugin/PluginFormInterface.php index c0a66a9..e029bba 100644 --- a/core/lib/Drupal/Core/Action/ConfigurableActionInterface.php +++ b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php @@ -2,28 +2,15 @@ /** * @file - * Contains \Drupal\Core\Action\ConfigurableActionInterface. + * Contains \Drupal\Core\Plugin\PluginFormInterface. */ -namespace Drupal\Core\Action; - -use Drupal\Core\Action\ActionInterface; +namespace Drupal\Core\Plugin; /** - * Provides an interface for an Action plugin. - * - * @see \Drupal\Core\Annotation\Operation - * @see \Drupal\Core\Action\OperationManager + * Provides an interface for a plugin that contains a form. */ -interface ConfigurableActionInterface extends ActionInterface { - - /** - * Returns this plugin's configuration. - * - * @return array - * An array of this action plugin's configuration. - */ - public function getConfiguration(); +interface PluginFormInterface { /** * Form constructor. @@ -36,7 +23,7 @@ public function getConfiguration(); * @return array * The form structure. */ - public function form(array $form, array &$form_state); + public function buildConfigurationForm(array $form, array &$form_state); /** * Form validation handler. @@ -46,16 +33,21 @@ public function form(array $form, array &$form_state); * @param array $form_state * An associative array containing the current state of the form. */ - public function validate(array &$form, array &$form_state); + public function validateConfigurationForm(array &$form, array &$form_state); /** * Form submission handler. * + * To properly store submitted form values store them in $this->configuration. + * @code + * $this->configuration['some_value'] = $form_state['values']['some_value']; + * @endcode + * * @param array $form * An associative array containing the structure of the form. * @param array $form_state * An associative array containing the current state of the form. */ - public function submit(array &$form, array &$form_state); + public function submitConfigurationForm(array &$form, array &$form_state); } diff --git a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php index ff48164..e9df397 100644 --- a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php +++ b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php @@ -10,8 +10,8 @@ use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityFormController; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Action\ConfigurableActionInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Plugin\PluginFormInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -97,8 +97,8 @@ public function form(array $form, array &$form_state) { '#value' => $this->entity->getType(), ); - if ($this->plugin instanceof ConfigurableActionInterface) { - $form += $this->plugin->form($form, $form_state); + if ($this->plugin instanceof PluginFormInterface) { + $form += $this->plugin->buildConfigurationForm($form, $form_state); } return parent::form($form, $form_state); @@ -133,8 +133,8 @@ protected function actions(array $form, array &$form_state) { public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); - if ($this->plugin instanceof ConfigurableActionInterface) { - $this->plugin->validate($form, $form_state); + if ($this->plugin instanceof PluginFormInterface) { + $this->plugin->validateConfigurationForm($form, $form_state); } } @@ -144,8 +144,8 @@ public function validate(array $form, array &$form_state) { public function submit(array $form, array &$form_state) { parent::submit($form, $form_state); - if ($this->plugin instanceof ConfigurableActionInterface) { - $this->plugin->submit($form, $form_state); + if ($this->plugin instanceof PluginFormInterface) { + $this->plugin->submitConfigurationForm($form, $form_state); } return $this->entity; } diff --git a/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php b/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php index d0244b1..d825415 100644 --- a/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php +++ b/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php @@ -57,7 +57,7 @@ public function getFormID() { public function buildForm(array $form, array &$form_state) { $actions = array(); foreach ($this->manager->getDefinitions() as $id => $definition) { - if (is_subclass_of($definition['class'], '\Drupal\Core\Action\ConfigurableActionInterface')) { + if (is_subclass_of($definition['class'], '\Drupal\Core\Plugin\PluginFormInterface')) { $key = Crypt::hashBase64($id); $actions[$key] = $definition['label'] . '...'; } diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php index 43908b0..77e5f21 100644 --- a/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php +++ b/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php @@ -116,7 +116,7 @@ protected function getDefaultConfiguration() { /** * {@inheritdoc} */ - public function form(array $form, array &$form_state) { + public function buildConfigurationForm(array $form, array &$form_state) { $form['recipient'] = array( '#type' => 'textfield', '#title' => t('Recipient'), @@ -145,7 +145,7 @@ public function form(array $form, array &$form_state) { /** * {@inheritdoc} */ - public function validate(array &$form, array &$form_state) { + public function validateConfigurationForm(array &$form, array &$form_state) { if (!valid_email_address($form_state['values']['recipient']) && strpos($form_state['values']['recipient'], ':mail') === FALSE) { // We want the literal %author placeholder to be emphasized in the error message. form_set_error('recipient', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]'))); @@ -155,7 +155,7 @@ public function validate(array &$form, array &$form_state) { /** * {@inheritdoc} */ - public function submit(array &$form, array &$form_state) { + public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['recipient'] = $form_state['values']['recipient']; $this->configuration['subject'] = $form_state['values']['subject']; $this->configuration['message'] = $form_state['values']['message']; diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php index 93a4c87..fd158fb 100644 --- a/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php +++ b/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php @@ -96,7 +96,7 @@ protected function getDefaultConfiguration() { /** * {@inheritdoc} */ - public function form(array $form, array &$form_state) { + public function buildConfigurationForm(array $form, array &$form_state) { $form['url'] = array( '#type' => 'textfield', '#title' => t('URL'), @@ -110,7 +110,7 @@ public function form(array $form, array &$form_state) { /** * {@inheritdoc} */ - public function submit(array &$form, array &$form_state) { + public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['url'] = $form_state['values']['url']; } diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php index b7f25a2..fef9ab9 100644 --- a/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php +++ b/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php @@ -70,7 +70,7 @@ protected function getDefaultConfiguration() { /** * {@inheritdoc} */ - public function form(array $form, array &$form_state) { + public function buildConfigurationForm(array $form, array &$form_state) { $form['message'] = array( '#type' => 'textarea', '#title' => t('Message'), @@ -85,7 +85,7 @@ public function form(array $form, array &$form_state) { /** * {@inheritdoc} */ - public function submit(array &$form, array &$form_state) { + public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['message'] = $form_state['values']['message']; unset($this->configuration['node']); } diff --git a/core/modules/block/lib/Drupal/block/BlockBase.php b/core/modules/block/lib/Drupal/block/BlockBase.php index b438dc1..947439e 100644 --- a/core/modules/block/lib/Drupal/block/BlockBase.php +++ b/core/modules/block/lib/Drupal/block/BlockBase.php @@ -50,50 +50,28 @@ public function settings() { } /** - * Returns the configuration data for the block plugin. - * - * @return array - * The plugin configuration array from PluginBase::$configuration. - * - * @todo This doesn't belong here. Move this into a new base class in - * http://drupal.org/node/1764380. - * @todo This does not return a config object, so the name is confusing. - * - * @see \Drupal\Component\Plugin\PluginBase::$configuration + * {@inheritdoc} */ - public function getConfig() { + public function getConfiguration() { return $this->configuration; } /** - * Sets a particular value in the block settings. - * - * @param string $key - * The key of PluginBase::$configuration to set. - * @param mixed $value - * The value to set for the provided key. - * - * @todo This doesn't belong here. Move this into a new base class in - * http://drupal.org/node/1764380. - * @todo This does not set a value in config(), so the name is confusing. - * - * @see \Drupal\Component\Plugin\PluginBase::$configuration + * {@inheritdoc} + */ + public function setConfiguration(array $configuration) { + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} */ public function setConfig($key, $value) { $this->configuration[$key] = $value; } /** - * Indicates whether block-specific criteria allow access to the block. - * - * Blocks with access restrictions that should always be applied, - * regardless of user-configured settings, should implement this method - * with that access control logic. - * - * @return bool - * FALSE to deny access to the block, or TRUE to allow access. - * - * @see hook_block_access() + * {@inheritdoc} */ public function access() { // By default, the block is visible unless user-configured rules indicate @@ -102,7 +80,7 @@ public function access() { } /** - * Implements \Drupal\block\BlockPluginInterface::form(). + * {@inheritdoc} * * Creates a generic configuration form for all block types. Individual * block plugins can add elements to this form by overriding @@ -111,7 +89,7 @@ public function access() { * * @see \Drupal\block\BlockBase::blockForm() */ - public function form($form, &$form_state) { + public function buildConfigurationForm(array $form, array &$form_state) { $definition = $this->getPluginDefinition(); $form['module'] = array( '#type' => 'value', @@ -138,27 +116,14 @@ public function form($form, &$form_state) { } /** - * Returns the configuration form elements specific to this block plugin. - * - * Blocks that need to add form elements to the normal block configuration - * form should implement this method. - * - * @param array $form - * The form definition array for the block configuration form. - * @param array $form_state - * An array containing the current state of the configuration form. - * - * @return array $form - * The renderable form array representing the entire configuration form. - * - * @see \Drupal\block\BlockBase::form() + * {@inheritdoc} */ public function blockForm($form, &$form_state) { return array(); } /** - * Implements \Drupal\block\BlockPluginInterface::validate(). + * {@inheritdoc} * * Most block plugins should not override this method. To add validation * for a specific block type, override BlockBase::blockValdiate(). @@ -167,30 +132,17 @@ public function blockForm($form, &$form_state) { * * @see \Drupal\block\BlockBase::blockValidate() */ - public function validate($form, &$form_state) { + public function validateConfigurationForm(array &$form, array &$form_state) { $this->blockValidate($form, $form_state); } /** - * Adds block type-specific validation for the block form. - * - * Note that this method takes the form structure and form state arrays for - * the full block configuration form as arguments, not just the elements - * defined in BlockBase::blockForm(). - * - * @param array $form - * The form definition array for the full block configuration form. - * @param array $form_state - * An array containing the current state of the configuration form. - * - * @see \Drupal\block\BlockBase::blockForm() - * @see \Drupal\block\BlockBase::blockSubmit() - * @see \Drupal\block\BlockBase::validate() + * {@inheritdoc} */ public function blockValidate($form, &$form_state) {} /** - * Implements \Drupal\block\BlockPluginInterface::submit(). + * {@inheritdoc} * * Most block plugins should not override this method. To add submission * handling for a specific block type, override BlockBase::blockSubmit(). @@ -199,7 +151,7 @@ public function blockValidate($form, &$form_state) {} * * @see \Drupal\block\BlockBase::blockSubmit() */ - public function submit($form, &$form_state) { + public function submitConfigurationForm(array &$form, array &$form_state) { if (!form_get_errors()) { $this->configuration['label'] = $form_state['values']['label']; $this->configuration['label_display'] = $form_state['values']['label_display']; @@ -209,20 +161,8 @@ public function submit($form, &$form_state) { } /** - * Adds block type-specific submission handling for the block form. - * - * Note that this method takes the form structure and form state arrays for - * the full block configuration form as arguments, not just the elements - * defined in BlockBase::blockForm(). - * - * @param array $form - * The form definition array for the full block configuration form. - * @param array $form_state - * An array containing the current state of the configuration form. - * - * @see \Drupal\block\BlockBase::blockForm() - * @see \Drupal\block\BlockBase::blockValidate() - * @see \Drupal\block\BlockBase::submit() + * {@inheritdoc} */ public function blockSubmit($form, &$form_state) {} + } diff --git a/core/modules/block/lib/Drupal/block/BlockFormController.php b/core/modules/block/lib/Drupal/block/BlockFormController.php index f562a68..7789c02 100644 --- a/core/modules/block/lib/Drupal/block/BlockFormController.php +++ b/core/modules/block/lib/Drupal/block/BlockFormController.php @@ -25,7 +25,7 @@ public function form(array $form, array &$form_state) { '#type' => 'value', '#value' => $entity->id(), ); - $form['settings'] = $entity->getPlugin()->form(array(), $form_state); + $form['settings'] = $entity->getPlugin()->buildConfigurationForm(array(), $form_state); $form['machine_name'] = array( '#type' => 'machine_name', @@ -208,7 +208,7 @@ public function validate(array $form, array &$form_state) { 'values' => &$form_state['values']['settings'] ); // Call the plugin validate handler. - $entity->getPlugin()->validate($form, $settings); + $entity->getPlugin()->validateConfigurationForm($form, $settings); } /** @@ -224,7 +224,7 @@ public function submit(array $form, array &$form_state) { 'values' => &$form_state['values']['settings'] ); // Call the plugin submit handler. - $entity->getPlugin()->submit($form, $settings); + $entity->getPlugin()->submitConfigurationForm($form, $settings); // Save the settings of the plugin. $entity->save(); diff --git a/core/modules/block/lib/Drupal/block/BlockPluginBag.php b/core/modules/block/lib/Drupal/block/BlockPluginBag.php index 5a68beb..7807034 100644 --- a/core/modules/block/lib/Drupal/block/BlockPluginBag.php +++ b/core/modules/block/lib/Drupal/block/BlockPluginBag.php @@ -7,38 +7,30 @@ namespace Drupal\block; -use Drupal\block\Plugin\Core\Entity\Block; -use Drupal\Component\Plugin\PluginBag; -use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Component\Utility\String; +use Drupal\Component\Plugin\DefaultSinglePluginBag; /** * Provides a collection of block plugins. */ -class BlockPluginBag extends PluginBag { +class BlockPluginBag extends DefaultSinglePluginBag { /** - * The manager used to instantiate the plugins. + * The block ID this plugin bag belongs to. * - * @var \Drupal\Component\Plugin\PluginManagerInterface + * @var string */ - protected $manager; + protected $blockId; /** - * Constructs a BlockPluginBag object. - * - * @param \Drupal\Component\Plugin\PluginManagerInterface $manager - * The manager to be used for instantiating plugins. - * @param array $instance_ids - * The ids of the plugin instances with which we are dealing. - * @param \Drupal\block\Plugin\Core\Entity\Block $entity - * The Block entity that holds our configuration. + * {@inheritdoc} */ - public function __construct(PluginManagerInterface $manager, array $instance_ids, Block $entity) { - $this->manager = $manager; - $this->entity = $entity; + public function __construct(PluginManagerInterface $manager, array $instance_ids, array $configuration, $block_id) { + parent::__construct($manager, $instance_ids, $configuration); - $this->instanceIDs = drupal_map_assoc($instance_ids); + $this->blockId = $block_id; } /** @@ -46,18 +38,14 @@ public function __construct(PluginManagerInterface $manager, array $instance_ids */ protected function initializePlugin($instance_id) { if (!$instance_id) { - throw new PluginException(format_string("The block '@block' did not specify a plugin.", array('@block' => $this->entity->id()))); - } - if (isset($this->pluginInstances[$instance_id])) { - return; + throw new PluginException(String::format("The block '@block' did not specify a plugin.", array('@block' => $this->blockId))); } - $settings = $this->entity->get('settings'); try { - $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $settings); + parent::initializePlugin($instance_id); } catch (PluginException $e) { - $module = $settings['module']; + $module = $this->configuration['module']; // Ignore blocks belonging to disabled modules, but re-throw valid // exceptions when the module is enabled and the plugin is misconfigured. if (!$module || \Drupal::moduleHandler()->moduleExists($module)) { diff --git a/core/modules/block/lib/Drupal/block/BlockPluginInterface.php b/core/modules/block/lib/Drupal/block/BlockPluginInterface.php index 1887816..86a7644 100644 --- a/core/modules/block/lib/Drupal/block/BlockPluginInterface.php +++ b/core/modules/block/lib/Drupal/block/BlockPluginInterface.php @@ -7,6 +7,10 @@ namespace Drupal\block; +use Drupal\Component\Plugin\PluginInspectionInterface; +use Drupal\Component\Plugin\ConfigurablePluginInterface; +use Drupal\Core\Plugin\PluginFormInterface; + /** * Defines the required interface for all block plugins. * @@ -14,10 +18,8 @@ * architecture and the relationships between the various objects, including * brif references to the important components that are not coupled to the * interface. - * - * @see \Drupal\block\BlockBase */ -interface BlockPluginInterface { +interface BlockPluginInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface { /** * Returns the default settings for this block plugin. @@ -45,61 +47,79 @@ public function settings(); public function access(); /** - * Constructs the block configuration form. + * Builds and returns the renderable array for this block plugin. * - * This method allows base implementations to add a generic configuration - * form for extending block plugins. + * @return array + * A renderable array representing the content of the block. * - * @param array $form - * The form definition array for the block configuration form. - * @param array $form_state - * An array containing the current state of the configuration form. + * @see \Drupal\block\BlockRenderController + */ + public function build(); + + /** + * Sets a particular value in the block settings. * - * @return array $form - * The renderable form array representing the entire configuration form. + * @param string $key + * The key of PluginBase::$configuration to set. + * @param mixed $value + * The value to set for the provided key. * - * @see \Drupal\block\BlockFormController::form() - * @see \Drupal\block\BlockInterace::validate() - * @see \Drupal\block\BlockInterace::submit() + * @todo This doesn't belong here. Move this into a new base class in + * http://drupal.org/node/1764380. + * @todo This does not set a value in config(), so the name is confusing. + * + * @see \Drupal\Component\Plugin\PluginBase::$configuration */ - public function form($form, &$form_state); + public function setConfig($key, $value); /** - * Handles form validation for the block configuration form. + * Returns the configuration form elements specific to this block plugin. + * + * Blocks that need to add form elements to the normal block configuration + * form should implement this method. * * @param array $form * The form definition array for the block configuration form. * @param array $form_state * An array containing the current state of the configuration form. * - * @see \Drupal\block\BlockFormController::validate() - * @see \Drupal\block\BlockInterace::form() - * @see \Drupal\block\BlockInterace::submit() + * @return array $form + * The renderable form array representing the entire configuration form. */ - public function validate($form, &$form_state); + public function blockForm($form, &$form_state); /** - * Handles form submissions for the block configuration form. + * Adds block type-specific validation for the block form. + * + * Note that this method takes the form structure and form state arrays for + * the full block configuration form as arguments, not just the elements + * defined in BlockPluginInterface::blockForm(). * * @param array $form - * The form definition array for the block configuration form. + * The form definition array for the full block configuration form. * @param array $form_state * An array containing the current state of the configuration form. * - * @see \Drupal\block\BlockFormController::submit() - * @see \Drupal\block\BlockInterace::form() - * @see \Drupal\block\BlockInterace::validate() + * @see \Drupal\block\BlockPluginInterface::blockForm() + * @see \Drupal\block\BlockPluginInterface::blockSubmit() */ - public function submit($form, &$form_state); + public function blockValidate($form, &$form_state); /** - * Builds and returns the renderable array for this block plugin. + * Adds block type-specific submission handling for the block form. * - * @return array - * A renderable array representing the content of the block. + * Note that this method takes the form structure and form state arrays for + * the full block configuration form as arguments, not just the elements + * defined in BlockPluginInterface::blockForm(). * - * @see \Drupal\block\BlockRenderController + * @param array $form + * The form definition array for the full block configuration form. + * @param array $form_state + * An array containing the current state of the configuration form. + * + * @see \Drupal\block\BlockPluginInterface::blockForm() + * @see \Drupal\block\BlockPluginInterface::blockValidate() */ - public function build(); + public function blockSubmit($form, &$form_state); } diff --git a/core/modules/block/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php index 45a85d9..57a5d62 100644 --- a/core/modules/block/lib/Drupal/block/BlockRenderController.php +++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php @@ -40,7 +40,7 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la $plugin_id = $plugin->getPluginId(); if ($content = $plugin->build()) { - $configuration = $plugin->getConfig(); + $configuration = $plugin->getConfiguration(); $build[$entity_id] = array( '#theme' => 'block', 'content' => $content, diff --git a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php index 1d3cca8..bb3a1d4 100644 --- a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php @@ -105,7 +105,7 @@ class Block extends ConfigEntityBase implements BlockInterface { public function __construct(array $values, $entity_type) { parent::__construct($values, $entity_type); - $this->pluginBag = new BlockPluginBag(\Drupal::service('plugin.manager.block'), array($this->plugin), $this); + $this->pluginBag = new BlockPluginBag(\Drupal::service('plugin.manager.block'), array($this->plugin), $this->get('settings'), $this->id()); } /** @@ -169,7 +169,7 @@ public function getExportProperties() { * {@inheritdoc} */ public function preSave(EntityStorageControllerInterface $storage_controller) { - $this->set('settings', $this->getPlugin()->getConfig()); + $this->set('settings', $this->getPlugin()->getConfiguration()); } } diff --git a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php index 4bb3b3a..1ecc29a 100644 --- a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php +++ b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php @@ -243,7 +243,7 @@ public function submitOptionsForm(&$form, &$form_state) { public function blockForm(ViewsBlock $block, array &$form, array &$form_state) { $allow_settings = array_filter($this->getOption('allow')); - $block_configuration = $block->getConfig(); + $block_configuration = $block->getConfiguration(); foreach ($allow_settings as $type => $enabled) { if (empty($enabled)) { @@ -310,7 +310,7 @@ public function blockSubmit(ViewsBlock $block, $form, &$form_state) { * The block plugin for views displays. */ public function preBlockBuild(ViewsBlock $block) { - $config = $block->getConfig(); + $config = $block->getConfiguration(); if ($config['items_per_page'] !== 'none') { $this->view->setItemsPerPage($config['items_per_page']); } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php index 327cf45..b3093d9 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php @@ -52,12 +52,12 @@ public function testBlockInterface() { ); // Initial configuration of the block at construction time. $display_block = $manager->createInstance('test_block_instantiation', $configuration); - $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block was configured correctly.'); + $this->assertIdentical($display_block->getConfiguration(), $expected_configuration, 'The block was configured correctly.'); // Updating an element of the configuration. $display_block->setConfig('display_message', 'My custom display message.'); $expected_configuration['display_message'] = 'My custom display message.'; - $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block configuration was updated correctly.'); + $this->assertIdentical($display_block->getConfiguration(), $expected_configuration, 'The block configuration was updated correctly.'); $expected_form = array( 'module' => array( @@ -85,7 +85,7 @@ public function testBlockInterface() { ); $form_state = array(); // Ensure there are no form elements that do not belong to the plugin. - $this->assertIdentical($display_block->form(array(), $form_state), $expected_form, 'Only the expected form elements were present.'); + $this->assertIdentical($display_block->buildConfigurationForm(array(), $form_state), $expected_form, 'Only the expected form elements were present.'); $expected_build = array( '#children' => 'My custom display message.', diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php index 51630ba..3042b5b 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php @@ -45,7 +45,7 @@ function testBlockThemeHookSuggestions() { $variables = array(); $variables['elements']['#block'] = $block; - $variables['elements']['#configuration'] = $block->getPlugin()->getConfig(); + $variables['elements']['#configuration'] = $block->getPlugin()->getConfiguration(); $variables['elements']['#plugin_id'] = $block->get('plugin'); $variables['elements']['content'] = array(); // Test adding a class to the block content. diff --git a/core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php b/core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php index 1582160..765cc57 100644 --- a/core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php +++ b/core/modules/block/tests/lib/Drupal/block/Tests/Plugin/views/display/BlockTest.php @@ -80,7 +80,7 @@ public function testBuildNoOverride() { ->method('setItemsPerPage'); $this->blockPlugin->expects($this->once()) - ->method('getConfig') + ->method('getConfiguration') ->will($this->returnValue(array('items_per_page' => 'none'))); $this->blockDisplay->preBlockBuild($this->blockPlugin); @@ -95,7 +95,7 @@ public function testBuildOverride() { ->with(5); $this->blockPlugin->expects($this->once()) - ->method('getConfig') + ->method('getConfiguration') ->will($this->returnValue(array('items_per_page' => 5))); $this->blockDisplay->preBlockBuild($this->blockPlugin); diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php index d123cfc..d669db4 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php @@ -49,7 +49,7 @@ protected function getDefaultConfiguration() { /** * {@inheritdoc} */ - public function form(array $form, array &$form_state) { + public function buildConfigurationForm(array $form, array &$form_state) { $form['keywords'] = array( '#title' => t('Keywords'), '#type' => 'textarea', @@ -62,7 +62,7 @@ public function form(array $form, array &$form_state) { /** * {@inheritdoc} */ - public function submit(array &$form, array &$form_state) { + public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['keywords'] = drupal_explode_tags($form_state['values']['keywords']); } diff --git a/core/modules/filter/config/filter.format.plain_text.yml b/core/modules/filter/config/filter.format.plain_text.yml index 586e28d..ea0a4bd 100644 --- a/core/modules/filter/config/filter.format.plain_text.yml +++ b/core/modules/filter/config/filter.format.plain_text.yml @@ -13,12 +13,14 @@ cache: '1' filters: # Escape all HTML. filter_html_escape: + id: filter_html_escape module: filter status: '1' weight: '-10' settings: { } # Convert URLs into links. filter_url: + id: filter_url module: filter status: '1' weight: '0' @@ -26,6 +28,7 @@ filters: filter_url_length: '72' # Convert linebreaks into paragraphs. filter_autop: + id: filter_autop module: filter status: '1' weight: '0' diff --git a/core/modules/filter/lib/Drupal/filter/FilterBag.php b/core/modules/filter/lib/Drupal/filter/FilterBag.php index 781cfda..8de6646 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterBag.php +++ b/core/modules/filter/lib/Drupal/filter/FilterBag.php @@ -7,31 +7,14 @@ namespace Drupal\filter; -use Drupal\Component\Plugin\PluginBag; -use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Plugin\DefaultPluginBag; /** * A collection of filters. */ -class FilterBag extends PluginBag { - - /** - * The initial configuration for each filter in the bag. - * - * @var array - * An associative array containing the initial configuration for each filter - * in the bag, keyed by plugin instance ID. - */ - protected $configurations = array(); - - /** - * The manager used to instantiate the plugins. - * - * @var \Drupal\Component\Plugin\PluginManagerInterface - */ - protected $manager; +class FilterBag extends DefaultPluginBag { /** * All possible filter plugin IDs. @@ -41,22 +24,9 @@ class FilterBag extends PluginBag { protected $definitions; /** - * Constructs a FilterBag object. - * - * @param \Drupal\Component\Plugin\PluginManagerInterface $manager - * The manager to be used for instantiating plugins. - * @param array $configurations - * (optional) An associative array containing the initial configuration for - * each filter in the bag, keyed by plugin instance ID. + * {@inheritdoc} */ - public function __construct(PluginManagerInterface $manager, array $configurations = array()) { - $this->manager = $manager; - $this->configurations = $configurations; - - if (!empty($configurations)) { - $this->instanceIDs = array_combine(array_keys($configurations), array_keys($configurations)); - } - } + protected $pluginKey = 'id'; /** * Retrieves filter definitions and creates an instance for each filter. @@ -86,22 +56,6 @@ public function getAll() { } /** - * Updates the configuration for a filter plugin instance. - * - * If there is no plugin instance yet, a new will be instantiated. Otherwise, - * the existing instance is updated with the new configuration. - * - * @param string $instance_id - * The ID of a filter plugin to set the configuration for. - * @param array $configuration - * The filter plugin configuration to set. - */ - public function setConfig($instance_id, array $configuration) { - $this->configurations[$instance_id] = $configuration; - $this->get($instance_id)->setPluginConfiguration($configuration); - } - - /** * {@inheritdoc} */ protected function initializePlugin($instance_id) { @@ -115,7 +69,6 @@ protected function initializePlugin($instance_id) { $definition = $this->manager->getDefinition($instance_id); if (isset($definition)) { - $this->addInstanceID($instance_id); // $configuration is the whole filter plugin instance configuration, as // contained in the text format configuration. The default configuration // is the filter plugin definition. @@ -126,7 +79,8 @@ protected function initializePlugin($instance_id) { if (isset($this->configurations[$instance_id])) { $configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]); } - $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $configuration, $this); + $this->configurations[$instance_id] = $configuration; + parent::initializePlugin($instance_id); } else { throw new PluginException(format_string("Unknown filter plugin ID '@filter'.", array('@filter' => $instance_id))); @@ -134,20 +88,15 @@ protected function initializePlugin($instance_id) { } /** - * Sorts all filter plugin instances in this bag. - * - * @return \Drupal\filter\FilterBag + * {@inheritdoc} */ public function sort() { $this->getAll(); - uasort($this->instanceIDs, array($this, 'sortHelper')); - return $this; + return parent::sort(); } /** - * uasort() callback to sort filters by status, weight, module, and name. - * - * @see \Drupal\filter\FilterFormatStorageController::preSave() + * {@inheritdoc} */ public function sortHelper($aID, $bID) { $a = $this->get($aID); @@ -164,22 +113,4 @@ public function sortHelper($aID, $bID) { return strnatcasecmp($a->getPluginId(), $b->getPluginId()); } - /** - * Returns the current configuration of all filters in this bag. - * - * @return array - * An associative array keyed by filter plugin instance ID, whose values - * are filter configurations. - * - * @see \Drupal\filter\Plugin\Filter\FilterInterface::export() - */ - public function export() { - $filters = array(); - $this->rewind(); - foreach ($this as $instance_id => $instance) { - $filters[$instance_id] = $instance->export(); - } - return $filters; - } - } diff --git a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php index b3cb277..3d9b649 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php +++ b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php @@ -8,12 +8,12 @@ namespace Drupal\filter; use Drupal\Component\Plugin\PluginManagerBase; -use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Language\Language; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\CacheDecorator; +use Drupal\Core\Plugin\Factory\ContainerFactory; /** * Manages text processing filters. @@ -36,15 +36,8 @@ public function __construct(\Traversable $namespaces) { $cache_key = 'filter_plugins:' . language(Language::TYPE_INTERFACE)->id; $cache_tags = array('filter_formats' => TRUE); $this->discovery = new CacheDecorator($this->discovery, $cache_key, 'cache', CacheBackendInterface::CACHE_PERMANENT, $cache_tags); - } - /** - * {@inheritdoc} - */ - public function createInstance($plugin_id, array $configuration = array(), FilterBag $filter_bag = NULL) { - $plugin_definition = $this->getDefinition($plugin_id); - $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition); - return new $plugin_class($configuration, $plugin_id, $plugin_definition, $filter_bag); + $this->factory = new ContainerFactory($this); } } diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php index a853bb6..7541b53 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php @@ -155,7 +155,7 @@ public function filters($instance_id = NULL) { public function setFilterConfig($instance_id, array $configuration) { $this->filters[$instance_id] = $configuration; if (isset($this->filterBag)) { - $this->filterBag->setConfig($instance_id, $configuration); + $this->filterBag->setConfiguration($instance_id, $configuration); } return $this; } @@ -166,7 +166,7 @@ public function setFilterConfig($instance_id, array $configuration) { public function getExportProperties() { $properties = parent::getExportProperties(); // Sort and export the configuration of all filters. - $properties['filters'] = $this->filters()->sort()->export(); + $properties['filters'] = $this->filters()->sort()->getConfiguration(); return $properties; } @@ -212,7 +212,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { // Determine whether the format can be cached. // @todo This is a derived/computed definition, not configuration. $this->cache = TRUE; - foreach ($this->filters() as $filter) { + foreach ($this->filters()->getAll() as $filter) { if ($filter->status && !$filter->cache) { $this->cache = FALSE; } diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php index 2e80bd0..859ff50 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php @@ -70,21 +70,19 @@ /** * {@inheritdoc} */ - public function __construct(array $configuration, $plugin_id, array $plugin_definition, FilterBag $bag) { + public function __construct(array $configuration, $plugin_id, array $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->module = $this->pluginDefinition['module']; $this->cache = $this->pluginDefinition['cache']; - $this->setPluginConfiguration($configuration); - - $this->bag = $bag; + $this->setConfiguration($configuration); } /** * {@inheritdoc} */ - public function setPluginConfiguration(array $configuration) { + public function setConfiguration(array $configuration) { if (isset($configuration['status'])) { $this->status = (bool) $configuration['status']; } @@ -100,8 +98,9 @@ public function setPluginConfiguration(array $configuration) { /** * {@inheritdoc} */ - public function export() { + public function getConfiguration() { return array( + 'id' => $this->getPluginId(), 'module' => $this->pluginDefinition['module'], 'status' => $this->status, 'weight' => $this->weight, diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php index 5b231a9..ee4ba2b 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php @@ -7,6 +7,9 @@ namespace Drupal\filter\Plugin; +use Drupal\Component\Plugin\PluginInspectionInterface; +use Drupal\Component\Plugin\ConfigurablePluginInterface; + /** * Defines the interface for text processing filter plugins. * @@ -74,26 +77,7 @@ * * @see \Drupal\filter\Plugin\Filter\FilterBase */ -interface FilterInterface { - - /** - * Sets the configuration for this filter plugin instance. - * - * @param array $configuration - * An associative array containing: - * - status: A Boolean indicating whether the plugin is enabled. - * - weight: The weight of the filter compared to others. - * - settings: An associative array containing configured settings for this - * filter implementation. - */ - public function setPluginConfiguration(array $configuration); - - /** - * Exports the complete configuration of this filter plugin instance. - * - * @return array - */ - public function export(); +interface FilterInterface extends ConfigurablePluginInterface, PluginInspectionInterface { /** * Returns the processing type of this filter plugin. diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php index b644b10..cd5a762 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php @@ -8,9 +8,7 @@ namespace Drupal\filter\Tests; use Drupal\simpletest\DrupalUnitTestBase; -use stdClass; use Drupal\filter\FilterBag; -use Drupal\filter\Plugin\Filter\FilterCaption; /** * Unit tests for core filters. @@ -24,6 +22,11 @@ class FilterUnitTest extends DrupalUnitTestBase { */ public static $modules = array('filter'); + /** + * @var \Drupal\filter\Plugin\FilterInterface[] + */ + protected $filters; + public static function getInfo() { return array( 'name' => 'Filter module filters', @@ -238,7 +241,7 @@ function testLineBreakFilter() { function testHtmlFilter() { // Get FilterHtml object. $filter = $this->filters['filter_html']; - $filter->setPluginConfiguration(array( + $filter->setConfiguration(array( 'settings' => array( 'allowed_html' => '