xero_sync-8.x-1.x-dev/src/XeroSyncItemFinder.php

src/XeroSyncItemFinder.php
<?php

namespace Drupal\xero_sync;

use Drupal\xero_sync\Plugin\XeroSync\ItemFinder\ItemFinderInterface;
use Drupal\xero_sync\Annotation\XeroSyncItemFinder as XeroSyncItemFinderAnnotation;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;

/**
 * Manages discovery, instantiation and chained execution of itemFinder plugins.
 *
 * @see plugin_api
 */
class XeroSyncItemFinder extends DefaultPluginManager implements XeroSyncItemFinderInterface {

  /**
   * A static cache of found items.
   *
   * This takes the form of an array keyed by entity types.
   * Each value is itself an array, keyed by entity id, with the item as value.
   *
   * @var array
   */
  protected static $cache;

  /**
   * Constructs a new XeroSyncItemFinder object.
   *
   * @param \Traversable $namespaces
   *   An object that implements \Traversable which contains the root paths
   *   keyed by the corresponding namespace to look for plugin implementations.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
   *   The cache backend.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   */
  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
    parent::__construct('Plugin/XeroSync/ItemFinder', $namespaces, $module_handler, ItemFinderInterface::class, XeroSyncItemFinderAnnotation::class);

    $this->alterInfo('xero_sync_item_finder_info');
    $this->setCacheBackend($cache_backend, 'xero_sync_item_finder_plugins');
  }

  /**
   * {@inheritdoc}
   */
  public function processDefinition(&$definition, $plugin_id) {
    parent::processDefinition($definition, $plugin_id);
    foreach (['id', 'create', 'priority', 'entity_types'] as $required_property) {
      if (!isset($definition[$required_property])) {
        throw new PluginException(sprintf('The item finder plugin "%s" must define the "%s" property in its annotation.', $plugin_id, $required_property));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getItem(EntityInterface $entity, $create = FALSE) {
    // Get the item from the static cache if it is there.
    $type = $entity->getEntityTypeId();
    $cached = $this->getItemFromCache($type, $entity->id(), $create);
    if ($cached === FALSE) {
      // The cache says that item is unfindable.
      return NULL;
    }
    elseif (!is_null($cached)) {
      // There is a cached item.
      return $cached;
    }

    // The cache was not informative, so try to find item.
    $definitions = $this->getMatchingDefinitions($entity, $create);
    $item = $this->getItemFromDefinitions($definitions, $entity);

    // Cache the result for reuse.
    self::$cache[$type][$entity->id()]['item'] = $item;
    self::$cache[$type][$entity->id()]['create'] = $create;

    return $item;
  }

  /**
   * {@inheritdoc}
   */
  public function clearCache() {
    self::$cache = [];
  }

  /**
   * Gets a Xero item from the static cache.
   *
   * @param string $type
   *   The entity type.
   * @param string|int $id
   *   The entity id.
   * @param bool $create
   *   Whether create new items is being considered.
   *
   * @return \Drupal\xero\TypedData\XeroComplexItemInterface|bool|null
   *   A cached item, or false if finding has been tried without success, or
   *   null if the cache has no result stored.
   */
  protected function getItemFromCache($type, $id, $create) {
    $typeCache = self::$cache[$type] ?? NULL;
    $entityCache = $typeCache && isset($typeCache[$id]) ? $typeCache[$id] : NULL;
    $item = $entityCache ? $entityCache['item'] : NULL;

    // If there is no cache, return null to be uninformative.
    if (empty($entityCache)) {
      return NULL;
    }

    // If there is a cache and an item, return it.
    if ($item) {
      return $item;
    }

    // If creation is now being considered, and hasn't previously been tried,
    // return null to indicate the cache results are inconclusive.
    if ($create && !$entityCache['create']) {
      return NULL;
    }

    // Return false to indicate the cache shows that no item can be identified.
    return FALSE;
  }

  /**
   * Instantiate and execute plugins successively, until an item is found.
   *
   * @param array $definitions
   *   An array of plugin definitions.
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to find an item for.
   *
   * @return \Drupal\xero\TypedData\XeroComplexItemInterface|null
   *   A typed data representation of the Xero item, or NULL if not found.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  protected function getItemFromDefinitions(array $definitions, EntityInterface $entity) {
    $item = NULL;
    foreach ($definitions as $definition) {
      $plugin = $this->createInstance($definition['id'], ['entity' => $entity]);
      $item = $plugin->getItem();
      if ($item) {
        $item->synced = $item->synced ?? FALSE;
        break;
      }
    }
    return $item;
  }

  /**
   * Gets a subset of plugin definitions.
   *
   * They must target the specified entity, create only if allowed, and be
   * sorted by priority.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to find an item for.
   * @param bool $create
   *   Whether to use plugins that may create new items if they cannot find
   *   existing items.
   */
  protected function getMatchingDefinitions(EntityInterface $entity, $create = FALSE) {
    $definitions = $this->getDefinitions();
    $type = $entity->getEntityTypeId();

    foreach ($definitions as $id => $definition) {
      // Filter out plugins that don't target the current entity type.
      $types = $definition['entity_types'];
      if (!in_array($type, $types) && !empty($types)) {
        unset($definitions[$id]);
        continue;
      }

      // Filter out plugins that may create items, unless definitely allowed.
      if (!$create && $definition['create']) {
        unset($definitions[$id]);
      }
    }

    // Sort the plugins by priority, descending order.
    $priorities = array_column($definitions, 'priority');
    array_multisort($priorities, SORT_NUMERIC, SORT_DESC, $definitions);

    return $definitions;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc