entity.inc 28.4 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\CacheBackendInterface;
9 10
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityInterface;
11
use Drupal\Core\Language\Language;
12 13

/**
14
 * Gets the entity definition for an entity type.
15
 *
16 17 18 19 20 21
 * @param string|null $entity_type
 *   (optional) The entity type (e.g. 'node'). Leave NULL to retrieve
 *   information for all entity types.
 *
 * @return array
 *   An array containing the entity type's definition, as retrieved with
22 23 24
 *   \Drupal\Core\Entity\EntityManagerInterface. If $entity_type is NULL, an
 *   associative array of all entity type definitions keyed by entity type is
 *   returned.
25
 *
26
 * @see \Drupal\Core\Entity\EntityManagerInterface
27
 * @see hook_entity_info_alter()
28
 *
29
 * @deprecated Use \Drupal\Core\Entity\EntityManagerInterface::getDefinitions() directly.
30 31 32
 */
function entity_get_info($entity_type = NULL) {
  if (empty($entity_type)) {
33
    return \Drupal::entityManager()->getDefinitions();
34
  }
35
  else {
36
    return \Drupal::entityManager()->getDefinition($entity_type);
37 38 39 40 41 42 43
  }
}

/**
 * Resets the cached information about entity types.
 */
function entity_info_cache_clear() {
44
  drupal_static_reset('entity_get_view_modes');
45
  // Clear all languages.
46 47
  \Drupal::entityManager()->clearCachedDefinitions();
  \Drupal::entityManager()->clearCachedFieldDefinitions();
48 49
}

50 51 52 53 54 55
/**
 * 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) {
56 57
    if ($entity_manager->hasController($entity_type, 'view_builder')) {
      $entity_manager->getViewBuilder($entity_type)->resetCache();
58 59 60 61
    }
  }
}

62
/**
63
 * Returns the entity bundle info.
64
 *
65 66 67 68 69 70
 * @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.
71
 *
72 73
 * @see \Drupal\Core\Entity\EntityManagerInterface::getBundleInfo()
 * @see \Drupal\Core\Entity\EntityManagerInterface::getAllBundleInfo()
74 75
 */
function entity_get_bundles($entity_type = NULL) {
76
  if (isset($entity_type)) {
77
    return \Drupal::entityManager()->getBundleInfo($entity_type);
78
  }
79
  else {
80
    return \Drupal::entityManager()->getAllBundleInfo();
81 82 83
  }
}

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/**
 * 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();
99 100 101

  // Notify the entity storage controller.
  $method = 'onBundle' . ucfirst($hook);
102 103 104 105
  $storage_controller = \Drupal::entityManager()->getStorageController($entity_type);
  if (method_exists($storage_controller, $method)) {
    $storage_controller->$method($bundle, $bundle_new);
  }
106
  // Invoke hook_entity_bundle_*() hooks.
107
  \Drupal::moduleHandler()->invokeAll('entity_bundle_' . $hook, array($entity_type, $bundle, $bundle_new));
108 109
}

110 111 112 113 114 115 116 117 118 119 120 121 122
/**
 * Returns the entity form mode info.
 *
 * @param string|null $entity_type
 *   The entity type whose form mode info should be returned, or NULL for all
 *   form mode info. Defaults to NULL.
 *
 * @return array
 *   The form mode info for a specific entity type, or all entity types.
 */
function entity_get_form_modes($entity_type = NULL) {
  $form_modes = &drupal_static(__FUNCTION__);
  if (!$form_modes) {
123
    $langcode = language(Language::TYPE_INTERFACE)->id;
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    if ($cache = cache()->get("entity_form_mode_info:$langcode")) {
      $form_modes = $cache->data;
    }
    else {
      $form_modes = array();
      foreach (entity_load_multiple('form_mode') as $form_mode) {
        list($form_mode_entity_type, $form_mode_name) = explode('.', $form_mode->id(), 2);
        $form_modes[$form_mode_entity_type][$form_mode_name] = (array) $form_mode;
      }
      drupal_alter('entity_form_mode_info', $form_modes);
      cache()->set("entity_form_mode_info:$langcode", $form_modes, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
    }
  }

  if (empty($entity_type)) {
    return $form_modes;
  }
  elseif (isset($form_modes[$entity_type])) {
    return $form_modes[$entity_type];
  }

  return array();
}

148 149 150 151 152 153
/**
 * Returns the entity view mode info.
 *
 * @param string|null $entity_type
 *   The entity type whose view mode info should be returned, or NULL for all
 *   view mode info. Defaults to NULL.
154 155
 *
 * @return array
156
 *   The view mode info for a specific entity type, or all entity types.
157
 */
158 159 160
function entity_get_view_modes($entity_type = NULL) {
  $view_modes = &drupal_static(__FUNCTION__);
  if (!$view_modes) {
161
    $langcode = language(Language::TYPE_INTERFACE)->id;
162 163 164 165
    if ($cache = cache()->get("entity_view_mode_info:$langcode")) {
      $view_modes = $cache->data;
    }
    else {
166 167 168 169
      $view_modes = array();
      foreach (entity_load_multiple('view_mode') as $view_mode) {
        list($view_mode_entity_type, $view_mode_name) = explode('.', $view_mode->id(), 2);
        $view_modes[$view_mode_entity_type][$view_mode_name] = (array) $view_mode;
170 171 172 173 174 175 176 177 178 179 180 181 182 183
      }
      drupal_alter('entity_view_mode_info', $view_modes);
      cache()->set("entity_view_mode_info:$langcode", $view_modes, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
    }
  }

  if (empty($entity_type)) {
    return $view_modes;
  }
  elseif (isset($view_modes[$entity_type])) {
    return $view_modes[$entity_type];
  }

  return array();
184 185
}

186
/**
187 188 189 190
 * Loads an entity from the database.
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
191
 * @param mixed $id
192 193 194 195
 *   The id of the entity to load.
 * @param bool $reset
 *   Whether to reset the internal cache for the requested entity type.
 *
196
 * @return \Drupal\Core\Entity\EntityInterface
197
 *   The entity object, or NULL if there is no entity with the given id.
198
 *
199
 * @see \Drupal\Core\Entity\EntityManagerInterface
200 201 202
 * @see \Drupal\Core\Entity\EntityStorageControllerInterface
 * @see \Drupal\Core\Entity\DatabaseStorageController
 * @see \Drupal\Core\Entity\Query\QueryInterface
203 204
 */
function entity_load($entity_type, $id, $reset = FALSE) {
205
  $controller = \Drupal::entityManager()->getStorageController($entity_type);
206 207 208 209
  if ($reset) {
    $controller->resetCache(array($id));
  }
  return $controller->load($id);
210 211
}

212 213 214 215 216 217 218 219
/**
 * 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.
 *
220
 * @return \Drupal\Core\Entity\EntityInterface
221 222 223
 *   The entity object, or FALSE if there is no entity with the given revision
 *   id.
 *
224
 * @see \Drupal\Core\Entity\EntityManagerInterface
225 226
 * @see \Drupal\Core\Entity\EntityStorageControllerInterface
 * @see \Drupal\Core\Entity\DatabaseStorageController
227 228
 */
function entity_revision_load($entity_type, $revision_id) {
229
  return \Drupal::entityManager()
230 231
    ->getStorageController($entity_type)
    ->loadRevision($revision_id);
232 233
}

234
/**
235
 * Deletes an entity revision.
236 237 238 239 240 241 242
 *
 * @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) {
243
  \Drupal::entityManager()
244 245
    ->getStorageController($entity_type)
    ->deleteRevision($revision_id);
246 247
}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
/**
 * Loads an entity by UUID.
 *
 * Note that some entity types may not support UUIDs.
 *
 * @param string $entity_type
 *   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.
 *
263
 * @throws \Drupal\Core\Entity\EntityStorageException
264 265
 *   Thrown in case the requested entity type does not support UUIDs.
 *
266
 * @see \Drupal\Core\Entity\EntityManagerInterface
267 268 269
 */
function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) {
  $entity_info = entity_get_info($entity_type);
270
  if (empty($entity_info['entity_keys']['uuid'])) {
271 272
    throw new EntityStorageException("Entity type $entity_type does not support UUIDs.");
  }
273
  $uuid_key = $entity_info['entity_keys']['uuid'];
274

275
  $controller = \Drupal::entityManager()->getStorageController($entity_type);
276 277 278
  if ($reset) {
    $controller->resetCache();
  }
279 280
  $entities = $controller->loadByProperties(array($uuid_key => $uuid));
  return reset($entities);
281 282
}

283 284
/**
 * Loads multiple entities from the database.
285 286 287 288 289 290
 *
 * 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
291 292
 * Drupal\Core\Entity\EntityStorageControllerInterface interface. By default,
 * Drupal\Core\Entity\DatabaseStorageController is used. Entity types can
293
 * specify that a different class should be used by setting the
294 295
 * "controllers['storage']" key in the entity plugin annotation. These classes
 * can either implement the Drupal\Core\Entity\EntityStorageControllerInterface
296 297
 * interface, or, most commonly, extend the
 * Drupal\Core\Entity\DatabaseStorageController class.
298
 * See Drupal\node\Entity\Node and Drupal\node\NodeStorageController
299
 * for an example.
300
 *
301
 * @param string $entity_type
302
 *   The entity type to load, e.g. node or user.
303 304
 * @param array $ids
 *   (optional) An array of entity IDs. If omitted, all entities are loaded.
305
 * @param bool $reset
306 307
 *   Whether to reset the internal cache for the requested entity type.
 *
308
 * @return array
309 310
 *   An array of entity objects indexed by their ids.
 *
311
 * @see \Drupal\Core\Entity\EntityManagerInterface
312 313 314
 * @see \Drupal\Core\Entity\EntityStorageControllerInterface
 * @see \Drupal\Core\Entity\DatabaseStorageController
 * @see \Drupal\Core\Entity\Query\QueryInterface
315
 */
316
function entity_load_multiple($entity_type, array $ids = NULL, $reset = FALSE) {
317
  $controller = \Drupal::entityManager()->getStorageController($entity_type);
318
  if ($reset) {
319
    $controller->resetCache($ids);
320
  }
321
  return $controller->loadMultiple($ids);
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
}

/**
 * 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) {
337
  return \Drupal::entityManager()
338 339
    ->getStorageController($entity_type)
    ->loadByProperties($values);
340 341 342 343 344 345 346 347 348 349 350 351 352
}

/**
 * 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
353
 *   The ID of the entity to load.
354 355 356 357 358
 *
 * @return
 *   The unchanged entity, or FALSE if the entity cannot be loaded.
 */
function entity_load_unchanged($entity_type, $id) {
359
  return \Drupal::entityManager()
360 361
    ->getStorageController($entity_type)
    ->loadUnchanged($id);
362 363
}

364 365 366
/**
 * Deletes multiple entities permanently.
 *
367
 * @param string $entity_type
368
 *   The type of the entity.
369
 * @param array $ids
370 371
 *   An array of entity IDs of the entities to delete.
 */
372
function entity_delete_multiple($entity_type, array $ids) {
373
  $controller = \Drupal::entityManager()->getStorageController($entity_type);
374
  $entities = $controller->loadMultiple($ids);
375
  $controller->delete($entities);
376 377 378
}

/**
379
 * Constructs a new entity object, without permanently saving it.
380 381 382 383 384 385 386
 *
 * @param $entity_type
 *   The type of the entity.
 * @param $values
 *   An array of values to set, keyed by property name. If the entity type has
 *   bundles the bundle key has to be specified.
 *
387
 * @return \Drupal\Core\Entity\EntityInterface
388 389 390
 *   A new entity object.
 */
function entity_create($entity_type, array $values) {
391
  return \Drupal::entityManager()
392 393
    ->getStorageController($entity_type)
    ->create($values);
394 395
}

396 397
/**
 * Gets the entity controller class for an entity type.
398
 *
399
 * @return \Drupal\Core\Entity\EntityStorageControllerInterface
400
 *
401
 * @deprecated Use \Drupal\Core\Entity\EntityManagerInterface::getStorageController().
402 403
 */
function entity_get_controller($entity_type) {
404
  return \Drupal::entityManager()
405
    ->getStorageController($entity_type);
406 407 408 409 410
}

/**
 * Returns the label of an entity.
 *
411
 * This is a wrapper for Drupal\Core\Entity\EntityInterface::label(). This function
412
 * should only be used as a callback, e.g. for menu title callbacks.
413
 *
414
 * @param \Drupal\Core\Entity\EntityInterface $entity
415
 *   The entity for which to generate the label.
416 417 418 419
 * @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.
420 421
 *
 * @return
422
 *   The label of the entity, or NULL if there is no label defined.
423
 *
424
 * @see \Drupal\Core\Entity\EntityInterface::label()
425
 */
426 427
function entity_page_label(EntityInterface $entity, $langcode = NULL) {
  return $entity->label($langcode);
428 429
}

430 431 432 433 434 435 436 437 438
/**
 * 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.
 *
439
 * @deprecated Use \Drupal\Core\Entity\EntityManagerInterface::getAccessController().
440 441
 */
function entity_access_controller($entity_type) {
442
  return \Drupal::entityManager()
443
    ->getAccessController($entity_type);
444 445
}

446
/**
447 448 449 450 451 452 453 454
 * Returns an entity form controller for the given operation.
 *
 * Since there might be different scenarios in which an entity is edited,
 * multiple form controllers suitable to the different operations may be defined.
 * If no controller is found for the default operation, the base class will be
 * used. If a non-existing non-default operation is specified an exception will
 * be thrown.
 *
455
 * @see \Drupal\Core\Entity\EntityManagerInterface
456 457 458 459 460 461 462 463
 *
 * @param $entity_type
 *   The type of the entity.
 * @param $operation
 *   (optional) The name of an operation, such as creation, editing or deletion,
 *   identifying the controlled form. Defaults to 'default' which is the usual
 *   create/edit form.
 *
464
 * @return \Drupal\Core\Entity\EntityFormControllerInterface
465
 *   An entity form controller instance.
466
 *
467
 * @deprecated Use \Drupal\Core\Entity\EntityManagerInterface::getFormController().
468 469
 */
function entity_form_controller($entity_type, $operation = 'default') {
470
  return \Drupal::entityManager()
471
    ->getFormController($entity_type, $operation);
472 473 474 475 476 477 478 479 480 481 482 483 484
}

/**
 * Returns the default form state for the given entity and operation.
 *
 * @param EntityInterface $entity
 *   The entity to be created or edited.
 * @param $operation
 *   (optional) The operation identifying the form to be processed.
 *
 * @return
 *   A $form_state array already filled the entity form controller.
 */
485
function entity_form_state_defaults(EntityInterface $entity, $operation = 'default') {
486
  $form_state = array();
487
  $controller = \Drupal::entityManager()->getFormController($entity->entityType(), $operation);
488 489 490 491
  $controller->setEntity($entity);
  $form_state['build_info']['callback_object'] = $controller;
  $form_state['build_info']['base_form_id'] = $controller->getBaseFormID();
  $form_state['build_info']['args'] = array();
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
  return $form_state;
}

/**
 * Retrieves, populates, and processes an entity form.
 *
 * @param EntityInterface $entity
 *   The entity to be created or edited.
 * @param $operation
 *   (optional) The operation identifying the form to be submitted.
 * @param $form_state
 *   (optional) A keyed array containing the current state of the form.
 *
 * @return
 *   A $form_state array already filled with the entity form controller.
 */
function entity_form_submit(EntityInterface $entity, $operation = 'default', &$form_state = array()) {
  $form_state += entity_form_state_defaults($entity, $operation);
510
  $form_id = $form_state['build_info']['callback_object']->getFormId();
511 512 513 514 515 516 517 518 519 520
  drupal_form_submit($form_id, $form_state);
}

/**
 * Returns the built and processed entity form for the given entity.
 *
 * @param EntityInterface $entity
 *   The entity to be created or edited.
 * @param $operation
 *   (optional) The operation identifying the form variation to be returned.
521 522 523 524 525 526 527
 * @param array $form_state
 *   (optional) An associative array containing the current state of the form.
 *   Use this to pass additional information to the form, such as the langcode.
 *   @code
 *   $form_state['langcode'] = $langcode;
 *   $form = entity_get_form($entity, 'default', $form_state);
 *   @endcode
528 529 530
 *
 * @return
 *   The processed form for the given entity and operation.
531
 *
532
 * @deprecated Use \Drupal::entityManager()->getForm() or _entity_form from a
533
 *   routing.yml file instead of a page callback.
534
 */
535
function entity_get_form(EntityInterface $entity, $operation = 'default', array $form_state = array()) {
536
  return \Drupal::entityManager()->getForm($entity, $operation, $form_state);
537 538
}

539 540 541 542 543 544
/**
 * Returns an entity list controller for a given entity type.
 *
 * @param string $entity_type
 *   The type of the entity.
 *
545
 * @return \Drupal\Core\Entity\EntityListControllerInterface
546 547
 *   An entity list controller.
 *
548
 * @deprecated Use \Drupal\Core\Entity\EntityManagerInterface::getFormController().
549 550
 */
function entity_list_controller($entity_type) {
551
  return \Drupal::entityManager()
552
    ->getListController($entity_type);
553
}
554 555 556 557

/**
 * Returns the render array for an entity.
 *
558
 * @param \Drupal\Core\Entity\EntityInterface $entity
559 560 561 562 563 564
 *   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.
565 566 567
 * @param bool $reset
 *   (optional) Whether to reset the render cache for the requested entity.
 *   Defaults to FALSE.
568 569 570 571
 *
 * @return array
 *   A render array for the entity.
 */
572
function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL, $reset = FALSE) {
573
  $render_controller = \Drupal::entityManager()->getViewBuilder($entity->entityType());
574 575 576 577
  if ($reset) {
    $render_controller->resetCache(array($entity->id()));
  }
  return $render_controller->view($entity, $view_mode, $langcode);
578 579 580 581 582 583 584 585 586 587 588 589
}

/**
 * Returns the render array for the provided entities.
 *
 * @param array $entities
 *   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.
590 591 592
 * @param bool $reset
 *   (optional) Whether to reset the render cache for the requested entities.
 *   Defaults to FALSE.
593 594 595 596 597
 *
 * @return array
 *   A render array for the entities, indexed by the same keys as the
 *   entities array passed in $entities.
 */
598
function entity_view_multiple(array $entities, $view_mode, $langcode = NULL, $reset = FALSE) {
599
  $render_controller = \Drupal::entityManager()->getViewBuilder(reset($entities)->entityType());
600 601 602 603
  if ($reset) {
    $render_controller->resetCache(array_keys($entities));
  }
  return $render_controller->viewMultiple($entities, $view_mode, $langcode);
604
}
605

606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
/**
 * Returns the entity_display object associated to a bundle and view mode.
 *
 * 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.
 *
 * The function reads the entity_display object 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.
 *
 * 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
624
 * entity_get_display('node', 'article', 'default')
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
 *   ->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.
 *
642
 * @return \Drupal\entity\Entity\EntityDisplay
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
 *   The display object associated to the view mode.
 */
function entity_get_display($entity_type, $bundle, $view_mode) {
  // Try loading the display from configuration.
  $display = entity_load('entity_display', $entity_type . '.' . $bundle . '.' . $view_mode);

  // If not found, create a fresh display object. We do not preemptively create
  // new entity_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.
  if (!$display) {
    $display = entity_create('entity_display', array(
      'targetEntityType' => $entity_type,
      'bundle' => $bundle,
658
      'mode' => $view_mode,
659
      'status' => TRUE,
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
    ));
  }

  return $display;
}

/**
 * Returns the entity_display object used to render an entity.
 *
 * Depending on the configuration of the view mode for the bundle, this can be
 * either the display object associated to the view mode, or the 'default'
 * display.
 *
 * This function should only be used internally when rendering an entity. When
 * assigning suggested display options for a component in a given view mode,
 * entity_get_display() should be used instead, in order to avoid inadvertently
 * modifying the output of other view modes that might happen to use the
 * 'default' display too. Those options will then be effectively applied only
 * if the view mode is configured to use them.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity being rendered.
 * @param string $view_mode
 *  The view mode being rendered.
 *
685
 * @return \Drupal\entity\Entity\EntityDisplay
686 687
 *   The display object that should be used to render the entity.
 *
688
 * @see entity_get_display().
689 690 691 692
 */
function entity_get_render_display(EntityInterface $entity, $view_mode) {
  $entity_type = $entity->entityType();
  $bundle = $entity->bundle();
693 694 695 696 697 698 699 700 701 702 703 704 705 706
  $render_view_mode = 'default';

  // Look at the default display and display for the view mode, and fallback to
  // the former if the latter does not exist is disabled.
  if ($view_mode != 'default') {
    $ids = array(
      'default' => $entity_type . '.' . $bundle . '.default',
      $view_mode => $entity_type . '.' . $bundle . '.' . $view_mode,
    );
    $entity_displays = entity_load_multiple('entity_display', $ids);
    if (isset($entity_displays[$ids[$view_mode]]) && $entity_displays[$ids[$view_mode]]->status()) {
      $render_view_mode = $view_mode;
    }
  }
707 708

  $display = entity_get_display($entity_type, $bundle, $render_view_mode);
709
  $display->originalMode = $view_mode;
710 711

  return $display;
712
}
713

