DefaultLazyPluginCollection.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace Drupal\Core\Plugin;
  3. use Drupal\Component\Plugin\Exception\PluginNotFoundException;
  4. use Drupal\Component\Plugin\LazyPluginCollection;
  5. use Drupal\Component\Plugin\PluginManagerInterface;
  6. use Drupal\Component\Plugin\ConfigurablePluginInterface;
  7. use Drupal\Core\DependencyInjection\DependencySerializationTrait;
  8. /**
  9. * Provides a default plugin collection for a plugin type.
  10. *
  11. * A plugin collection is used to contain plugins that will be lazily
  12. * instantiated. The configurations of each potential plugin are passed in, and
  13. * the configuration key containing the plugin ID is specified by
  14. * self::$pluginKey.
  15. */
  16. class DefaultLazyPluginCollection extends LazyPluginCollection {
  17. use DependencySerializationTrait;
  18. /**
  19. * The manager used to instantiate the plugins.
  20. *
  21. * @var \Drupal\Component\Plugin\PluginManagerInterface
  22. */
  23. protected $manager;
  24. /**
  25. * The initial configuration for each plugin in the collection.
  26. *
  27. * @var array
  28. * An associative array containing the initial configuration for each plugin
  29. * in the collection, keyed by plugin instance ID.
  30. */
  31. protected $configurations = [];
  32. /**
  33. * The key within the plugin configuration that contains the plugin ID.
  34. *
  35. * @var string
  36. */
  37. protected $pluginKey = 'id';
  38. /**
  39. * The original order of the instances.
  40. *
  41. * @var array
  42. */
  43. protected $originalOrder = [];
  44. /**
  45. * Constructs a new DefaultLazyPluginCollection object.
  46. *
  47. * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
  48. * The manager to be used for instantiating plugins.
  49. * @param array $configurations
  50. * (optional) An associative array containing the initial configuration for
  51. * each plugin in the collection, keyed by plugin instance ID.
  52. */
  53. public function __construct(PluginManagerInterface $manager, array $configurations = []) {
  54. $this->manager = $manager;
  55. $this->configurations = $configurations;
  56. if (!empty($configurations)) {
  57. $instance_ids = array_keys($configurations);
  58. $this->instanceIDs = array_combine($instance_ids, $instance_ids);
  59. // Store the original order of the instance IDs for export.
  60. $this->originalOrder = $this->instanceIDs;
  61. }
  62. }
  63. /**
  64. * {@inheritdoc}
  65. */
  66. protected function initializePlugin($instance_id) {
  67. $configuration = isset($this->configurations[$instance_id]) ? $this->configurations[$instance_id] : [];
  68. if (!isset($configuration[$this->pluginKey])) {
  69. throw new PluginNotFoundException($instance_id);
  70. }
  71. $this->set($instance_id, $this->manager->createInstance($configuration[$this->pluginKey], $configuration));
  72. }
  73. /**
  74. * Sorts all plugin instances in this collection.
  75. *
  76. * @return $this
  77. */
  78. public function sort() {
  79. uasort($this->instanceIDs, [$this, 'sortHelper']);
  80. return $this;
  81. }
  82. /**
  83. * Provides uasort() callback to sort plugins.
  84. */
  85. public function sortHelper($aID, $bID) {
  86. $a = $this->get($aID);
  87. $b = $this->get($bID);
  88. return strnatcasecmp($a->getPluginId(), $b->getPluginId());
  89. }
  90. /**
  91. * {@inheritdoc}
  92. */
  93. public function getConfiguration() {
  94. $instances = [];
  95. // Store the current order of the instances.
  96. $current_order = $this->instanceIDs;
  97. // Reorder the instances to match the original order, adding new instances
  98. // to the end.
  99. $this->instanceIDs = $this->originalOrder + $current_order;
  100. foreach ($this as $instance_id => $instance) {
  101. if ($instance instanceof ConfigurablePluginInterface) {
  102. $instances[$instance_id] = $instance->getConfiguration();
  103. }
  104. else {
  105. $instances[$instance_id] = $this->configurations[$instance_id];
  106. }
  107. }
  108. // Restore the current order.
  109. $this->instanceIDs = $current_order;
  110. return $instances;
  111. }
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function setConfiguration($configuration) {
  116. // Track each instance ID as it is updated.
  117. $unprocessed_instance_ids = $this->getInstanceIds();
  118. foreach ($configuration as $instance_id => $instance_configuration) {
  119. $this->setInstanceConfiguration($instance_id, $instance_configuration);
  120. // Remove this instance ID from the list being updated.
  121. unset($unprocessed_instance_ids[$instance_id]);
  122. }
  123. // Remove remaining instances that had no configuration specified for them.
  124. foreach ($unprocessed_instance_ids as $unprocessed_instance_id) {
  125. $this->removeInstanceId($unprocessed_instance_id);
  126. }
  127. return $this;
  128. }
  129. /**
  130. * Updates the configuration for a plugin instance.
  131. *
  132. * If there is no plugin instance yet, a new will be instantiated. Otherwise,
  133. * the existing instance is updated with the new configuration.
  134. *
  135. * @param string $instance_id
  136. * The ID of a plugin to set the configuration for.
  137. * @param array $configuration
  138. * The plugin configuration to set.
  139. */
  140. public function setInstanceConfiguration($instance_id, array $configuration) {
  141. $this->configurations[$instance_id] = $configuration;
  142. $instance = $this->get($instance_id);
  143. if ($instance instanceof ConfigurablePluginInterface) {
  144. $instance->setConfiguration($configuration);
  145. }
  146. }
  147. /**
  148. * {@inheritdoc}
  149. */
  150. public function addInstanceId($id, $configuration = NULL) {
  151. parent::addInstanceId($id);
  152. if ($configuration !== NULL) {
  153. $this->setInstanceConfiguration($id, $configuration);
  154. }
  155. if (!isset($this->originalOrder[$id])) {
  156. $this->originalOrder[$id] = $id;
  157. }
  158. }
  159. /**
  160. * {@inheritdoc}
  161. */
  162. public function removeInstanceId($instance_id) {
  163. parent::removeInstanceId($instance_id);
  164. unset($this->originalOrder[$instance_id]);
  165. unset($this->configurations[$instance_id]);
  166. }
  167. }