entity.inc 26.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
 *
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getDefinitions() directly.
28 29 30
 */
function entity_get_info($entity_type = NULL) {
  if (empty($entity_type)) {
31
    return drupal_container()->get('plugin.manager.entity')->getDefinitions();
32
  }
33 34
  else {
    return drupal_container()->get('plugin.manager.entity')->getDefinition($entity_type);
35 36 37 38 39 40 41
  }
}

/**
 * Resets the cached information about entity types.
 */
function entity_info_cache_clear() {
42 43
  drupal_static_reset('entity_get_view_modes');
  drupal_static_reset('entity_get_bundles');
44
  // Clear all languages.
45
  drupal_container()->get('plugin.manager.entity')->clearCachedDefinitions();
46 47
}

48
/**
49
 * Returns the entity bundle info.
50
 *
51 52 53 54 55 56 57 58 59 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
 * @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();
}

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/**
 * 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();
  module_invoke_all('entity_bundle_' . $hook, $entity_type, $bundle, $bundle_new);
}

106 107 108 109 110 111
/**
 * 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.
112 113
 *
 * @return array
114
 *   The view mode info for a specific entity type, or all entity types.
115
 */
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
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();
145 146
}

147
/**
148 149 150 151 152 153 154 155 156
 * 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.
 *
157
 * @return Drupal\Core\Entity\EntityInterface
158 159
 *   The entity object, or FALSE if there is no entity with the given id.
 *
160
 * @see \Drupal\Core\Entity\EntityManager
161
 * @see entity_load_multiple()
162 163
 * @see Drupal\Core\Entity\EntityStorageControllerInterface
 * @see Drupal\Core\Entity\DatabaseStorageController
164
 * @see Drupal\Core\Entity\Query\QueryInterface
165 166
 */
function entity_load($entity_type, $id, $reset = FALSE) {
167
  $entities = entity_load_multiple($entity_type, array($id), $reset);
168 169 170
  return isset($entities[$id]) ? $entities[$id] : FALSE;
}

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

193
/**
194
 * Deletes an entity revision.
195 196 197 198 199 200 201
 *
 * @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) {
202 203 204
  drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->deleteRevision($revision_id);
205 206
}

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

234
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
235 236 237
  if ($reset) {
    $controller->resetCache();
  }
238 239
  $entities = $controller->loadByProperties(array($uuid_key => $uuid));
  return reset($entities);
240 241
}

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

/**
 * 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) {
296 297 298
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->loadByProperties($values);
299 300 301 302 303 304 305 306 307 308 309 310 311
}

/**
 * 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
312
 *   The ID of the entity to load.
313 314 315 316 317
 *
 * @return
 *   The unchanged entity, or FALSE if the entity cannot be loaded.
 */
function entity_load_unchanged($entity_type, $id) {
318 319 320
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
    ->loadUnchanged($id);
321 322
}

323 324 325
/**
 * Deletes multiple entities permanently.
 *
326
 * @param string $entity_type
327
 *   The type of the entity.
328
 * @param array $ids
329 330
 *   An array of entity IDs of the entities to delete.
 */
331
function entity_delete_multiple($entity_type, array $ids) {
332
  $controller = drupal_container()->get('plugin.manager.entity')->getStorageController($entity_type);
333 334
  $entities = $controller->load($ids);
  $controller->delete($entities);
335 336 337
}

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

355 356
/**
 * Gets the entity controller class for an entity type.
357
 *
358
 * @return Drupal\Core\Entity\EntityStorageControllerInterface
359 360
 *
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getStorageController().
361 362
 */
function entity_get_controller($entity_type) {
363 364
  return drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type);
365 366 367 368 369
}

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

389 390 391 392 393 394 395 396 397
/**
 * 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.
 *
398
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getRenderController().
399 400
 */
function entity_access_controller($entity_type) {
401 402
  return drupal_container()->get('plugin.manager.entity')
    ->getAccessController($entity_type);
403 404
}

405
/**
406 407 408 409 410 411 412 413
 * 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.
 *
414
 * @see \Drupal\Core\Entity\EntityManager
415 416 417 418 419 420 421 422
 *
 * @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.
 *
423
 * @return Drupal\Core\Entity\EntityFormControllerInterface
424
 *   An entity form controller instance.
425 426
 *
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
427 428
 */