714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
/**
 * Returns the entity_form_display object associated to a bundle and form mode.
 *
 * The function reads the entity_form_display object from the current
 * configuration, or returns a ready-to-use empty one if configuration entry
 * exists yet for this bundle and form mode. This streamlines manipulation of
 * EntityFormDisplay objects by always returning a consistent object that
 * reflects the current state of the configuration.
 *
 * 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.
 *
746
 * @return \Drupal\entity\Entity\EntityFormDisplay
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
 *   The EntityFormDisplay object associated to the form mode.
 */
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
  // new EntityFormDisplay configuration entries for each existing entity type
  // and bundle whenever a new form mode becomes available. Instead,
  // configuration entries are only created when a EntityFormDisplay object is
  // 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,
763
      'status' => TRUE,
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
    ));
  }

  return $entity_form_display;
}

/**
 * Returns the entity_form_display object used to render an entity form.
 *
 * This function should only be used internally when rendering an entity form.
 * When assigning suggested form display options for a component in a given form
 * mode, entity_get_form_display() should be used instead, in order to avoid
 * inadvertently modifying the output of other form modes that might happen to
 * use the 'default' form display too. Those options will then be effectively
 * applied only if the form mode is configured to use them.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity for which the form is being rendered.
 * @param string $form_mode
 *   The form mode being rendered.
 *
785
 * @return \Drupal\entity\Entity\EntityFormDisplay
786 787 788 789 790 791 792
 *   The form display object that should be used to render the entity form.
 *
 * @see entity_get_form_display().
 */
