EclipseGc/Plugins

View on GitHub
src/Traits/PluginDictionaryTrait.php

Summary

Maintainability
A
45 mins
Test Coverage
<?php

namespace EclipseGc\Plugin\Traits;

use EclipseGc\Plugin\Discovery\PluginDefinitionSet;
use EclipseGc\Plugin\Factory\FactoryInterface;
use EclipseGc\Plugin\Filter\PluginDefinitionFilterInterface;
use EclipseGc\Plugin\PluginDefinitionInterface;
use EclipseGc\Plugin\PluginInterface;

/**
 * A trait which implements all the methods of the PluginDiscoveryInterface.
 *
 * @see \EclipseGc\Plugin\Discovery\PluginDiscoveryInterface;
 */
trait PluginDictionaryTrait {

  /**
   * The plugin type.
   *
   * @var string
   */
  protected $pluginType;

  /**
   * The discovery object to use for this dictionary.
   *
   * @var \EclipseGc\Plugin\Discovery\PluginDiscoveryInterface
   */
  protected $discovery;

  /**
   * A list of mutators to apply to the PluginDefinitionSet.
   *
   * @var \EclipseGc\Plugin\Mutator\PluginDefinitionMutatorInterface[]
   */
  protected $mutators = [];

  /**
   * A PluginDefinitionSet with all the PluginDefinitionInterface objects.
   *
   * @var \EclipseGc\Plugin\Discovery\PluginDefinitionSet
   */
  protected $set = NULL;

  /**
   * A class name which implements \EclipseGc\Plugin\Factory\FactoryInterface.
   *
   * @var string
   */
  protected $factoryClass;

  /**
   * The default plugin factory.
   *
   * This is used when a plugin definition does not specify its own factory.
   *
   * @var \EclipseGc\Plugin\Factory\FactoryInterface
   */
  protected $factory;

  /**
   * The factory resolver.
   *
   * This class resolves factory_class strings into FactoryInterface objects.
   *
   * @var \EclipseGc\Plugin\Factory\FactoryResolverInterface
   */
  protected $factoryResolver;

  /**
   * The cache backend object.
   *
   * @var \EclipseGc\Plugin\Cache\CacheInterface
   */
  protected $cache;

  /**
   * {@inheritdoc}
   */
  public function getPluginType() : string {
    return $this->pluginType;
  }

  /**
   * Allow individual plugin dictionaries to customize getting the initial set.
   *
   * @return \EclipseGc\Plugin\Discovery\PluginDefinitionSet
   *   The initial set of plugin definitions.
   */
  protected function getInitialSet() : PluginDefinitionSet {
    return $this->discovery->findPluginImplementations();
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinitions() : PluginDefinitionSet {
    if (is_null($this->set) && $this->cache) {
      $values = $this->cache->get();
      $this->set = $values->count() ? $values : NULL;
    }
    if (is_null($this->set) && !is_null($this->discovery)) {
      $set = $this->getInitialSet();
      foreach ($this->mutators as $mutator) {
        $set->applyMutator($mutator);
      }
      $this->set = $set;
      if ($this->cache) {
        $this->cache->set($set);
      }
    }
    return $this->set;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinition(string $pluginId) : PluginDefinitionInterface {
    $set = $this->getDefinitions();
    return $set->getDefinition($pluginId);
  }

  /**
   * {@inheritdoc}
   */
  public function hasDefinition(string $pluginId) : bool {
    $set = $this->getDefinitions();
    return $set->hasDefinition($pluginId);
  }

  /**
   * {@inheritdoc}
   */
  public function getFilteredDefinitions(PluginDefinitionFilterInterface ...$filters) : PluginDefinitionSet {
    $set = $this->getDefinitions();
    return $set->getFilteredSet(...$filters);
  }

  /**
   * {@inheritdoc}
   */
  public function createInstance(string $pluginId, ...$constructors) : PluginInterface {
    $definition = $this->getDefinition($pluginId);
    $factory_class = $definition->getFactory();
    if (!$factory_class) {
      $factory_class = $this->factoryClass;
    }
    $factory = $this->resolveFactory($factory_class);
    return $factory->createInstance($definition, ...$constructors);
  }

  /**
   * Resolves the factory class string into a FactoryInterface object.
   *
   * @param string $factory_class
   *   The factory class string from the plugin definition.
   *
   * @return \EclipseGc\Plugin\Factory\FactoryInterface
   *   The instantiated factory.
   */
  protected function resolveFactory(string $factory_class) : FactoryInterface {
    // If the requested factory is the default.
    if ($this->factoryClass == $factory_class) {
      // If we've not yet instantiated the default.
      if (empty($this->factory)) {
        $this->factory = $this->factoryResolver->getFactoryInstance($this->factoryClass);
      }
      // Return the default.
      return $this->factory;
    }
    // If the requested factory is NOT the default.
    return $this->factoryResolver->getFactoryInstance($factory_class);
  }

  /**
   * {@inheritdoc}
   */
  public function invalidateCache() {
    if ($this->cache) {
      $this->cache->invalidate();
    }
  }

}