entity.inc 17.9 KB
Newer Older
1
2
3
4
5
6
7
<?php

/**
 * @file
 * Entity API for handling entities like nodes or users.
 */

8
use Drupal\Core\Cache\Cache;
9
10
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityInterface;
11
use Drupal\Core\Language\Language;
12
13
14
15
16
17

/**
 * Resets the cached information about entity types.
 */
function entity_info_cache_clear() {
  // Clear all languages.
18
19
  \Drupal::entityManager()->clearCachedDefinitions();
  \Drupal::entityManager()->clearCachedFieldDefinitions();
20
21
}

22
23
24
25
26
27
/**
 * Clears the entity render cache for all entity types.
 */
function entity_render_cache_clear() {
  $entity_manager = Drupal::entityManager();
  foreach ($entity_manager->getDefinitions() as $entity_type => $info) {
28
29
    if ($entity_manager->hasController($entity_type, 'view_builder')) {
      $entity_manager->getViewBuilder($entity_type)->resetCache();
30
31
32
33
    }
  }
}

34
/**
35
 * Returns the entity bundle info.
36
 *
37
38
39
40
41
42
 * @param string|null $entity_type
 *   The entity type whose bundle info should be returned, or NULL for all
 *   bundles info. Defaults to NULL.
 *
 * @return array
 *   The bundle info for a specific entity type, or all entity types.
43
 *
44
45
 * @see \Drupal\Core\Entity\EntityManagerInterface::getBundleInfo()
 * @see \Drupal\Core\Entity\EntityManagerInterface::getAllBundleInfo()
46
47
 */
function entity_get_bundles($entity_type = NULL) {
48
  if (isset($entity_type)) {
49
    return \Drupal::entityManager()->getBundleInfo($entity_type);
50
  }
51
  else {
52
    return \Drupal::entityManager()->getAllBundleInfo();
53
54
55
  }
}

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
 * Notifies modules about an operation that was performed on a entity bundle.
 *
 * @param string $hook
 *   One of 'create', 'rename' or 'delete'.
 * @param string $entity_type
 *   The entity type to which the bundle is bound.
 * @param string $bundle
 *   The name of the bundle on which the operation was performed.
 * @param string|null $bundle_new
 *   The new name of the bundle in case of a 'rename' operation. Defaults to
 *   NULL.
 */
function entity_invoke_bundle_hook($hook, $entity_type, $bundle, $bundle_new = NULL) {
  entity_info_cache_clear();
71

72
  // Notify the entity storage.
73
  $method = 'onBundle' . ucfirst($hook);
74
75
76
  $storage = \Drupal::entityManager()->getStorage($entity_type);
  if (method_exists($storage, $method)) {
    $storage->$method($bundle, $bundle_new);
77
  }
78
  // Invoke hook_entity_bundle_*() hooks.
79
  \Drupal::moduleHandler()->invokeAll('entity_bundle_' . $hook, array($entity_type, $bundle, $bundle_new));
80
81
}

82
/**
83
84
85
86
 * Loads an entity from the database.
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
87
 * @param mixed $id
88
89
90
91
 *   The id of the entity to load.
 * @param bool $reset
 *   Whether to reset the internal cache for the requested entity type.
 *
92
 * @return \Drupal\Core\Entity\EntityInterface
93
 *   The entity object, or NULL if there is no entity with the given id.
94
 *
95
 * @see \Drupal\Core\Entity\EntityManagerInterface
96
97
 * @see \Drupal\Core\Entity\EntityStorageInterface
 * @see \Drupal\Core\Entity\ContentEntityDatabaseStorage
98
 * @see \Drupal\Core\Entity\Query\QueryInterface
99
100
 */
function entity_load($entity_type, $id, $reset = FALSE) {
101
  $controller = \Drupal::entityManager()->getStorage($entity_type);
102
103
104
105
  if ($reset) {
    $controller->resetCache(array($id));
  }
  return $controller->load($id);
106
107
}

