PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php

https://bitbucket.org/aswinvk28/smartpan-stock-drupal
PHP | 446 lines | 209 code | 62 blank | 175 comment | 21 complexity | 750fd474ebe202d6b86ee0cbe06b5d21 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @file
  4. * Definition of Drupal\Core\Config\Entity\ConfigStorageController.
  5. */
  6. namespace Drupal\Core\Config\Entity;
  7. use Drupal\Component\Utility\String;
  8. use Drupal\Core\Config\ConfigFactoryInterface;
  9. use Drupal\Core\Entity\EntityInterface;
  10. use Drupal\Core\Entity\EntityMalformedException;
  11. use Drupal\Core\Entity\EntityStorageControllerBase;
  12. use Drupal\Core\Config\Config;
  13. use Drupal\Core\Config\StorageInterface;
  14. use Drupal\Core\Entity\EntityTypeInterface;
  15. use Drupal\Core\Entity\EntityStorageException;
  16. use Drupal\Core\Entity\Query\QueryFactory;
  17. use Drupal\Component\Uuid\UuidInterface;
  18. use Symfony\Component\DependencyInjection\ContainerInterface;
  19. /**
  20. * Defines the storage controller class for configuration entities.
  21. *
  22. * Configuration object names of configuration entities are comprised of two
  23. * parts, separated by a dot:
  24. * - config_prefix: A string denoting the owner (module/extension) of the
  25. * configuration object, followed by arbitrary other namespace identifiers
  26. * that are declared by the owning extension; e.g., 'node.type'. The
  27. * config_prefix does NOT contain a trailing dot. It is defined by the entity
  28. * type's annotation.
  29. * - ID: A string denoting the entity ID within the entity type namespace; e.g.,
  30. * 'article'. Entity IDs may contain dots/periods. The entire remaining string
  31. * after the config_prefix in a config name forms the entity ID. Additional or
  32. * custom suffixes are not possible.
  33. */
  34. class ConfigStorageController extends EntityStorageControllerBase implements ConfigStorageControllerInterface {
  35. /**
  36. * Name of the entity's UUID property.
  37. *
  38. * @var string
  39. */
  40. protected $uuidKey = 'uuid';
  41. /**
  42. * The UUID service.
  43. *
  44. * @var \Drupal\Component\Uuid\UuidInterface
  45. */
  46. protected $uuidService;
  47. /**
  48. * Name of the entity's status key or FALSE if a status is not supported.
  49. *
  50. * @var string|bool
  51. */
  52. protected $statusKey = 'status';
  53. /**
  54. * The config factory service.
  55. *
  56. * @var \Drupal\Core\Config\ConfigFactoryInterface
  57. */
  58. protected $configFactory;
  59. /**
  60. * The config storage service.
  61. *
  62. * @var \Drupal\Core\Config\StorageInterface
  63. */
  64. protected $configStorage;
  65. /**
  66. * The entity query factory.
  67. *
  68. * @var \Drupal\Core\Entity\Query\QueryFactory
  69. */
  70. protected $entityQueryFactory;
  71. /**
  72. * Constructs a ConfigStorageController object.
  73. *
  74. * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  75. * The entity type definition.
  76. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
  77. * The config factory service.
  78. * @param \Drupal\Core\Config\StorageInterface $config_storage
  79. * The config storage service.
  80. * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory
  81. * The entity query factory.
  82. * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
  83. * The UUID service.
  84. */
  85. public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service) {
  86. parent::__construct($entity_type);
  87. $this->idKey = $this->entityType->getKey('id');
  88. $this->statusKey = $this->entityType->getKey('status');
  89. $this->configFactory = $config_factory;
  90. $this->configStorage = $config_storage;
  91. $this->entityQueryFactory = $entity_query_factory;
  92. $this->uuidService = $uuid_service;
  93. }
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
  98. return new static(
  99. $entity_type,
  100. $container->get('config.factory'),
  101. $container->get('config.storage'),
  102. $container->get('entity.query'),
  103. $container->get('uuid')
  104. );
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function loadMultiple(array $ids = NULL) {
  110. $entities = array();
  111. // Create a new variable which is either a prepared version of the $ids
  112. // array for later comparison with the entity cache, or FALSE if no $ids
  113. // were passed.
  114. $passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
  115. // Load any remaining entities. This is the case if $ids is set to NULL (so
  116. // we load all entities).
  117. if ($ids === NULL || $ids) {
  118. $queried_entities = $this->buildQuery($ids);
  119. }
  120. // Pass all entities loaded from the database through $this->postLoad(),
  121. // which calls the
  122. // entity type specific load callback, for example hook_node_type_load().
  123. if (!empty($queried_entities)) {
  124. $this->postLoad($queried_entities);
  125. $entities += $queried_entities;
  126. }
  127. // Ensure that the returned array is ordered the same as the original
  128. // $ids array if this was passed in and remove any invalid ids.
  129. if ($passed_ids) {
  130. // Remove any invalid ids from the array.
  131. $passed_ids = array_intersect_key($passed_ids, $entities);
  132. foreach ($entities as $entity) {
  133. $passed_ids[$entity->{$this->idKey}] = $entity;
  134. }
  135. $entities = $passed_ids;
  136. }
  137. return $entities;
  138. }
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public function load($id) {
  143. $entities = $this->loadMultiple(array($id));
  144. return isset($entities[$id]) ? $entities[$id] : NULL;
  145. }
  146. /**
  147. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::loadRevision().
  148. */
  149. public function loadRevision($revision_id) {
  150. return FALSE;
  151. }
  152. /**
  153. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::deleteRevision().
  154. */
  155. public function deleteRevision($revision_id) {
  156. return NULL;
  157. }
  158. /**
  159. * {@inheritdoc}
  160. */
  161. public function getQuery($conjunction = 'AND') {
  162. return $this->entityQueryFactory->get($this->entityTypeId, $conjunction);
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function getConfigPrefix() {
  168. return $this->entityType->getConfigPrefix() . '.';
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public static function getIDFromConfigName($config_name, $config_prefix) {
  174. return substr($config_name, strlen($config_prefix . '.'));
  175. }
  176. /**
  177. * Builds the query to load the entity.
  178. *
  179. * This has full revision support. For entities requiring special queries,
  180. * the class can be extended, and the default query can be constructed by
  181. * calling parent::buildQuery(). This is usually necessary when the object
  182. * being loaded needs to be augmented with additional data from another
  183. * table, such as loading node type into comments or vocabulary machine name
  184. * into terms, however it can also support $conditions on different tables.
  185. * See Drupal\comment\CommentStorageController::buildQuery() or
  186. * Drupal\taxonomy\TermStorageController::buildQuery() for examples.
  187. *
  188. * @param $ids
  189. * An array of entity IDs, or NULL to load all entities.
  190. * @param $revision_id
  191. * The ID of the revision to load, or FALSE if this query is asking for the
  192. * most current revision(s).
  193. *
  194. * @return SelectQuery
  195. * A SelectQuery object for loading the entity.
  196. */
  197. protected function buildQuery($ids, $revision_id = FALSE) {
  198. $config_class = $this->entityType->getClass();
  199. $prefix = $this->getConfigPrefix();
  200. // Get the names of the configuration entities we are going to load.
  201. if ($ids === NULL) {
  202. $names = $this->configStorage->listAll($prefix);
  203. }
  204. else {
  205. $names = array();
  206. foreach ($ids as $id) {
  207. // Add the prefix to the ID to serve as the configuration object name.
  208. $names[] = $prefix . $id;
  209. }
  210. }
  211. // Load all of the configuration entities.
  212. $result = array();
  213. foreach ($this->configFactory->loadMultiple($names) as $config) {
  214. $result[$config->get($this->idKey)] = new $config_class($config->get(), $this->entityTypeId);
  215. }
  216. return $result;
  217. }
  218. /**
  219. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create().
  220. */
  221. public function create(array $values = array()) {
  222. $class = $this->entityType->getClass();
  223. $class::preCreate($this, $values);
  224. // Set default language to site default if not provided.
  225. $values += array('langcode' => language_default()->id);
  226. $entity = new $class($values, $this->entityTypeId);
  227. // Mark this entity as new, so isNew() returns TRUE. This does not check
  228. // whether a configuration entity with the same ID (if any) already exists.
  229. $entity->enforceIsNew();
  230. // Assign a new UUID if there is none yet.
  231. if (!isset($entity->{$this->uuidKey})) {
  232. $entity->{$this->uuidKey} = $this->uuidService->generate();
  233. }
  234. $entity->postCreate($this);
  235. // Modules might need to add or change the data initially held by the new
  236. // entity object, for instance to fill-in default values.
  237. $this->invokeHook('create', $entity);
  238. // Default status to enabled.
  239. if (!empty($this->statusKey) && !isset($entity->{$this->statusKey})) {
  240. $entity->{$this->statusKey} = TRUE;
  241. }
  242. return $entity;
  243. }
  244. /**
  245. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::delete().
  246. */
  247. public function delete(array $entities) {
  248. if (!$entities) {
  249. // If no IDs or invalid IDs were passed, do nothing.
  250. return;
  251. }
  252. $entity_class = $this->entityType->getClass();
  253. $entity_class::preDelete($this, $entities);
  254. foreach ($entities as $entity) {
  255. $this->invokeHook('predelete', $entity);
  256. }
  257. foreach ($entities as $entity) {
  258. $config = $this->configFactory->get($this->getConfigPrefix() . $entity->id());
  259. $config->delete();
  260. }
  261. $entity_class::postDelete($this, $entities);
  262. foreach ($entities as $entity) {
  263. $this->invokeHook('delete', $entity);
  264. }
  265. }
  266. /**
  267. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::save().
  268. *
  269. * @throws EntityMalformedException
  270. * When attempting to save a configuration entity that has no ID.
  271. */
  272. public function save(EntityInterface $entity) {
  273. $prefix = $this->getConfigPrefix();
  274. // Configuration entity IDs are strings, and '0' is a valid ID.
  275. $id = $entity->id();
  276. if ($id === NULL || $id === '') {
  277. throw new EntityMalformedException('The entity does not have an ID.');
  278. }
  279. // Load the stored entity, if any.
  280. // At this point, the original ID can only be NULL or a valid ID.
  281. if ($entity->getOriginalId() !== NULL) {
  282. $id = $entity->getOriginalId();
  283. }
  284. $config = $this->configFactory->get($prefix . $id);
  285. // Prevent overwriting an existing configuration file if the entity is new.
  286. if ($entity->isNew() && !$config->isNew()) {
  287. throw new EntityStorageException(String::format('@type entity with ID @id already exists.', array('@type' => $this->entityTypeId, '@id' => $id)));
  288. }
  289. if (!$config->isNew() && !isset($entity->original)) {
  290. $this->resetCache(array($id));
  291. $entity->original = $this->load($id);
  292. }
  293. if ($id !== $entity->id()) {
  294. // Renaming a config object needs to cater for:
  295. // - Storage controller needs to access the original object.
  296. // - The object needs to be renamed/copied in ConfigFactory and reloaded.
  297. // - All instances of the object need to be renamed.
  298. $config = $this->configFactory->rename($prefix . $id, $prefix . $entity->id());
  299. }
  300. // Build an ID if none is set.
  301. if (!isset($entity->{$this->idKey})) {
  302. $entity->{$this->idKey} = $entity->id();
  303. }
  304. $entity->preSave($this);
  305. $this->invokeHook('presave', $entity);
  306. // Retrieve the desired properties and set them in config.
  307. foreach ($entity->getExportProperties() as $key => $value) {
  308. $config->set($key, $value);
  309. }
  310. if (!$config->isNew()) {
  311. $return = SAVED_UPDATED;
  312. $config->save();
  313. $entity->postSave($this, TRUE);
  314. $this->invokeHook('update', $entity);
  315. // Immediately update the original ID.
  316. $entity->setOriginalId($entity->id());
  317. }
  318. else {
  319. $return = SAVED_NEW;
  320. $config->save();
  321. $entity->enforceIsNew(FALSE);
  322. $entity->postSave($this, FALSE);
  323. $this->invokeHook('insert', $entity);
  324. }
  325. unset($entity->original);
  326. return $return;
  327. }
  328. /**
  329. * Invokes a hook on behalf of the entity.
  330. *
  331. * @param $hook
  332. * One of 'presave', 'insert', 'update', 'predelete', or 'delete'.
  333. * @param $entity
  334. * The entity object.
  335. */
  336. protected function invokeHook($hook, EntityInterface $entity) {
  337. // Invoke the hook.
  338. module_invoke_all($this->entityTypeId . '_' . $hook, $entity);
  339. // Invoke the respective entity-level hook.
  340. module_invoke_all('entity_' . $hook, $entity, $this->entityTypeId);
  341. }
  342. /**
  343. * Implements Drupal\Core\Entity\EntityStorageControllerInterface::getQueryServicename().
  344. */
  345. public function getQueryServicename() {
  346. return 'entity.query.config';
  347. }
  348. /**
  349. * {@inheritdoc}
  350. */
  351. public function importCreate($name, Config $new_config, Config $old_config) {
  352. $entity = $this->create($new_config->get());
  353. $entity->setSyncing(TRUE);
  354. $entity->save();
  355. return TRUE;
  356. }
  357. /**
  358. * {@inheritdoc}
  359. */
  360. public function importUpdate($name, Config $new_config, Config $old_config) {
  361. $id = static::getIDFromConfigName($name, $this->entityType->getConfigPrefix());
  362. $entity = $this->load($id);
  363. $entity->setSyncing(TRUE);
  364. $entity->original = clone $entity;
  365. foreach ($old_config->get() as $property => $value) {
  366. $entity->original->set($property, $value);
  367. }
  368. foreach ($new_config->get() as $property => $value) {
  369. $entity->set($property, $value);
  370. }
  371. $entity->save();
  372. return TRUE;
  373. }
  374. /**
  375. * {@inheritdoc}
  376. */
  377. public function importDelete($name, Config $new_config, Config $old_config) {
  378. $id = static::getIDFromConfigName($name, $this->entityType->getConfigPrefix());
  379. $entity = $this->load($id);
  380. $entity->setSyncing(TRUE);
  381. $entity->delete();
  382. return TRUE;
  383. }
  384. }