diff -u b/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc --- b/core/modules/field/field.crud.inc +++ b/core/modules/field/field.crud.inc @@ -169,10 +169,13 @@ // Conditions. foreach ($params as $key => $value) { if ($key == 'storage.active') { - $checked_value = $field['storage']['active']; + $checked_value = $field->storage['active']; + } + elseif ($key == 'field_name') { + $checked_value = $field->id; } else { - $checked_value = $field[$key]; + $checked_value = $field->$key; } if ($checked_value != $value) { continue 2; @@ -182,11 +185,8 @@ // Invoke read field. module_invoke_all('field_read_field', $field); - $field_name = $field['field_name']; - if ($include_deleted) { - $field_name = $field['uuid']; - } - $fields[$field_name] = $field; + $key = $include_deleted ? $field->uuid : $field->id; + $fields[$key] = $field; } return $fields; } diff -u b/core/modules/field/field.install b/core/modules/field/field.install --- b/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -361,7 +361,6 @@ $config = array( 'id' => $field['field_name'], 'uuid' => $uuid->generate(), - 'field_name' => $field['field_name'], 'type' => $field['type'], 'module' => $field['module'], 'active' => $field['active'], @@ -408,8 +407,7 @@ $config = array( 'id' => $instance['entity_type'] . '.' . $instance['bundle'] . '.' . $instance['field_name'], 'uuid' => $uuid->generate(), - 'field_id' => $field_uuids[$instance['field_id']], - 'field_name' => $instance['field_name'], + 'field_uuid' => $field_uuids[$instance['field_id']], 'entity_type' => $instance['entity_type'], 'bundle' => $instance['bundle'], 'label' => $instance['data']['label'], @@ -437,7 +435,7 @@ // Update file_usage table in case this instance has a default image. if (!empty($config['settings']['default_image'])) { db_update('file_usage') - ->fields(array('id' => $config['field_id'])) + ->fields(array('id' => $config['field_uuid'])) ->condition('fid', $config['settings']['default_image']) ->execute(); } diff -u b/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php --- b/core/modules/field/lib/Drupal/field/FieldInfo.php +++ b/core/modules/field/lib/Drupal/field/FieldInfo.php @@ -146,18 +146,19 @@ foreach (config_get_storage_names_with_prefix('field.field') as $config_id) { $field_config = config($config_id)->get(); if ($field_config['active'] && $field_config['storage']['active']) { - $fields[$field_config['field_name']] = $field_config; + $fields[$field_config['uuid']] = $field_config; } } // Get field instances. foreach (config_get_storage_names_with_prefix('field.instance') as $config_id) { $instance_config = config($config_id)->get(); - $field_name = $instance_config['field_name']; + $field_uuid = $instance_config['field_uuid']; // Filter out instances of inactive fields, and instances on unknown // entity types. - if (isset($fields[$field_name])) { - $map[$field_name]['bundles'][$instance_config['entity_type']][] = $instance_config['bundle']; - $map[$field_name]['type'] = $fields[$field_name]['type']; + if (isset($fields[$field_uuid])) { + $field = $fields[$field_uuid]; + $map[$field['id']]['bundles'][$instance_config['entity_type']][] = $instance_config['bundle']; + $map[$field['id']]['type'] = $field['type']; } } @@ -197,7 +198,7 @@ // Fill the name/ID map. foreach ($this->fieldsById as $field) { if (!$field['deleted']) { - $this->fieldIdsByName[$field['field_name']] = $field['uuid']; + $this->fieldIdsByName[$field['id']] = $field['uuid']; } } diff -u b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php --- b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php @@ -48,13 +48,6 @@ public $uuid; /** - * The field name. - * - * @var string - */ - public $field_name; - - /** * The field type. * * @var string @@ -153,15 +146,18 @@ if (empty($values['type'])) { throw new FieldException('Attempt to create a field with no type.'); } - if (empty($values['field_name'])) { + // Temporary BC layer: accept both 'id' and 'field_name'. + if (empty($values['field_name']) && empty($values['id'])) { throw new FieldException('Attempt to create an unnamed field.'); } - if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $values['field_name'])) { + if (empty($values['id'])) { + $values['id'] = $values['field_name']; + unset($values['field_name']); + } + if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $values['id'])) { throw new FieldException('Attempt to create a field with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character'); } - $this->id = $values['field_name']; - // Provide defaults. $values += array( 'settings' => array(), @@ -185,7 +181,6 @@ 'uuid', 'status', 'langcode', - 'field_name', 'type', 'settings', 'module', @@ -218,24 +213,24 @@ // Field name cannot be longer than 32 characters. We use drupal_strlen() // because the DB layer assumes that column widths are given in characters, // not bytes. - if (drupal_strlen($this->field_name) > 32) { - throw new FieldException(format_string('Attempt to create a field with a name longer than 32 characters: %name', array('%name' => $this->field_name))); + if (drupal_strlen($this->id) > 32) { + throw new FieldException(format_string('Attempt to create a field with an ID longer than 32 characters: %id', array('%id' => $this->id))); } // Ensure the field name is unique (we do not care about deleted fields). if ($prior_field = current($storage_controller->load(array($this->id)))) { $message = $prior_field->active ? - 'Attempt to create field name %name which already exists and is active.' : - 'Attempt to create field name %name which already exists, although it is inactive.'; - throw new FieldException(format_string($message, array('%name' => $this->field_name))); + 'Attempt to create field name %id which already exists and is active.' : + 'Attempt to create field name %id which already exists, although it is inactive.'; + throw new FieldException(format_string($message, array('%id' => $this->id))); } // Disallow reserved field names. This can't prevent all field name // collisions with existing entity properties, but some is better // than none. foreach (\Drupal::service('plugin.manager.entity')->getDefinitions() as $type => $info) { - if (in_array($this->field_name, $info['entity_keys'])) { - throw new FieldException(format_string('Attempt to create field name %name which is reserved by entity type %type.', array('%name' => $this->field_name, '%type' => $type))); + if (in_array($this->id, $info['entity_keys'])) { + throw new FieldException(format_string('Attempt to create field %id which is reserved by entity type %type.', array('%id' => $this->id, '%type' => $type))); } } @@ -324,7 +319,7 @@ $instance_ids = array(); foreach ($this->getBundles() as $entity_type => $bundles) { foreach ($bundles as $bundle) { - $instance_ids[] = "$entity_type.$bundle.$this->field_name"; + $instance_ids[] = "$entity_type.$bundle.$this->id"; } } foreach ($instance_controller->load($instance_ids) as $instance) { @@ -402,8 +397,8 @@ public function getBundles() { if (empty($this->deleted)) { $map = field_info_field_map(); - if (isset($map[$this->field_name]['bundles'])) { - return $map[$this->field_name]['bundles']; + if (isset($map[$this->id]['bundles'])) { + return $map[$this->id]['bundles']; } } return array(); @@ -421,6 +416,12 @@ */ public function &offsetGet($offset) { switch ($offset) { + case 'id': + return $this->uuid; + + case 'field_name': + return $this->id; + case 'columns': $this->getSchema(); return $this->schema['columns']; diff -u b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php --- b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php @@ -38,25 +38,26 @@ public $id; /** - * The field UUID. + * The instance UUID. * * @var string */ public $uuid; /** - * The field name. + * The field UUID. * * @var string */ - public $field_name; + public $field_uuid; /** - * The instance field id. + * The field name. + * @todo Revisit that in favor of a getField() method. * * @var string */ - public $field_id; + public $field_name; /** * The instance entity type. @@ -140,9 +141,6 @@ */ public function __construct(array $values, $entity_type) { // Check required properties. - if (empty($values['field_name'])) { - throw new FieldException('Attempt to create an instance of an unspecified field.'); - } if (empty($values['entity_type'])) { throw new FieldException(format_string('Attempt to create an instance of field @field_name without an entity type.', array('@field_name' => $values['field_name']))); } @@ -150,6 +148,33 @@ throw new FieldException(format_string('Attempt to create an instance of field @field_name without a bundle.', array('@field_name' => $values['field_name']))); } + // Accept incoming 'field_name' instead of 'field_uuid', for easier DX on + // creation of new instances. + if (isset($values['field_name']) && !isset($values['field_uuid'])) { + $field = field_info_field($values['field_name']); + if ($field) { + $values['field_uuid'] = $field->uuid; + } + else { + throw new FieldException(format_string('Attempt to create an instance of unknown, disabled or deleted field @name', array('@name' => $values['field_name']))); + } + } + // Fill in the field_name property for data coming out of config. + // @todo Revisit that in favor of a getField() method. + elseif (isset($values['field_uuid']) && !isset($values['field_name'])) { + $field = current(field_read_fields(array('uuid' => $values['field_uuid']), array('include_inactive' => TRUE, 'include_deleted' => TRUE))); + if ($field) { + $values['field_name'] = $field->id; + } + else { + throw new FieldException(format_string('Attempt to create an instance of unknown field @uuid', array('@uuid' => $values['field_uuid']))); + } + } + + if (empty($values['field_uuid'])) { + throw new FieldException('Attempt to create an instance of an unspecified field.'); + } + // Provide defaults. $values += array( 'label' => $values['field_name'], @@ -173,8 +198,7 @@ 'uuid', 'status', 'langcode', - 'field_name', - 'field_id', + 'field_uuid', 'entity_type', 'bundle', 'label', @@ -205,7 +229,7 @@ if ($this->isNew()) { if (empty($field)) { - throw new FieldException(format_string("Attempt to save an instance of a field @field_name that doesn't exist or is currently inactive.", array('@field_name' => $this->field_name))); + throw new FieldException(format_string("Attempt to save an instance of a field @field_id that doesn't exist or is currently inactive.", array('@field_name' => $this->field_name))); } // Check that the field can be attached to this entity type. if (!empty($field->entity_types) && !in_array($this->entity_type, $field->entity_types)) { @@ -221,7 +245,7 @@ } // Set the field uuid. - $this->field_id = $field->uuid; + $this->field_uuid = $field->uuid; $hook = 'field_create_instance'; $hook_args = array($this); @@ -238,7 +262,7 @@ if ($this->bundle != $original->bundle) { throw new FieldException("Cannot change an existing instance's bundle."); } - if ($this->field_name != $original->field_name || $this->field_id != $original->field_id) { + if ($this->field_name != $original->field_name || $this->field_uuid != $original->field_uuid) { throw new FieldException("Cannot change an existing instance's field."); } @@ -330,7 +354,7 @@ $context = array( 'entity_type' => $this->entity_type, 'bundle' => $this->bundle, - 'field' => field_info_field($this->field_name), + 'field' => field_info_field_by_id($this->field_uuid), 'instance' => $this, ); drupal_alter(array('field_widget_properties', 'field_widget_properties_' . $this->entity_type), $widget_properties, $context); @@ -351,13 +375,16 @@ * Implements ArrayAccess::offsetExists(). */ public function offsetExists($offset) { - return isset($this->{$offset}); + return (isset($this->{$offset}) || $offset == 'field_id'); } /** * Implements ArrayAccess::offsetGet(). */ public function &offsetGet($offset) { + if ($offset == 'field_id') { + return $this->field_uuid; + } return $this->{$offset}; } @@ -365,6 +392,9 @@ * Implements ArrayAccess::offsetSet(). */ public function offsetSet($offset, $value) { + if ($offset == 'field_id') { + $offset = 'field_uuid'; + } $this->{$offset} = $value; } @@ -372,6 +402,9 @@ * Implements ArrayAccess::offsetUnset(). */ public function offsetUnset($offset) { + if ($offset == 'field_id') { + $offset = 'field_uuid'; + } unset($this->{$offset}); } diff -u b/core/modules/field/tests/modules/field_test_config/config/field.field.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.field.field_test_import.yml --- b/core/modules/field/tests/modules/field_test_config/config/field.field.field_test_import.yml +++ b/core/modules/field/tests/modules/field_test_config/config/field.field.field_test_import.yml @@ -1,7 +1,6 @@ id: field_test_import uuid: fb38277f-1fd4-49d5-8d09-9d7037fdcce9 langcode: und -field_name: field_test_import type: text settings: max_length: '255' diff -u b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml --- b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml +++ b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml @@ -1,8 +1,7 @@ id: test_entity.test_bundle.field_test_import uuid: 392b4e9d-6157-412e-9603-3d622512f498 langcode: und -field_name: field_test_import -field_id: fb38277f-1fd4-49d5-8d09-9d7037fdcce9 +field_uuid: fb38277f-1fd4-49d5-8d09-9d7037fdcce9 entity_type: test_entity bundle: test_bundle label: 'Test import field' diff -u b/core/modules/field/tests/modules/field_test_config/staging/field.field.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.field_test_import_staging.yml --- b/core/modules/field/tests/modules/field_test_config/staging/field.field.field_test_import_staging.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.field_test_import_staging.yml @@ -1,7 +1,6 @@ id: field_test_import_staging uuid: 0bf654cc-f14a-4881-b94c-76959e47466b langcode: und -field_name: field_test_import_staging type: text settings: max_length: '255' diff -u b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml --- b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml @@ -1,8 +1,7 @@ id: test_entity.test_bundle.field_test_import_staging uuid: ea711065-6940-47cd-813d-618f64095481 langcode: und -field_name: field_test_import_staging -field_id: 0bf654cc-f14a-4881-b94c-76959e47466b +field_uuid: 0bf654cc-f14a-4881-b94c-76959e47466b entity_type: test_entity bundle: test_bundle label: 'Import from staging'