entity.inc 25.6 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 12

/**
13
 * Gets the entity definition for an entity type.
14
 *
15 16 17 18 19 20 21 22
 * @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
 *   \Drupal\Core\Entity\EntityManager. If $entity_type is NULL, an associative
 *   array of all entity type definitions keyed by entity type is returned.
23
 *
24
 * @see \Drupal\Core\Entity\EntityManager
25
 * @see hook_entity_info_alter()
26 27 28 29 30 31 32 33 34 35
 */
function entity_get_info($entity_type = NULL) {
  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast['entity_info'] = &drupal_static(__FUNCTION__);
  }
  $entity_info = &$drupal_static_fast['entity_info'];

  if (empty($entity_info)) {
36
    $entity_info = drupal_container()->get('plugin.manager.entity')->getDefinitions();
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  }

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

/**
 * Resets the cached information about entity types.
 */
function entity_info_cache_clear() {
  drupal_static_reset('entity_get_info');
52 53
  drupal_static_reset('entity_get_view_modes');
  drupal_static_reset('entity_get_bundles');
54
  // Clear all languages.
55
  cache()->deleteTags(array('entity_info' => TRUE));
56 57
}

58
/**
59
 * Returns the entity bundle info.
60
 *
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
 * @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.
 */
function entity_get_bundles($entity_type = NULL) {
  $bundles = &drupal_static(__FUNCTION__);
  if (!$bundles) {
    $langcode = language(LANGUAGE_TYPE_INTERFACE)->langcode;
    if ($cache = cache()->get("entity_bundle_info:$langcode")) {
      $bundles = $cache->data;
    }
    else {
      $bundles = module_invoke_all('entity_bundle_info');
      // If no bundles are provided, use the entity type name and label.
      foreach (entity_get_info() as $type => $entity_info) {
        if (!isset($bundles[$type])) {
          $bundles[$type][$type]['label'] = $entity_info['label'];
        }
      }
      drupal_alter('entity_bundle_info', $bundles);
      cache()->set("entity_bundle_info:$langcode", $bundles, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
    }
  }

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

  return array();
}

/**
 * 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.
104 105
 *
 * @return array
106
 *   The view mode info for a specific entity type, or all entity types.
107
 */
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
function entity_get_view_modes($entity_type = NULL) {
  $view_modes = &drupal_static(__FUNCTION__);
  if (!$view_modes) {
    $langcode = language(LANGUAGE_TYPE_INTERFACE)->langcode;
    if ($cache = cache()->get("entity_view_mode_info:$langcode")) {
      $view_modes = $cache->data;
    }
    else {
      $view_modes = module_invoke_all('entity_view_mode_info');
      foreach ($view_modes as $type => $entity_info) {
        foreach ($entity_info as $view_mode => $view_mode_info) {
          $view_modes[$type][$view_mode] += array(
            'custom_settings' => FALSE,
          );
        }
      }
      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();
137 138
}

139
/**
140 141 142 143 144 145 146 147 148
 * Loads an entity from the database.
 *
 * @param string $entity_type
 *   The entity type to load, e.g. node or user.
 * @param int $id
 *   The id of the entity to load.
 * @param bool $reset
 *   Whether to reset the internal cache for the requested entity type.
 *
149
 * @return Drupal\Core\Entity\EntityInterface
150 151
 *   The entity object, or FALSE if there is no entity with the given id.
 *
152
 * @see \Drupal\Core\Entity\EntityManager
153
 * @see entity_load_multiple()
154 155
 * @see Drupal\Core\Entity\EntityStorageControllerInterface
 * @see Drupal\Core\Entity\DatabaseStorageController
156
 * @see Drupal\Core\Entity\Query\QueryInterface
157 158
 */
function entity_load($entity_type, $id, $reset = FALSE) {
159
  $entities = entity_load_multiple($entity_type, array($id), $reset);
160 161 162
  return isset($entities[$id]) ? $entities[$id] : FALSE;
}

163 164 165 166 167 168 169 170
/**
 * 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.
 *
171
 * @return Drupal\Core\Entity\EntityInterface
172 173 174
 *   The entity object, or FALSE if there is no entity with the given revision
 *   id.
 *
175
 * @see \Drupal\Core\Entity\EntityManager
176 177
 * @see Drupal\Core\Entity\EntityStorageControllerInterface
 * @see Drupal\Core\Entity\DatabaseStorageController
178 179
 */
function entity_revision_load($entity_type, $revision_id) {
180 181 182
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->loadRevision($revision_id);
183 184
}

185
/**
186
 * Deletes an entity revision.
187 188 189 190 191 192 193
 *
 * @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) {
194 195 196
  drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->deleteRevision($revision_id);
197 198
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
/**
 * 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.
 *
214
 * @throws Drupal\Core\Entity\EntityStorageException
215 216
 *   Thrown in case the requested entity type does not support UUIDs.
 *
217
 * @see \Drupal\Core\Entity\EntityManager
218 219 220
 */
function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) {
  $entity_info = entity_get_info($entity_type);
221
  if (empty($entity_info['entity_keys']['uuid'])) {
222 223
    throw new EntityStorageException("Entity type $entity_type does not support UUIDs.");
  }
224
  $uuid_key = $entity_info['entity_keys']['uuid'];
225

226
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
227 228 229
  if ($reset) {
    $controller->resetCache();
  }
230 231
  $entities = $controller->loadByProperties(array($uuid_key => $uuid));
  return reset($entities);
232 233
}

234 235
/**
 * Loads multiple entities from the database.
236 237 238 239 240 241
 *
 * 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
242 243
 * Drupal\Core\Entity\EntityStorageControllerInterface interface. By default,
 * Drupal\Core\Entity\DatabaseStorageController is used. Entity types can
244
 * specify that a different class should be used by setting the
245 246 247 248 249 250
 * 'controller_class' key in the entity plugin annotation. These classes can
 * either implement the Drupal\Core\Entity\EntityStorageControllerInterface
 * interface, or, most commonly, extend the
 * Drupal\Core\Entity\DatabaseStorageController class.
 * See Drupal\node\Plugin\Core\Entity\Node and Drupal\node\NodeStorageController
 * for an example.
251
 *
252
 * @param string $entity_type
253
 *   The entity type to load, e.g. node or user.
254 255
 * @param array $ids
 *   (optional) An array of entity IDs. If omitted, all entities are loaded.
256
 * @param bool $reset
257 258
 *   Whether to reset the internal cache for the requested entity type.
 *
259
 * @return array
260 261
 *   An array of entity objects indexed by their ids.
 *
262
 * @see \Drupal\Core\Entity\EntityManager
263 264
 * @see Drupal\Core\Entity\EntityStorageControllerInterface
 * @see Drupal\Core\Entity\DatabaseStorageController
265
 * @see Drupal\Core\Entity\Query\QueryInterface
266
 */
267
function entity_load_multiple($entity_type, array $ids = NULL, $reset = FALSE) {
268
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
269
  if ($reset) {
270
    $controller->resetCache();
271
  }
272
  return $controller->load($ids);
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
}

/**
 * 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) {
288 289 290
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->loadByProperties($values);
291 292 293 294 295 296 297 298 299 300 301 302 303
}

/**
 * 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
304
 *   The ID of the entity to load.
305 306 307 308 309
 *
 * @return
 *   The unchanged entity, or FALSE if the entity cannot be loaded.
 */
function entity_load_unchanged($entity_type, $id) {
310 311 312
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
  $controller->resetCache(array($id));
  $result = $controller->load(array($id));
313 314 315
  return reset($result);
}

316 317 318
/**
 * Deletes multiple entities permanently.
 *
319
 * @param string $entity_type
320
 *   The type of the entity.
321
 * @param array $ids
322 323
 *   An array of entity IDs of the entities to delete.
 */
324
function entity_delete_multiple($entity_type, array $ids) {
325
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
326 327
  $entities = $controller->load($ids);
  $controller->delete($entities);
328 329 330
}

/**
331
 * Constructs a new entity object, without permanently saving it.
332 333 334 335 336 337 338
 *
 * @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.
 *
339
 * @return Drupal\Core\Entity\EntityInterface
340 341 342
 *   A new entity object.
 */
function entity_create($entity_type, array $values) {
343 344 345
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->create($values);
346 347
}

348 349
/**
 * Gets the entity controller class for an entity type.
350
 *
351
 * @return Drupal\Core\Entity\EntityStorageControllerInterface
352 353
 *
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getStorageController().
354 355
 */
function entity_get_controller($entity_type) {
356 357
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type);
358 359 360 361 362
}

/**
 * Returns the label of an entity.
 *
363
 * This is a wrapper for Drupal\Core\Entity\EntityInterface::label(). This function
364
 * should only be used as a callback, e.g. for menu title callbacks.
365
 *
366
 * @param Drupal\Core\Entity\EntityInterface $entity
367
 *   The entity for which to generate the label.
368 369 370 371
 * @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.
372 373
 *
 * @return
374
 *   The label of the entity, or NULL if there is no label defined.
375
 *
376
 * @see Drupal\Core\Entity\EntityInterface::label()
377
 */
378 379
function entity_page_label(EntityInterface $entity, $langcode = NULL) {
  return $entity->label($langcode);
380 381
}

382 383 384 385 386 387 388 389 390
/**
 * 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.
 *
391
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getRenderController().
392 393
 */
function entity_access_controller($entity_type) {
394 395
  return drupal_container()->get('plugin.manager.entity')
    ->getAccessController($entity_type);
396 397
}

398
/**
399 400 401 402 403 404 405 406
 * 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.
 *
407
 * @see \Drupal\Core\Entity\EntityManager
408 409 410 411 412 413 414 415
 *
 * @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.
 *
416
 * @return Drupal\Core\Entity\EntityFormControllerInterface
417
 *   An entity form controller instance.
418 419
 *
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
420 421
 */
function entity_form_controller($entity_type, $operation = 'default') {
422 423
  return drupal_container()->get('plugin.manager.entity')
    ->getFormController($entity_type, $operation);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
}

/**
 * Returns the form id for the given entity and operation.
 *
 * @param EntityInterface $entity
 *   The entity to be created or edited.
 * @param $operation
 *   (optional) The operation for the form to be processed.
 *
 * @return
 *   A string representing the entity form id.
 */
function entity_form_id(EntityInterface $entity, $operation = 'default') {
  $entity_type = $entity->entityType();
  $bundle = $entity->bundle();
  $form_id = $entity_type;
  if ($bundle != $entity_type) {
    $form_id = $bundle . '_' . $form_id;
  }
  if ($operation != 'default') {
    $form_id = $form_id . '_' . $operation;
  }
  return $form_id . '_form';
}

/**
 * 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.
 */
461
function entity_form_state_defaults(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
462
  $form_state = array();
463
  $controller = drupal_container()->get('plugin.manager.entity')->getFormController($entity->entityType(), $operation);
464 465 466
  $form_state['build_info']['callback'] = array($controller, 'build');
  $form_state['build_info']['base_form_id'] = $entity->entityType() . '_form';
  $form_state['build_info']['args'] = array($entity);
467
  $form_state['langcode'] = $langcode;
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
  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);
  $form_id = entity_form_id($entity, $operation);
  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.
 *
 * @return
 *   The processed form for the given entity and operation.
500
 */
501 502
function entity_get_form(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
  $form_state = entity_form_state_defaults($entity, $operation, $langcode);
503 504
  $form_id = entity_form_id($entity, $operation);
  return drupal_build_form($form_id, $form_state);
505 506 507
}

/**
508
 * Copies submitted values to entity properties for simple entity forms.
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
 *
 * During the submission handling of an entity form's "Save", "Preview", and
 * possibly other buttons, the form state's entity needs to be updated with the
 * submitted form values. Each entity form implements its own builder function
 * for doing this, appropriate for the particular entity and form, whereas
 * modules may specify additional builder functions in $form['#entity_builders']
 * for copying the form values of added form elements to entity properties.
 * Many of the main entity builder functions can call this helper function to
 * re-use its logic of copying $form_state['values'][PROPERTY] values to
 * $entity->PROPERTY for all entries in $form_state['values'] that are not field
 * data, and calling field_attach_submit() to copy field data. Apart from that
 * this helper invokes any additional builder functions that have been specified
 * in $form['#entity_builders'].
 *
 * For some entity forms (e.g., forms with complex non-field data and forms that
 * simultaneously edit multiple entities), this behavior may be inappropriate,
 * so the builder function for such forms needs to implement the required
 * functionality instead of calling this function.
 */
function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_state) {
  $info = entity_get_info($entity_type);

  // Copy top-level form values that are not for fields to entity properties,
  // without changing existing entity properties that are not being edited by
  // this form. Copying field values must be done using field_attach_submit().
534
  $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values'];
535
  foreach ($values_excluding_fields as $key => $value) {
536
    $entity->set($key, $value);
537 538 539 540 541
  }

  // Invoke all specified builders for copying form values to entity properties.
  if (isset($form['#entity_builders'])) {
    foreach ($form['#entity_builders'] as $function) {
542
      call_user_func_array($function, array($entity_type, $entity, &$form, &$form_state));
543 544 545 546 547
    }
  }

  // Copy field values to the entity.
  if ($info['fieldable']) {
548
    field_attach_submit($entity, $form, $form_state);
549 550
  }
}
551 552 553 554 555 556 557 558 559 560

/**
 * Returns an entity list controller for a given entity type.
 *
 * @param string $entity_type
 *   The type of the entity.
 *
 * @return Drupal\Core\Entity\EntityListControllerInterface
 *   An entity list controller.
 *
561
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
562 563
 */
function entity_list_controller($entity_type) {
564 565
  return drupal_container()->get('plugin.manager.entity')
    ->getListController($entity_type);
566
}
567 568 569 570 571 572 573 574 575 576

/**
 * Returns an entity render controller for a given entity type.
 *
 * @param string $entity_type
 *   The type of the entity.
 *
 * @return Drupal\Core\Entity\EntityRenderControllerInterface
 *   An entity render controller.
 *
577
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
578 579
 */
function entity_render_controller($entity_type) {
580 581
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController($entity_type);
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
}

/**
 * Returns the render array for an entity.
 *
 * @param Drupal\Core\Entity\EntityInterface $entity
 *   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.
 *
 * @return array
 *   A render array for the entity.
 */
function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL) {
599 600 601
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController($entity->entityType())
    ->view($entity, $view_mode, $langcode);
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
}

/**
 * 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.
 *
 * @return array
 *   A render array for the entities, indexed by the same keys as the
 *   entities array passed in $entities.
 */
function entity_view_multiple(array $entities, $view_mode, $langcode = NULL) {
620 621 622
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController(reset($entities)->entityType())
    ->viewMultiple($entities, $view_mode, $langcode);
623
}
624