108
109
110
111
112
113
114
115
/**
 * Loads an entity from the database.
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
 * @param int $revision_id
 *   The id of the entity to load.
 *
116
 * @return \Drupal\Core\Entity\EntityInterface
117
118
119
 *   The entity object, or FALSE if there is no entity with the given revision
 *   id.
 *
120
 * @see \Drupal\Core\Entity\EntityManagerInterface
121
122
 * @see \Drupal\Core\Entity\EntityStorageInterface
 * @see \Drupal\Core\Entity\ContentEntityDatabaseStorage
123
124
 */
function entity_revision_load($entity_type, $revision_id) {
125
  return \Drupal::entityManager()
126
    ->getStorage($entity_type)
127
    ->loadRevision($revision_id);
128
129
}

130
/**
131
 * Deletes an entity revision.
132
133
134
135
136
137
138
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
 * @param $revision_id
 *   The revision ID to delete.
 */
function entity_revision_delete($entity_type, $revision_id) {
139
  \Drupal::entityManager()
140
    ->getStorage($entity_type)
141
    ->deleteRevision($revision_id);
142
143
}

144
145
146
147
148
/**
 * Loads an entity by UUID.
 *
 * Note that some entity types may not support UUIDs.
 *
149
 * @param string $entity_type_id
150
151
152
153
154
155
156
157
158
 *   The entity type to load; e.g., 'node' or 'user'.
 * @param string $uuid
 *   The UUID of the entity to load.
 * @param bool $reset
 *   Whether to reset the internal cache for the requested entity type.
 *
 * @return EntityInterface|FALSE
 *   The entity object, or FALSE if there is no entity with the given UUID.
 *
159
 * @throws \Drupal\Core\Entity\EntityStorageException
160
161
 *   Thrown in case the requested entity type does not support UUIDs.
 *
162
 * @see \Drupal\Core\Entity\EntityManagerInterface
163
 */
164
165
function entity_load_by_uuid($entity_type_id, $uuid, $reset = FALSE) {
  $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
166

167
  if (!$uuid_key = $entity_type->getKey('uuid')) {
168
    throw new EntityStorageException("Entity type $entity_type_id does not support UUIDs.");
169
170
  }

171
  $controller = \Drupal::entityManager()->getStorage($entity_type_id);
172
173
174
  if ($reset) {
    $controller->resetCache();
  }
175
176
  $entities = $controller->loadByProperties(array($uuid_key => $uuid));
  return reset($entities);
177
178
}

179
180
/**
 * Loads multiple entities from the database.
181
182
183
184
185
186
 *
 * This function should be used whenever you need to load more than one entity
 * from the database. The entities are loaded into memory and will not require
 * database access if loaded again during the same page request.
 *
 * The actual loading is done through a class that has to implement the
187
188
189
190
 * Drupal\Core\Entity\EntityStorageInterface interface. By default,
 * Drupal\Core\Entity\ContentEntityDatabaseStorage is used for content entities
 * and Drupal\Core\Config\Entity\ConfigEntityStorage for config entities. Entity
 * types can specify that a different class should be used by setting the
191
 * "controllers['storage']" key in the entity plugin annotation. These classes
192
 * can either implement the Drupal\Core\Entity\EntityStorageInterface
193
 * interface, or, most commonly, extend the
194
195
 * Drupal\Core\Entity\ContentEntityDatabaseStorage class.
 * See Drupal\node\Entity\Node and Drupal\node\NodeStorage
196
 * for an example.
197
 *
198
 * @param string $entity_type
199
 *   The entity type to load, e.g. node or user.
200
201
 * @param array $ids
 *   (optional) An array of entity IDs. If omitted, all entities are loaded.
202
 * @param bool $reset
203
204
 *   Whether to reset the internal cache for the requested entity type.
 *
205
 * @return array
206
207
 *   An array of entity objects indexed by their ids.
 *
208
 * @see \Drupal\Core\Entity\EntityManagerInterface
209
210
 * @see \Drupal\Core\Entity\EntityStorageInterface
 * @see \Drupal\Core\Entity\ContentEntityDatabaseStorage
211
 * @see \Drupal\Core\Entity\Query\QueryInterface
212
 */
