updated core to 7.80
This commit is contained in:
@@ -11,7 +11,7 @@ dependencies[] = field_sql_storage
|
||||
required = TRUE
|
||||
stylesheets[all][] = theme/field.css
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -7,7 +7,7 @@ dependencies[] = field
|
||||
files[] = field_sql_storage.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -434,6 +434,81 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for array_filter().
|
||||
*/
|
||||
function _field_sql_storage_write_compare_filter_callback($value) {
|
||||
return NULL !== $value && '' !== $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup field values for later values comparison.
|
||||
*
|
||||
* @param array $field
|
||||
* Field info as returned by field_info_field_by_id().
|
||||
*
|
||||
* @param array $array
|
||||
* Field values to cleanup.
|
||||
*
|
||||
* @return array
|
||||
* Filtered values.
|
||||
*/
|
||||
function _field_sql_storage_write_compare_filter($field, $array) {
|
||||
foreach ($array as $language => $items) {
|
||||
if (empty($items)) {
|
||||
unset($array[$language]);
|
||||
}
|
||||
else {
|
||||
foreach ($items as $delta => $item) {
|
||||
// This should not happen but some modules provide invalid data to the
|
||||
// field API.
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
// Let's start by pruning empty values and non storable values.
|
||||
$array[$language][$delta] = array_filter(array_intersect_key($item, $field['columns']), '_field_sql_storage_write_compare_filter_callback');
|
||||
// Ordering is important because for widget elements and loaded columns
|
||||
// from database order might differ and give false positives on field
|
||||
// value change, especially with complex fields such as image fields.
|
||||
ksort($array[$language][$delta]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a single field value for both entities and tell us if it changed.
|
||||
*
|
||||
* @param array $field
|
||||
* Loaded field structure.
|
||||
* @param object $entity1
|
||||
* First entity to compare.
|
||||
* @param object $entity2
|
||||
* Second entity to compare.
|
||||
*
|
||||
* @return bool
|
||||
* True if field value changed, false otherwise.
|
||||
*/
|
||||
function _field_sql_storage_write_compare($field, $entity1, $entity2) {
|
||||
$field_name = $field['field_name'];
|
||||
if (empty($entity1->$field_name) && empty($entity2->$field_name)) {
|
||||
// Both are empty we can safely assume that it did not change.
|
||||
return FALSE;
|
||||
}
|
||||
if (!isset($entity1->$field_name) || !isset($entity2->$field_name)) {
|
||||
// One of them is missing but not the other the value changed.
|
||||
return TRUE;
|
||||
}
|
||||
// We need to proceed to deep array comparison, but we cannot do it naively:
|
||||
// in most cases the field values come from the edit form, and some Form API
|
||||
// widget values that are not field columns may be present. We need to clean
|
||||
// up both original and new field values before comparison.
|
||||
$items1 = _field_sql_storage_write_compare_filter($field, (array) $entity1->$field_name);
|
||||
$items2 = _field_sql_storage_write_compare_filter($field, (array) $entity2->$field_name);
|
||||
return $items1 != $items2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_storage_write().
|
||||
*/
|
||||
@@ -443,8 +518,29 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel
|
||||
$vid = $id;
|
||||
}
|
||||
|
||||
// Check if the given entity is a new revision or not. In case of a new
|
||||
// revision creation, we cannot skip any field.
|
||||
if (!empty($vid) && !empty($entity->original)) {
|
||||
list(, $original_vid) = entity_extract_ids($entity_type, $entity->original);
|
||||
if (NULL === $original_vid) {
|
||||
$original_vid = $id;
|
||||
}
|
||||
$is_new_revision = $original_vid != $vid;
|
||||
}
|
||||
else {
|
||||
$is_new_revision = FALSE;
|
||||
}
|
||||
|
||||
// Allow this optimization to be optional.
|
||||
$skip_unchanged_fields = variable_get('field_sql_storage_skip_writing_unchanged_fields', FALSE);
|
||||
|
||||
foreach ($fields as $field_id) {
|
||||
$field = field_info_field_by_id($field_id);
|
||||
|
||||
if ($skip_unchanged_fields && !$is_new_revision && !empty($entity->original) && !_field_sql_storage_write_compare($field, $entity, $entity->original)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_name = $field['field_name'];
|
||||
$table_name = _field_sql_storage_tablename($field);
|
||||
$revision_name = _field_sql_storage_revision_tablename($field);
|
||||
|
@@ -281,6 +281,69 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
|
||||
$this->assertEqual($count, 1, 'NULL field translation is wiped.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the expected return values of _field_sql_storage_write_compare().
|
||||
*/
|
||||
public function testFieldCompareDataModification() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$field_info = field_info_field($this->field_name);
|
||||
|
||||
// Make sure we have 2 sample field values that are unique.
|
||||
$value1 = 0;
|
||||
$value2 = 0;
|
||||
while ($value1 == $value2) {
|
||||
$value1 = mt_rand();
|
||||
$value2 = (string) mt_rand();
|
||||
}
|
||||
|
||||
// Create the 2 entities to compare.
|
||||
$entity = field_test_create_stub_entity();
|
||||
$entity->{$this->field_name}[$langcode][]['value'] = $value1;
|
||||
$entity1 = clone $entity;
|
||||
$entity2 = clone $entity;
|
||||
|
||||
// Make sure that it correctly compares identical entities.
|
||||
$this->assert(!_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'The entities are identical.');
|
||||
|
||||
// Compare to an empty object.
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, new stdClass()), 'The entity is not the same as an empty object.');
|
||||
|
||||
// Change one of the values.
|
||||
$entity2->{$this->field_name}[$langcode][0]['value'] = $value2;
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'The values are not the same.');
|
||||
|
||||
// Reset $entity2.
|
||||
$entity2 = clone $entity;
|
||||
|
||||
// Duplicate the value on one of the entities.
|
||||
$entity1->{$this->field_name}[$langcode][]['value'] = $value1;
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'The fields do not have the same number of values.');
|
||||
|
||||
// Add a second value to both entities.
|
||||
$entity2->{$this->field_name}[$langcode][]['value'] = $value2;
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'The values are not the same.');
|
||||
|
||||
// Replace the array containing the value with the actual value.
|
||||
$entity2->{$this->field_name}[$langcode] = $entity2->{$this->field_name}[$langcode][0];
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'The array to hold field values is replaced by the value.');
|
||||
|
||||
// Null one value.
|
||||
$entity2->{$this->field_name}[$langcode] = NULL;
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'One field is NULL and the other is not.');
|
||||
|
||||
// Null both values.
|
||||
$entity1->{$this->field_name}[$langcode] = NULL;
|
||||
$this->assert(!_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'Both fields are NULL.');
|
||||
|
||||
// Unset one of the fields.
|
||||
unset($entity2->{$this->field_name});
|
||||
$this->assert(_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'One field structure is unset.');
|
||||
|
||||
// Unset both of the fields.
|
||||
unset($entity1->{$this->field_name});
|
||||
$this->assert(!_field_sql_storage_write_compare($field_info, $entity1, $entity2), 'Both field structures are unset.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test trying to update a field with data.
|
||||
*/
|
||||
@@ -313,9 +376,13 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
|
||||
$field = array('field_name' => 'test_text', 'type' => 'text', 'settings' => array('max_length' => 255));
|
||||
$field = field_create_field($field);
|
||||
|
||||
// Attempt to update the field in a way that would break the storage.
|
||||
// Attempt to update the field in a way that would break the storage. The
|
||||
// parenthesis suffix is needed because SQLite has *very* relaxed rules for
|
||||
// data types, so we actually need to provide an invalid SQL syntax in order
|
||||
// to break it.
|
||||
// @see https://www.sqlite.org/datatype3.html
|
||||
$prior_field = $field;
|
||||
$field['settings']['max_length'] = -1;
|
||||
$field['settings']['max_length'] = '-1)';
|
||||
try {
|
||||
field_update_field($field);
|
||||
$this->fail(t('Update succeeded.'));
|
||||
|
@@ -7,7 +7,7 @@ dependencies[] = field
|
||||
dependencies[] = options
|
||||
files[] = tests/list.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -5,7 +5,7 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -6,7 +6,7 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = number.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -174,7 +174,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
|
||||
),
|
||||
'display' => array(
|
||||
'default' => array(
|
||||
'type' => 'number_float',
|
||||
'type' => 'number_decimal',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@@ -6,7 +6,7 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = options.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -7,7 +7,7 @@ dependencies[] = field
|
||||
files[] = text.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -6,7 +6,7 @@ files[] = field_test.entity.inc
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2019-05-08
|
||||
version = "7.67"
|
||||
; Information added by Drupal.org packaging script on 2021-04-21
|
||||
version = "7.80"
|
||||
project = "drupal"
|
||||
datestamp = "1557336079"
|
||||
datestamp = "1619021862"
|
||||
|
@@ -240,111 +240,6 @@ function field_test_field_storage_delete_revision($entity_type, $entity, $fields
|
||||
_field_test_storage_data($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_storage_query().
|
||||
*/
|
||||
function field_test_field_storage_query($field_id, $conditions, $count, &$cursor = NULL, $age) {
|
||||
$data = _field_test_storage_data();
|
||||
|
||||
$load_current = $age == FIELD_LOAD_CURRENT;
|
||||
|
||||
$field = field_info_field_by_id($field_id);
|
||||
$field_columns = array_keys($field['columns']);
|
||||
|
||||
$field_data = $data[$field['id']];
|
||||
$sub_table = $load_current ? 'current' : 'revisions';
|
||||
// We need to sort records by entity type and entity id.
|
||||
usort($field_data[$sub_table], '_field_test_field_storage_query_sort_helper');
|
||||
|
||||
// Initialize results array.
|
||||
$return = array();
|
||||
$entity_count = 0;
|
||||
$rows_count = 0;
|
||||
$rows_total = count($field_data[$sub_table]);
|
||||
$skip = $cursor;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($field_data[$sub_table] as $row) {
|
||||
if ($count != FIELD_QUERY_NO_LIMIT && $entity_count >= $count) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($row->field_id == $field['id']) {
|
||||
$match = TRUE;
|
||||
$condition_deleted = FALSE;
|
||||
// Add conditions.
|
||||
foreach ($conditions as $condition) {
|
||||
@list($column, $value, $operator) = $condition;
|
||||
if (empty($operator)) {
|
||||
$operator = is_array($value) ? 'IN' : '=';
|
||||
}
|
||||
switch ($operator) {
|
||||
case '=':
|
||||
$match = $match && $row->{$column} == $value;
|
||||
break;
|
||||
case '<>':
|
||||
case '<':
|
||||
case '<=':
|
||||
case '>':
|
||||
case '>=':
|
||||
eval('$match = $match && ' . $row->{$column} . ' ' . $operator . ' '. $value);
|
||||
break;
|
||||
case 'IN':
|
||||
$match = $match && in_array($row->{$column}, $value);
|
||||
break;
|
||||
case 'NOT IN':
|
||||
$match = $match && !in_array($row->{$column}, $value);
|
||||
break;
|
||||
case 'BETWEEN':
|
||||
$match = $match && $row->{$column} >= $value[0] && $row->{$column} <= $value[1];
|
||||
break;
|
||||
case 'STARTS_WITH':
|
||||
case 'ENDS_WITH':
|
||||
case 'CONTAINS':
|
||||
// Not supported.
|
||||
$match = FALSE;
|
||||
break;
|
||||
}
|
||||
// Track condition on 'deleted'.
|
||||
if ($column == 'deleted') {
|
||||
$condition_deleted = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Exclude deleted data unless we have a condition on it.
|
||||
if (!$condition_deleted && $row->deleted) {
|
||||
$match = FALSE;
|
||||
}
|
||||
|
||||
if ($match) {
|
||||
if (!isset($skip) || $skipped >= $skip) {
|
||||
$cursor++;
|
||||
// If querying all revisions and the entity type has revisions, we need
|
||||
// to key the results by revision_ids.
|
||||
$entity_type = entity_get_info($row->type);
|
||||
$id = ($load_current || empty($entity_type['entity keys']['revision'])) ? $row->entity_id : $row->revision_id;
|
||||
|
||||
if (!isset($return[$row->type][$id])) {
|
||||
$return[$row->type][$id] = entity_create_stub_entity($row->type, array($row->entity_id, $row->revision_id, $row->bundle));
|
||||
$entity_count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$skipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
$rows_count++;
|
||||
|
||||
// The query is complete if we walked the whole array.
|
||||
if ($count != FIELD_QUERY_NO_LIMIT && $rows_count >= $rows_total) {
|
||||
$cursor = FIELD_QUERY_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort helper for field_test_field_storage_query().
|
||||
*
|
||||
@@ -455,13 +350,13 @@ function field_test_field_attach_rename_bundle($bundle_old, $bundle_new) {
|
||||
function field_test_field_attach_delete_bundle($entity_type, $bundle, $instances) {
|
||||
$data = _field_test_storage_data();
|
||||
|
||||
foreach ($instances as $field_name => $instance) {
|
||||
$field = field_info_field($field_name);
|
||||
foreach ($instances as $instance) {
|
||||
$field = field_info_field_by_id($instance['field_id']);
|
||||
if ($field['storage']['type'] == 'field_test_storage') {
|
||||
$field_data = &$data[$field['id']];
|
||||
foreach (array('current', 'revisions') as $sub_table) {
|
||||
foreach ($field_data[$sub_table] as &$row) {
|
||||
if ($row->bundle == $bundle_old) {
|
||||
if ($row->bundle == $bundle) {
|
||||
$row->deleted = TRUE;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user