625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
/**
 * 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
643
 * entity_get_display('node', 'article', 'default')
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 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 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
 *   ->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.
 *
 * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay
 *   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,
      'viewMode' => $view_mode,
    ));
  }

  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.
 *
 * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay
 *   The display object that should be used to render the entity.
 *
 * @see entity_get_render_display().
 */
function entity_get_render_display(EntityInterface $entity, $view_mode) {
  $entity_type = $entity->entityType();
  $bundle = $entity->bundle();

  // Determine the display to use for rendering this entity. Depending on the
  // configuration of the view mode for this bundle, this will be either the
  // display associated to the view mode, or the 'default' display.
  $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
  $render_view_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default';

  $display = entity_get_display($entity_type, $bundle, $render_view_mode);
  $display->originalViewMode = $view_mode;

  return $display;
}

724 725 726 727 728 729 730 731 732 733 734 735 736
/**
 * Returns the entity query object for this entity type.
 *
 * @param $entity_type
 *   The entity type, e.g. node, for which the query object should be
 *   returned.
 * @param $conjunction
 *   AND if all conditions in the query need to apply, OR if any of them is
 *   enough. Optional, defaults to AND.
 */
function entity_query($entity_type, $conjunction = 'AND') {
  return drupal_container()->get('entity.query')->get($entity_type, $conjunction);
}
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751

/**
 * 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);
}