213
function entity_load_multiple($entity_type, array $ids = NULL, $reset = FALSE) {
214
  $controller = \Drupal::entityManager()->getStorage($entity_type);
215
  if ($reset) {
216
    $controller->resetCache($ids);
217
  }
218
  return $controller->loadMultiple($ids);
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
}

/**
 * Load entities by their property values.
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
 * @param array $values
 *   An associative array where the keys are the property names and the
 *   values are the values those properties must have.
 *
 * @return array
 *   An array of entity objects indexed by their ids.
 */
function entity_load_multiple_by_properties($entity_type, array $values) {
234
  return \Drupal::entityManager()
235
    ->getStorage($entity_type)
236
    ->loadByProperties($values);
237
238
239
240
241
242
243
244
245
246
247
248
249
}

/**
 * Loads the unchanged, i.e. not modified, entity from the database.
 *
 * Unlike entity_load() this function ensures the entity is directly loaded from
 * the database, thus bypassing any static cache. In particular, this function
 * is useful to determine changes by comparing the entity being saved to the
 * stored entity.
 *
 * @param $entity_type
 *   The entity type to load, e.g. node or user.
 * @param $id
250
 *   The ID of the entity to load.
251
252
253
254
255
 *
 * @return
 *   The unchanged entity, or FALSE if the entity cannot be loaded.
 */
function entity_load_unchanged($entity_type, $id) {
256
  return \Drupal::entityManager()
257
    ->getStorage($entity_type)
258
    ->loadUnchanged($id);
259
260
}

261
262
263
/**
 * Deletes multiple entities permanently.
 *
264
 * @param string $entity_type
265
 *   The type of the entity.
266
 * @param array $ids
267
268
 *   An array of entity IDs of the entities to delete.
 */
269
function entity_delete_multiple($entity_type, array $ids) {
270
  $controller = \Drupal::entityManager()->getStorage($entity_type);
271
  $entities = $controller->loadMultiple($ids);
272
  $controller->delete($entities);
273
274
275
}

/**
276
 * Constructs a new entity object, without permanently saving it.
277
 *
278
 * @param string $entity_type
279
 *   The type of the entity.
280
281
282
 * @param array $values
 *   (optional) An array of values to set, keyed by property name. If the
 *   entity type has bundles, the bundle key has to be specified.
283
 *
284
 * @return \Drupal\Core\Entity\EntityInterface
285
286
 *   A new entity object.
 */
287
function entity_create($entity_type, array $values = array()) {
288
  return \Drupal::entityManager()
289
    ->getStorage($entity_type)
290
    ->create($values);
291
292
}

293
294
/**
 * Gets the entity controller class for an entity type.
295
 *
296
 * @return \Drupal\Core\Entity\EntityStorageInterface
297
 *
298
 * @see \Drupal\Core\Entity\EntityManagerInterface::getStorage()
299
300
 *
 * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
301
 *   Use \Drupal::entityManager()->getStorage().
302
303
 */
function entity_get_controller($entity_type) {
304
  return \Drupal::entityManager()
305
    ->getStorage($entity_type);
306
307
308
309
310
}

/**
 * Returns the label of an entity.
 *
311
 * This is a wrapper for Drupal\Core\Entity\EntityInterface::label(). This function
312
 * should only be used as a callback, e.g. for menu title callbacks.
313
 *
314
 * @param \Drupal\Core\Entity\EntityInterface $entity
315
 *   The entity for which to generate the label.
316
317
318
319
 * @param $langcode
 *   (optional) The language code of the language that should be used for
 *   getting the label. If set to NULL, the entity's default language is
 *   used.
320
321
 *
 * @return
322
 *   The label of the entity, or NULL if there is no label defined.
323
 *
324
 * @see \Drupal\Core\Entity\EntityInterface::label()
325
 */
326
327
function entity_page_label(EntityInterface $entity, $langcode = NULL) {
  return $entity->label($langcode);
328
329
}

