DefaultFactory.php 3.85 KB
Newer Older
1 2 3 4
<?php

namespace Drupal\Component\Plugin\Factory;

5
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
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 retrieves the definitions of the plugins that this factory instantiates.
   *
   * The plugin definition includes the plugin class and possibly other
   * information necessary for proper instantiation.
   *
25
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
26 27 28
   */
  protected $discovery;

29 30 31 32 33 34 35
  /**
   * Defines an interface each plugin should implement.
   *
   * @var string|null
   */
  protected $interface;

36 37
  /**
   * Constructs a Drupal\Component\Plugin\Factory\DefaultFactory object.
38 39 40 41 42
   *
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
   *   The plugin discovery.
   * @param string|null $plugin_interface
   *   (optional) The interface each plugin should implement.
43
   */
44
  public function __construct(DiscoveryInterface $discovery, $plugin_interface = NULL) {
45
    $this->discovery = $discovery;
46
    $this->interface = $plugin_interface;
47 48 49
  }

  /**
50
   * {@inheritdoc}
51
   */
52
  public function createInstance($plugin_id, array $configuration = []) {
53
    $plugin_definition = $this->discovery->getDefinition($plugin_id);
54
    $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface);
55
    return new $plugin_class($configuration, $plugin_id, $plugin_definition);
56 57 58 59 60
  }

  /**
   * Finds the class relevant for a given plugin.
   *
61 62
   * @param string $plugin_id
   *   The id of a plugin.
63
   * @param \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|mixed[] $plugin_definition
64
   *   The plugin definition associated with the plugin ID.
65
   * @param string $required_interface
66
   *   (optional) The required plugin interface.
67
   *
68 69
   * @return string
   *   The appropriate class name.
70 71
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
72 73
   *   Thrown when there is no class specified, the class doesn't exist, or
   *   the class does not implement the specified required interface.
74
   */
75
  public static function getPluginClass($plugin_id, $plugin_definition = NULL, $required_interface = NULL) {
76 77 78 79 80 81 82
    $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'];
83
    }
84 85 86 87
    elseif ($plugin_definition instanceof PluginDefinitionInterface) {
      if (!$plugin_definition->getClass()) {
        throw new PluginException($missing_class_message);
      }
88

89 90 91 92 93 94
      $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));
    }
95 96

    if (!class_exists($class)) {
97
      throw new PluginException(sprintf('Plugin (%s) instance class "%s" does not exist.', $plugin_id, $class));
98 99
    }

100 101
    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));
102 103
    }

104 105
    return $class;
  }
106

107
}