Update to Drupal 8.2.0. For more information, see https://www.drupal.org/project/drupal/releases/8.2.0
This commit is contained in:
parent
2f563ab520
commit
f1c8716f57
1732 changed files with 52334 additions and 11780 deletions
|
@ -436,6 +436,13 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con
|
|||
$result = [];
|
||||
$args = array_slice(func_get_args(), 2);
|
||||
$langcodes = array_keys($entity->getTranslationLanguages());
|
||||
// Ensure that the field method is invoked as first on the current entity
|
||||
// translation and then on all other translations.
|
||||
$current_entity_langcode = $entity->language()->getId();
|
||||
if (reset($langcodes) != $current_entity_langcode) {
|
||||
$langcodes = array_diff($langcodes, [$current_entity_langcode]);
|
||||
array_unshift($langcodes, $current_entity_langcode);
|
||||
}
|
||||
foreach ($langcodes as $langcode) {
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
// For non translatable fields, there is only one field object instance
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Drupal\Core\Entity;
|
|||
use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Validates module uninstall readiness based on existing content entities.
|
||||
|
@ -37,10 +38,14 @@ class ContentUninstallValidator implements ModuleUninstallValidatorInterface {
|
|||
*/
|
||||
public function validate($module) {
|
||||
$entity_types = $this->entityManager->getDefinitions();
|
||||
$reasons = array();
|
||||
$reasons = [];
|
||||
foreach ($entity_types as $entity_type) {
|
||||
if ($module == $entity_type->getProvider() && $entity_type instanceof ContentEntityTypeInterface && $this->entityManager->getStorage($entity_type->id())->hasData()) {
|
||||
$reasons[] = $this->t('There is content for the entity type: @entity_type', array('@entity_type' => $entity_type->getLabel()));
|
||||
$reasons[] = $this->t('There is content for the entity type: @entity_type. <a href=":url">Remove @entity_type_plural</a>.', [
|
||||
'@entity_type' => $entity_type->getLabel(),
|
||||
'@entity_type_plural' => $entity_type->getPluralLabel(),
|
||||
':url' => Url::fromRoute('system.prepare_modules_entity_uninstall', ['entity_type_id' => $entity_type->id()])->toString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $reasons;
|
||||
|
|
|
@ -273,7 +273,7 @@ class EntityController implements ContainerInjectionInterface {
|
|||
* (optional) The entity, set in
|
||||
* \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface|NULL
|
||||
* @return \Drupal\Core\Entity\EntityInterface|null
|
||||
* The entity, if it is passed in directly or if the first parameter of the
|
||||
* active route is an entity; otherwise, NULL.
|
||||
*/
|
||||
|
|
|
@ -346,8 +346,8 @@ class EntityAccessControlHandler extends EntityHandlerBase implements EntityAcce
|
|||
* is checked for the field definition, without any specific value
|
||||
* available. Defaults to NULL.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if access is allowed, FALSE otherwise.
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
return AccessResult::allowed();
|
||||
|
|
|
@ -10,7 +10,9 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
|||
/**
|
||||
* Provides a wrapper around many other services relating to entities.
|
||||
*
|
||||
* @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
|
||||
* Deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. We cannot
|
||||
* use the deprecated PHPDoc tag because this service class is still used in
|
||||
* legacy code paths. Symfony would fail test cases with deprecation warnings.
|
||||
*
|
||||
* @todo Enforce the deprecation of each method once
|
||||
* https://www.drupal.org/node/2578361 is in.
|
||||
|
|
|
@ -482,6 +482,7 @@ class EntityType implements EntityTypeInterface {
|
|||
public function setStorageClass($class) {
|
||||
$this->checkStorageClass($class);
|
||||
$this->handlers['storage'] = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -526,7 +526,9 @@ interface EntityTypeInterface extends PluginDefinitionInterface {
|
|||
/**
|
||||
* Gets the name of the entity type which provides bundles.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
* The name of the entity type which provides bundles, or NULL if the entity
|
||||
* type does not have a bundle entity type.
|
||||
*/
|
||||
public function getBundleEntityType();
|
||||
|
||||
|
|
|
@ -17,13 +17,21 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
|||
/**
|
||||
* Manages entity type plugin definitions.
|
||||
*
|
||||
* Each entity type definition array is set in the entity type's
|
||||
* annotation and altered by hook_entity_type_alter().
|
||||
* Each entity type definition array is set in the entity type's annotation and
|
||||
* altered by hook_entity_type_alter().
|
||||
*
|
||||
* Do not use hook_entity_type_alter() hook to add information to entity types,
|
||||
* unless one of the following is true:
|
||||
* - You are filling in default values.
|
||||
* - You need to dynamically add information only in certain circumstances.
|
||||
* - Your hook needs to run after hook_entity_type_build() implementations.
|
||||
* Use hook_entity_type_build() instead in all other cases.
|
||||
*
|
||||
* @see \Drupal\Core\Entity\Annotation\EntityType
|
||||
* @see \Drupal\Core\Entity\EntityInterface
|
||||
* @see \Drupal\Core\Entity\EntityTypeInterface
|
||||
* @see hook_entity_type_alter()
|
||||
* @see hook_entity_type_build()
|
||||
*/
|
||||
class EntityTypeManager extends DefaultPluginManager implements EntityTypeManagerInterface, ContainerAwareInterface {
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Core\Entity\Plugin\DataType\Deriver;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -32,6 +33,13 @@ class EntityDeriver implements ContainerDeriverInterface {
|
|||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The bundle info service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $bundleInfoService;
|
||||
|
||||
/**
|
||||
* Constructs an EntityDeriver object.
|
||||
*
|
||||
|
@ -40,9 +48,10 @@ class EntityDeriver implements ContainerDeriverInterface {
|
|||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
*/
|
||||
public function __construct($base_plugin_id, EntityManagerInterface $entity_manager) {
|
||||
public function __construct($base_plugin_id, EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $bundle_info_service) {
|
||||
$this->basePluginId = $base_plugin_id;
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->bundleInfoService = $bundle_info_service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +60,8 @@ class EntityDeriver implements ContainerDeriverInterface {
|
|||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$base_plugin_id,
|
||||
$container->get('entity.manager')
|
||||
$container->get('entity.manager'),
|
||||
$container->get('entity_type.bundle.info')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -82,7 +92,7 @@ class EntityDeriver implements ContainerDeriverInterface {
|
|||
) + $base_plugin_definition;
|
||||
|
||||
// Incorporate the bundles as entity:$entity_type:$bundle, if any.
|
||||
foreach (entity_get_bundles($entity_type_id) as $bundle => $bundle_info) {
|
||||
foreach ($this->bundleInfoService->getBundleInfo($entity_type_id) as $bundle => $bundle_info) {
|
||||
if ($bundle !== $entity_type_id) {
|
||||
$this->derivatives[$entity_type_id . ':' . $bundle] = array(
|
||||
'label' => $bundle_info['label'],
|
||||
|
|
|
@ -67,7 +67,9 @@ class EntityReference extends DataReferenceBase {
|
|||
public function getTarget() {
|
||||
if (!isset($this->target) && isset($this->id)) {
|
||||
// If we have a valid reference, return the entity's TypedData adapter.
|
||||
$entity = entity_load($this->getTargetDefinition()->getEntityTypeId(), $this->id);
|
||||
$entity = \Drupal::entityTypeManager()
|
||||
->getStorage($this->getTargetDefinition()->getEntityTypeId())
|
||||
->load($this->id);
|
||||
$this->target = isset($entity) ? $entity->getTypedData() : NULL;
|
||||
}
|
||||
return $this->target;
|
||||
|
|
|
@ -33,10 +33,10 @@ class ReferenceAccessConstraintValidator extends ConstraintValidator {
|
|||
$referenced_entities = $existing_entity->{$value->getFieldDefinition()->getName()}->referencedEntities();
|
||||
// Check permission if we are not already referencing the entity.
|
||||
foreach ($referenced_entities as $ref) {
|
||||
if (isset($referenced_entities[$ref->id()])) {
|
||||
$check_permission = FALSE;
|
||||
break;
|
||||
}
|
||||
if (isset($referenced_entities[$ref->id()])) {
|
||||
$check_permission = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We check that the current user had access to view any newly added
|
||||
|
|
|
@ -46,13 +46,6 @@ class Query extends QueryBase implements QueryInterface {
|
|||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Stores the entity manager used by the query.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* Constructs a query object.
|
||||
*
|
||||
|
@ -232,7 +225,7 @@ class Query extends QueryBase implements QueryInterface {
|
|||
if ($this->range) {
|
||||
$this->sqlQuery->range($this->range['start'], $this->range['length']);
|
||||
}
|
||||
foreach ($this->sqlGroupBy as $field) {
|
||||
foreach ($this->sqlGroupBy as $field) {
|
||||
$this->sqlQuery->groupBy($field);
|
||||
}
|
||||
foreach ($this->sqlFields as $field) {
|
||||
|
|
|
@ -23,6 +23,7 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
* - add-form
|
||||
* - edit-form
|
||||
* - delete-form
|
||||
* - collection
|
||||
*
|
||||
* @see \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider.
|
||||
*
|
||||
|
@ -95,6 +96,10 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
$collection->add("entity.{$entity_type_id}.delete_form", $delete_route);
|
||||
}
|
||||
|
||||
if ($collection_route = $this->getCollectionRoute($entity_type)) {
|
||||
$collection->add("entity.{$entity_type_id}.collection", $collection_route);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
|
@ -298,6 +303,33 @@ class DefaultHtmlRouteProvider implements EntityRouteProviderInterface, EntityHa
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collection route.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\Route|null
|
||||
* The generated route, if available.
|
||||
*/
|
||||
protected function getCollectionRoute(EntityTypeInterface $entity_type) {
|
||||
// If the entity type does not provide an admin permission, there is no way
|
||||
// to control access, so we cannot provide a route in a sensible way.
|
||||
if ($entity_type->hasLinkTemplate('collection') && $entity_type->hasListBuilderClass() && ($admin_permission = $entity_type->getAdminPermission())) {
|
||||
$route = new Route($entity_type->getLinkTemplate('collection'));
|
||||
$route
|
||||
->addDefaults([
|
||||
'_entity_list' => $entity_type->id(),
|
||||
// @todo Improve this in https://www.drupal.org/node/2767025
|
||||
'_title' => '@label entities',
|
||||
'_title_arguments' => ['@label' => $entity_type->getLabel()],
|
||||
])
|
||||
->setRequirement('_permission', $admin_permission);
|
||||
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the ID key for a given entity type.
|
||||
*
|
||||
|
|
|
@ -526,7 +526,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
$all_fields = $revisioned_fields;
|
||||
if ($data_fields) {
|
||||
$all_fields = array_merge($revisioned_fields, $data_fields);
|
||||
$query->leftJoin($this->dataTable, 'data', "(revision.$this->idKey = data.$this->idKey)");
|
||||
$query->leftJoin($this->dataTable, 'data', "(revision.$this->idKey = data.$this->idKey and revision.$this->langcodeKey = data.$this->langcodeKey)");
|
||||
$column_names = [];
|
||||
// Some fields can have more then one columns in the data table so
|
||||
// column names are needed.
|
||||
|
|
|
@ -1443,7 +1443,7 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
*
|
||||
* @param array $entity_schema
|
||||
* The entity schema definition.
|
||||
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface|NULL $storage_definition
|
||||
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface|null $storage_definition
|
||||
* (optional) If a field storage definition is specified, only indexes and
|
||||
* keys involving its columns will be processed. Otherwise all defined
|
||||
* entity indexes and keys will be processed.
|
||||
|
@ -1500,7 +1500,7 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
*
|
||||
* @param array $entity_schema_data
|
||||
* The entity schema data definition.
|
||||
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface|NULL $storage_definition
|
||||
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface|null $storage_definition
|
||||
* (optional) If a field storage definition is specified, only indexes and
|
||||
* keys involving its columns will be processed. Otherwise all defined
|
||||
* entity indexes and keys will be processed.
|
||||
|
|
|
@ -893,9 +893,9 @@ function hook_ENTITY_TYPE_storage_load(array $entities) {
|
|||
* @see hook_ENTITY_TYPE_presave()
|
||||
*/
|
||||
function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
|
||||
if ($entity instanceof ContentEntityInterface && $entity->isTranslatable()) {
|
||||
$route_match = \Drupal::routeMatch();
|
||||
\Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode'));
|
||||
if ($entity instanceof ContentEntityInterface && $entity->isTranslatable()) {
|
||||
$route_match = \Drupal::routeMatch();
|
||||
\Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue