DefaultFactory.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace Drupal\Component\Plugin\Factory;
  3. use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
  4. use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
  5. use Drupal\Component\Plugin\Exception\PluginException;
  6. /**
  7. * Default plugin factory.
  8. *
  9. * Instantiates plugin instances by passing the full configuration array as a
  10. * single constructor argument. Plugin types wanting to support plugin classes
  11. * with more flexible constructor signatures can do so by using an alternate
  12. * factory such as Drupal\Component\Plugin\Factory\ReflectionFactory.
  13. */
  14. class DefaultFactory implements FactoryInterface {
  15. /**
  16. * The object that retrieves the definitions of the plugins that this factory instantiates.
  17. *
  18. * The plugin definition includes the plugin class and possibly other
  19. * information necessary for proper instantiation.
  20. *
  21. * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
  22. */
  23. protected $discovery;
  24. /**
  25. * Defines an interface each plugin should implement.
  26. *
  27. * @var string|null
  28. */
  29. protected $interface;
  30. /**
  31. * Constructs a Drupal\Component\Plugin\Factory\DefaultFactory object.
  32. *
  33. * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
  34. * The plugin discovery.
  35. * @param string|null $plugin_interface
  36. * (optional) The interface each plugin should implement.
  37. */
  38. public function __construct(DiscoveryInterface $discovery, $plugin_interface = NULL) {
  39. $this->discovery = $discovery;
  40. $this->interface = $plugin_interface;
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public function createInstance($plugin_id, array $configuration = []) {
  46. $plugin_definition = $this->discovery->getDefinition($plugin_id);
  47. $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface);
  48. return new $plugin_class($configuration, $plugin_id, $plugin_definition);
  49. }
  50. /**
  51. * Finds the class relevant for a given plugin.
  52. *
  53. * @param string $plugin_id
  54. * The id of a plugin.
  55. * @param \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|mixed[] $plugin_definition
  56. * The plugin definition associated with the plugin ID.
  57. * @param string $required_interface
  58. * (optional) The required plugin interface.
  59. *
  60. * @return string
  61. * The appropriate class name.
  62. *
  63. * @throws \Drupal\Component\Plugin\Exception\PluginException
  64. * Thrown when there is no class specified, the class doesn't exist, or
  65. * the class does not implement the specified required interface.
  66. */
  67. public static function getPluginClass($plugin_id, $plugin_definition = NULL, $required_interface = NULL) {
  68. $missing_class_message = sprintf('The plugin (%s) did not specify an instance class.', $plugin_id);
  69. if (is_array($plugin_definition)) {
  70. if (empty($plugin_definition['class'])) {
  71. throw new PluginException($missing_class_message);
  72. }
  73. $class = $plugin_definition['class'];
  74. }
  75. elseif ($plugin_definition instanceof PluginDefinitionInterface) {
  76. if (!$plugin_definition->getClass()) {
  77. throw new PluginException($missing_class_message);
  78. }
  79. $class = $plugin_definition->getClass();
  80. }
  81. else {
  82. $plugin_definition_type = is_object($plugin_definition) ? get_class($plugin_definition) : gettype($plugin_definition);
  83. 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));
  84. }
  85. if (!class_exists($class)) {
  86. throw new PluginException(sprintf('Plugin (%s) instance class "%s" does not exist.', $plugin_id, $class));
  87. }
  88. if ($required_interface && !is_subclass_of($class, $required_interface)) {
  89. throw new PluginException(sprintf('Plugin "%s" (%s) must implement interface %s.', $plugin_id, $class, $required_interface));
  90. }
  91. return $class;
  92. }
  93. }