330
331
332
333
334
335
336
337
338
/**
 * Returns the entity access controller for the given entity type.
 *
 * @param string $entity_type
 *   The type of the entity.
 *
 * @return \Drupal\Core\Entity\EntityAccessControllerInterface
 *   An entity access controller instance.
 *
339
340
341
342
 * @see \Drupal\Core\Entity\EntityManagerInterface::getAccessController().
 *
 * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
 *   Use \Drupal::entityManager()->getAccessController().
343
344
 */
function entity_access_controller($entity_type) {
345
  return \Drupal::entityManager()
346
    ->getAccessController($entity_type);
347
348
}

349
350
351
/**
 * Returns the render array for an entity.
 *
352
 * @param \Drupal\Core\Entity\EntityInterface $entity
353
354
355
356
357
358
 *   The entity to be rendered.
 * @param string $view_mode
 *   The view mode that should be used to display the entity.
 * @param string $langcode
 *   (optional) For which language the entity should be rendered, defaults to
 *   the current content language.
359
360
361
 * @param bool $reset
 *   (optional) Whether to reset the render cache for the requested entity.
 *   Defaults to FALSE.
362
363
364
365
 *
 * @return array
 *   A render array for the entity.
 */
366
function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL, $reset = FALSE) {
367
  $render_controller = \Drupal::entityManager()->getViewBuilder($entity->getEntityTypeId());
368
369
370
371
  if ($reset) {
    $render_controller->resetCache(array($entity->id()));
  }
  return $render_controller->view($entity, $view_mode, $langcode);
372
373
374
375
376
}

/**
 * Returns the render array for the provided entities.
 *
377
 * @param \Drupal\Core\Entity\EntityInterface[] $entities
378
379
380
381
382
383
 *   The entities to be rendered, must be of the same type.
 * @param string $view_mode
 *   The view mode that should be used to display the entity.
 * @param string $langcode
 *   (optional) For which language the entity should be rendered, defaults to
 *   the current content language.
384
385
386
 * @param bool $reset
 *   (optional) Whether to reset the render cache for the requested entities.
 *   Defaults to FALSE.
387
388
389
390
391
 *
 * @return array
 *   A render array for the entities, indexed by the same keys as the
 *   entities array passed in $entities.
 */
392
function entity_view_multiple(array $entities, $view_mode, $langcode = NULL, $reset = FALSE) {
393
  $render_controller = \Drupal::entityManager()->getViewBuilder(reset($entities)->getEntityTypeId());
394
395
396
397
  if ($reset) {
    $render_controller->resetCache(array_keys($entities));
  }
  return $render_controller->viewMultiple($entities, $view_mode, $langcode);
398
}
399

400
/**
401
 * Returns the entity view display associated to a bundle and view mode.
402
403
404
405
406
407
 *
 * Use this function when assigning suggested display options for a component
 * in a given view mode. Note that they will only be actually used at render
 * time if the view mode itself is configured to use dedicated display settings
 * for the bundle; if not, the 'default' display is used instead.
 *
408
409
410
411
412
 * The function reads the entity view display from the current configuration, or
 * returns a ready-to-use empty one if configuration entry exists yet for this
 * bundle and view mode. This streamlines manipulation of display objects by
 * always returning a consistent object that reflects the current state of the
 * configuration.
413
414
415
416
417
 *
 * Example usage:
 * - Set the 'body' field to be displayed and the 'field_image' field to be
 *   hidden on article nodes in the 'default' display.
 * @code
418
 * entity_get_display('node', 'article', 'default')
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
 *   ->setComponent('body', array(
 *     'type' => 'text_summary_or_trimmed',
 *     'settings' => array('trim_length' => '200')
 *     'weight' => 1,
 *   ))
 *   ->removeComponent('field_image')
 *   ->save();
 * @endcode
 *
 * @param string $entity_type
 *   The entity type.
 * @param string $bundle
 *   The bundle.
 * @param string $view_mode
 *   The view mode, or 'default' to retrieve the 'default' display object for
 *   this bundle.
 *
436
 * @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
437
 *   The entity view display associated to the view mode.
438
439
440
 */