function entity_form_controller($entity_type, $operation = 'default') {
429 430
  return drupal_container()->get('plugin.manager.entity')
    ->getFormController($entity_type, $operation);
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 461 462 463 464 465 466 467
}

/**
 * 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.
 */
468
function entity_form_state_defaults(EntityInterface $entity, $operation = 'default') {
469
  $form_state = array();
470
  $controller = drupal_container()->get('plugin.manager.entity')->getFormController($entity->entityType(), $operation);
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 500 501 502
  $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);
  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.
503 504 505 506 507 508 509
 * @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
510 511 512
 *
 * @return
 *   The processed form for the given entity and operation.
513
 */
514 515
function entity_get_form(EntityInterface $entity, $operation = 'default', array $form_state = array()) {
  $form_state += entity_form_state_defaults($entity, $operation);
516 517
  $form_id = entity_form_id($entity, $operation);
  return drupal_build_form($form_id, $form_state);
518 519 520
}

/**
521
 * Copies submitted values to entity properties for simple entity forms.
522 523 524 525 526 527 528 529 530
 *
 * 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
531 532 533 534
 * $entity->PROPERTY for all entries in $form_state['values'] that are not
 * field data, and calling field_attach_extract_form_values() to copy field
 * data. Apart from that this helper invokes any additional builder functions
 * that have been specified in $form['#entity_builders'].
535 536 537 538 539 540 541 542 543 544 545
 *
 * 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
546 547
  // this form. Copying field values must be done using
  // field_attach_extract_form_values().
548
  $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values'];
549
  foreach ($values_excluding_fields as $key => $value) {
550
    $entity->set($key, $value);
551 552 553 554 555
  }

  // Invoke all specified builders for copying form values to entity properties.
  if (isset($form['#entity_builders'])) {
    foreach ($form['#entity_builders'] as $function) {
556
      call_user_func_array($function, array($entity_type, $entity, &$form, &$form_state));
557 558 559 560 561
    }
  }

  // Copy field values to the entity.
  if ($info['fieldable']) {
562
    field_attach_extract_form_values($entity, $form, $form_state);
563 564
  }
}
565 566 567 568 569 570 571 572 573 574

/**
 * 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.
 *
575
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
576 577
 */
function entity_list_controller($entity_type) {
578 579
  return drupal_container()->get('plugin.manager.entity')
    ->getListController($entity_type);
580
}
581 582 583 584 585 586 587 588 589 590

/**
 * 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.
 *
591
 * @deprecated Use \Drupal\Core\Entity\EntityManager::getFormController().
592 593
 */
function entity_render_controller($entity_type) {
594 595
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController($entity_type);
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
}

/**
 * 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) {
613 614 615
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController($entity->entityType())
    ->view($entity, $view_mode, $langcode);
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
}

/**
 * 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) {
634 635 636
  return drupal_container()->get('plugin.manager.entity')
    ->getRenderController(reset($entities)->entityType())
    ->viewMultiple($entities, $view_mode, $langcode);
637
}
638

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
/**
 * 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
657
 * entity_get_display('node', 'article', 'default')
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 724 725 726 727 728 729 730 731 732 733 734 735
 *   ->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;
736
}
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);
}
752 753 754 755 756 757

/**
 * Generic access callback for create entity pages.
 *
 * @param string $entity_type
 *   The entity type.
758 759 760
 * @param string $bundle
 *   (optional) The bundle of the entity. Required if the entity supports
 *   bundles, defaults to the entity type otherwise.
761 762 763 764
 *
 * @return bool
 *   TRUE if the access is granted. FALSE if access is denied.
 */
765 766 767 768 769 770 771 772
function entity_page_create_access($entity_type, $bundle = NULL) {
  $definition = Drupal::service('plugin.manager.entity')->getDefinition($entity_type);

  // Pass in the entity bundle if given and required.
  $values = array();
  if ($bundle && isset($definition['entity_keys']['bundle'])) {
    $values[$definition['entity_keys']['bundle']] = $bundle;
  }
773 774
  $entity = drupal_container()->get('plugin.manager.entity')
    ->getStorageController($entity_type)
775
    ->create($values);
776 777
  return $entity->access('create');
}