EntityManager.php 6.78 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
<?php

/**
 * @file
 * Contains \Drupal\Core\Entity\EntityManager.
 */

namespace Drupal\Core\Entity;

use Drupal\Component\Plugin\PluginManagerBase;
use Drupal\Component\Plugin\Factory\DefaultFactory;
use Drupal\Core\Plugin\Discovery\AlterDecorator;
13
use Drupal\Core\Plugin\Discovery\CacheDecorator;
14
use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
15
use Drupal\Core\Plugin\Discovery\InfoHookDecorator;
16 17 18 19 20
use Drupal\Core\Cache\CacheBackendInterface;

/**
 * Manages entity type plugin definitions.
 *
21 22
 * Each entity type definition array is set in the entity type's
 * annotation and altered by hook_entity_info_alter().
23 24 25 26
 *
 * The defaults for the plugin definition are provided in
 * \Drupal\Core\Entity\EntityManager::defaults.
 *
27 28
 * @see \Drupal\Core\Entity\Annotation\EntityType
 * @see \Drupal\Core\Entity\EntityInterface
29 30 31 32 33
 * @see entity_get_info()
 * @see hook_entity_info_alter()
 */
class EntityManager extends PluginManagerBase {

34 35 36 37 38 39 40
  /**
   * Contains instantiated controllers keyed by controller type and entity type.
   *
   * @var array
   */
  protected $controllers = array();

41 42
  /**
   * Constructs a new Entity plugin manager.
43 44 45
   *
   * @param array $namespaces
   *   An array of paths keyed by it's corresponding namespaces.
46
   */
47
  public function __construct(array $namespaces) {
48
    // Allow the plugin definition to be altered by hook_entity_info_alter().
49 50 51 52
    $annotation_namespaces = array(
      'Drupal\Core\Entity\Annotation' => DRUPAL_ROOT . '/core/lib',
    );
    $this->discovery = new AnnotatedClassDiscovery('Core', 'Entity', $namespaces, $annotation_namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
53
    $this->discovery = new InfoHookDecorator($this->discovery, 'entity_info');
54
    $this->discovery = new AlterDecorator($this->discovery, 'entity_info');
55
    $this->discovery = new CacheDecorator($this->discovery, 'entity_info:' . language(LANGUAGE_TYPE_INTERFACE)->langcode, 'cache', CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
56

57
    $this->factory = new DefaultFactory($this->discovery);
58 59
  }

60 61 62 63 64 65 66 67 68 69 70 71 72
  /**
   * Checks whether a certain entity type has a certain controller.
   *
   * @param string $entity_type
   *   The name of the entity type.
   * @param string $controller_type
   *   The name of the controller.
   *
   * @return bool
   *   Returns TRUE if the entity type has the controller, else FALSE.
   */
  public function hasController($entity_type, $controller_type) {
    $definition = $this->getDefinition($entity_type);
73
    return !empty($definition['controllers'][$controller_type]);
74 75
  }

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  /**
   * Returns an entity controller class.
   *
   * @param string $entity_type
   *   The name of the entity type
   * @param string $controller_type
   *   The name of the controller.
   * @param string|null $nested
   *   (optional) If this controller definition is nested, the name of the key.
   *   Defaults to NULL.
   *
   * @return string
   *   The class name for this controller instance.
   */
  public function getControllerClass($entity_type, $controller_type, $nested = NULL) {
    $definition = $this->getDefinition($entity_type);
92
    $definition = $definition['controllers'];
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    if (empty($definition[$controller_type])) {
      throw new \InvalidArgumentException(sprintf('The entity (%s) did not specify a %s.', $entity_type, $controller_type));
    }

    $class = $definition[$controller_type];

    // Some class definitions can be nested.
    if (isset($nested)) {
      if (empty($class[$nested])) {
        throw new \InvalidArgumentException(sprintf("Missing '%s: %s' for entity '%s'", $controller_type, $nested, $entity_type));
      }

      $class = $class[$nested];
    }

    if (!class_exists($class)) {
      throw new \InvalidArgumentException(sprintf('Entity (%s) %s "%s" does not exist.', $entity_type, $controller_type, $class));
    }

    return $class;
  }

  /**
   * Creates a new storage controller instance.
   *
   * @param string $entity_type
   *   The entity type for this storage controller.
   *
   * @return \Drupal\Core\Entity\EntityStorageControllerInterface
   *   A storage controller instance.
   */
  public function getStorageController($entity_type) {
    if (!isset($this->controllers['storage'][$entity_type])) {
126
      $class = $this->getControllerClass($entity_type, 'storage');
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
      $this->controllers['storage'][$entity_type] = new $class($entity_type);
    }
    return $this->controllers['storage'][$entity_type];
  }

  /**
   * Creates a new list controller instance.
   *
   * @param string $entity_type
   *   The entity type for this list controller.
   *
   * @return \Drupal\Core\Entity\EntityListControllerInterface
   *   A list controller instance.
   */
  public function getListController($entity_type) {
    if (!isset($this->controllers['listing'][$entity_type])) {
143
      $class = $this->getControllerClass($entity_type, 'list');
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
      $this->controllers['listing'][$entity_type] = new $class($entity_type, $this->getStorageController($entity_type));
    }
    return $this->controllers['listing'][$entity_type];
  }

  /**
   * Creates a new form controller instance.
   *
   * @param string $entity_type
   *   The entity type for this form controller.
   * @param string $operation
   *   The name of the operation to use, e.g., 'default'.
   *
   * @return \Drupal\Core\Entity\EntityFormControllerInterface
   *   A form controller instance.
   */
  public function getFormController($entity_type, $operation) {
    if (!isset($this->controllers['form'][$operation][$entity_type])) {
162
      $class = $this->getControllerClass($entity_type, 'form', $operation);
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
      $this->controllers['form'][$operation][$entity_type] = new $class($operation);
    }
    return $this->controllers['form'][$operation][$entity_type];
  }

  /**
   * Creates a new render controller instance.
   *
   * @param string $entity_type
   *   The entity type for this render controller.
   *
   * @return \Drupal\Core\Entity\EntityRenderControllerInterface.
   *   A render controller instance.
   */
  public function getRenderController($entity_type) {
    if (!isset($this->controllers['render'][$entity_type])) {
179
      $class = $this->getControllerClass($entity_type, 'render');
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
      $this->controllers['render'][$entity_type] = new $class($entity_type);
    }
    return $this->controllers['render'][$entity_type];
  }

  /**
   * Creates a new access controller instance.
   *
   * @param string $entity_type
   *   The entity type for this access controller.
   *
   * @return \Drupal\Core\Entity\EntityRenderControllerInterface.
   *   A access controller instance.
   */
  public function getAccessController($entity_type) {
    if (!isset($this->controllers['access'][$entity_type])) {
196
      $class = $this->getControllerClass($entity_type, 'access');
197 198 199 200 201
      $this->controllers['access'][$entity_type] = new $class($entity_type);
    }
    return $this->controllers['access'][$entity_type];
  }

202
}