function entity_get_display($entity_type, $bundle, $view_mode) {
  // Try loading the display from configuration.
441
  $display = entity_load('entity_view_display', $entity_type . '.' . $bundle . '.' . $view_mode);
442
443

  // If not found, create a fresh display object. We do not preemptively create
444
445
446
447
  // new entity_view_display configuration entries for each existing entity type
  // and bundle whenever a new view mode becomes available. Instead,
  // configuration entries are only created when a display object is explicitly
  // configured and saved.
448
  if (!$display) {
449
    $display = entity_create('entity_view_display', array(
450
451
      'targetEntityType' => $entity_type,
      'bundle' => $bundle,
452
      'mode' => $view_mode,
453
      'status' => TRUE,
454
455
456
457
458
459
    ));
  }

  return $display;
}

460
/**
461
 * Returns the entity form display associated to a bundle and form mode.
462
 *
463
464
 * The function reads the entity form display object from the current
 * configuration, or returns a ready-to-use empty one if no configuration entry
465
 * exists yet for this bundle and form mode. This streamlines manipulation of
466
467
 * entity form displays by always returning a consistent object that reflects
 * the current state of the configuration.
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
 *
 * Example usage:
 * - Set the 'body' field to be displayed with the 'text_textarea_with_summary'
 *   widget and the 'field_image' field to be hidden on article nodes in the
 *  'default' form mode.
 * @code
 * entity_get_form_display('node', 'article', 'default')
 *   ->setComponent('body', array(
 *     'type' => 'text_textarea_with_summary',
 *     'weight' => 1,
 *   ))
 *   ->setComponent('field_image', array(
 *     'type' => 'hidden',
 *   ))
 *   ->save();
 * @endcode
 *
 * @param string $entity_type
 *   The entity type.
 * @param string $bundle
 *   The bundle.
 * @param string $form_mode
 *   The form mode.
 *
492
 * @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface
493
 *   The entity form display associated to the given form mode.
494
495
496
497
498
499
 */
function entity_get_form_display($entity_type, $bundle, $form_mode) {
  // Try loading the entity from configuration.
  $entity_form_display = entity_load('entity_form_display', $entity_type . '.' . $bundle . '.' . $form_mode);

  // If not found, create a fresh entity object. We do not preemptively create
500
  // new entity form display configuration entries for each existing entity type
501
  // and bundle whenever a new form mode becomes available. Instead,
502
  // configuration entries are only created when an entity form display is
503
504
505
506
507
508
  // explicitly configured and saved.
  if (!$entity_form_display) {
    $entity_form_display = entity_create('entity_form_display', array(
      'targetEntityType' => $entity_type,
      'bundle' => $bundle,
      'mode' => $form_mode,
509
      'status' => TRUE,
510
511
512
513
514
515
    ));
  }

  return $entity_form_display;
}

516
517
518
519
520
521
522
523
524
525
526
527
528
529
/**
 * Generic access callback for entity pages.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity for which access is being checked.
 * @param string $operation
 *   (optional) The operation being performed on the entity. Defaults to 'view'.
 *
 * @return bool
 *   TRUE if the access is granted. FALSE if access is denied.
 */
function entity_page_access(EntityInterface $entity, $operation = 'view') {
  return $entity->access($operation);
}
530
531
532
533
534
535

/**
 * Generic access callback for create entity pages.
 *
 * @param string $entity_type
 *   The entity type.
536
537
 * @param string $bundle
 *   (optional) The bundle of the entity. Required if the entity supports
538
 *   bundles, defaults to NULL otherwise.
539
540
541
542
 *
 * @return bool
 *   TRUE if the access is granted. FALSE if access is denied.
 */
543
function entity_page_create_access($entity_type, $bundle = NULL) {
544
  return \Drupal::entityManager()->getAccessController($entity_type)->createAccess($bundle);
545
}