diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsArrayFlattenUnitTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsArrayFlattenUnitTest.php new file mode 100644 index 0000000..259c5d5 --- /dev/null +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsArrayFlattenUnitTest.php @@ -0,0 +1,43 @@ + 'Options flatten array', + 'description' => 'Test multi-dimensional array is flattened.', + 'group' => 'Field types', + ); + } + + public function testArrayFlatten() { + $p = array('v1' => 'l1', 'g1' => array('v2' => 'l2', 'v3' => 'l3')); + $sub = options_array_flatten($p); + $this->assertEqual(array('v1' => 'l1', 'v2' => 'l2', 'v3' => 'l3'), $sub); + + $p = array ( + 'parent1' => array(3 => 'child1', 4 => 'child2', 5 => 'child3'), + 'parent2' => array(8 => 'child1', 9 => 'child2') + ); + $sub = options_array_flatten($p); + $this->assertEqual(array( + 3 => 'child1', 4 => 'child2', 5 => 'child3', + 8 => 'child1', 9 => 'child2'), $sub + ); + } +} diff --git a/core/modules/options/options.module b/core/modules/options/options.module index 5953ab1..9ad549b 100644 --- a/core/modules/options/options.module +++ b/core/modules/options/options.module @@ -124,3 +124,74 @@ function _options_values_in_use($entity_type, $field_name, $values) { return FALSE; } + +/** + * Implements hook_field_validate(). + * + * Possible error codes: + * - 'list_illegal_value': The value is not part of the list of allowed values. + */ +function options_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) { + // When configuring a field instance, the default value is validated without + // an entity, but options_allowed_values() and the callback it invokes + // require an entity, because the result can depend on entity type, bundle, + // and other entity data. + if (!isset($entity)) { + $ids = (object) array('entity_type' => $instance->entity_type, 'bundle' => $instance->bundle, 'entity_id' => NULL); + $entity = _field_create_entity_from_ids($ids); + } + + // Flatten the array before validating to account for optgroups. + $allowed_values = options_array_flatten(options_allowed_values($field, $instance, $entity)); + foreach ($items as $delta => $item) { + if (!empty($item['value'])) { + if (!empty($allowed_values) && !isset($allowed_values[$item['value']])) { + $errors[$field['field_name']][$langcode][$delta][] = array( + 'error' => 'list_illegal_value', + 'message' => t('%name: illegal value.', array('%name' => $instance['label'])), + ); + } + } + } +} + +/** + * Implements hook_field_is_empty(). + */ +function options_field_is_empty($item, $field_type) { + if (empty($item['value']) && (string) $item['value'] !== '0') { + return TRUE; + } + return FALSE; +} + +/** + * Implements hook_options_list(). + */ +function options_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) { + return options_allowed_values($field_definition, $entity); +} + +/** + * Flattens an array of allowed values. + * + * @param array $array + * A single or multidimensional array + * + * @return array + * A flattened array + */ +function options_array_flatten($array) { + $result = array(); + if (is_array($array)) { + foreach ($array as $key => $value) { + if (is_array($value)) { + $result += options_array_flatten($value); + } + else { + $result[$key] = $value; + } + } + } + return $result; +}