diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php index 52bf9c9d23..3735ef358e 100644 --- a/core/lib/Drupal/Core/Field/FieldItemList.php +++ b/core/lib/Drupal/Core/Field/FieldItemList.php @@ -397,7 +397,51 @@ public function equals(FieldItemListInterface $list_to_compare) { array_walk($value1, $callback); array_walk($value2, $callback); - return $value1 == $value2; + return $this->arrayEquals($value1, $value2); + } + + /** + * Compares multidimensional arrays. + * + * Please pay attention, + * it uses soft rules for comparision of scalar values inside of the arrays. + * + * @param array $array1 + * The array to compare to. + * @param array $array2 + * The array to compare to. + * + * @return bool + * TRUE if arrays are equal, FALSE if not. + */ + protected function arrayEquals(array $array1, array $array2) { + $result = TRUE; + + foreach ($array1 as $key => $value) { + if (!array_key_exists($key, $array2)) { + return FALSE; + } + if (is_array($value)) { + if (!is_array($array2[$key]) || !$this->arrayEquals($value, $array2[$key])) { + return FALSE; + } + } + elseif (gettype($array2[$key]) === gettype($value)) { + if ($array2[$key] !== $value) { + return FALSE; + } + } + elseif (is_bool($array2[$key]) || is_bool($value)){ + if ($array2[$key] != $value) { + return FALSE; + } + } + elseif ((string) $array2[$key] !== (string) $value) { + return FALSE; + } + } + + return $result; } } diff --git a/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php b/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php index 83a0854dfb..913625e137 100644 --- a/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php +++ b/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php @@ -133,6 +133,76 @@ public function providerTestEquals() { // not exist ('3'). $datasets[] = [TRUE, $field_item_h, $field_item_i]; + /** @var \Drupal\Core\Field\FieldItemBase $field_item_j */ + $field_item_j = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_j->setValue(['+2']); + + // Tests field item lists where both have same values but different data + // types with leading plus. + $datasets[] = [FALSE, $field_item_e, $field_item_j]; + + // Tests field item lists where both have different data type + // and different data. + $datasets[] = [FALSE, $field_item_b, $field_item_j]; + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_k */ + $field_item_k = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_k->setValue(['02']); + + // Tests field item lists where string values differ. + $datasets[] = [FALSE, $field_item_j, $field_item_k]; + + // Tests field item lists where both have different data type + // and different data. + $datasets[] = [FALSE, $field_item_b, $field_item_k]; + + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_j */ + $field_item_l = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_l->setValue([true]); + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_k */ + $field_item_m = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_m->setValue(['true']); + + // Tests field item lists where converted to string values differ. + //$datasets[] = [FALSE, $field_item_l, $field_item_m]; + // Tests field item lists where boolean converted to string values differ. + $datasets[] = [TRUE, $field_item_l, $field_item_m]; + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_j */ + $field_item_n = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_n->setValue([false]); + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_k */ + $field_item_o = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_o->setValue([0]); + + // Tests field item lists where converted to string values differ. + $datasets[] = [TRUE, $field_item_n, $field_item_o]; + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_j */ + $field_item_p = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_p->setValue(['1']); + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_k */ + $field_item_r = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_r->setValue([1]); + + // Tests field item lists where boolean compared with text is equal. + $datasets[] = [TRUE, $field_item_l, $field_item_p]; + // Tests field item lists where boolean compared with int is equal. + $datasets[] = [TRUE, $field_item_l, $field_item_r]; + + /** @var \Drupal\Core\Field\FieldItemBase $field_item_k */ + $field_item_s = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE); + $field_item_s->setValue(['']); + + // Tests field item lists where boolean compared with text is equal. + $datasets[] = [TRUE, $field_item_n, $field_item_s]; + // Tests field item lists where boolean compared with int differs. + $datasets[] = [FALSE, $field_item_o, $field_item_s]; + return $datasets; }