plus-8.x-4.x-dev/src/Plugin/ChainedPluginProviderTypes.php
src/Plugin/ChainedPluginProviderTypes.php
<?php namespace Drupal\plus\Plugin; use Drupal\plus\Utility\ArrayObject; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class PluginProviderTypes. */ class ChainedPluginProviderTypes extends BasePluginProviderType { /** * The plugin providers. * * @var \Drupal\plus\Plugin\PluginProviderTypeInterface[] */ protected $providers; /** * PluginProviderTypes constructor. * * @param \Drupal\plus\Plugin\PluginProviderTypeInterface ... * One or more plugin providers that implement * \Drupal\plus\Plugin\PluginProviderTypeInterface. */ public function __construct() { /** @var \Drupal\plus\Plugin\PluginProviderTypeInterface[] $providers */ $providers = func_get_args(); assert('Drupal\\Component\\Assertion\\Inspector::assertAllObjects($providers, \'\\Drupal\\plus\\Plugin\\PluginProviderTypeInterface\')', 'All passed arguments must be an instance of \Drupal\plus\Plugin\PluginProviderTypeInterface.'); $this->providers = []; foreach ($providers as $provider) { $this->providers[$provider->getType()] = $provider; } } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, string ...$providers) { foreach ($providers as $key => $service_id) { $providers[$key] = $container->get($service_id); } return new static(...$providers); } /** * Invokes a method on all providers. * * @param string $method * The method to invoke. * @param array $arguments * An array of arguments to pass to the method. * * @return \Drupal\plus\Utility\ArrayObject * An array of return values from each provider method. If the provider * returns an array from its implementation, those are merged into the * single results array recursively. Note: integer keys in arrays will be * lost, as the merge is done using NestedArray::mergeDeep(). */ protected function invokeProviders($method, array $arguments = []) { $return = ArrayObject::create(); foreach ($this->providers as $provider) { // Since profiles and modules both use the Module Handler service, skip // any profile alters so it doesn't duplicate when module runs. // @todo Remove in 8.6.x. // @see https://www.drupal.org/node/2709919 if ($method === 'alterDefinitions' && $provider->getType() === 'profile' && isset($this->providers['module'])) { continue; } $result = call_user_func_array([$provider, $method], $arguments); if (isset($result)) { if ($result instanceof ArrayObject || is_array($result)) { $return->mergeDeep($result); } else { $return->append($result); } } } return $return; } /** * {@inheritdoc} */ public function alterDefinitions($hook, array &$definitions) { $this->invokeProviders(__FUNCTION__, [$hook, &$definitions]); } /** * {@inheritdoc} */ public function getNamespaces($name = NULL, $type = NULL) { return $this->invokeProviders(__FUNCTION__, func_get_args()); } /** * {@inheritdoc} */ public function getType() { return implode(':', array_keys($this->providers)); } /** * {@inheritdoc} */ public function providerExists($provider) { $exists = $this->invokeProviders(__FUNCTION__, func_get_args()); return !$exists->isEmpty(); } }