diff --git a/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php new file mode 100644 index 0000000..bada685 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinition.php @@ -0,0 +1,107 @@ +field = $field; + $this->definition = $field->getDefinition() + \Drupal::typedData()->getDefinition($field->getType()); + } + + /** + * {@inheritdoc} + */ + public function getFieldName() { + return $this->field->getName(); + } + + /** + * {@inheritdoc} + */ + public function getFieldType() { + return $this->definition['field_type']; + } + + /** + * {@inheritdoc} + */ + public function getFieldSettings() { + return $this->definition['field_settings']; + } + + /** + * {@inheritdoc} + */ + public function getFieldSetting($setting_name) { + return $this->definition['field_settings'][$setting_name]; + } + + /** + * {@inheritdoc} + */ + public function getFieldPropertyNames() { + return array_keys($this->field->getPropertyDefinitions()); + } + + /** + * {@inheritdoc} + */ + public function isFieldTranslatable() { + return !empty($this->definition['translatable']); + } + + /** + * {@inheritdoc} + */ + public function getFieldLabel() { + return $this->definition['label']; + } + + /** + * {@inheritdoc} + */ + public function getFieldDescription() { + return $this->definition['description']; + } + + /** + * {@inheritdoc} + */ + public function getFieldCardinality() { + return isset($this->definition['cardinality']) ? $this->definition['cardinality'] : 1; + } + + /** + * {@inheritdoc} + */ + public function isFieldRequired() { + return !empty($this->definition['required']); + } + +} diff --git a/core/lib/Drupal/Core/Entity/Field/FieldInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldInterface.php index c2dfbdb..4db0c48 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldInterface.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldInterface.php @@ -28,6 +28,13 @@ interface FieldInterface extends ListInterface, AccessibleInterface { /** + * Gets the field definition. + * + * @return \Drupal\Core\Entity\Field\FieldDefinitionInterface + */ + public function getFieldDefinition(); + + /** * Filters out empty field items and re-numbers the item deltas. */ public function filterEmptyValues(); diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php index d21c8cc..6e09f0b 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php @@ -37,6 +37,13 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface } /** + * {@inheritdoc} + */ + public function getFieldDefinition() { + return $this->getParent()->getFieldDefinition(); + } + + /** * Overrides \Drupal\Core\TypedData\TypedData::setValue(). * * @param array|null $values diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php index 059a477..5d380a2 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemInterface.php @@ -24,6 +24,13 @@ interface FieldItemInterface extends ComplexDataInterface { /** + * Gets the field definition. + * + * @return \Drupal\Core\Entity\Field\FieldDefinitionInterface + */ + public function getFieldDefinition(); + + /** * Magic method: Gets a property value. * * @param $property_name diff --git a/core/lib/Drupal/Core/Entity/Field/Type/Field.php b/core/lib/Drupal/Core/Entity/Field/Type/Field.php index 4d53c18..4b8186d 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/Field.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/Field.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Entity\Field\Type; +use Drupal\Core\Entity\Field\FieldDefinition; use Drupal\Core\Entity\Field\FieldInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\TypedDataInterface; @@ -37,6 +38,13 @@ class Field extends ItemList implements FieldInterface { protected $list = array(); /** + * The field definition. + * + * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface + */ + protected $fieldDefinition; + + /** * Overrides TypedData::__construct(). */ public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { @@ -51,6 +59,16 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface /** * {@inheritdoc} */ + public function getFieldDefinition() { + if (!isset($this->fieldDefinition)) { + $this->fieldDefinition = new FieldDefinition($this); + } + return $this->fieldDefinition; + } + + /** + * {@inheritdoc} + */ public function filterEmptyValues() { if (isset($this->list)) { $this->list = array_values(array_filter($this->list, function($item) { diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php index 504e427..2085618 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/FieldDataTypeDerivative.php @@ -43,6 +43,8 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { $definition['list class'] = $definition['list_class']; unset($definition['list_class']); + $definition['field_type'] = $plugin_id; + $definition['field_settings'] = $definition['instance_settings'] + $definition['settings']; $this->derivatives[$plugin_id] = $definition; } return $this->derivatives; diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php index 3134160..1e356b3 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigField.php @@ -24,6 +24,13 @@ class ConfigField extends Field implements ConfigFieldInterface { protected $instance; /** + * @todo Document. + * + * @var array + */ + protected $instances; + + /** * {@inheritdoc} */ public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) { @@ -37,9 +44,14 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface * {@inheritdoc} */ public function getInstance() { - if (!isset($this->instance) && $parent = $this->getParent()) { - $instances = FieldAPI::fieldInfo()->getBundleInstances($parent->entityType(), $parent->bundle()); - $this->instance = $instances[$this->getName()]; + if (!isset($this->instance)) { + if (!isset($this->instances) && $parent = $this->getParent()) { + $this->instances = FieldAPI::fieldInfo()->getBundleInstances($parent->entityType(), $parent->bundle()); + } + $field_name = $this->getName(); + if (isset($this->instances[$field_name])) { + $this->instance = $this->instances[$field_name]; + } } return $this->instance; } @@ -47,18 +59,25 @@ public function getInstance() { /** * {@inheritdoc} */ + public function getFieldDefinition() { + return $this->getInstance() ?: parent::getFieldDefinition(); + } + + /** + * {@inheritdoc} + */ public function getConstraints() { $constraints = array(); // Check that the number of values doesn't exceed the field cardinality. For // form submitted values, this can only happen with 'multiple value' // widgets. - $cardinality = $this->getInstance()->getField()->cardinality; + $cardinality = $this->getFieldDefinition()->getFieldCardinality(); if ($cardinality != FIELD_CARDINALITY_UNLIMITED) { $constraints[] = \Drupal::typedData() ->getValidationConstraintManager() ->create('Count', array( 'max' => $cardinality, - 'maxMessage' => t('%name: this field cannot hold more than @count values.', array('%name' => $this->getInstance()->label, '@count' => $cardinality)), + 'maxMessage' => t('%name: this field cannot hold more than @count values.', array('%name' => $this->getFieldDefinition()->getFieldLabel(), '@count' => $cardinality)), )); } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php index fa780a5..b6e70f7 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php @@ -134,7 +134,7 @@ protected function checkFieldAccess($op, $entity) { return field_access($op, $field, $entity->entityType(), $entity); } else { - return FALSE; + return TRUE; } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php index 7c2e35a..d1851f3 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php @@ -12,7 +12,8 @@ use Drupal\Core\Plugin\Discovery\CacheDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\AlterDecorator; -use Drupal\field\Plugin\Core\Entity\FieldInstance; +use Drupal\Core\Entity\Field\FieldDefinitionInterface; +use Drupal\Core\Entity\Field\FieldInterface; /** * Plugin type manager for field formatters. @@ -160,4 +161,30 @@ public function getOptions($field_type = NULL) { return $this->formatterOptions; } + /** + * @todo Document. + */ + public function viewBaseField(FieldInterface $field) { + $options = array( + 'field_definition' => $field->getFieldDefinition(), + 'view_mode' => 'default', + 'configuration' => array( + 'label' => 'hidden', + ), + ); + $formatter = $this->getInstance($options); + + $entity = $field->getParent(); + $entity_id = $entity->id(); + $langcode = $entity->language()->langcode; + $items = $field->getValue(); + + $items_multi = array($entity_id => $items); + $formatter->prepareView(array($entity_id => $entity), $langcode, $items_multi); + $items = $items_multi[$entity_id]; + + $result = $formatter->view($entity, $langcode, $items); + $field_name = $field->getName(); + return isset($result[$field_name]) ? $result[$field_name] : array(); + } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigField.php b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigField.php index ca37842..aad8af0 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigField.php +++ b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigField.php @@ -42,13 +42,14 @@ public function validate() { $entity = $this->getParent(); $langcode = $entity->language()->langcode; - if (isset($legacy_errors[$this->getInstance()->getField()->id()][$langcode])) { - foreach ($legacy_errors[$this->getInstance()->getField()->id()][$langcode] as $delta => $item_errors) { + if (isset($legacy_errors[$this->getName()][$langcode])) { + foreach ($legacy_errors[$this->getName()][$langcode] as $delta => $item_errors) { foreach ($item_errors as $item_error) { - // We do not have the information about which column triggered the - // error, so assume the first column... - $column = key($this->getInstance()->getField()->getColumns()); - $violations->add(new ConstraintViolation($item_error['message'], $item_error['message'], array(), $this, $delta . '.' . $column, $this->offsetGet($delta)->get($column)->getValue(), NULL, $item_error['error'])); + // We do not have the information about which property triggered the + // error, so assume the first one. + $property_names = $this->getFieldDefinition()->getPropertyNames(); + $property_name = $property_names[0]; + $violations->add(new ConstraintViolation($item_error['message'], $item_error['message'], array(), $this, $delta . '.' . $property_name, $this->offsetGet($delta)->get($property_name)->getValue(), NULL, $item_error['error'])); } } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php index d965401..69d9505 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php +++ b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php @@ -48,7 +48,7 @@ public function isEmpty() { $item = $this->getValue(TRUE); // The previous hook was never called on an empty item, but EntityNG always // creates a FieldItem element for an empty field. - return empty($item) || $callback($item, $this->getInstance()->getField()->type); + return empty($item) || $callback($item, $this->getFieldDefinition()->getFieldType()); } /** diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index 524036b..a248461 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -154,7 +154,7 @@ public function baseFieldDefinitions() { $properties['title'] = array( 'label' => t('Title'), 'description' => t('The title of this node, always treated as non-markup plain text.'), - 'type' => 'string_field', + 'type' => 'field_item:text', ); $properties['uid'] = array( 'label' => t('User ID'), diff --git a/core/modules/node/node.module b/core/modules/node/node.module index fbdf07d..14714cf 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1053,7 +1053,7 @@ function template_preprocess_node(&$variables) { $uri = $node->uri(); $variables['node_url'] = url($uri['path'], $uri['options']); - $variables['label'] = check_plain($node->label()); + $variables['label'] = Drupal::service('plugin.manager.field.formatter')->viewBaseField($node->getNGEntity()->title); $variables['page'] = $variables['view_mode'] == 'full' && node_is_page($node); // Helpful $content variable for templates. diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module index 526ef66..bb29703 100644 --- a/core/modules/rdf/rdf.module +++ b/core/modules/rdf/rdf.module @@ -315,7 +315,7 @@ function rdf_preprocess_node(&$variables) { $element = array( '#tag' => 'meta', '#attributes' => array( - 'content' => $variables['label'], + 'content' => $variables['node']->label(), 'about' => $variables['node_url'], ), ); diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php index 26326fc..1c79cf7 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php @@ -63,6 +63,27 @@ public static function schema(Field $field) { /** * {@inheritdoc} */ + public function getConstraints() { + $constraint_manager = \Drupal::typedData()->getValidationConstraintManager(); + $constraints = parent::getConstraints(); + + if ($max_length = $this->getFieldDefinition()->getFieldSetting('max_length')) { + $constraints[] = $constraint_manager->create('ComplexData', array( + 'value' => array( + 'Length' => array( + 'max' => $max_length, + 'maxMessage' => t('%name: the text may not be longer than @max characters.', array('%name' => $this->getFieldDefinition()->getFieldLabel(), '@max' => $max_length)), + ) + ), + )); + } + + return $constraints; + } + + /** + * {@inheritdoc} + */ public function settingsForm(array $form, array &$form_state) { $element = array(); $field = $this->getInstance()->getField(); diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php index 17f2ba3..e16f961 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php @@ -70,38 +70,17 @@ public function isEmpty() { /** * {@inheritdoc} */ - public function getConstraints() { - $constraint_manager = \Drupal::typedData()->getValidationConstraintManager(); - $constraints = parent::getConstraints(); - - if (!empty($this->getInstance()->getField()->settings['max_length'])) { - $max_length = $this->getInstance()->getField()->settings['max_length']; - $constraints[] = $constraint_manager->create('ComplexData', array( - 'value' => array( - 'Length' => array( - 'max' => $max_length, - 'maxMessage' => t('%name: the text may not be longer than @max characters.', array('%name' => $this->getInstance()->label, '@max' => $max_length)), - ) - ), - )); - } - - return $constraints; - } - - /** - * {@inheritdoc} - */ public function prepareCache() { // Where possible, generate the sanitized version of each field early so // that it is cached in the field cache. This avoids the need to look up the // field in the filter cache separately. - if (!$this->getInstance()->settings['text_processing'] || filter_format_allowcache($this->get('format')->getValue())) { + $text_processing = $this->getFieldDefinition()->getFieldSetting('text_processing'); + if (!$text_processing || filter_format_allowcache($this->get('format')->getValue())) { $itemBC = $this->getValue(); $langcode = $this->getParent()->getParent()->language()->langcode; - $this->set('safe_value', text_sanitize($this->getInstance()->settings['text_processing'], $langcode, $itemBC, 'value')); + $this->set('safe_value', text_sanitize($text_processing, $langcode, $itemBC, 'value')); if ($this->getType() == 'field_item:text_with_summary') { - $this->set('safe_summary', text_sanitize($this->getInstance()->settings['text_processing'], $langcode, $itemBC, 'summary')); + $this->set('safe_summary', text_sanitize($text_processing, $langcode, $itemBC, 'summary')); } } } diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php index 4d9030d..7aecf67 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php @@ -106,28 +106,6 @@ public function isEmpty() { /** * {@inheritdoc} */ - public function getConstraints() { - $constraint_manager = \Drupal::typedData()->getValidationConstraintManager(); - $constraints = parent::getConstraints(); - - if (!empty($this->getInstance()->getField()->settings['max_length'])) { - $max_length = $this->getInstance()->getField()->settings['max_length']; - $constraints[] = $constraint_manager->create('ComplexData', array( - 'summary' => array( - 'Length' => array( - 'max' => $max_length, - 'maxMessage' => t('%name: the summary may not be longer than @max characters.', array('%name' => $this->getInstance()->label, '@max' => $max_length)), - ) - ), - )); - } - - return $constraints; - } - - /** - * {@inheritdoc} - */ public function instanceSettingsForm(array $form, array &$form_state) { $element = array();