Update to Drupal 8.1.5. For more information, see https://www.drupal.org/project/drupal/releases/8.1.5
This commit is contained in:
parent
13b6ca7cc2
commit
38ba7c357d
342 changed files with 7814 additions and 1534 deletions
|
@ -306,7 +306,7 @@ abstract class Entity implements EntityInterface {
|
|||
// The entity ID is needed as a route parameter.
|
||||
$uri_route_parameters[$this->getEntityTypeId()] = $this->id();
|
||||
}
|
||||
if ($rel === 'revision') {
|
||||
if ($rel === 'revision' && $this instanceof RevisionableInterface) {
|
||||
$uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
|
||||
}
|
||||
|
||||
|
|
|
@ -339,10 +339,17 @@ interface EntityInterface extends AccessibleInterface, CacheableDependencyInterf
|
|||
public static function preCreate(EntityStorageInterface $storage, array &$values);
|
||||
|
||||
/**
|
||||
* Acts on an entity after it is created but before hooks are invoked.
|
||||
* Acts on a created entity before hooks are invoked.
|
||||
*
|
||||
* Used after the entity is created, but before saving the entity and before
|
||||
* any of the presave hooks are invoked.
|
||||
*
|
||||
* See the @link entity_crud Entity CRUD topic @endlink for more information.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage object.
|
||||
*
|
||||
* @see \Drupal\Core\Entity\EntityInterface::create()
|
||||
*/
|
||||
public function postCreate(EntityStorageInterface $storage);
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ interface EntityTypeBundleInfoInterface {
|
|||
* Get the bundle info of all entity types.
|
||||
*
|
||||
* @return array
|
||||
* An array of all bundle information.
|
||||
* An array of bundle information where the outer array is keyed by entity
|
||||
* type. The next level is keyed by the bundle name. The inner arrays are
|
||||
* associative arrays of bundle information, such as the label for the
|
||||
* bundle.
|
||||
*/
|
||||
public function getAllBundleInfo();
|
||||
|
||||
|
@ -22,7 +25,10 @@ interface EntityTypeBundleInfoInterface {
|
|||
* The entity type.
|
||||
*
|
||||
* @return array
|
||||
* Returns the bundle information for the specified entity type.
|
||||
* An array of bundle information where the outer array is keyed by the
|
||||
* bundle name, or the entity type name if the entity does not have bundles.
|
||||
* The inner arrays are associative arrays of bundle information, such as
|
||||
* the label for the bundle.
|
||||
*/
|
||||
public function getBundleInfo($entity_type);
|
||||
|
||||
|
|
|
@ -28,24 +28,47 @@ interface QueryInterface extends AlterableInterface {
|
|||
* and the Polish 'siema' within a 'greetings' text field:
|
||||
* @code
|
||||
* $entity_ids = \Drupal::entityQuery($entity_type)
|
||||
* ->condition('greetings', 'merhaba', '=', 'tr');
|
||||
* ->condition('greetings.value', 'siema', '=', 'pl');
|
||||
* ->condition('greetings', 'merhaba', '=', 'tr')
|
||||
* ->condition('greetings.value', 'siema', '=', 'pl')
|
||||
* ->execute();
|
||||
* $entity_ids = $query->execute();
|
||||
* @endcode
|
||||
*
|
||||
* @param $field
|
||||
* Name of the field being queried. It must contain a field name,
|
||||
* optionally followed by a column name. The column can be "entity" for
|
||||
* reference fields and that can be followed similarly by a field name
|
||||
* and so on. Some examples:
|
||||
* Name of the field being queried. It must contain a field name, optionally
|
||||
* followed by a column name. The column can be "entity" for reference
|
||||
* fields and that can be followed similarly by a field name and so on. Some
|
||||
* examples:
|
||||
* - nid
|
||||
* - tags.value
|
||||
* - tags
|
||||
* - uid.entity.name
|
||||
* "tags" "is the same as "tags.value" as value is the default column.
|
||||
* If two or more conditions have the same field names they apply to the
|
||||
* same delta within that field.
|
||||
* same delta within that field. In order to limit the condition to a
|
||||
* specific item a numeric delta should be added between the field name and
|
||||
* the column name.
|
||||
* @code
|
||||
* ->condition('tags.5.value', 'news')
|
||||
* @endcode
|
||||
* This will require condition to be satisfied on a specific delta of the
|
||||
* field. The condition above will require the 6th value of the field to
|
||||
* match the provided value. Further, it's possible to create a condition on
|
||||
* the delta itself by using '%delta'. For example,
|
||||
* @code
|
||||
* ->condition('tags.%delta', 5)
|
||||
* @endcode
|
||||
* will find only entities which have at least six tags. Finally, the
|
||||
* condition on the delta itself accompanied with a condition on the value
|
||||
* will require the value to appear in the specific delta range. For
|
||||
* example,
|
||||
* @code
|
||||
* ->condition('tags.%delta', 0, '>'))
|
||||
* ->condition('tags.%delta.value', 'news'))
|
||||
* @endcode
|
||||
* will only find the "news" tag if it is not the first value. It should be
|
||||
* noted that conditions on specific deltas and delta ranges are only
|
||||
* supported when querying content entities.
|
||||
* @param $value
|
||||
* The value for $field. In most cases, this is a scalar and it's treated as
|
||||
* case-insensitive. For more complex operators, it is an array. The meaning
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Drupal\Core\Entity\Query\Sql;
|
|||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
use Drupal\Core\Entity\Query\QueryException;
|
||||
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
|
||||
use Drupal\Core\Entity\Sql\TableMappingInterface;
|
||||
|
||||
/**
|
||||
* Adds tables and fields to the SQL entity query.
|
||||
|
@ -112,11 +113,37 @@ class Tables implements TablesInterface {
|
|||
|
||||
// Check whether this field is stored in a dedicated table.
|
||||
if ($field_storage && $table_mapping->requiresDedicatedTableStorage($field_storage)) {
|
||||
$delta = NULL;
|
||||
// Find the field column.
|
||||
$column = $field_storage->getMainPropertyName();
|
||||
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
// If this is a numeric specifier we're adding a condition on the
|
||||
// specific delta.
|
||||
if (is_numeric($next)) {
|
||||
$delta = $next;
|
||||
$index_prefix .= ".$delta";
|
||||
// Do not process it again.
|
||||
$key++;
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
// If this specifier is the reserved keyword "%delta" we're adding a
|
||||
// condition on a delta range.
|
||||
elseif ($next == TableMappingInterface::DELTA) {
|
||||
$index_prefix .= TableMappingInterface::DELTA;
|
||||
// Do not process it again.
|
||||
$key++;
|
||||
// If there are more specifiers to work with then continue
|
||||
// processing. If this is the last specifier then use the reserved
|
||||
// keyword as a column name.
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
else {
|
||||
$column = TableMappingInterface::DELTA;
|
||||
}
|
||||
}
|
||||
// Is this a field column?
|
||||
$columns = $field_storage->getColumns();
|
||||
if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
|
||||
|
@ -140,7 +167,7 @@ class Tables implements TablesInterface {
|
|||
$next_index_prefix = "$relationship_specifier.$column";
|
||||
}
|
||||
}
|
||||
$table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field);
|
||||
$table = $this->ensureFieldTable($index_prefix, $field_storage, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta);
|
||||
$sql_column = $table_mapping->getFieldColumnName($field_storage, $column);
|
||||
$property_definitions = $field_storage->getPropertyDefinitions();
|
||||
if (isset($property_definitions[$column])) {
|
||||
|
@ -173,6 +200,27 @@ class Tables implements TablesInterface {
|
|||
// next one is a column of this field.
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
// If this specifier is the reserved keyword "%delta" we're adding a
|
||||
// condition on a delta range.
|
||||
if ($next == TableMappingInterface::DELTA) {
|
||||
$key++;
|
||||
if ($key < $count) {
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// If this is a numeric specifier we're adding a condition on the
|
||||
// specific delta. Since we know that this is a single value base
|
||||
// field no other value than 0 makes sense.
|
||||
if (is_numeric($next)) {
|
||||
if ($next > 0) {
|
||||
$this->sqlQuery->condition('1 <> 1');
|
||||
}
|
||||
$key++;
|
||||
$next = $specifiers[$key + 1];
|
||||
}
|
||||
// Is this a field column?
|
||||
$columns = $field_storage->getColumns();
|
||||
if (isset($columns[$next]) || in_array($next, $table_mapping->getReservedColumns())) {
|
||||
|
@ -264,7 +312,7 @@ class Tables implements TablesInterface {
|
|||
* @return string
|
||||
* @throws \Drupal\Core\Entity\Query\QueryException
|
||||
*/
|
||||
protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field) {
|
||||
protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field, $delta) {
|
||||
$field_name = $field->getName();
|
||||
if (!isset($this->fieldTables[$index_prefix . $field_name])) {
|
||||
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
|
||||
|
@ -274,12 +322,12 @@ class Tables implements TablesInterface {
|
|||
if ($field->getCardinality() != 1) {
|
||||
$this->sqlQuery->addMetaData('simple_query', FALSE);
|
||||
}
|
||||
$this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode);
|
||||
$this->fieldTables[$index_prefix . $field_name] = $this->addJoin($type, $table, "%alias.$field_id_field = $base_table.$entity_id_field", $langcode, $delta);
|
||||
}
|
||||
return $this->fieldTables[$index_prefix . $field_name];
|
||||
}
|
||||
|
||||
protected function addJoin($type, $table, $join_condition, $langcode) {
|
||||
protected function addJoin($type, $table, $join_condition, $langcode, $delta = NULL) {
|
||||
$arguments = array();
|
||||
if ($langcode) {
|
||||
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
|
||||
|
@ -291,6 +339,11 @@ class Tables implements TablesInterface {
|
|||
$join_condition .= ' AND %alias.' . $langcode_key . ' = ' . $placeholder;
|
||||
$arguments[$placeholder] = $langcode;
|
||||
}
|
||||
if (isset($delta)) {
|
||||
$placeholder = ':delta' . $this->sqlQuery->nextPlaceholder();
|
||||
$join_condition .= ' AND %alias.delta = ' . $placeholder;
|
||||
$arguments[$placeholder] = $delta;
|
||||
}
|
||||
return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@ interface TablesInterface {
|
|||
* Adds a field to a database query.
|
||||
*
|
||||
* @param string $field
|
||||
* If it contains a dot, then field name dot field column. If it doesn't
|
||||
* then entity property name.
|
||||
* If it doesn't contain a dot, then an entity base field name. If it
|
||||
* contains a dot, then either field name dot field column or field name dot
|
||||
* delta dot field column. Delta can be a numeric value or a "%delta" for
|
||||
* any value.
|
||||
* @param string $type
|
||||
* Join type, can either be INNER or LEFT.
|
||||
* @param string $langcode
|
||||
|
|
|
@ -204,7 +204,12 @@ class DefaultTableMapping implements TableMappingInterface {
|
|||
$column_name = count($storage_definition->getColumns()) == 1 ? $field_name : $field_name . '__' . $property_name;
|
||||
}
|
||||
elseif ($this->requiresDedicatedTableStorage($storage_definition)) {
|
||||
$column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
|
||||
if ($property_name == TableMappingInterface::DELTA) {
|
||||
$column_name = 'delta';
|
||||
}
|
||||
else {
|
||||
$column_name = !in_array($property_name, $this->getReservedColumns()) ? $field_name . '_' . $property_name : $property_name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new SqlContentEntityStorageException("Column information not available for the '$field_name' field.");
|
||||
|
|
|
@ -150,7 +150,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
* The database connection to be used.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
||||
* The cache backend to be used.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
|
|
|
@ -1837,6 +1837,24 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
}
|
||||
}
|
||||
|
||||
// Add unique keys.
|
||||
foreach ($schema['unique keys'] as $index_name => $columns) {
|
||||
$real_name = $this->getFieldIndexName($storage_definition, $index_name);
|
||||
foreach ($columns as $column_name) {
|
||||
// Unique keys can be specified as either a column name or an array with
|
||||
// column name and length. Allow for either case.
|
||||
if (is_array($column_name)) {
|
||||
$data_schema['unique keys'][$real_name][] = array(
|
||||
$table_mapping->getFieldColumnName($storage_definition, $column_name[0]),
|
||||
$column_name[1],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$data_schema['unique keys'][$real_name][] = $table_mapping->getFieldColumnName($storage_definition, $column_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add foreign keys.
|
||||
foreach ($schema['foreign keys'] as $specifier => $specification) {
|
||||
$real_name = $this->getFieldIndexName($storage_definition, $specifier);
|
||||
|
|
|
@ -19,6 +19,11 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
|||
*/
|
||||
interface TableMappingInterface {
|
||||
|
||||
/**
|
||||
* A property that represents delta used in entity query conditions.
|
||||
*/
|
||||
const DELTA = '%delta';
|
||||
|
||||
/**
|
||||
* Gets a list of table names for this mapping.
|
||||
*
|
||||
|
|
Reference in a new issue