Initial Drupal 11 with DDEV setup
This commit is contained in:
		@ -0,0 +1,77 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Attribute;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a base class for classed attributes.
 | 
			
		||||
 */
 | 
			
		||||
abstract class AttributeBase implements AttributeInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The class used for this attribute class.
 | 
			
		||||
   *
 | 
			
		||||
   * @var class-string
 | 
			
		||||
   */
 | 
			
		||||
  protected string $class;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The provider of the attribute class.
 | 
			
		||||
   */
 | 
			
		||||
  protected string|null $provider = NULL;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @param string $id
 | 
			
		||||
   *   The attribute class ID.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(
 | 
			
		||||
    protected readonly string $id,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getProvider(): ?string {
 | 
			
		||||
    return $this->provider;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setProvider(string $provider): void {
 | 
			
		||||
    $this->provider = $provider;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getId(): string {
 | 
			
		||||
    return $this->id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getClass(): string {
 | 
			
		||||
    return $this->class;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setClass(string $class): void {
 | 
			
		||||
    $this->class = $class;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function get(): array|object {
 | 
			
		||||
    return array_filter(get_object_vars($this) + [
 | 
			
		||||
      'class' => $this->getClass(),
 | 
			
		||||
      'provider' => $this->getProvider(),
 | 
			
		||||
    ], function ($value, $key) {
 | 
			
		||||
      return !($value === NULL && ($key === 'deriver' || $key === 'provider'));
 | 
			
		||||
    }, ARRAY_FILTER_USE_BOTH);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Attribute;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a common interface for classed attributes.
 | 
			
		||||
 */
 | 
			
		||||
interface AttributeInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the value of an attribute.
 | 
			
		||||
   */
 | 
			
		||||
  public function get(): mixed;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the name of the provider of the attribute class.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string|null
 | 
			
		||||
   *   The provider of the attribute class.
 | 
			
		||||
   */
 | 
			
		||||
  public function getProvider(): ?string;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the name of the provider of the attribute class.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $provider
 | 
			
		||||
   *   The provider of the annotated class.
 | 
			
		||||
   */
 | 
			
		||||
  public function setProvider(string $provider): void;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the unique ID for this attribute class.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The attribute class ID.
 | 
			
		||||
   */
 | 
			
		||||
  public function getId(): string;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the class of the attribute class.
 | 
			
		||||
   *
 | 
			
		||||
   * @return class-string|null
 | 
			
		||||
   *   The attribute class.
 | 
			
		||||
   */
 | 
			
		||||
  public function getClass(): ?string;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the class of the attributed class.
 | 
			
		||||
   *
 | 
			
		||||
   * @param class-string $class
 | 
			
		||||
   *   The class of the attributed class.
 | 
			
		||||
   */
 | 
			
		||||
  public function setClass(string $class): void;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								web/core/lib/Drupal/Component/Plugin/Attribute/Plugin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								web/core/lib/Drupal/Component/Plugin/Attribute/Plugin.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Attribute;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a Plugin attribute object.
 | 
			
		||||
 *
 | 
			
		||||
 * Attributes in plugin classes can use this class in order to pass various
 | 
			
		||||
 * metadata about the plugin through the parser to
 | 
			
		||||
 * DiscoveryInterface::getDefinitions() calls.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
#[\Attribute(\Attribute::TARGET_CLASS)]
 | 
			
		||||
class Plugin extends AttributeBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs a plugin attribute object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $id
 | 
			
		||||
   *   The plugin ID.
 | 
			
		||||
   * @param class-string|null $deriver
 | 
			
		||||
   *   (optional) The deriver class.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(
 | 
			
		||||
    public readonly string $id,
 | 
			
		||||
    public readonly ?string $deriver = NULL,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								web/core/lib/Drupal/Component/Plugin/Attribute/PluginID.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								web/core/lib/Drupal/Component/Plugin/Attribute/PluginID.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Attribute;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a Plugin attribute object that just contains an ID.
 | 
			
		||||
 */
 | 
			
		||||
#[\Attribute(\Attribute::TARGET_CLASS)]
 | 
			
		||||
class PluginID extends AttributeBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function get(): array {
 | 
			
		||||
    return [
 | 
			
		||||
      'id' => $this->getId(),
 | 
			
		||||
      'class' => $this->getClass(),
 | 
			
		||||
      'provider' => $this->getProvider(),
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,46 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines an interface for plugin managers that categorize plugin definitions.
 | 
			
		||||
 */
 | 
			
		||||
interface CategorizingPluginManagerInterface extends PluginManagerInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the names of all categories.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string[]
 | 
			
		||||
   *   An array of translated categories, sorted alphabetically.
 | 
			
		||||
   */
 | 
			
		||||
  public function getCategories();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets sorted plugin definitions.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array[]|null $definitions
 | 
			
		||||
   *   (optional) The plugin definitions to sort. If omitted, all plugin
 | 
			
		||||
   *   definitions are used.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array[]
 | 
			
		||||
   *   An array of plugin definitions, sorted by category and label.
 | 
			
		||||
   */
 | 
			
		||||
  public function getSortedDefinitions(?array $definitions = NULL);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets sorted plugin definitions grouped by category.
 | 
			
		||||
   *
 | 
			
		||||
   * In addition to grouping, both categories and its entries are sorted,
 | 
			
		||||
   * whereas plugin definitions are sorted by label.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array[]|null $definitions
 | 
			
		||||
   *   (optional) The plugin definitions to group. If omitted, all plugin
 | 
			
		||||
   *   definitions are used.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array[]
 | 
			
		||||
   *   Keys are category names, and values are arrays of which the keys are
 | 
			
		||||
   *   plugin IDs and the values are plugin definitions.
 | 
			
		||||
   */
 | 
			
		||||
  public function getGroupedDefinitions(?array $definitions = NULL);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides an interface for a configurable plugin.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface ConfigurableInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets this plugin's configuration.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of this plugin's configuration.
 | 
			
		||||
   */
 | 
			
		||||
  public function getConfiguration();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the configuration for this plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An associative array containing the plugin's configuration.
 | 
			
		||||
   */
 | 
			
		||||
  public function setConfiguration(array $configuration);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets default configuration for this plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An associative array with the default configuration.
 | 
			
		||||
   */
 | 
			
		||||
  public function defaultConfiguration();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										94
									
								
								web/core/lib/Drupal/Component/Plugin/Context/Context.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								web/core/lib/Drupal/Component/Plugin/Context/Context.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Context;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Exception\ContextException;
 | 
			
		||||
use Symfony\Component\Validator\Constraints\Type;
 | 
			
		||||
use Symfony\Component\Validator\Validation;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A generic context class for wrapping data a plugin needs to operate.
 | 
			
		||||
 */
 | 
			
		||||
class Context implements ContextInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The value of the context.
 | 
			
		||||
   *
 | 
			
		||||
   * @var mixed
 | 
			
		||||
   */
 | 
			
		||||
  protected $contextValue;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The definition to which a context must conform.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Context\ContextDefinitionInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $contextDefinition;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a context object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Context\ContextDefinitionInterface $context_definition
 | 
			
		||||
   *   The context definition.
 | 
			
		||||
   * @param mixed|null $context_value
 | 
			
		||||
   *   The value of the context.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(ContextDefinitionInterface $context_definition, $context_value = NULL) {
 | 
			
		||||
    $this->contextDefinition = $context_definition;
 | 
			
		||||
    $this->contextValue = $context_value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextValue() {
 | 
			
		||||
    // Support optional contexts.
 | 
			
		||||
    if (!isset($this->contextValue)) {
 | 
			
		||||
      $definition = $this->getContextDefinition();
 | 
			
		||||
      $default_value = $definition->getDefaultValue();
 | 
			
		||||
 | 
			
		||||
      if (!isset($default_value) && $definition->isRequired()) {
 | 
			
		||||
        $type = $definition->getDataType();
 | 
			
		||||
        throw new ContextException(sprintf("The %s context is required and not present.", $type));
 | 
			
		||||
      }
 | 
			
		||||
      // Keep the default value here so that subsequent calls don't have to look
 | 
			
		||||
      // it up again.
 | 
			
		||||
      $this->contextValue = $default_value;
 | 
			
		||||
    }
 | 
			
		||||
    return $this->contextValue;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function hasContextValue() {
 | 
			
		||||
    return $this->contextValue !== NULL || $this->getContextDefinition()->getDefaultValue() !== NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinition() {
 | 
			
		||||
    return $this->contextDefinition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getConstraints() {
 | 
			
		||||
    if (empty($this->contextDefinition['class'])) {
 | 
			
		||||
      throw new ContextException("An error was encountered while trying to validate the context.");
 | 
			
		||||
    }
 | 
			
		||||
    return [new Type($this->contextDefinition['class'])];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function validate() {
 | 
			
		||||
    $validator = Validation::createValidatorBuilder()
 | 
			
		||||
      ->getValidator();
 | 
			
		||||
    return $validator->validateValue($this->getContextValue(), $this->getConstraints());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,176 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Context;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface used to define definition objects found in ContextInterface.
 | 
			
		||||
 *
 | 
			
		||||
 * @see \Drupal\Component\Plugin\Context\ContextInterface
 | 
			
		||||
 *
 | 
			
		||||
 * @todo WARNING: This interface is going to receive some additions as part of
 | 
			
		||||
 * https://www.drupal.org/node/2346999.
 | 
			
		||||
 */
 | 
			
		||||
interface ContextDefinitionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a human readable label.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The label.
 | 
			
		||||
   */
 | 
			
		||||
  public function getLabel();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the human readable label.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $label
 | 
			
		||||
   *   The label to set.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setLabel($label);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a human readable description.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string|null
 | 
			
		||||
   *   The description, or NULL if no description is available.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDescription();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the human readable description.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string|null $description
 | 
			
		||||
   *   The description to set.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setDescription($description);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the data type needed by the context.
 | 
			
		||||
   *
 | 
			
		||||
   * If the context is multiple-valued, this represents the type of each value.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The data type.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDataType();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the data type needed by the context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $data_type
 | 
			
		||||
   *   The data type to set.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setDataType($data_type);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Determines whether the data is multi-valued, i.e. a list of data items.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   Whether the data is multi-valued; i.e. a list of data items.
 | 
			
		||||
   */
 | 
			
		||||
  public function isMultiple();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets whether the data is multi-valued.
 | 
			
		||||
   *
 | 
			
		||||
   * @param bool $multiple
 | 
			
		||||
   *   (optional) Whether the data is multi-valued. Defaults to TRUE.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setMultiple($multiple = TRUE);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Determines whether the context is required.
 | 
			
		||||
   *
 | 
			
		||||
   * For required data a non-NULL value is mandatory.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   Whether a data value is required.
 | 
			
		||||
   */
 | 
			
		||||
  public function isRequired();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets whether the data is required.
 | 
			
		||||
   *
 | 
			
		||||
   * @param bool $required
 | 
			
		||||
   *   (optional) Whether the data is multi-valued. Defaults to TRUE.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setRequired($required = TRUE);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the default value for this context definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed
 | 
			
		||||
   *   The default value or NULL if no default value is set.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefaultValue();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the default data value.
 | 
			
		||||
   *
 | 
			
		||||
   * @param mixed $default_value
 | 
			
		||||
   *   The default value to be set or NULL to remove any default value.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setDefaultValue($default_value);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets an array of validation constraints.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of validation constraint definitions, keyed by constraint name.
 | 
			
		||||
   *   Each constraint definition can be used for instantiating
 | 
			
		||||
   *   \Symfony\Component\Validator\Constraint objects.
 | 
			
		||||
   */
 | 
			
		||||
  public function getConstraints();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the array of validation constraints.
 | 
			
		||||
   *
 | 
			
		||||
   * NOTE: This will override any previously set constraints. In most cases
 | 
			
		||||
   * ContextDefinitionInterface::addConstraint() should be used instead.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $constraints
 | 
			
		||||
   *   The array of constraints.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   *
 | 
			
		||||
   * @see self::addConstraint()
 | 
			
		||||
   */
 | 
			
		||||
  public function setConstraints(array $constraints);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds a validation constraint.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $constraint_name
 | 
			
		||||
   *   The name of the constraint to add, i.e. its plugin id.
 | 
			
		||||
   * @param array|null $options
 | 
			
		||||
   *   The constraint options as required by the constraint plugin, or NULL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function addConstraint($constraint_name, $options = NULL);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a validation constraint.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $constraint_name
 | 
			
		||||
   *   The name of the constraint, i.e. its plugin id.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   A validation constraint definition which can be used for instantiating a
 | 
			
		||||
   *   \Symfony\Component\Validator\Constraint object.
 | 
			
		||||
   */
 | 
			
		||||
  public function getConstraint($constraint_name);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Context;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides data and definitions for plugins during runtime and administration.
 | 
			
		||||
 *
 | 
			
		||||
 * Plugin contexts are satisfied by ContextInterface implementing objects.
 | 
			
		||||
 * These objects always contain a definition of what data they will provide
 | 
			
		||||
 * during runtime. During run time, ContextInterface implementing objects must
 | 
			
		||||
 * also provide the corresponding data value.
 | 
			
		||||
 *
 | 
			
		||||
 * @see \Drupal\Component\Plugin\Context\ContextDefinitionInterface
 | 
			
		||||
 */
 | 
			
		||||
interface ContextInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the context value.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed
 | 
			
		||||
   *   The currently set context value, or NULL if it is not set.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextValue();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns whether the context has a value.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   TRUE if the context has a value, FALSE otherwise.
 | 
			
		||||
   */
 | 
			
		||||
  public function hasContextValue();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the provided definition that the context must conform to.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface
 | 
			
		||||
   *   The defining characteristic representation of the context.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinition();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a list of validation constraints.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   Array of constraints, each being an instance of
 | 
			
		||||
   *   \Symfony\Component\Validator\Constraint.
 | 
			
		||||
   */
 | 
			
		||||
  public function getConstraints();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Validates the set context value.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
 | 
			
		||||
   *   A list of constraint violations. If the list is empty, validation
 | 
			
		||||
   *   succeeded.
 | 
			
		||||
   */
 | 
			
		||||
  public function validate();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,147 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Context\ContextInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface for defining context aware plugins.
 | 
			
		||||
 *
 | 
			
		||||
 * Context aware plugins can specify an array of context definitions keyed by
 | 
			
		||||
 * context name at the plugin definition under the "context" key.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface ContextAwarePluginInterface extends PluginInspectionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the context definitions of the plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]
 | 
			
		||||
   *   The array of context definitions, keyed by context name.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinitions();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a specific context definition of the plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The name of the context in the plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface
 | 
			
		||||
   *   The definition against which the context value must validate.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   If the requested context is not defined.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinition($name);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the defined contexts.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   The set context objects.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   If contexts are defined but not set.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContexts();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a defined context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The name of the context in the plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextInterface
 | 
			
		||||
   *   The context object.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   If the requested context is not set.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContext($name);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the values for all defined contexts.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of set context values, keyed by context name. If a context is
 | 
			
		||||
   *   unset its value is returned as NULL.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextValues();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the value for a defined context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The name of the context in the plugin configuration.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed
 | 
			
		||||
   *   The currently set context value.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   If the requested context is not set.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextValue($name);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set a context on this plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The name of the context in the plugin configuration.
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Context\ContextInterface $context
 | 
			
		||||
   *   The context object to set.
 | 
			
		||||
   */
 | 
			
		||||
  public function setContext($name, ContextInterface $context);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the value for a defined context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The name of the context in the plugin definition.
 | 
			
		||||
   * @param mixed $value
 | 
			
		||||
   *   The value to set the context to. The value has to validate against the
 | 
			
		||||
   *   provided context definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   *   A context aware plugin object for chaining.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   If the value does not pass validation.
 | 
			
		||||
   */
 | 
			
		||||
  public function setContextValue($name, $value);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Validates the set values for the defined contexts.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Symfony\Component\Validator\ConstraintViolationListInterface
 | 
			
		||||
   *   A list of constraint violations. If the list is empty, validation
 | 
			
		||||
   *   succeeded.
 | 
			
		||||
   */
 | 
			
		||||
  public function validateContexts();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a mapping of the expected assignment names to their context names.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   A mapping of the expected assignment names to their context names. For
 | 
			
		||||
   *   example, if one of the $contexts is named 'user.current_user', but the
 | 
			
		||||
   *   plugin expects a context named 'user', then this map would contain
 | 
			
		||||
   *   'user' => 'user.current_user'.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextMapping();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets a mapping of the expected assignment names to their context names.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $context_mapping
 | 
			
		||||
   *   A mapping of the expected assignment names to their context names. For
 | 
			
		||||
   *   example, if one of the $contexts is named 'user.current_user', but the
 | 
			
		||||
   *   plugin expects a context named 'user', then this map would contain
 | 
			
		||||
   *   'user' => 'user.current_user'.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setContextMapping(array $context_mapping);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Definition;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Context\ContextDefinitionInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides an interface for plugin definitions which use contexts.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup Plugin
 | 
			
		||||
 */
 | 
			
		||||
interface ContextAwarePluginDefinitionInterface extends PluginDefinitionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks if the plugin defines a particular context.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The context name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   TRUE if the plugin defines the given context, otherwise FALSE.
 | 
			
		||||
   */
 | 
			
		||||
  public function hasContextDefinition($name);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns all context definitions for this plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]
 | 
			
		||||
   *   The context definitions.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinitions();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a particular context definition for this plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The context name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Context\ContextDefinitionInterface
 | 
			
		||||
   *   The context definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\ContextException
 | 
			
		||||
   *   Thrown if the plugin does not define the given context.
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinition($name);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds a context to this plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The context name.
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Context\ContextDefinitionInterface $definition
 | 
			
		||||
   *   The context definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   *   The called object.
 | 
			
		||||
   */
 | 
			
		||||
  public function addContextDefinition($name, ContextDefinitionInterface $definition);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes a context definition from this plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $name
 | 
			
		||||
   *   The context name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   *   The called object.
 | 
			
		||||
   */
 | 
			
		||||
  public function removeContextDefinition($name);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,60 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Definition;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Context\ContextDefinitionInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Exception\ContextException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a trait for context-aware object-based plugin definitions.
 | 
			
		||||
 */
 | 
			
		||||
trait ContextAwarePluginDefinitionTrait {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The context definitions for this plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Context\ContextDefinitionInterface[]
 | 
			
		||||
   */
 | 
			
		||||
  protected $contextDefinitions = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::hasContextDefinition().
 | 
			
		||||
   */
 | 
			
		||||
  public function hasContextDefinition($name) {
 | 
			
		||||
    return array_key_exists($name, $this->contextDefinitions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::getContextDefinitions().
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinitions() {
 | 
			
		||||
    return $this->contextDefinitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::getContextDefinition().
 | 
			
		||||
   */
 | 
			
		||||
  public function getContextDefinition($name) {
 | 
			
		||||
    if ($this->hasContextDefinition($name)) {
 | 
			
		||||
      return $this->contextDefinitions[$name];
 | 
			
		||||
    }
 | 
			
		||||
    throw new ContextException($this->id() . " does not define a '$name' context");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::addContextDefinition().
 | 
			
		||||
   */
 | 
			
		||||
  public function addContextDefinition($name, ContextDefinitionInterface $definition) {
 | 
			
		||||
    $this->contextDefinitions[$name] = $definition;
 | 
			
		||||
    return $this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements \Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface::removeContextDefinition().
 | 
			
		||||
   */
 | 
			
		||||
  public function removeContextDefinition($name) {
 | 
			
		||||
    unset($this->contextDefinitions[$name]);
 | 
			
		||||
    return $this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Definition;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides an interface for a derivable plugin definition.
 | 
			
		||||
 *
 | 
			
		||||
 * @see \Drupal\Component\Plugin\Derivative\DeriverInterface
 | 
			
		||||
 */
 | 
			
		||||
interface DerivablePluginDefinitionInterface extends PluginDefinitionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the name of the deriver of this plugin definition, if it exists.
 | 
			
		||||
   *
 | 
			
		||||
   * @return class-string|null
 | 
			
		||||
   *   Either the deriver class name, or NULL if the plugin is not derived.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDeriver();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the deriver of this plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param class-string|null $deriver
 | 
			
		||||
   *   Either the name of a class that implements
 | 
			
		||||
   *   \Drupal\Component\Plugin\Derivative\DeriverInterface, or NULL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  public function setDeriver($deriver);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,61 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Definition;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides object-based plugin definitions.
 | 
			
		||||
 */
 | 
			
		||||
#[\AllowDynamicProperties]
 | 
			
		||||
class PluginDefinition implements PluginDefinitionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The plugin ID.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $id;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A fully qualified class name.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $class;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The plugin provider.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $provider;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function id() {
 | 
			
		||||
    return $this->id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setClass($class) {
 | 
			
		||||
    $this->class = $class;
 | 
			
		||||
    return $this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getClass() {
 | 
			
		||||
    return $this->class;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getProvider() {
 | 
			
		||||
    return $this->provider;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,54 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Definition;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a plugin definition.
 | 
			
		||||
 *
 | 
			
		||||
 * Object-based plugin definitions MUST implement this interface.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup Plugin
 | 
			
		||||
 */
 | 
			
		||||
interface PluginDefinitionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the unique identifier of the plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The unique identifier of the plugin.
 | 
			
		||||
   */
 | 
			
		||||
  public function id();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the class.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $class
 | 
			
		||||
   *   A fully qualified class name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return static
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \InvalidArgumentException
 | 
			
		||||
   *   If the class is invalid.
 | 
			
		||||
   */
 | 
			
		||||
  public function setClass($class);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the class.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   A fully qualified class name.
 | 
			
		||||
   */
 | 
			
		||||
  public function getClass();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the plugin provider.
 | 
			
		||||
   *
 | 
			
		||||
   * The provider is the name of the module that provides the plugin, or "core',
 | 
			
		||||
   * or "component".
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The provider.
 | 
			
		||||
   */
 | 
			
		||||
  public function getProvider();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides an interface for a plugin that has dependencies.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface DependentPluginInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Calculates dependencies for the configured plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * Dependencies are saved in the plugin's configuration entity and are used to
 | 
			
		||||
   * determine configuration synchronization order. For example, if the plugin
 | 
			
		||||
   * integrates with specific user roles, this method should return an array of
 | 
			
		||||
   * dependencies listing the specified roles.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of dependencies grouped by type (config, content, module,
 | 
			
		||||
   *   theme). For example:
 | 
			
		||||
   *   @code
 | 
			
		||||
   *   [
 | 
			
		||||
   *     'config' => ['user.role.anonymous', 'user.role.authenticated'],
 | 
			
		||||
   *     'content' => ['node:article:f0a189e6-55fb-47fb-8005-5bef81c44d6d'],
 | 
			
		||||
   *     'module' => ['node', 'user'],
 | 
			
		||||
   *     'theme' => ['claro'],
 | 
			
		||||
   *   ];
 | 
			
		||||
   *   @endcode
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
 | 
			
		||||
   * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName()
 | 
			
		||||
   */
 | 
			
		||||
  public function calculateDependencies();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Derivative;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a basic deriver.
 | 
			
		||||
 */
 | 
			
		||||
abstract class DeriverBase implements DeriverInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * List of derivative definitions.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $derivatives = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeDefinition($derivative_id, $base_plugin_definition) {
 | 
			
		||||
    if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
 | 
			
		||||
      return $this->derivatives[$derivative_id];
 | 
			
		||||
    }
 | 
			
		||||
    $this->getDerivativeDefinitions($base_plugin_definition);
 | 
			
		||||
    return $this->derivatives[$derivative_id];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeDefinitions($base_plugin_definition) {
 | 
			
		||||
    return $this->derivatives;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Derivative;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides additional plugin definitions based on an existing definition.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface DeriverInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the definition of a derivative plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $derivative_id
 | 
			
		||||
   *   The derivative id. The id must uniquely identify the derivative within a
 | 
			
		||||
   *   given base plugin, but derivative ids can be reused across base plugins.
 | 
			
		||||
   * @param array|\Drupal\Component\Plugin\Definition\PluginDefinitionInterface $base_plugin_definition
 | 
			
		||||
   *   The definition of the base plugin from which the derivative plugin
 | 
			
		||||
   *   is derived. It is maybe an entire object or just some array, depending
 | 
			
		||||
   *   on the discovery mechanism.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array|null
 | 
			
		||||
   *   The full definition array of the derivative plugin, typically a merge of
 | 
			
		||||
   *   $base_plugin_definition with extra derivative-specific information. NULL
 | 
			
		||||
   *   if the derivative doesn't exist.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeDefinition($derivative_id, $base_plugin_definition);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the definition of all derivatives of a base plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $base_plugin_definition
 | 
			
		||||
   *   The definition array of the base plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of full derivative definitions keyed on derivative id.
 | 
			
		||||
   *
 | 
			
		||||
   * @see getDerivativeDefinition()
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeDefinitions($base_plugin_definition);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a plugin interface for providing derivative metadata inspection.
 | 
			
		||||
 */
 | 
			
		||||
interface DerivativeInspectionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the base_plugin_id of the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The base_plugin_id of the plugin instance.
 | 
			
		||||
   */
 | 
			
		||||
  public function getBaseId();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the derivative_id of the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string|null
 | 
			
		||||
   *   The derivative_id of the plugin instance NULL otherwise.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeId();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,69 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Ensures that all definitions are run through the attribute process.
 | 
			
		||||
 */
 | 
			
		||||
class AttributeBridgeDecorator implements DiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * AttributeBridgeDecorator constructor.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $decorated
 | 
			
		||||
   *   The discovery object that is being decorated.
 | 
			
		||||
   * @param string $pluginDefinitionAttributeName
 | 
			
		||||
   *   The name of the attribute that contains the plugin definition. The class
 | 
			
		||||
   *   corresponding to this name must implement
 | 
			
		||||
   *   \Drupal\Component\Plugin\Attribute\AttributeInterface.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(
 | 
			
		||||
    protected readonly DiscoveryInterface $decorated,
 | 
			
		||||
    protected readonly string $pluginDefinitionAttributeName,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    $definitions = $this->decorated->getDefinitions();
 | 
			
		||||
    foreach ($definitions as $id => $definition) {
 | 
			
		||||
      // Attribute constructors expect an array of values. If the definition is
 | 
			
		||||
      // not an array, it usually means it has been processed already and can be
 | 
			
		||||
      // ignored.
 | 
			
		||||
      if (is_array($definition)) {
 | 
			
		||||
        $class = $definition['class'] ?? NULL;
 | 
			
		||||
        $provider = $definition['provider'] ?? NULL;
 | 
			
		||||
        unset($definition['class'], $definition['provider']);
 | 
			
		||||
        /** @var \Drupal\Component\Plugin\Attribute\AttributeInterface $attribute */
 | 
			
		||||
        $attribute = new $this->pluginDefinitionAttributeName(...$definition);
 | 
			
		||||
        if (isset($class)) {
 | 
			
		||||
          $attribute->setClass($class);
 | 
			
		||||
        }
 | 
			
		||||
        if (isset($provider)) {
 | 
			
		||||
          $attribute->setProvider($provider);
 | 
			
		||||
        }
 | 
			
		||||
        $definitions[$id] = $attribute->get();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $definitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Passes through all unknown calls onto the decorated object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $method
 | 
			
		||||
   *   The method to call on the decorated plugin discovery.
 | 
			
		||||
   * @param array $args
 | 
			
		||||
   *   The arguments to send to the method.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed
 | 
			
		||||
   *   The method result.
 | 
			
		||||
   */
 | 
			
		||||
  public function __call($method, $args) {
 | 
			
		||||
    return $this->decorated->{$method}(...$args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,246 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Discovery\MissingClassDetectionClassLoader;
 | 
			
		||||
use Drupal\Component\Plugin\Attribute\AttributeInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Attribute\Plugin;
 | 
			
		||||
use Drupal\Component\FileCache\FileCacheFactory;
 | 
			
		||||
use Drupal\Component\FileCache\FileCacheInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a discovery mechanism to find plugins with attributes.
 | 
			
		||||
 */
 | 
			
		||||
class AttributeClassDiscovery implements DiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The file cache object.
 | 
			
		||||
   */
 | 
			
		||||
  protected FileCacheInterface $fileCache;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * An array of classes to skip.
 | 
			
		||||
   *
 | 
			
		||||
   * This must be static because once a class has been autoloaded by PHP, it
 | 
			
		||||
   * cannot be unregistered again.
 | 
			
		||||
   */
 | 
			
		||||
  protected static array $skipClasses = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs a new instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string[] $pluginNamespaces
 | 
			
		||||
   *   (optional) An array of namespace that may contain plugin implementations.
 | 
			
		||||
   *   Defaults to an empty array.
 | 
			
		||||
   * @param string $pluginDefinitionAttributeName
 | 
			
		||||
   *   (optional) The name of the attribute that contains the plugin definition.
 | 
			
		||||
   *   Defaults to 'Drupal\Component\Plugin\Attribute\Plugin'.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(
 | 
			
		||||
    protected readonly array $pluginNamespaces = [],
 | 
			
		||||
    protected readonly string $pluginDefinitionAttributeName = Plugin::class,
 | 
			
		||||
  ) {
 | 
			
		||||
    $file_cache_suffix = str_replace('\\', '_', $this->pluginDefinitionAttributeName);
 | 
			
		||||
    $this->fileCache = FileCacheFactory::get('attribute_discovery:' . $this->getFileCacheSuffix($file_cache_suffix));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the file cache suffix.
 | 
			
		||||
   *
 | 
			
		||||
   * This method allows classes that extend this class to add additional
 | 
			
		||||
   * information to the file cache collection name.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $default_suffix
 | 
			
		||||
   *   The default file cache suffix.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The file cache suffix.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getFileCacheSuffix(string $default_suffix): string {
 | 
			
		||||
    return $default_suffix;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    $definitions = [];
 | 
			
		||||
 | 
			
		||||
    $autoloader = new MissingClassDetectionClassLoader();
 | 
			
		||||
    spl_autoload_register([$autoloader, 'loadClass']);
 | 
			
		||||
 | 
			
		||||
    // Search for classes within all PSR-4 namespace locations.
 | 
			
		||||
    foreach ($this->getPluginNamespaces() as $namespace => $dirs) {
 | 
			
		||||
      foreach ($dirs as $dir) {
 | 
			
		||||
        if (file_exists($dir)) {
 | 
			
		||||
          $iterator = new \RecursiveIteratorIterator(
 | 
			
		||||
            new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS)
 | 
			
		||||
          );
 | 
			
		||||
          foreach ($iterator as $fileinfo) {
 | 
			
		||||
            assert($fileinfo instanceof \SplFileInfo);
 | 
			
		||||
            if ($fileinfo->getExtension() === 'php') {
 | 
			
		||||
              if ($cached = $this->fileCache->get($fileinfo->getPathName())) {
 | 
			
		||||
                if (isset($cached['id'])) {
 | 
			
		||||
                  // Explicitly unserialize this to create a new object
 | 
			
		||||
                  // instance.
 | 
			
		||||
                  $definitions[$cached['id']] = unserialize($cached['content']);
 | 
			
		||||
                }
 | 
			
		||||
                continue;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              $sub_path = $iterator->getSubIterator()->getSubPath();
 | 
			
		||||
              $sub_path = $sub_path ? str_replace(DIRECTORY_SEPARATOR, '\\', $sub_path) . '\\' : '';
 | 
			
		||||
              $class = $namespace . '\\' . $sub_path . $fileinfo->getBasename('.php');
 | 
			
		||||
              // Plugins may rely on Attribute classes defined by modules that
 | 
			
		||||
              // are not installed. In such a case, a 'class not found' error
 | 
			
		||||
              // may be thrown from reflection. However, this is an unavoidable
 | 
			
		||||
              // situation with optional dependencies and plugins. Therefore,
 | 
			
		||||
              // silently skip over this class and avoid writing to the cache,
 | 
			
		||||
              // so that it is scanned each time. This ensures that the plugin
 | 
			
		||||
              // definition will be found if the module it requires is
 | 
			
		||||
              // enabled.
 | 
			
		||||
              // PHP handles missing traits as an unrecoverable error.
 | 
			
		||||
              // Register a special classloader that prevents a missing
 | 
			
		||||
              // trait from causing an error. When it encounters a missing
 | 
			
		||||
              // trait it stores that it was unable to find the trait.
 | 
			
		||||
              // Because the classloader will result in the class being
 | 
			
		||||
              // autoloaded we store an array of classes to skip if this
 | 
			
		||||
              // method is called again.
 | 
			
		||||
              // If discovery runs twice in a single request, first without
 | 
			
		||||
              // the module that defines the missing trait, and second after it
 | 
			
		||||
              // has been installed, we want the plugin to be discovered in the
 | 
			
		||||
              // second case. Therefore, if a module has been added to skipped
 | 
			
		||||
              // classes, check if the trait's namespace is available.
 | 
			
		||||
              // If it is available, allow discovery.
 | 
			
		||||
              // @todo a fix for this has been committed to PHP. Once that is
 | 
			
		||||
              // available, attempt to make the class loader registration
 | 
			
		||||
              // conditional on PHP version, then remove the logic entirely once
 | 
			
		||||
              // Drupal requires PHP 8.5.
 | 
			
		||||
              // @see https://github.com/php/php-src/issues/17959
 | 
			
		||||
              // @see https://github.com/php/php-src/commit/8731c95b35f6838bacd12a07c50886e020aad5a6
 | 
			
		||||
              if (array_key_exists($class, self::$skipClasses)) {
 | 
			
		||||
                $missing_classes = self::$skipClasses[$class];
 | 
			
		||||
                foreach ($missing_classes as $missing_class) {
 | 
			
		||||
                  $missing_class_namespace = implode('\\', array_slice(explode('\\', $missing_class), 0, 2));
 | 
			
		||||
 | 
			
		||||
                  // If we arrive here a second time, and the namespace is still
 | 
			
		||||
                  // unavailable, ensure discovery is skipped. Without this
 | 
			
		||||
                  // explicit check for already checked classes, an invalid
 | 
			
		||||
                  // class would be discovered, because once we've detected a
 | 
			
		||||
                  // a missing trait and aliased the stub instead, this can't
 | 
			
		||||
                  // happen again, so the class appears valid. However, if the
 | 
			
		||||
                  // namespace has become available in the meantime, assume that
 | 
			
		||||
                  // the class actually should be discovered since this probably
 | 
			
		||||
                  // means the optional module it depends on has been enabled.
 | 
			
		||||
                  if (!isset($this->getPluginNamespaces()[$missing_class_namespace])) {
 | 
			
		||||
                    $autoloader->reset();
 | 
			
		||||
                    continue 2;
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              try {
 | 
			
		||||
                $class_exists = class_exists($class, TRUE);
 | 
			
		||||
                if (!$class_exists || \count($autoloader->getMissingTraits()) > 0) {
 | 
			
		||||
                  // @todo remove this workaround once PHP treats missing traits
 | 
			
		||||
                  // as catchable fatal errors.
 | 
			
		||||
                  if (\count($autoloader->getMissingTraits()) > 0) {
 | 
			
		||||
                    self::$skipClasses[$class] = $autoloader->getMissingTraits();
 | 
			
		||||
                  }
 | 
			
		||||
                  $autoloader->reset();
 | 
			
		||||
                  continue;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              catch (\Error $e) {
 | 
			
		||||
                if (!$autoloader->hasMissingClass()) {
 | 
			
		||||
                  // @todo Add test coverage for unexpected Error exceptions in
 | 
			
		||||
                  // https://www.drupal.org/project/drupal/issues/3520811.
 | 
			
		||||
                  $autoloader->reset();
 | 
			
		||||
                  spl_autoload_unregister([$autoloader, 'loadClass']);
 | 
			
		||||
                  throw $e;
 | 
			
		||||
                }
 | 
			
		||||
                $autoloader->reset();
 | 
			
		||||
                continue;
 | 
			
		||||
              }
 | 
			
		||||
              ['id' => $id, 'content' => $content] = $this->parseClass($class, $fileinfo);
 | 
			
		||||
              if ($id) {
 | 
			
		||||
                $definitions[$id] = $content;
 | 
			
		||||
                // Explicitly serialize this to create a new object instance.
 | 
			
		||||
                if (!isset(self::$skipClasses[$class])) {
 | 
			
		||||
                  $this->fileCache->set($fileinfo->getPathName(), ['id' => $id, 'content' => serialize($content)]);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              else {
 | 
			
		||||
                // Store a NULL object, so that the file is not parsed again.
 | 
			
		||||
                $this->fileCache->set($fileinfo->getPathName(), [NULL]);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    spl_autoload_unregister([$autoloader, 'loadClass']);
 | 
			
		||||
 | 
			
		||||
    // Plugin discovery is a memory expensive process due to reflection and the
 | 
			
		||||
    // number of files involved. Collect cycles at the end of discovery to be as
 | 
			
		||||
    // efficient as possible.
 | 
			
		||||
    gc_collect_cycles();
 | 
			
		||||
    return $definitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Parses attributes from a class.
 | 
			
		||||
   *
 | 
			
		||||
   * @param class-string $class
 | 
			
		||||
   *   The class to parse.
 | 
			
		||||
   * @param \SplFileInfo $fileinfo
 | 
			
		||||
   *   The SPL file information for the class.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array with the keys 'id' and 'content'. The 'id' is the plugin ID and
 | 
			
		||||
   *   'content' is the plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \ReflectionException
 | 
			
		||||
   * @throws \Error
 | 
			
		||||
   */
 | 
			
		||||
  protected function parseClass(string $class, \SplFileInfo $fileinfo): array {
 | 
			
		||||
    // @todo Consider performance improvements over using reflection.
 | 
			
		||||
    // @see https://www.drupal.org/project/drupal/issues/3395260.
 | 
			
		||||
    $reflection_class = new \ReflectionClass($class);
 | 
			
		||||
 | 
			
		||||
    $id = $content = NULL;
 | 
			
		||||
    if ($attributes = $reflection_class->getAttributes($this->pluginDefinitionAttributeName, \ReflectionAttribute::IS_INSTANCEOF)) {
 | 
			
		||||
      /** @var \Drupal\Component\Plugin\Attribute\AttributeInterface $attribute */
 | 
			
		||||
      $attribute = $attributes[0]->newInstance();
 | 
			
		||||
      $this->prepareAttributeDefinition($attribute, $class);
 | 
			
		||||
 | 
			
		||||
      $id = $attribute->getId();
 | 
			
		||||
      $content = $attribute->get();
 | 
			
		||||
    }
 | 
			
		||||
    return ['id' => $id, 'content' => $content];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Prepares the attribute definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Attribute\AttributeInterface $attribute
 | 
			
		||||
   *   The attribute derived from the plugin.
 | 
			
		||||
   * @param string $class
 | 
			
		||||
   *   The class used for the plugin.
 | 
			
		||||
   */
 | 
			
		||||
  protected function prepareAttributeDefinition(AttributeInterface $attribute, string $class): void {
 | 
			
		||||
    $attribute->setClass($class);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets an array of PSR-4 namespaces to search for plugin classes.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string[][]
 | 
			
		||||
   *   An array of namespaces to search.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getPluginNamespaces(): array {
 | 
			
		||||
    return $this->pluginNamespaces;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,32 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface for discovery components holding a cache of plugin definitions.
 | 
			
		||||
 */
 | 
			
		||||
interface CachedDiscoveryInterface extends DiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Clears static and persistent plugin definition caches.
 | 
			
		||||
   *
 | 
			
		||||
   * Don't resort to calling \Drupal::cache()->delete() and friends to make
 | 
			
		||||
   * Drupal detect new or updated plugin definitions. Always use this method on
 | 
			
		||||
   * the appropriate plugin type's plugin manager!
 | 
			
		||||
   */
 | 
			
		||||
  public function clearCachedDefinitions();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Disable the use of caches.
 | 
			
		||||
   *
 | 
			
		||||
   * Can be used to ensure that uncached plugin definitions are returned,
 | 
			
		||||
   * without invalidating all cached information.
 | 
			
		||||
   *
 | 
			
		||||
   * This will also remove all local/static caches.
 | 
			
		||||
   *
 | 
			
		||||
   * @param bool $use_caches
 | 
			
		||||
   *   FALSE to not use any caches.
 | 
			
		||||
   */
 | 
			
		||||
  public function useCaches($use_caches = FALSE);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,270 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Definition\DerivablePluginDefinitionInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Exception\InvalidDeriverException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class providing the tools for a plugin discovery to be derivative aware.
 | 
			
		||||
 *
 | 
			
		||||
 * Provides a decorator that allows the use of plugin derivatives for normal
 | 
			
		||||
 * implementations DiscoveryInterface.
 | 
			
		||||
 */
 | 
			
		||||
class DerivativeDiscoveryDecorator implements CachedDiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Plugin derivers.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Derivative\DeriverInterface[]
 | 
			
		||||
   *   Keys are base plugin IDs.
 | 
			
		||||
   */
 | 
			
		||||
  protected $derivers = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The decorated plugin discovery.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $decorated;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a new instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $decorated
 | 
			
		||||
   *   The parent object implementing DiscoveryInterface that is being
 | 
			
		||||
   *   decorated.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(DiscoveryInterface $decorated) {
 | 
			
		||||
    $this->decorated = $decorated;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\InvalidDeriverException
 | 
			
		||||
   *   Thrown if the 'deriver' class specified in the plugin definition
 | 
			
		||||
   *   does not implement \Drupal\Component\Plugin\Derivative\DeriverInterface.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
 | 
			
		||||
    // This check is only for derivative plugins that have explicitly provided
 | 
			
		||||
    // an ID. This is not common, and can be expected to fail. Therefore, opt
 | 
			
		||||
    // out of the thrown exception, which will be handled when checking the
 | 
			
		||||
    // $base_plugin_id.
 | 
			
		||||
    $plugin_definition = $this->decorated->getDefinition($plugin_id, FALSE);
 | 
			
		||||
 | 
			
		||||
    [$base_plugin_id, $derivative_id] = $this->decodePluginId($plugin_id);
 | 
			
		||||
    $base_plugin_definition = $this->decorated->getDefinition($base_plugin_id, $exception_on_invalid);
 | 
			
		||||
    if ($base_plugin_definition) {
 | 
			
		||||
      $deriver = $this->getDeriver($base_plugin_id, $base_plugin_definition);
 | 
			
		||||
      if ($deriver) {
 | 
			
		||||
        $derivative_plugin_definition = $deriver->getDerivativeDefinition($derivative_id, $base_plugin_definition);
 | 
			
		||||
        // If a plugin defined itself as a derivative, merge in possible
 | 
			
		||||
        // defaults from the derivative.
 | 
			
		||||
        if ($derivative_id && isset($plugin_definition)) {
 | 
			
		||||
          $plugin_definition = $this->mergeDerivativeDefinition($plugin_definition, $derivative_plugin_definition);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          $plugin_definition = $derivative_plugin_definition;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $plugin_definition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\InvalidDeriverException
 | 
			
		||||
   *   Thrown if the 'deriver' class specified in the plugin definition
 | 
			
		||||
   *   does not implement \Drupal\Component\Plugin\Derivative\DeriverInterface.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    $plugin_definitions = $this->decorated->getDefinitions();
 | 
			
		||||
    return $this->getDerivatives($plugin_definitions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds derivatives to a list of plugin definitions.
 | 
			
		||||
   *
 | 
			
		||||
   * This should be called by the class extending this in
 | 
			
		||||
   * DiscoveryInterface::getDefinitions().
 | 
			
		||||
   */
 | 
			
		||||
  protected function getDerivatives(array $base_plugin_definitions) {
 | 
			
		||||
    $plugin_definitions = [];
 | 
			
		||||
    foreach ($base_plugin_definitions as $base_plugin_id => $plugin_definition) {
 | 
			
		||||
      $deriver = $this->getDeriver($base_plugin_id, $plugin_definition);
 | 
			
		||||
      if ($deriver) {
 | 
			
		||||
        $derivative_definitions = $deriver->getDerivativeDefinitions($plugin_definition);
 | 
			
		||||
        foreach ($derivative_definitions as $derivative_id => $derivative_definition) {
 | 
			
		||||
          $plugin_id = $this->encodePluginId($base_plugin_id, $derivative_id);
 | 
			
		||||
          // Use this definition as defaults if a plugin already defined
 | 
			
		||||
          // itself as this derivative.
 | 
			
		||||
          if ($derivative_id && isset($base_plugin_definitions[$plugin_id])) {
 | 
			
		||||
            $derivative_definition = $this->mergeDerivativeDefinition($base_plugin_definitions[$plugin_id], $derivative_definition);
 | 
			
		||||
          }
 | 
			
		||||
          $plugin_definitions[$plugin_id] = $derivative_definition;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      // If a plugin already defined itself as a derivative it might already
 | 
			
		||||
      // be merged into the definitions.
 | 
			
		||||
      elseif (!isset($plugin_definitions[$base_plugin_id])) {
 | 
			
		||||
        $plugin_definitions[$base_plugin_id] = $plugin_definition;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $plugin_definitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Decodes derivative id and plugin id from a string.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   Plugin identifier that may point to a derivative plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array with the base plugin id as the first index and the derivative id
 | 
			
		||||
   *   as the second. If there is no derivative id it will be null.
 | 
			
		||||
   */
 | 
			
		||||
  protected function decodePluginId($plugin_id) {
 | 
			
		||||
    // Try and split the passed plugin definition into a plugin and a
 | 
			
		||||
    // derivative id. We don't need to check for !== FALSE because a leading
 | 
			
		||||
    // colon would break the derivative system and doesn't makes sense.
 | 
			
		||||
    if (strpos($plugin_id, ':')) {
 | 
			
		||||
      return explode(':', $plugin_id, 2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return [$plugin_id, NULL];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Encodes plugin and derivative id's into a string.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $base_plugin_id
 | 
			
		||||
   *   The base plugin identifier.
 | 
			
		||||
   * @param string $derivative_id
 | 
			
		||||
   *   The derivative identifier.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   A uniquely encoded combination of the $base_plugin_id and $derivative_id.
 | 
			
		||||
   */
 | 
			
		||||
  protected function encodePluginId($base_plugin_id, $derivative_id) {
 | 
			
		||||
    if ($derivative_id) {
 | 
			
		||||
      return "$base_plugin_id:$derivative_id";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // By returning the unmerged plugin_id, we are able to support derivative
 | 
			
		||||
    // plugins that support fetching the base definitions.
 | 
			
		||||
    return $base_plugin_id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a deriver for a base plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $base_plugin_id
 | 
			
		||||
   *   The base plugin id of the plugin.
 | 
			
		||||
   * @param mixed $base_definition
 | 
			
		||||
   *   The base plugin definition to build derivatives.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Derivative\DeriverInterface|null
 | 
			
		||||
   *   A DerivativeInterface or NULL if none exists for the plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\InvalidDeriverException
 | 
			
		||||
   *   Thrown if the 'deriver' class specified in the plugin definition
 | 
			
		||||
   *   does not implement \Drupal\Component\Plugin\Derivative\DeriverInterface.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getDeriver($base_plugin_id, $base_definition) {
 | 
			
		||||
    if (!isset($this->derivers[$base_plugin_id])) {
 | 
			
		||||
      $this->derivers[$base_plugin_id] = FALSE;
 | 
			
		||||
      $class = $this->getDeriverClass($base_definition);
 | 
			
		||||
      if ($class) {
 | 
			
		||||
        $this->derivers[$base_plugin_id] = new $class($base_plugin_id);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $this->derivers[$base_plugin_id] ?: NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the deriver class name from the base plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $base_definition
 | 
			
		||||
   *   The base plugin definition to build derivatives.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string|null
 | 
			
		||||
   *   The name of a class implementing
 | 
			
		||||
   *   \Drupal\Component\Plugin\Derivative\DeriverInterface.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\InvalidDeriverException
 | 
			
		||||
   *   Thrown if the 'deriver' class specified in the plugin definition
 | 
			
		||||
   *   does not implement
 | 
			
		||||
   *   \Drupal\Component\Plugin\Derivative\DerivativeInterface.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getDeriverClass($base_definition) {
 | 
			
		||||
    $class = NULL;
 | 
			
		||||
    $id = NULL;
 | 
			
		||||
    if ($base_definition instanceof DerivablePluginDefinitionInterface) {
 | 
			
		||||
      $class = $base_definition->getDeriver();
 | 
			
		||||
      $id = $base_definition->id();
 | 
			
		||||
    }
 | 
			
		||||
    if ((is_array($base_definition) || ($base_definition = (array) $base_definition)) && (isset($base_definition['deriver']))) {
 | 
			
		||||
      $class = $base_definition['deriver'];
 | 
			
		||||
      $id = $base_definition['id'];
 | 
			
		||||
    }
 | 
			
		||||
    if ($class) {
 | 
			
		||||
      if (!class_exists($class)) {
 | 
			
		||||
        throw new InvalidDeriverException(sprintf('Plugin (%s) deriver "%s" does not exist.', $id, $class));
 | 
			
		||||
      }
 | 
			
		||||
      if (!is_subclass_of($class, '\Drupal\Component\Plugin\Derivative\DeriverInterface')) {
 | 
			
		||||
        throw new InvalidDeriverException(sprintf('Plugin (%s) deriver "%s" must implement \Drupal\Component\Plugin\Derivative\DeriverInterface.', $id, $class));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $class;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Merges a base and derivative definition, taking into account empty values.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $base_plugin_definition
 | 
			
		||||
   *   The base plugin definition.
 | 
			
		||||
   * @param array $derivative_definition
 | 
			
		||||
   *   The derivative plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   The merged definition.
 | 
			
		||||
   */
 | 
			
		||||
  protected function mergeDerivativeDefinition($base_plugin_definition, $derivative_definition) {
 | 
			
		||||
    // Use this definition as defaults if a plugin already defined itself as
 | 
			
		||||
    // this derivative, but filter out empty values first.
 | 
			
		||||
    $filtered_base = array_filter($base_plugin_definition);
 | 
			
		||||
    $derivative_definition = $filtered_base + ($derivative_definition ?: []);
 | 
			
		||||
    // Add back any empty keys that the derivative didn't have.
 | 
			
		||||
    return $derivative_definition + $base_plugin_definition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function clearCachedDefinitions() {
 | 
			
		||||
    $this->derivers = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function useCaches($use_caches = FALSE) {
 | 
			
		||||
    if (!$use_caches) {
 | 
			
		||||
      $this->clearCachedDefinitions();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Passes through all unknown calls onto the decorated object.
 | 
			
		||||
   */
 | 
			
		||||
  public function __call($method, $args) {
 | 
			
		||||
    return call_user_func_array([$this->decorated, $method], $args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Trait for accessing cached definitions of the plugin discovery component.
 | 
			
		||||
 */
 | 
			
		||||
trait DiscoveryCachedTrait {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Cached definitions array.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $definitions;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
 | 
			
		||||
    // Fetch definitions if they're not loaded yet.
 | 
			
		||||
    if (!isset($this->definitions)) {
 | 
			
		||||
      $this->getDefinitions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $this->doGetDefinition($this->definitions, $plugin_id, $exception_on_invalid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines the minimum requirements for a plugin discovery component.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface DiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a specific plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   A plugin id.
 | 
			
		||||
   * @param bool $exception_on_invalid
 | 
			
		||||
   *   (optional) If TRUE, an invalid plugin ID will throw an exception.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed
 | 
			
		||||
   *   A plugin definition, or NULL if the plugin ID is invalid and
 | 
			
		||||
   *   $exception_on_invalid is FALSE.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
 | 
			
		||||
   *   Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the definition of all plugins for this type.
 | 
			
		||||
   *
 | 
			
		||||
   * @return mixed[]
 | 
			
		||||
   *   An array of plugin definitions (empty array if no definitions were
 | 
			
		||||
   *   found). Keys are plugin IDs.
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Drupal\Core\Plugin\FilteredPluginManagerInterface::getFilteredDefinitions()
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Indicates if a specific plugin definition exists.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   A plugin ID.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   TRUE if the definition exists, FALSE otherwise.
 | 
			
		||||
   */
 | 
			
		||||
  public function hasDefinition($plugin_id);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @see Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
 */
 | 
			
		||||
trait DiscoveryTrait {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  abstract public function getDefinitions();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
 | 
			
		||||
    $definitions = $this->getDefinitions();
 | 
			
		||||
    return $this->doGetDefinition($definitions, $plugin_id, $exception_on_invalid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a specific plugin definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $definitions
 | 
			
		||||
   *   An array of the available plugin definitions.
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   A plugin id.
 | 
			
		||||
   * @param bool $exception_on_invalid
 | 
			
		||||
   *   If TRUE, an invalid plugin ID will cause an exception to be thrown; if
 | 
			
		||||
   *   FALSE, NULL will be returned.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array|null
 | 
			
		||||
   *   A plugin definition, or NULL if the plugin ID is invalid and
 | 
			
		||||
   *   $exception_on_invalid is TRUE.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
 | 
			
		||||
   *   Thrown if $plugin_id is invalid and $exception_on_invalid is TRUE.
 | 
			
		||||
   */
 | 
			
		||||
  protected function doGetDefinition(array $definitions, $plugin_id, $exception_on_invalid) {
 | 
			
		||||
    // Avoid using a ternary that would create a copy of the array.
 | 
			
		||||
    if (isset($definitions[$plugin_id])) {
 | 
			
		||||
      return $definitions[$plugin_id];
 | 
			
		||||
    }
 | 
			
		||||
    elseif (!$exception_on_invalid) {
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $valid_ids = implode(', ', array_keys($definitions));
 | 
			
		||||
    throw new PluginNotFoundException($plugin_id, sprintf('The "%s" plugin does not exist. Valid plugin IDs for %s are: %s', $plugin_id, static::class, $valid_ids));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function hasDefinition($plugin_id) {
 | 
			
		||||
    return (bool) $this->getDefinition($plugin_id, FALSE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allows plugin definitions to be manually registered.
 | 
			
		||||
 */
 | 
			
		||||
class StaticDiscovery implements DiscoveryInterface {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryCachedTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    if (!$this->definitions) {
 | 
			
		||||
      $this->definitions = [];
 | 
			
		||||
    }
 | 
			
		||||
    return $this->definitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets a plugin definition.
 | 
			
		||||
   */
 | 
			
		||||
  public function setDefinition($plugin, $definition) {
 | 
			
		||||
    $this->definitions[$plugin] = $definition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Deletes a plugin definition.
 | 
			
		||||
   */
 | 
			
		||||
  public function deleteDefinition($plugin) {
 | 
			
		||||
    unset($this->definitions[$plugin]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Discovery;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A decorator that allows manual registration of undiscoverable definitions.
 | 
			
		||||
 */
 | 
			
		||||
class StaticDiscoveryDecorator extends StaticDiscovery {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The Discovery object being decorated.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $decorated;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A callback or closure used for registering additional definitions.
 | 
			
		||||
   *
 | 
			
		||||
   * @var callable
 | 
			
		||||
   */
 | 
			
		||||
  protected $registerDefinitions;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs StaticDiscoveryDecorator object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $decorated
 | 
			
		||||
   *   The discovery object that is being decorated.
 | 
			
		||||
   * @param callable|null $registerDefinitions
 | 
			
		||||
   *   (optional) A callback or closure used for registering additional
 | 
			
		||||
   *   definitions.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(DiscoveryInterface $decorated, $registerDefinitions = NULL) {
 | 
			
		||||
    $this->decorated = $decorated;
 | 
			
		||||
    $this->registerDefinitions = $registerDefinitions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
 | 
			
		||||
    if (isset($this->registerDefinitions)) {
 | 
			
		||||
      call_user_func($this->registerDefinitions);
 | 
			
		||||
    }
 | 
			
		||||
    $this->definitions += $this->decorated->getDefinitions();
 | 
			
		||||
    return parent::getDefinition($base_plugin_id, $exception_on_invalid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    if (isset($this->registerDefinitions)) {
 | 
			
		||||
      call_user_func($this->registerDefinitions);
 | 
			
		||||
    }
 | 
			
		||||
    $this->definitions += $this->decorated->getDefinitions();
 | 
			
		||||
    return parent::getDefinitions();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Passes through all unknown calls onto the decorated object.
 | 
			
		||||
   */
 | 
			
		||||
  public function __call($method, $args) {
 | 
			
		||||
    return call_user_func_array([$this->decorated, $method], $args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An exception class to be thrown for context plugin exceptions.
 | 
			
		||||
 */
 | 
			
		||||
class ContextException extends \Exception implements ExceptionInterface {}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Exception interface for all exceptions thrown by the Plugin component.
 | 
			
		||||
 */
 | 
			
		||||
interface ExceptionInterface {}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Thrown when a decorator's _call() method uses a method that does not exist.
 | 
			
		||||
 */
 | 
			
		||||
class InvalidDecoratedMethod extends \BadMethodCallException implements ExceptionInterface {}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Exception to be thrown if a plugin tries to use an invalid deriver.
 | 
			
		||||
 */
 | 
			
		||||
class InvalidDeriverException extends PluginException {}
 | 
			
		||||
@ -0,0 +1,46 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines a class for invalid plugin definition exceptions.
 | 
			
		||||
 */
 | 
			
		||||
class InvalidPluginDefinitionException extends PluginException {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The plugin ID of the mapper.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $pluginId;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs an InvalidPluginDefinitionException.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The plugin ID of the mapper.
 | 
			
		||||
   * @param string $message
 | 
			
		||||
   *   The exception message.
 | 
			
		||||
   * @param int $code
 | 
			
		||||
   *   The exception code.
 | 
			
		||||
   * @param \Throwable|null $previous
 | 
			
		||||
   *   The previous throwable used for exception chaining.
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Exception
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct($plugin_id, $message = '', $code = 0, ?\Throwable $previous = NULL) {
 | 
			
		||||
    $this->pluginId = $plugin_id;
 | 
			
		||||
    parent::__construct($message, $code, $previous);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the plugin ID of the mapper that raised the exception.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The plugin ID.
 | 
			
		||||
   */
 | 
			
		||||
  public function getPluginId() {
 | 
			
		||||
    return $this->pluginId;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base exception interface for grouping mapper exceptions.
 | 
			
		||||
 *
 | 
			
		||||
 * Extended interface for exceptions thrown specifically by the Mapper subsystem
 | 
			
		||||
 * within the Plugin component.
 | 
			
		||||
 */
 | 
			
		||||
interface MapperExceptionInterface extends ExceptionInterface {}
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An exception class thrown when contexts exist but are missing a value.
 | 
			
		||||
 */
 | 
			
		||||
class MissingValueContextException extends ContextException {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * MissingValueContextException constructor.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string[] $contexts_without_value
 | 
			
		||||
   *   List of contexts with missing value.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(array $contexts_without_value = []) {
 | 
			
		||||
    $message = 'Required contexts without a value: ' . implode(', ', $contexts_without_value);
 | 
			
		||||
    parent::__construct($message);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for plugin exceptions.
 | 
			
		||||
 */
 | 
			
		||||
class PluginException extends \Exception implements ExceptionInterface {}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plugin exception class to be thrown when a plugin ID could not be found.
 | 
			
		||||
 */
 | 
			
		||||
class PluginNotFoundException extends PluginException {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Construct a PluginNotFoundException exception.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The plugin ID that was not found.
 | 
			
		||||
   * @param string $message
 | 
			
		||||
   *   The exception message.
 | 
			
		||||
   * @param int $code
 | 
			
		||||
   *   The exception code.
 | 
			
		||||
   * @param \Throwable|null $previous
 | 
			
		||||
   *   The previous throwable used for exception chaining.
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Exception
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct($plugin_id, $message = '', $code = 0, ?\Throwable $previous = NULL) {
 | 
			
		||||
    if (empty($message)) {
 | 
			
		||||
      $message = sprintf("Plugin ID '%s' was not found.", $plugin_id);
 | 
			
		||||
    }
 | 
			
		||||
    parent::__construct($message, $code, $previous);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										107
									
								
								web/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								web/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Factory;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Exception\PluginException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Default plugin factory.
 | 
			
		||||
 *
 | 
			
		||||
 * Instantiates plugin instances by passing the full configuration array as a
 | 
			
		||||
 * single constructor argument. Plugin types wanting to support plugin classes
 | 
			
		||||
 * with more flexible constructor signatures can do so by using an alternate
 | 
			
		||||
 * factory such as Drupal\Component\Plugin\Factory\ReflectionFactory.
 | 
			
		||||
 */
 | 
			
		||||
class DefaultFactory implements FactoryInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The object that gets the plugin definitions that this factory instantiates.
 | 
			
		||||
   *
 | 
			
		||||
   * The plugin definition includes the plugin class and possibly other
 | 
			
		||||
   * information necessary for proper instantiation.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $discovery;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Defines an interface each plugin should implement.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string|null
 | 
			
		||||
   */
 | 
			
		||||
  protected $interface;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs a Drupal\Component\Plugin\Factory\DefaultFactory object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
 | 
			
		||||
   *   The plugin discovery.
 | 
			
		||||
   * @param string|null $plugin_interface
 | 
			
		||||
   *   (optional) The interface each plugin should implement.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(DiscoveryInterface $discovery, $plugin_interface = NULL) {
 | 
			
		||||
    $this->discovery = $discovery;
 | 
			
		||||
    $this->interface = $plugin_interface;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function createInstance($plugin_id, array $configuration = []) {
 | 
			
		||||
    $plugin_definition = $this->discovery->getDefinition($plugin_id);
 | 
			
		||||
    $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface);
 | 
			
		||||
    return new $plugin_class($configuration, $plugin_id, $plugin_definition);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Finds the class relevant for a given plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The id of a plugin.
 | 
			
		||||
   * @param \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|mixed[] $plugin_definition
 | 
			
		||||
   *   The plugin definition associated with the plugin ID.
 | 
			
		||||
   * @param string $required_interface
 | 
			
		||||
   *   (optional) The required plugin interface.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The appropriate class name.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\PluginException
 | 
			
		||||
   *   Thrown when there is no class specified, the class doesn't exist, or
 | 
			
		||||
   *   the class does not implement the specified required interface.
 | 
			
		||||
   */
 | 
			
		||||
  public static function getPluginClass($plugin_id, $plugin_definition = NULL, $required_interface = NULL) {
 | 
			
		||||
    $missing_class_message = sprintf('The plugin (%s) did not specify an instance class.', $plugin_id);
 | 
			
		||||
    if (is_array($plugin_definition)) {
 | 
			
		||||
      if (empty($plugin_definition['class'])) {
 | 
			
		||||
        throw new PluginException($missing_class_message);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $class = $plugin_definition['class'];
 | 
			
		||||
    }
 | 
			
		||||
    elseif ($plugin_definition instanceof PluginDefinitionInterface) {
 | 
			
		||||
      if (!$plugin_definition->getClass()) {
 | 
			
		||||
        throw new PluginException($missing_class_message);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $class = $plugin_definition->getClass();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $plugin_definition_type = is_object($plugin_definition) ? get_class($plugin_definition) : gettype($plugin_definition);
 | 
			
		||||
      throw new PluginException(sprintf('%s can only handle plugin definitions that are arrays or that implement %s, but %s given.', __CLASS__, PluginDefinitionInterface::class, $plugin_definition_type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!class_exists($class)) {
 | 
			
		||||
      throw new PluginException(sprintf('Plugin (%s) instance class "%s" does not exist.', $plugin_id, $class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($required_interface && !is_subclass_of($class, $required_interface)) {
 | 
			
		||||
      throw new PluginException(sprintf('Plugin "%s" (%s) must implement interface %s.', $plugin_id, $class, $required_interface));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $class;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Factory;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Factory interface implemented by all plugin factories.
 | 
			
		||||
 */
 | 
			
		||||
interface FactoryInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a plugin instance based on the provided ID and configuration.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The ID of the plugin being instantiated.
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of configuration relevant to the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return object
 | 
			
		||||
   *   A fully configured plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\PluginException
 | 
			
		||||
   *   If the instance cannot be created, such as if the ID is invalid.
 | 
			
		||||
   */
 | 
			
		||||
  public function createInstance($plugin_id, array $configuration = []);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,80 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Factory;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A plugin factory that maps instance configuration to constructor arguments.
 | 
			
		||||
 *
 | 
			
		||||
 * Provides logic for any basic plugin type that needs to provide individual
 | 
			
		||||
 * plugins based upon some basic logic.
 | 
			
		||||
 */
 | 
			
		||||
class ReflectionFactory extends DefaultFactory {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function createInstance($plugin_id, array $configuration = []) {
 | 
			
		||||
    $plugin_definition = $this->discovery->getDefinition($plugin_id);
 | 
			
		||||
    $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface);
 | 
			
		||||
 | 
			
		||||
    // Lets figure out of there's a constructor for this class and pull
 | 
			
		||||
    // arguments from the $options array if so to populate it.
 | 
			
		||||
    $reflector = new \ReflectionClass($plugin_class);
 | 
			
		||||
    if ($reflector->hasMethod('__construct')) {
 | 
			
		||||
      $arguments = $this->getInstanceArguments($reflector, $plugin_id, $plugin_definition, $configuration);
 | 
			
		||||
      $instance = $reflector->newInstanceArgs($arguments);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $instance = new $plugin_class();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $instance;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Inspects the plugin class and builds a list of constructor arguments.
 | 
			
		||||
   *
 | 
			
		||||
   * This is provided as a helper method so factories extending this class can
 | 
			
		||||
   * replace this and insert their own reflection logic.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \ReflectionClass $reflector
 | 
			
		||||
   *   The reflector object being used to inspect the plugin class.
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The identifier of the plugin implementation.
 | 
			
		||||
   * @param mixed $plugin_definition
 | 
			
		||||
   *   The definition associated with the plugin ID.
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of configuration that may be passed to the instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of arguments to be passed to the constructor.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getInstanceArguments(\ReflectionClass $reflector, $plugin_id, $plugin_definition, array $configuration) {
 | 
			
		||||
 | 
			
		||||
    $arguments = [];
 | 
			
		||||
    foreach ($reflector->getMethod('__construct')->getParameters() as $param) {
 | 
			
		||||
      $param_name = $param->getName();
 | 
			
		||||
 | 
			
		||||
      if ($param_name == 'plugin_id') {
 | 
			
		||||
        $arguments[] = $plugin_id;
 | 
			
		||||
      }
 | 
			
		||||
      elseif ($param_name == 'plugin_definition') {
 | 
			
		||||
        $arguments[] = $plugin_definition;
 | 
			
		||||
      }
 | 
			
		||||
      elseif ($param_name == 'configuration') {
 | 
			
		||||
        $arguments[] = $configuration;
 | 
			
		||||
      }
 | 
			
		||||
      elseif (\array_key_exists($param_name, $configuration)) {
 | 
			
		||||
        $arguments[] = $configuration[$param_name];
 | 
			
		||||
      }
 | 
			
		||||
      elseif ($param->isDefaultValueAvailable()) {
 | 
			
		||||
        $arguments[] = $param->getDefaultValue();
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $arguments[] = NULL;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $arguments;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An interface implemented by plugin managers with fallback plugin behaviors.
 | 
			
		||||
 */
 | 
			
		||||
interface FallbackPluginManagerInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a fallback id for a missing plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The ID of the missing requested plugin.
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of configuration relevant to the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The id of an existing plugin to use when the plugin does not exist.
 | 
			
		||||
   */
 | 
			
		||||
  public function getFallbackPluginId($plugin_id, array $configuration = []);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										339
									
								
								web/core/lib/Drupal/Component/Plugin/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								web/core/lib/Drupal/Component/Plugin/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,339 @@
 | 
			
		||||
        GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
           Version 2, June 1991
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 | 
			
		||||
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
			
		||||
 Everyone is permitted to copy and distribute verbatim copies
 | 
			
		||||
 of this license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
          Preamble
 | 
			
		||||
 | 
			
		||||
  The licenses for most software are designed to take away your
 | 
			
		||||
freedom to share and change it.  By contrast, the GNU General Public
 | 
			
		||||
License is intended to guarantee your freedom to share and change free
 | 
			
		||||
software--to make sure the software is free for all its users.  This
 | 
			
		||||
General Public License applies to most of the Free Software
 | 
			
		||||
Foundation's software and to any other program whose authors commit to
 | 
			
		||||
using it.  (Some other Free Software Foundation software is covered by
 | 
			
		||||
the GNU Lesser General Public License instead.)  You can apply it to
 | 
			
		||||
your programs, too.
 | 
			
		||||
 | 
			
		||||
  When we speak of free software, we are referring to freedom, not
 | 
			
		||||
price.  Our General Public Licenses are designed to make sure that you
 | 
			
		||||
have the freedom to distribute copies of free software (and charge for
 | 
			
		||||
this service if you wish), that you receive source code or can get it
 | 
			
		||||
if you want it, that you can change the software or use pieces of it
 | 
			
		||||
in new free programs; and that you know you can do these things.
 | 
			
		||||
 | 
			
		||||
  To protect your rights, we need to make restrictions that forbid
 | 
			
		||||
anyone to deny you these rights or to ask you to surrender the rights.
 | 
			
		||||
These restrictions translate to certain responsibilities for you if you
 | 
			
		||||
distribute copies of the software, or if you modify it.
 | 
			
		||||
 | 
			
		||||
  For example, if you distribute copies of such a program, whether
 | 
			
		||||
gratis or for a fee, you must give the recipients all the rights that
 | 
			
		||||
you have.  You must make sure that they, too, receive or can get the
 | 
			
		||||
source code.  And you must show them these terms so they know their
 | 
			
		||||
rights.
 | 
			
		||||
 | 
			
		||||
  We protect your rights with two steps: (1) copyright the software, and
 | 
			
		||||
(2) offer you this license which gives you legal permission to copy,
 | 
			
		||||
distribute and/or modify the software.
 | 
			
		||||
 | 
			
		||||
  Also, for each author's protection and ours, we want to make certain
 | 
			
		||||
that everyone understands that there is no warranty for this free
 | 
			
		||||
software.  If the software is modified by someone else and passed on, we
 | 
			
		||||
want its recipients to know that what they have is not the original, so
 | 
			
		||||
that any problems introduced by others will not reflect on the original
 | 
			
		||||
authors' reputations.
 | 
			
		||||
 | 
			
		||||
  Finally, any free program is threatened constantly by software
 | 
			
		||||
patents.  We wish to avoid the danger that redistributors of a free
 | 
			
		||||
program will individually obtain patent licenses, in effect making the
 | 
			
		||||
program proprietary.  To prevent this, we have made it clear that any
 | 
			
		||||
patent must be licensed for everyone's free use or not licensed at all.
 | 
			
		||||
 | 
			
		||||
  The precise terms and conditions for copying, distribution and
 | 
			
		||||
modification follow.
 | 
			
		||||
 | 
			
		||||
        GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
			
		||||
 | 
			
		||||
  0. This License applies to any program or other work which contains
 | 
			
		||||
a notice placed by the copyright holder saying it may be distributed
 | 
			
		||||
under the terms of this General Public License.  The "Program", below,
 | 
			
		||||
refers to any such program or work, and a "work based on the Program"
 | 
			
		||||
means either the Program or any derivative work under copyright law:
 | 
			
		||||
that is to say, a work containing the Program or a portion of it,
 | 
			
		||||
either verbatim or with modifications and/or translated into another
 | 
			
		||||
language.  (Hereinafter, translation is included without limitation in
 | 
			
		||||
the term "modification".)  Each licensee is addressed as "you".
 | 
			
		||||
 | 
			
		||||
Activities other than copying, distribution and modification are not
 | 
			
		||||
covered by this License; they are outside its scope.  The act of
 | 
			
		||||
running the Program is not restricted, and the output from the Program
 | 
			
		||||
is covered only if its contents constitute a work based on the
 | 
			
		||||
Program (independent of having been made by running the Program).
 | 
			
		||||
Whether that is true depends on what the Program does.
 | 
			
		||||
 | 
			
		||||
  1. You may copy and distribute verbatim copies of the Program's
 | 
			
		||||
source code as you receive it, in any medium, provided that you
 | 
			
		||||
conspicuously and appropriately publish on each copy an appropriate
 | 
			
		||||
copyright notice and disclaimer of warranty; keep intact all the
 | 
			
		||||
notices that refer to this License and to the absence of any warranty;
 | 
			
		||||
and give any other recipients of the Program a copy of this License
 | 
			
		||||
along with the Program.
 | 
			
		||||
 | 
			
		||||
You may charge a fee for the physical act of transferring a copy, and
 | 
			
		||||
you may at your option offer warranty protection in exchange for a fee.
 | 
			
		||||
 | 
			
		||||
  2. You may modify your copy or copies of the Program or any portion
 | 
			
		||||
of it, thus forming a work based on the Program, and copy and
 | 
			
		||||
distribute such modifications or work under the terms of Section 1
 | 
			
		||||
above, provided that you also meet all of these conditions:
 | 
			
		||||
 | 
			
		||||
    a) You must cause the modified files to carry prominent notices
 | 
			
		||||
    stating that you changed the files and the date of any change.
 | 
			
		||||
 | 
			
		||||
    b) You must cause any work that you distribute or publish, that in
 | 
			
		||||
    whole or in part contains or is derived from the Program or any
 | 
			
		||||
    part thereof, to be licensed as a whole at no charge to all third
 | 
			
		||||
    parties under the terms of this License.
 | 
			
		||||
 | 
			
		||||
    c) If the modified program normally reads commands interactively
 | 
			
		||||
    when run, you must cause it, when started running for such
 | 
			
		||||
    interactive use in the most ordinary way, to print or display an
 | 
			
		||||
    announcement including an appropriate copyright notice and a
 | 
			
		||||
    notice that there is no warranty (or else, saying that you provide
 | 
			
		||||
    a warranty) and that users may redistribute the program under
 | 
			
		||||
    these conditions, and telling the user how to view a copy of this
 | 
			
		||||
    License.  (Exception: if the Program itself is interactive but
 | 
			
		||||
    does not normally print such an announcement, your work based on
 | 
			
		||||
    the Program is not required to print an announcement.)
 | 
			
		||||
 | 
			
		||||
These requirements apply to the modified work as a whole.  If
 | 
			
		||||
identifiable sections of that work are not derived from the Program,
 | 
			
		||||
and can be reasonably considered independent and separate works in
 | 
			
		||||
themselves, then this License, and its terms, do not apply to those
 | 
			
		||||
sections when you distribute them as separate works.  But when you
 | 
			
		||||
distribute the same sections as part of a whole which is a work based
 | 
			
		||||
on the Program, the distribution of the whole must be on the terms of
 | 
			
		||||
this License, whose permissions for other licensees extend to the
 | 
			
		||||
entire whole, and thus to each and every part regardless of who wrote it.
 | 
			
		||||
 | 
			
		||||
Thus, it is not the intent of this section to claim rights or contest
 | 
			
		||||
your rights to work written entirely by you; rather, the intent is to
 | 
			
		||||
exercise the right to control the distribution of derivative or
 | 
			
		||||
collective works based on the Program.
 | 
			
		||||
 | 
			
		||||
In addition, mere aggregation of another work not based on the Program
 | 
			
		||||
with the Program (or with a work based on the Program) on a volume of
 | 
			
		||||
a storage or distribution medium does not bring the other work under
 | 
			
		||||
the scope of this License.
 | 
			
		||||
 | 
			
		||||
  3. You may copy and distribute the Program (or a work based on it,
 | 
			
		||||
under Section 2) in object code or executable form under the terms of
 | 
			
		||||
Sections 1 and 2 above provided that you also do one of the following:
 | 
			
		||||
 | 
			
		||||
    a) Accompany it with the complete corresponding machine-readable
 | 
			
		||||
    source code, which must be distributed under the terms of Sections
 | 
			
		||||
    1 and 2 above on a medium customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    b) Accompany it with a written offer, valid for at least three
 | 
			
		||||
    years, to give any third party, for a charge no more than your
 | 
			
		||||
    cost of physically performing source distribution, a complete
 | 
			
		||||
    machine-readable copy of the corresponding source code, to be
 | 
			
		||||
    distributed under the terms of Sections 1 and 2 above on a medium
 | 
			
		||||
    customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    c) Accompany it with the information you received as to the offer
 | 
			
		||||
    to distribute corresponding source code.  (This alternative is
 | 
			
		||||
    allowed only for noncommercial distribution and only if you
 | 
			
		||||
    received the program in object code or executable form with such
 | 
			
		||||
    an offer, in accord with Subsection b above.)
 | 
			
		||||
 | 
			
		||||
The source code for a work means the preferred form of the work for
 | 
			
		||||
making modifications to it.  For an executable work, complete source
 | 
			
		||||
code means all the source code for all modules it contains, plus any
 | 
			
		||||
associated interface definition files, plus the scripts used to
 | 
			
		||||
control compilation and installation of the executable.  However, as a
 | 
			
		||||
special exception, the source code distributed need not include
 | 
			
		||||
anything that is normally distributed (in either source or binary
 | 
			
		||||
form) with the major components (compiler, kernel, and so on) of the
 | 
			
		||||
operating system on which the executable runs, unless that component
 | 
			
		||||
itself accompanies the executable.
 | 
			
		||||
 | 
			
		||||
If distribution of executable or object code is made by offering
 | 
			
		||||
access to copy from a designated place, then offering equivalent
 | 
			
		||||
access to copy the source code from the same place counts as
 | 
			
		||||
distribution of the source code, even though third parties are not
 | 
			
		||||
compelled to copy the source along with the object code.
 | 
			
		||||
 | 
			
		||||
  4. You may not copy, modify, sublicense, or distribute the Program
 | 
			
		||||
except as expressly provided under this License.  Any attempt
 | 
			
		||||
otherwise to copy, modify, sublicense or distribute the Program is
 | 
			
		||||
void, and will automatically terminate your rights under this License.
 | 
			
		||||
However, parties who have received copies, or rights, from you under
 | 
			
		||||
this License will not have their licenses terminated so long as such
 | 
			
		||||
parties remain in full compliance.
 | 
			
		||||
 | 
			
		||||
  5. You are not required to accept this License, since you have not
 | 
			
		||||
signed it.  However, nothing else grants you permission to modify or
 | 
			
		||||
distribute the Program or its derivative works.  These actions are
 | 
			
		||||
prohibited by law if you do not accept this License.  Therefore, by
 | 
			
		||||
modifying or distributing the Program (or any work based on the
 | 
			
		||||
Program), you indicate your acceptance of this License to do so, and
 | 
			
		||||
all its terms and conditions for copying, distributing or modifying
 | 
			
		||||
the Program or works based on it.
 | 
			
		||||
 | 
			
		||||
  6. Each time you redistribute the Program (or any work based on the
 | 
			
		||||
Program), the recipient automatically receives a license from the
 | 
			
		||||
original licensor to copy, distribute or modify the Program subject to
 | 
			
		||||
these terms and conditions.  You may not impose any further
 | 
			
		||||
restrictions on the recipients' exercise of the rights granted herein.
 | 
			
		||||
You are not responsible for enforcing compliance by third parties to
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  7. If, as a consequence of a court judgment or allegation of patent
 | 
			
		||||
infringement or for any other reason (not limited to patent issues),
 | 
			
		||||
conditions are imposed on you (whether by court order, agreement or
 | 
			
		||||
otherwise) that contradict the conditions of this License, they do not
 | 
			
		||||
excuse you from the conditions of this License.  If you cannot
 | 
			
		||||
distribute so as to satisfy simultaneously your obligations under this
 | 
			
		||||
License and any other pertinent obligations, then as a consequence you
 | 
			
		||||
may not distribute the Program at all.  For example, if a patent
 | 
			
		||||
license would not permit royalty-free redistribution of the Program by
 | 
			
		||||
all those who receive copies directly or indirectly through you, then
 | 
			
		||||
the only way you could satisfy both it and this License would be to
 | 
			
		||||
refrain entirely from distribution of the Program.
 | 
			
		||||
 | 
			
		||||
If any portion of this section is held invalid or unenforceable under
 | 
			
		||||
any particular circumstance, the balance of the section is intended to
 | 
			
		||||
apply and the section as a whole is intended to apply in other
 | 
			
		||||
circumstances.
 | 
			
		||||
 | 
			
		||||
It is not the purpose of this section to induce you to infringe any
 | 
			
		||||
patents or other property right claims or to contest validity of any
 | 
			
		||||
such claims; this section has the sole purpose of protecting the
 | 
			
		||||
integrity of the free software distribution system, which is
 | 
			
		||||
implemented by public license practices.  Many people have made
 | 
			
		||||
generous contributions to the wide range of software distributed
 | 
			
		||||
through that system in reliance on consistent application of that
 | 
			
		||||
system; it is up to the author/donor to decide if he or she is willing
 | 
			
		||||
to distribute software through any other system and a licensee cannot
 | 
			
		||||
impose that choice.
 | 
			
		||||
 | 
			
		||||
This section is intended to make thoroughly clear what is believed to
 | 
			
		||||
be a consequence of the rest of this License.
 | 
			
		||||
 | 
			
		||||
  8. If the distribution and/or use of the Program is restricted in
 | 
			
		||||
certain countries either by patents or by copyrighted interfaces, the
 | 
			
		||||
original copyright holder who places the Program under this License
 | 
			
		||||
may add an explicit geographical distribution limitation excluding
 | 
			
		||||
those countries, so that distribution is permitted only in or among
 | 
			
		||||
countries not thus excluded.  In such case, this License incorporates
 | 
			
		||||
the limitation as if written in the body of this License.
 | 
			
		||||
 | 
			
		||||
  9. The Free Software Foundation may publish revised and/or new versions
 | 
			
		||||
of the General Public License from time to time.  Such new versions will
 | 
			
		||||
be similar in spirit to the present version, but may differ in detail to
 | 
			
		||||
address new problems or concerns.
 | 
			
		||||
 | 
			
		||||
Each version is given a distinguishing version number.  If the Program
 | 
			
		||||
specifies a version number of this License which applies to it and "any
 | 
			
		||||
later version", you have the option of following the terms and conditions
 | 
			
		||||
either of that version or of any later version published by the Free
 | 
			
		||||
Software Foundation.  If the Program does not specify a version number of
 | 
			
		||||
this License, you may choose any version ever published by the Free Software
 | 
			
		||||
Foundation.
 | 
			
		||||
 | 
			
		||||
  10. If you wish to incorporate parts of the Program into other free
 | 
			
		||||
programs whose distribution conditions are different, write to the author
 | 
			
		||||
to ask for permission.  For software which is copyrighted by the Free
 | 
			
		||||
Software Foundation, write to the Free Software Foundation; we sometimes
 | 
			
		||||
make exceptions for this.  Our decision will be guided by the two goals
 | 
			
		||||
of preserving the free status of all derivatives of our free software and
 | 
			
		||||
of promoting the sharing and reuse of software generally.
 | 
			
		||||
 | 
			
		||||
          NO WARRANTY
 | 
			
		||||
 | 
			
		||||
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 | 
			
		||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 | 
			
		||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 | 
			
		||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 | 
			
		||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 | 
			
		||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 | 
			
		||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 | 
			
		||||
REPAIR OR CORRECTION.
 | 
			
		||||
 | 
			
		||||
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
			
		||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 | 
			
		||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 | 
			
		||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 | 
			
		||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 | 
			
		||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 | 
			
		||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 | 
			
		||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 | 
			
		||||
POSSIBILITY OF SUCH DAMAGES.
 | 
			
		||||
 | 
			
		||||
         END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
      How to Apply These Terms to Your New Programs
 | 
			
		||||
 | 
			
		||||
  If you develop a new program, and you want it to be of the greatest
 | 
			
		||||
possible use to the public, the best way to achieve this is to make it
 | 
			
		||||
free software which everyone can redistribute and change under these terms.
 | 
			
		||||
 | 
			
		||||
  To do so, attach the following notices to the program.  It is safest
 | 
			
		||||
to attach them to the start of each source file to most effectively
 | 
			
		||||
convey the exclusion of warranty; and each file should have at least
 | 
			
		||||
the "copyright" line and a pointer to where the full notice is found.
 | 
			
		||||
 | 
			
		||||
    <one line to give the program's name and a brief idea of what it does.>
 | 
			
		||||
    Copyright (C) <year>  <name of author>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License along
 | 
			
		||||
    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
Also add information on how to contact you by electronic and paper mail.
 | 
			
		||||
 | 
			
		||||
If the program is interactive, make it output a short notice like this
 | 
			
		||||
when it starts in an interactive mode:
 | 
			
		||||
 | 
			
		||||
    Gnomovision version 69, Copyright (C) year name of author
 | 
			
		||||
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
			
		||||
    This is free software, and you are welcome to redistribute it
 | 
			
		||||
    under certain conditions; type `show c' for details.
 | 
			
		||||
 | 
			
		||||
The hypothetical commands `show w' and `show c' should show the appropriate
 | 
			
		||||
parts of the General Public License.  Of course, the commands you use may
 | 
			
		||||
be called something other than `show w' and `show c'; they could even be
 | 
			
		||||
mouse-clicks or menu items--whatever suits your program.
 | 
			
		||||
 | 
			
		||||
You should also get your employer (if you work as a programmer) or your
 | 
			
		||||
school, if any, to sign a "copyright disclaimer" for the program, if
 | 
			
		||||
necessary.  Here is a sample; alter the names:
 | 
			
		||||
 | 
			
		||||
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 | 
			
		||||
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 | 
			
		||||
 | 
			
		||||
  <signature of Ty Coon>, 1 April 1989
 | 
			
		||||
  Ty Coon, President of Vice
 | 
			
		||||
 | 
			
		||||
This General Public License does not permit incorporating your program into
 | 
			
		||||
proprietary programs.  If your program is a subroutine library, you may
 | 
			
		||||
consider it more useful to permit linking proprietary applications with the
 | 
			
		||||
library.  If this is what you want to do, use the GNU Lesser General
 | 
			
		||||
Public License instead of this License.
 | 
			
		||||
							
								
								
									
										164
									
								
								web/core/lib/Drupal/Component/Plugin/LazyPluginCollection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								web/core/lib/Drupal/Component/Plugin/LazyPluginCollection.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,164 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines an object which stores multiple plugin instances to lazy load them.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
abstract class LazyPluginCollection implements \IteratorAggregate, \Countable {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Stores all instantiated plugins.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $pluginInstances = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Stores the IDs of all potential plugin instances.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $instanceIds = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Initializes and stores a plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $instance_id
 | 
			
		||||
   *   The ID of the plugin instance to initialize.
 | 
			
		||||
   */
 | 
			
		||||
  abstract protected function initializePlugin($instance_id);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the current configuration of all plugins in this collection.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of up-to-date plugin configuration.
 | 
			
		||||
   */
 | 
			
		||||
  abstract public function getConfiguration();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the configuration for all plugins in this collection.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of up-to-date plugin configuration.
 | 
			
		||||
   *
 | 
			
		||||
   * @return $this
 | 
			
		||||
   */
 | 
			
		||||
  abstract public function setConfiguration(array $configuration);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Clears all instantiated plugins.
 | 
			
		||||
   */
 | 
			
		||||
  public function clear() {
 | 
			
		||||
    $this->pluginInstances = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 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]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets 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;
 | 
			
		||||
    $this->addInstanceId($instance_id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes an initialized plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * The plugin can still be used; it will be reinitialized.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $instance_id
 | 
			
		||||
   *   The ID of the plugin instance to remove.
 | 
			
		||||
   */
 | 
			
		||||
  public function remove($instance_id) {
 | 
			
		||||
    unset($this->pluginInstances[$instance_id]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds an instance ID to the available instance IDs.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $id
 | 
			
		||||
   *   The ID of the plugin instance to add.
 | 
			
		||||
   * @param array|null $configuration
 | 
			
		||||
   *   (optional) The configuration used by this instance. Defaults to NULL.
 | 
			
		||||
   */
 | 
			
		||||
  public function addInstanceId($id, $configuration = NULL) {
 | 
			
		||||
    if (!isset($this->instanceIds[$id])) {
 | 
			
		||||
      $this->instanceIds[$id] = $id;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets all instance IDs.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   An array of all available instance IDs.
 | 
			
		||||
   */
 | 
			
		||||
  public function getInstanceIds() {
 | 
			
		||||
    return $this->instanceIds;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes an instance ID.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $instance_id
 | 
			
		||||
   *   The ID of the plugin instance to remove.
 | 
			
		||||
   */
 | 
			
		||||
  public function removeInstanceId($instance_id) {
 | 
			
		||||
    unset($this->instanceIds[$instance_id]);
 | 
			
		||||
    $this->remove($instance_id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @return \Traversable<string, mixed>
 | 
			
		||||
   *   A traversable generator.
 | 
			
		||||
   */
 | 
			
		||||
  public function getIterator(): \Traversable {
 | 
			
		||||
    $instances = [];
 | 
			
		||||
    foreach ($this->getInstanceIds() as $instance_id) {
 | 
			
		||||
      $instances[$instance_id] = $this->get($instance_id);
 | 
			
		||||
    }
 | 
			
		||||
    return new \ArrayIterator($instances);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function count(): int {
 | 
			
		||||
    return count($this->instanceIds);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,30 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin\Mapper;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plugin mapper interface.
 | 
			
		||||
 *
 | 
			
		||||
 * Plugin mappers are responsible for mapping a plugin request to its
 | 
			
		||||
 * implementation. For example, it might map a cache bin to a memcache bin.
 | 
			
		||||
 *
 | 
			
		||||
 * Mapper objects incorporate the best practices of retrieving configurations,
 | 
			
		||||
 * type information, and factory instantiation.
 | 
			
		||||
 */
 | 
			
		||||
interface MapperInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets or creates a plugin instance that satisfies the given options.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $options
 | 
			
		||||
   *   An array of options that can be used to determine a suitable plugin to
 | 
			
		||||
   *   instantiate and how to configure it.
 | 
			
		||||
   *
 | 
			
		||||
   * @return object|false
 | 
			
		||||
   *   A fully configured plugin instance. The interface of the plugin instance
 | 
			
		||||
   *   will depend on the plugin type. If no instance can be retrieved, FALSE
 | 
			
		||||
   *   will be returned.
 | 
			
		||||
   */
 | 
			
		||||
  public function getInstance(array $options);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides an interface for objects that depend on a plugin.
 | 
			
		||||
 */
 | 
			
		||||
interface PluginAwareInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the plugin for this object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Drupal\Component\Plugin\PluginInspectionInterface $plugin
 | 
			
		||||
   *   The plugin.
 | 
			
		||||
   */
 | 
			
		||||
  public function setPlugin(PluginInspectionInterface $plugin);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								web/core/lib/Drupal/Component/Plugin/PluginBase.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								web/core/lib/Drupal/Component/Plugin/PluginBase.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for plugins wishing to support metadata inspection.
 | 
			
		||||
 */
 | 
			
		||||
abstract class PluginBase implements PluginInspectionInterface, DerivativeInspectionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A string which is used to separate base plugin IDs from the derivative ID.
 | 
			
		||||
   */
 | 
			
		||||
  const DERIVATIVE_SEPARATOR = ':';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The plugin ID.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $pluginId;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The plugin implementation definition.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|array
 | 
			
		||||
   */
 | 
			
		||||
  protected $pluginDefinition;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Configuration information passed into the plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * When using an interface like
 | 
			
		||||
   * \Drupal\Component\Plugin\ConfigurableInterface, this is where the
 | 
			
		||||
   * configuration should be stored.
 | 
			
		||||
   *
 | 
			
		||||
   * Plugin configuration is optional, so plugin implementations must provide
 | 
			
		||||
   * their own setters and getters.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $configuration;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs a \Drupal\Component\Plugin\PluginBase object.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   A configuration array containing information about the plugin instance.
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The plugin ID for the plugin instance.
 | 
			
		||||
   * @param mixed $plugin_definition
 | 
			
		||||
   *   The plugin implementation definition.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
 | 
			
		||||
    $this->configuration = $configuration;
 | 
			
		||||
    $this->pluginId = $plugin_id;
 | 
			
		||||
    $this->pluginDefinition = $plugin_definition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getPluginId() {
 | 
			
		||||
    return $this->pluginId;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getBaseId() {
 | 
			
		||||
    $plugin_id = $this->getPluginId();
 | 
			
		||||
    if (strpos($plugin_id, static::DERIVATIVE_SEPARATOR)) {
 | 
			
		||||
      [$plugin_id] = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 2);
 | 
			
		||||
    }
 | 
			
		||||
    return $plugin_id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDerivativeId() {
 | 
			
		||||
    $plugin_id = $this->getPluginId();
 | 
			
		||||
    $derivative_id = NULL;
 | 
			
		||||
    if (strpos($plugin_id, static::DERIVATIVE_SEPARATOR)) {
 | 
			
		||||
      [, $derivative_id] = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 2);
 | 
			
		||||
    }
 | 
			
		||||
    return $derivative_id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getPluginDefinition() {
 | 
			
		||||
    return $this->pluginDefinition;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Determines if the plugin is configurable.
 | 
			
		||||
   *
 | 
			
		||||
   * @return bool
 | 
			
		||||
   *   A boolean indicating whether the plugin is configurable.
 | 
			
		||||
   *
 | 
			
		||||
   * @deprecated in drupal:11.1.0 and is removed from drupal:12.0.0. Use
 | 
			
		||||
   * instanceof to check if the plugin implements
 | 
			
		||||
   * \Drupal\Component\Plugin\ConfigurableInterface instead.
 | 
			
		||||
   *
 | 
			
		||||
   * @see https://www.drupal.org/node/3198285
 | 
			
		||||
   */
 | 
			
		||||
  public function isConfigurable() {
 | 
			
		||||
    @trigger_error(__CLASS__ . "::" . __FUNCTION__ . " is deprecated in drupal:11.1.0 and is removed from drupal:12.0.0. Use instanceof to check if the plugin implements \Drupal\Component\Plugin\ConfigurableInterface instead. See https://www.drupal.org/node/3198285", E_USER_DEPRECATED);
 | 
			
		||||
    return $this instanceof ConfigurableInterface;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,32 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plugin interface for providing some metadata inspection.
 | 
			
		||||
 *
 | 
			
		||||
 * This interface provides some simple tools for code receiving a plugin to
 | 
			
		||||
 * interact with the plugin system.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface PluginInspectionInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the plugin ID of the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The plugin ID of the plugin instance.
 | 
			
		||||
   */
 | 
			
		||||
  public function getPluginId();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the definition of the plugin implementation.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|array
 | 
			
		||||
   *   The plugin definition, as returned by the discovery object used by the
 | 
			
		||||
   *   plugin manager.
 | 
			
		||||
   */
 | 
			
		||||
  public function getPluginDefinition();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										144
									
								
								web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Discovery\DiscoveryTrait;
 | 
			
		||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for plugin managers.
 | 
			
		||||
 */
 | 
			
		||||
abstract class PluginManagerBase implements PluginManagerInterface {
 | 
			
		||||
 | 
			
		||||
  use DiscoveryTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The object that discovers plugins managed by this manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $discovery;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The object that instantiates plugins managed by this manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Factory\FactoryInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $factory;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The preconfigured plugin instance for a particular runtime condition.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Component\Plugin\Mapper\MapperInterface|null
 | 
			
		||||
   */
 | 
			
		||||
  protected $mapper;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the plugin discovery.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Discovery\DiscoveryInterface
 | 
			
		||||
   *   The plugin discovery.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getDiscovery() {
 | 
			
		||||
    return $this->discovery;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets the plugin factory.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\Component\Plugin\Factory\FactoryInterface
 | 
			
		||||
   *   The plugin factory.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getFactory() {
 | 
			
		||||
    return $this->factory;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
 | 
			
		||||
    return $this->getDiscovery()->getDefinition($plugin_id, $exception_on_invalid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getDefinitions() {
 | 
			
		||||
    return $this->getDiscovery()->getDefinitions();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function createInstance($plugin_id, array $configuration = []) {
 | 
			
		||||
    // If this PluginManager has fallback capabilities catch
 | 
			
		||||
    // PluginNotFoundExceptions.
 | 
			
		||||
    if ($this instanceof FallbackPluginManagerInterface) {
 | 
			
		||||
      try {
 | 
			
		||||
        return $this->getFactory()->createInstance($plugin_id, $configuration);
 | 
			
		||||
      }
 | 
			
		||||
      catch (PluginNotFoundException) {
 | 
			
		||||
        return $this->handlePluginNotFound($plugin_id, $configuration);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      return $this->getFactory()->createInstance($plugin_id, $configuration);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Allows plugin managers to specify custom behavior if a plugin is not found.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The ID of the missing requested plugin.
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of configuration relevant to the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @return object
 | 
			
		||||
   *   A fallback plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \BadMethodCallException
 | 
			
		||||
   *   When ::getFallbackPluginId() is not implemented in the concrete plugin
 | 
			
		||||
   *   manager class.
 | 
			
		||||
   */
 | 
			
		||||
  protected function handlePluginNotFound($plugin_id, array $configuration) {
 | 
			
		||||
    $fallback_id = $this->getFallbackPluginId($plugin_id, $configuration);
 | 
			
		||||
    return $this->getFactory()->createInstance($fallback_id, $configuration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Gets a fallback id for a missing plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * This method should be implemented in extending classes that also implement
 | 
			
		||||
   * FallbackPluginManagerInterface. It is called by
 | 
			
		||||
   * PluginManagerBase::handlePluginNotFound on the abstract class, and
 | 
			
		||||
   * therefore should be defined as well on the abstract class to prevent static
 | 
			
		||||
   * analysis errors.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $plugin_id
 | 
			
		||||
   *   The ID of the missing requested plugin.
 | 
			
		||||
   * @param array $configuration
 | 
			
		||||
   *   An array of configuration relevant to the plugin instance.
 | 
			
		||||
   *
 | 
			
		||||
   * phpcs:ignore Drupal.Commenting.FunctionComment.InvalidNoReturn
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The id of an existing plugin to use when the plugin does not exist.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \BadMethodCallException
 | 
			
		||||
   *   If the method is not implemented in the concrete plugin manager class.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getFallbackPluginId($plugin_id, array $configuration = []) {
 | 
			
		||||
    throw new \BadMethodCallException(static::class . '::getFallbackPluginId() not implemented.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getInstance(array $options) {
 | 
			
		||||
    if (!$this->mapper) {
 | 
			
		||||
      throw new \BadMethodCallException(sprintf('%s does not support this method unless %s::$mapper is set.', static::class, static::class));
 | 
			
		||||
    }
 | 
			
		||||
    return $this->mapper->getInstance($options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Component\Plugin;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Factory\FactoryInterface;
 | 
			
		||||
use Drupal\Component\Plugin\Mapper\MapperInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface implemented by plugin managers.
 | 
			
		||||
 *
 | 
			
		||||
 * There are no explicit methods on the manager interface. Instead plugin
 | 
			
		||||
 * managers broker the interactions of the different plugin components, and
 | 
			
		||||
 * therefore, must implement each component interface, which is enforced by
 | 
			
		||||
 * this interface extending all of the component ones.
 | 
			
		||||
 *
 | 
			
		||||
 * While a plugin manager may directly implement these interface methods with
 | 
			
		||||
 * custom logic, it is expected to be more common for plugin managers to proxy
 | 
			
		||||
 * the method invocations to the respective components, and directly implement
 | 
			
		||||
 * only the additional functionality needed by the specific pluggable system.
 | 
			
		||||
 * To follow this pattern, plugin managers can extend from the PluginManagerBase
 | 
			
		||||
 * class, which contains the proxying logic.
 | 
			
		||||
 *
 | 
			
		||||
 * @see \Drupal\Component\Plugin\PluginManagerBase
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup plugin_api
 | 
			
		||||
 */
 | 
			
		||||
interface PluginManagerInterface extends DiscoveryInterface, FactoryInterface, MapperInterface {
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								web/core/lib/Drupal/Component/Plugin/README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/core/lib/Drupal/Component/Plugin/README.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
The Drupal Plugin Component
 | 
			
		||||
 | 
			
		||||
Thanks for using this Drupal component.
 | 
			
		||||
 | 
			
		||||
You can participate in its development on Drupal.org, through our issue system:
 | 
			
		||||
https://www.drupal.org/project/issues/drupal
 | 
			
		||||
 | 
			
		||||
You can get the full Drupal repo here:
 | 
			
		||||
https://www.drupal.org/project/drupal/git-instructions
 | 
			
		||||
 | 
			
		||||
You can browse the full Drupal repo here:
 | 
			
		||||
https://git.drupalcode.org/project/drupal
 | 
			
		||||
							
								
								
									
										18
									
								
								web/core/lib/Drupal/Component/Plugin/TESTING.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								web/core/lib/Drupal/Component/Plugin/TESTING.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
HOW-TO: Test this Drupal component
 | 
			
		||||
 | 
			
		||||
In order to test this component, you'll need to get the entire Drupal repo and
 | 
			
		||||
run the tests there.
 | 
			
		||||
 | 
			
		||||
You'll find the tests under core/tests/Drupal/Tests/Component.
 | 
			
		||||
 | 
			
		||||
You can get the full Drupal repo here:
 | 
			
		||||
https://www.drupal.org/project/drupal/git-instructions
 | 
			
		||||
 | 
			
		||||
You can find more information about running PHPUnit tests with Drupal here:
 | 
			
		||||
https://www.drupal.org/node/2116263
 | 
			
		||||
 | 
			
		||||
Each component in the Drupal\Component namespace has its own annotated test
 | 
			
		||||
group. You can use this group to run only the tests for this component. Like
 | 
			
		||||
this:
 | 
			
		||||
 | 
			
		||||
$ ./vendor/bin/phpunit -c core --group Plugin
 | 
			
		||||
							
								
								
									
										29
									
								
								web/core/lib/Drupal/Component/Plugin/composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								web/core/lib/Drupal/Component/Plugin/composer.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "drupal/core-plugin",
 | 
			
		||||
    "description": "Base building block for a scalable and extensible plug-in system for PHP components and application framework extensions.",
 | 
			
		||||
    "keywords": [
 | 
			
		||||
        "drupal",
 | 
			
		||||
        "plugin",
 | 
			
		||||
        "plugins"
 | 
			
		||||
    ],
 | 
			
		||||
    "homepage": "https://www.drupal.org/project/drupal",
 | 
			
		||||
    "license": "GPL-2.0-or-later",
 | 
			
		||||
    "require": {
 | 
			
		||||
        "php": ">=8.3.0",
 | 
			
		||||
        "symfony/validator": "^7.3"
 | 
			
		||||
    },
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "Drupal\\Component\\Plugin\\": ""
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "suggest": {
 | 
			
		||||
        "symfony/validator": "Leveraged in the use of context aware plugins."
 | 
			
		||||
    },
 | 
			
		||||
    "extra": {
 | 
			
		||||
        "_readme": [
 | 
			
		||||
            "This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    "minimum-stability": "beta"
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user