diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index 0e786bd..408caa2 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -379,7 +379,7 @@ public function getConstraints($definition) { // definition for performing interface checks. $class = isset($definition['class']) ? $definition['class'] : $type_definition['class']; // Check if the class provides allowed values. - if (array_key_exists('Drupal\Core\TypedData\AllowedValuesInterface', class_implements($class))) { + if (array_key_exists('Drupal\Core\TypedData\AllowedValuesInterface', class_implements($class)) && array_key_exists('Drupal\Core\TypedData\PrimitiveInterface', class_implements($class))) { $constraints[] = $validation_manager->create('AllowedValues', array()); } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php new file mode 100644 index 0000000..3997007 --- /dev/null +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/field_type/TaxonomyTermReferenceItem.php @@ -0,0 +1,213 @@ +flattenOptions($this->getPossibleOptions($account)); + return array_keys($flatten_options); + } + + /** + * {@inheritdoc} + */ + public function getPossibleOptions(AccountInterface $account = NULL) { + return $this->getSettableOptions($account); + } + + /** + * {@inheritdoc} + */ + public function getSettableValues(AccountInterface $account = NULL) { + // Flatten options firstly, because Settable Options may contain group + // arrays. + $flatten_options = $this->flattenOptions($this->getSettableOptions($account)); + return array_keys($flatten_options); + } + + /** + * {@inheritdoc} + */ + public function getSettableOptions(AccountInterface $account = NULL) { + $instance = $this->getFieldDefinition(); + $entity = $this->getParent()->getParent(); + $function = $this->getFieldSetting('options_list_callback') ?: 'taxonomy_allowed_values'; + return $function($instance, $entity); + } + + /** + * {@inheritdoc} + */ + public function getPropertyDefinitions() { + $this->definition['settings']['target_type'] = 'taxonomy_term'; + return parent::getPropertyDefinitions(); + } + + /** + * {@inheritdoc} + */ + public static function schema(FieldInterface $field) { + return array( + 'columns' => array( + 'target_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), + ), + 'indexes' => array( + 'target_id' => array('target_id'), + ), + 'foreign keys' => array( + 'target_id' => array( + 'table' => 'taxonomy_term_data', + 'columns' => array('target_id' => 'tid'), + ), + ), + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, array &$form_state, $has_data) { + // Get proper values for 'allowed_values_function', which is a core setting. + $vocabularies = entity_load_multiple('taxonomy_vocabulary'); + $options = array(); + foreach ($vocabularies as $vocabulary) { + $options[$vocabulary->id()] = $vocabulary->name; + } + + $settings = $this->getFieldSettings(); + $element = array(); + $element['#tree'] = TRUE; + + foreach ($settings['allowed_values'] as $delta => $tree) { + $element['allowed_values'][$delta]['vocabulary'] = array( + '#type' => 'select', + '#title' => t('Vocabulary'), + '#default_value' => $tree['vocabulary'], + '#options' => $options, + '#required' => TRUE, + '#description' => t('The vocabulary which supplies the options for this field.'), + '#disabled' => $has_data, + ); + $element['allowed_values'][$delta]['parent'] = array( + '#type' => 'value', + '#value' => $tree['parent'], + ); + } + + return $element; + } + + /** + * {@inheritdoc} + */ + public function instanceSettingsForm(array $form, array &$form_state) { + return; + } + + /** + * {@inheritdoc} + */ + public function isEmpty() { + $target_id = $this->get('target_id')->getValue(); + $entity = $this->get('entity')->getValue(); + return (empty($target_id) && empty($entity)); + } + + /** + * {@inheritdoc} + */ + public function preSave() { + $target_id = $this->get('target_id')->getValue(); + $entity = $this->get('entity')->getValue(); + if (!$target_id) { + $this->entity = $entity->save(); + $this->target_id = $entity->id(); + } + } + + /** + * {@inheritdoc} + * + * Taxonomy field settings allow for either a single vocabulary ID, multiple + * vocabulary IDs, or sub-trees of a vocabulary to be specified as allowed + * values, although only the first of these is supported via the field UI. + * Confirm that terms entered as values meet at least one of these conditions. + */ + public function getConstraints() { + $constraint_manager = \Drupal::typedData()->getValidationConstraintManager(); + $constraints = parent::getConstraints(); + + $target_id = $this->get('target_id')->getValue(); + $instance = $this->getFieldDefinition(); + if (!empty($target_id) && $target_id != 'autocreate') { + $constraints[] = $constraint_manager->create('ComplexData', array( + 'target_id' => array( + 'AllowedValues' => array( + 'message' => t('%name: illegal value.', array('%name' => $instance['label'])), + ), + ), + )); + } + return $constraints; + } + + /** + * Flattens an array of allowed values. + * + * @param array $array + * A single or multidimensional array. + * + * @return array + * The flattened array. + */ + protected function flattenOptions(array $array) { + $result = array(); + array_walk_recursive($array, function($a, $b) use (&$result) { $result[$b] = $a; }); + return $result; + } + +} diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php deleted file mode 100644 index 21c210b..0000000 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php +++ /dev/null @@ -1,34 +0,0 @@ -definition['settings']['target_type'] = 'taxonomy_term'; - return parent::getPropertyDefinitions(); - } - -} diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install index 7648ba0..429b029 100644 --- a/core/modules/taxonomy/taxonomy.install +++ b/core/modules/taxonomy/taxonomy.install @@ -182,30 +182,6 @@ function taxonomy_schema() { } /** - * Implements hook_field_schema(). - */ -function taxonomy_field_schema($field) { - return array( - 'columns' => array( - 'target_id' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => FALSE, - ), - ), - 'indexes' => array( - 'target_id' => array('target_id'), - ), - 'foreign keys' => array( - 'target_id' => array( - 'table' => 'taxonomy_term_data', - 'columns' => array('target_id' => 'tid'), - ), - ), - ); -} - -/** * Implements hook_update_dependencies(). */ function taxonomy_update_dependencies() { diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 0827bef..4ca5676 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -858,38 +858,6 @@ function taxonomy_implode_tags($tags, $vid = NULL) { } /** - * Implements hook_field_info(). - * - * Field settings: - * - allowed_values: a list array of one or more vocabulary trees: - * - vocabulary: a vocabulary machine name. - * - parent: a term ID of a term whose children are allowed. This should be - * '0' if all terms in a vocabulary are allowed. The allowed values do not - * include the parent term. - * - */ -function taxonomy_field_info() { - return array( - 'taxonomy_term_reference' => array( - 'label' => t('Term reference'), - 'description' => t('This field stores a reference to a taxonomy term.'), - 'default_widget' => 'options_select', - 'default_formatter' => 'taxonomy_term_reference_link', - 'class' => 'Drupal\taxonomy\Type\TaxonomyTermReferenceItem', - 'settings' => array( - 'options_list_callback' => NULL, - 'allowed_values' => array( - array( - 'vocabulary' => '', - 'parent' => '0', - ), - ), - ), - ), - ); -} - -/** * Implements hook_field_widget_info_alter(). */ function taxonomy_field_widget_info_alter(&$info) { @@ -898,80 +866,6 @@ function taxonomy_field_widget_info_alter(&$info) { } /** - * Implements hook_options_list(). - */ -function taxonomy_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) { - $function = $field_definition->getFieldSetting('options_list_callback') ?: 'taxonomy_allowed_values'; - return $function($field_definition, $entity); -} - -/** - * Implements hook_field_validate(). - * - * Taxonomy field settings allow for either a single vocabulary ID, multiple - * vocabulary IDs, or sub-trees of a vocabulary to be specified as allowed - * values, although only the first of these is supported via the field UI. - * Confirm that terms entered as values meet at least one of these conditions. - * - * Possible error codes: - * - 'taxonomy_term_illegal_value': The value is not part of the list of allowed values. - */ -function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) { - // Build an array of existing term IDs so they can be loaded with - // entity_load_multiple('taxonomy_term'); - foreach ($items as $delta => $item) { - if (!empty($item['target_id']) && $item['target_id'] != 'autocreate') { - $tids[] = $item['target_id']; - } - } - if (!empty($tids)) { - $terms = entity_load_multiple('taxonomy_term', $tids); - - // Check each existing item to ensure it can be found in the - // allowed values for this field. - foreach ($items as $delta => $item) { - $validate = TRUE; - if (!empty($item['target_id']) && $item['target_id'] != 'autocreate') { - $validate = FALSE; - foreach ($field['settings']['allowed_values'] as $settings) { - // If no parent is specified, check if the term is in the vocabulary. - if (isset($settings['vocabulary']) && empty($settings['parent'])) { - if ($settings['vocabulary'] == $terms[$item['target_id']]->bundle()) { - $validate = TRUE; - break; - } - } - // If a parent is specified, then to validate it must appear in the - // array returned by taxonomy_term_load_parents_all(). - elseif (!empty($settings['parent'])) { - $ancestors = taxonomy_term_load_parents_all($item['target_id']); - foreach ($ancestors as $ancestor) { - if ($ancestor->id() == $settings['parent']) { - $validate = TRUE; - break 2; - } - } - } - } - } - if (!$validate) { - $errors[$field['field_name']][$langcode][$delta][] = array( - 'error' => 'taxonomy_term_reference_illegal_value', - 'message' => t('%name: illegal value.', array('%name' => $instance['label'])), - ); - } - } - } -} - -/** - * Implements hook_field_is_empty(). - */ -function taxonomy_field_is_empty($item, $field_type) { - return !is_array($item) || (empty($item['target_id']) && empty($item['entity'])); -} - -/** * Returns the set of valid terms for a taxonomy field. * * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition @@ -1023,39 +917,6 @@ function taxonomy_autocomplete_validate($element, &$form_state) { } /** - * Implements hook_field_settings_form(). - */ -function taxonomy_field_settings_form($field, $instance) { - // Get proper values for 'allowed_values_function', which is a core setting. - $vocabularies = entity_load_multiple('taxonomy_vocabulary'); - $options = array(); - foreach ($vocabularies as $vocabulary) { - $options[$vocabulary->id()] = $vocabulary->name; - } - $form['allowed_values'] = array( - '#tree' => TRUE, - ); - - foreach ($field['settings']['allowed_values'] as $delta => $tree) { - $form['allowed_values'][$delta]['vocabulary'] = array( - '#type' => 'select', - '#title' => t('Vocabulary'), - '#default_value' => $tree['vocabulary'], - '#options' => $options, - '#required' => TRUE, - '#description' => t('The vocabulary which supplies the options for this field.'), - '#disabled' => $field->hasData(), - ); - $form['allowed_values'][$delta]['parent'] = array( - '#type' => 'value', - '#value' => $tree['parent'], - ); - } - - return $form; -} - -/** * @defgroup taxonomy_index Taxonomy indexing * @{ * Functions to maintain taxonomy indexing. @@ -1074,20 +935,6 @@ function taxonomy_field_settings_form($field, $instance) { */ /** - * Implements hook_field_presave(). - * - * Create any new terms defined in a freetagging vocabulary. - */ -function taxonomy_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) { - foreach ($items as $delta => $item) { - if (!$item['target_id'] && isset($item['target_id'])) { - $item['entity']->save(); - $items[$delta]['target_id'] = $item['entity']->id(); - } - } -} - -/** * Implements hook_node_insert(). */ function taxonomy_node_insert(EntityInterface $node) {