function entity_get_render_form_display(EntityInterface $entity, $form_mode) {
  $entity_type = $entity->entityType();
  $bundle = $entity->bundle();
793 794 795 796 797 798 799 800 801 802 803 804 805 806
  $render_form_mode = 'default';

  // Look at the default form display and form display for the view mode, and
  // fallback to the former if the latter does not exist is disabled.
  if ($form_mode != 'default') {
    $ids = array(
      'default' => $entity_type . '.' . $bundle . '.default',
      $form_mode => $entity_type . '.' . $bundle . '.' . $form_mode,
    );
    $entity_form_displays = entity_load_multiple('entity_form_display', $ids);
    if (isset($entity_form_displays[$ids[$form_mode]]) && $entity_form_displays[$ids[$form_mode]]->status()) {
      $render_form_mode = $form_mode;
    }
  }
807 808

  $form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode);
809 810 811 812 813
  $form_display->originalMode = $form_mode;

  return $form_display;
}

814 815 816 817 818 819 820 821 822 823 824 825 826 827
/**
 * 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);
}
828 829 830 831 832 833

/**
 * Generic access callback for create entity pages.
 *
 * @param string $entity_type
 *   The entity type.
834 835
 * @param string $bundle
 *   (optional) The bundle of the entity. Required if the entity supports
836
 *   bundles, defaults to NULL otherwise.
837 838 839 840
 *
 * @return bool
 *   TRUE if the access is granted. FALSE if access is denied.
 */
841
function entity_page_create_access($entity_type, $bundle = NULL) {
842
  return \Drupal::entityManager()->getAccessController($entity_type)->createAccess($bundle);
843
}