diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 566b2cc..7681bd4 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -194,7 +194,7 @@ public function processDefinition(&$definition, $plugin_id) { // Prepare entity schema fields SQL info for // Drupal\Core\Entity\DatabaseStorageControllerInterface::buildQuery(). - if (isset($definition['base_table'])) { + if (isset($definition['base_table']) && drupal_get_schema($definition['base_table']) !== FALSE) { $definition['schema_fields_sql']['base_table'] = drupal_schema_fields_sql($definition['base_table']); if (isset($definition['data_table'])) { $definition['schema_fields_sql']['data_table'] = drupal_schema_fields_sql($definition['data_table']); diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php index 27dbfa1..1069273 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php @@ -278,7 +278,7 @@ function testBlock() { // Check to see if the block was created by checking its configuration. $instance = entity_load('block', $block['theme'] . '.' . $block['machine_name']); - $this->assertEqual($instance->label(), $block['label'], 'Stored block title found.'); + $this->assertEqual($instance['label'](), $block['label'], 'Stored block title found.'); // Check whether the block can be moved to all available regions. foreach ($this->regions as $region) { diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index 48bb5a4..2c6d416 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -16,7 +16,7 @@ function comment_uninstall() { variable_del('comment_block_count'); $node_types = array_keys(node_type_get_types()); foreach ($node_types as $node_type) { - field_attach_delete_bundle('comment', 'comment_node_' . $node_type); + field_attach_delete_bundle('comment', 'comment_node_' . $node_type, FALSE); variable_del('comment_' . $node_type); variable_del('comment_anonymous_' . $node_type); variable_del('comment_controls_' . $node_type); diff --git a/core/modules/datetime/datetime.install b/core/modules/datetime/datetime.install index df1ed81..e0362a8 100644 --- a/core/modules/datetime/datetime.install +++ b/core/modules/datetime/datetime.install @@ -21,21 +21,3 @@ function datetime_field_schema($field) { ); return array('columns' => $db_columns, 'indexes' => $indexes); } - -/** - * Install the new to D8 Datetime module. - * - * As part of adding this new module to Drupal 8, the Datetime namespace is now - * reserved for this module. This is a possible conflict with a popular contrib - * field DateTime that existed in D7. Hence, any Datetime fields that may have - * existed prior to D8 need to renamed for later upgrade by contrib modules like - * the Date module. - */ -function datetime_install() { - db_update('field_config') - ->fields(array( - 'type' => 'datetime_old', - )) - ->condition('type', 'datetime') - ->execute(); -} diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module index 79905f8..a7d6958 100644 --- a/core/modules/datetime/datetime.module +++ b/core/modules/datetime/datetime.module @@ -274,7 +274,7 @@ function datetime_default_value($entity, $field, $instance, $langcode) { $value = ''; $date = ''; - if ($instance['settings']['default_value'] == 'now') { + if ($instance['default_value'] == 'now') { // A default value should be in the format and timezone used for date // storage. $date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE); diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php index 57f2bfc..cdfdff4 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php @@ -12,7 +12,7 @@ use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\field\Plugin\PluginSettingsBase; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\datetime\DateHelper; diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php index 479c613..997cebf 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php @@ -12,7 +12,7 @@ use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\field\Plugin\PluginSettingsBase; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\Core\Datetime\DrupalDateTime; /** diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php index 232d019..b74684f 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php +++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php @@ -53,7 +53,7 @@ function setUp() { 'type' => 'datetime', 'settings' => array('datetime_type' => 'date'), ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -65,7 +65,7 @@ function setUp() { 'default_value' => 'blank', ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); $this->display_options = array( 'type' => 'datetime_default', @@ -285,7 +285,7 @@ function testDefaultValue() { field_update_field($this->field); // Set the default value to 'now'. - $this->instance['settings']['default_value'] = 'now'; + $this->instance['default_value'] = 'now'; $this->instance['default_value_function'] = 'datetime_default_value'; field_update_instance($this->instance); @@ -303,7 +303,7 @@ function testDefaultValue() { $this->assertNoFieldByName("{$this->field['field_name']}[$langcode][0][value][time]", '', 'Time element found.'); // Set the default value to 'blank'. - $this->instance['settings']['default_value'] = 'blank'; + $this->instance['default_value'] = 'blank'; field_update_instance($this->instance); // Display creation form. diff --git a/core/modules/edit/lib/Drupal/edit/EditorBase.php b/core/modules/edit/lib/Drupal/edit/EditorBase.php index d2e4d09..a0844d1 100644 --- a/core/modules/edit/lib/Drupal/edit/EditorBase.php +++ b/core/modules/edit/lib/Drupal/edit/EditorBase.php @@ -9,7 +9,7 @@ use Drupal\Component\Plugin\PluginBase; use Drupal\edit\EditorInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Defines a base editor (Create.js PropertyEditor widget) implementation. diff --git a/core/modules/edit/lib/Drupal/edit/EditorInterface.php b/core/modules/edit/lib/Drupal/edit/EditorInterface.php index 251233a..df4c7f9 100644 --- a/core/modules/edit/lib/Drupal/edit/EditorInterface.php +++ b/core/modules/edit/lib/Drupal/edit/EditorInterface.php @@ -8,7 +8,7 @@ namespace Drupal\edit; use Drupal\Component\Plugin\PluginInspectionInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Defines an interface for in-place editors (Create.js PropertyEditor widgets). diff --git a/core/modules/edit/lib/Drupal/edit/EditorSelector.php b/core/modules/edit/lib/Drupal/edit/EditorSelector.php index 131eea2..fe71340 100644 --- a/core/modules/edit/lib/Drupal/edit/EditorSelector.php +++ b/core/modules/edit/lib/Drupal/edit/EditorSelector.php @@ -9,7 +9,7 @@ use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Utility\NestedArray; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Selects an in-place editor (an Editor plugin) for a field. diff --git a/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php b/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php index 2c180cd..926c7a6 100644 --- a/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php +++ b/core/modules/edit/lib/Drupal/edit/EditorSelectorInterface.php @@ -7,7 +7,7 @@ namespace Drupal\edit; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Interface for selecting an in-place editor (an Editor plugin) for a field. diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php index 3ec8ce2..3e7dd21 100644 --- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php +++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Component\Plugin\PluginManagerInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\edit\Access\EditEntityFieldAccessCheckInterface; diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php b/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php index 2b6b1d8..71e447d 100644 --- a/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php +++ b/core/modules/edit/lib/Drupal/edit/MetadataGeneratorInterface.php @@ -8,7 +8,7 @@ namespace Drupal\edit; use Drupal\Core\Entity\EntityInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Interface for generating in-place editing metadata for an entity field. diff --git a/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/DirectEditor.php b/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/DirectEditor.php index 0a386c5..95f75d9 100644 --- a/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/DirectEditor.php +++ b/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/DirectEditor.php @@ -9,7 +9,7 @@ use Drupal\edit\EditorBase; use Drupal\Core\Annotation\Plugin; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Defines the "direct" Create.js PropertyEditor widget. diff --git a/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/FormEditor.php b/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/FormEditor.php index 59e8d67..d1bec24 100644 --- a/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/FormEditor.php +++ b/core/modules/edit/lib/Drupal/edit/Plugin/edit/editor/FormEditor.php @@ -9,7 +9,7 @@ use Drupal\edit\EditorBase; use Drupal\Core\Annotation\Plugin; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Defines the "form" Create.js PropertyEditor widget. diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php index c3a91fb..0ffe89f 100644 --- a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php +++ b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php @@ -29,7 +29,6 @@ function setUp() { parent::setUp(); $this->installSchema('system', 'variable'); - $this->installSchema('field', array('field_config', 'field_config_instance')); $this->installSchema('field_test', 'test_entity'); // Set default storage backend. @@ -59,12 +58,12 @@ function setUp() { */ function createFieldWithInstance($field_name, $type, $cardinality, $label, $instance_settings, $widget_type, $widget_settings, $formatter_type, $formatter_settings) { $field = $field_name . '_field'; - $this->$field = array( + $field_definition = array( 'field_name' => $field_name, 'type' => $type, 'cardinality' => $cardinality, ); - $this->$field_name = field_create_field($this->$field); + $this->$field = field_create_field($field_definition); $instance = $field_name . '_instance'; $this->$instance = array( @@ -81,7 +80,7 @@ function createFieldWithInstance($field_name, $type, $cardinality, $label, $inst 'settings' => $widget_settings, ), ); - field_create_instance($this->$instance); + $this->$instance = field_create_instance($this->$instance); entity_get_display('test_entity', 'test_bundle', 'default') ->setComponent($field_name, array( diff --git a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/edit/editor/WysiwygEditor.php b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/edit/editor/WysiwygEditor.php index 943848f..50ec9e2 100644 --- a/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/edit/editor/WysiwygEditor.php +++ b/core/modules/edit/tests/modules/lib/Drupal/edit_test/Plugin/edit/editor/WysiwygEditor.php @@ -9,7 +9,7 @@ use Drupal\edit\EditorBase; use Drupal\Core\Annotation\Plugin; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Defines the "wysiwyg" Create.js PropertyEditor widget. diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php index c719c97..8586ace 100644 --- a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php +++ b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php @@ -49,7 +49,7 @@ function testEmailField() { 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'email', ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php index 3396f89..ca5ad67 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php @@ -24,12 +24,6 @@ public static function getInfo() { ); } - protected function setUp() { - parent::setUp(); - - $this->installSchema('field', array('field_config', 'field_config_instance')); - } - /** * Tests basic CRUD operations on EntityDisplay objects. */ diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php index 70961b0..bbfd6bf 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php @@ -57,7 +57,7 @@ function setUp() { ), ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('node', 'article', 'default') ->setComponent($this->instance['field_name'], array( 'type' => 'entity_reference_label', diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php index cf1c619..cfa678d 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php @@ -58,7 +58,7 @@ protected function assertReferencable($field, $instance, $tests, $handler_name) */ public function testNodeHandler() { // Build a fake field instance. - $field = array( + $field = entity_create('field_entity', array( 'translatable' => FALSE, 'entity_types' => array(), 'settings' => array( @@ -67,15 +67,15 @@ public function testNodeHandler() { 'field_name' => 'test_field', 'type' => 'entity_reference', 'cardinality' => '1', - ); - $instance = array( + )); + $instance = entity_create('field_instance', array( 'settings' => array( 'handler' => 'default', 'handler_settings' => array( 'target_bundles' => array(), ), ), - ); + )); // Build a set of test data. // Titles contain HTML-special characters to test escaping. @@ -196,7 +196,7 @@ public function testNodeHandler() { */ public function testUserHandler() { // Build a fake field instance. - $field = array( + $field = entity_create('field_entity', array( 'translatable' => FALSE, 'entity_types' => array(), 'settings' => array( @@ -205,15 +205,15 @@ public function testUserHandler() { 'field_name' => 'test_field', 'type' => 'entity_reference', 'cardinality' => '1', - ); - $instance = array( + )); + $instance = entity_create('field_instance', array( 'settings' => array( 'handler' => 'default', 'handler_settings' => array( 'target_bundles' => array(), ), ), - ); + )); // Build a set of test data. $user_values = array( @@ -336,7 +336,7 @@ public function testUserHandler() { */ public function testCommentHandler() { // Build a fake field instance. - $field = array( + $field = entity_create('field_entity', array( 'translatable' => FALSE, 'entity_types' => array(), 'settings' => array( @@ -345,15 +345,15 @@ public function testCommentHandler() { 'field_name' => 'test_field', 'type' => 'entity_reference', 'cardinality' => '1', - ); - $instance = array( + )); + $instance = entity_create('field_instance', array( 'settings' => array( 'handler' => 'default', 'handler_settings' => array( 'target_bundles' => array(), ), ), - ); + )); // Build a set of test data. $node_values = array( diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php index cc768e2..ba6790c 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php @@ -55,7 +55,7 @@ public function testSort() { // Build a fake field instance. - $field = array( + $field = entity_create('field_entity', array( 'translatable' => FALSE, 'entity_types' => array(), 'settings' => array( @@ -64,9 +64,9 @@ public function testSort() { 'field_name' => 'test_field', 'type' => 'entity_reference', 'cardinality' => 1, - ); + )); - $instance = array( + $instance = entity_create('field_instance', array( 'settings' => array( 'handler' => 'default', 'handler_settings' => array( @@ -78,7 +78,7 @@ public function testSort() { ), ), ), - ); + )); // Build a set of test data. $node_values = array( diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php index 6998209..e601121 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php @@ -40,7 +40,7 @@ public function testSelectionHandler() { } // Build a fake field instance. - $field = array( + $field = entity_create('field_entity', array( 'translatable' => FALSE, 'entity_types' => array(), 'settings' => array( @@ -49,8 +49,8 @@ public function testSelectionHandler() { 'field_name' => 'test_field', 'type' => 'entity_reference', 'cardinality' => '1', - ); - $instance = array( + )); + $instance = entity_create('field_instance', array( 'settings' => array( 'handler' => 'views', 'handler_settings' => array( @@ -62,7 +62,7 @@ public function testSelectionHandler() { ), ), ), - ); + )); // Get values from selection handler. $handler = entity_reference_get_selection_handler($field, $instance); diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 29112ef..7c0f8b4 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -1055,7 +1055,7 @@ function hook_field_attach_delete_revision(\Drupal\Core\Entity\EntityInterface $ */ function hook_field_attach_purge(\Drupal\Core\Entity\EntityInterface $entity, $field, $instance) { // find the corresponding data in mymodule and purge it - if ($entity->entityType() == 'node' && $field->field_name == 'my_field_name') { + if ($entity->entityType() == 'node' && $field['field_name'] == 'my_field_name') { mymodule_remove_mydata($entity->nid); } } diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 69102f4..455f320 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -1170,7 +1170,7 @@ function field_attach_insert(EntityInterface $entity) { $storages = array(); foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) { $field = field_info_field_by_id($instance['field_id']); - $field_id = $field['id']; + $field_id = $field['uuid']; $field_name = $field['field_name']; if (!empty($entity->$field_name)) { // Collect the storage backend if the field has not been written yet. @@ -1211,7 +1211,7 @@ function field_attach_update(EntityInterface $entity) { $storages = array(); foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) { $field = field_info_field_by_id($instance['field_id']); - $field_id = $field['id']; + $field_id = $field['uuid']; $field_name = $field['field_name']; // Leave the field untouched if $entity comes with no $field_name property, // but empty the field if it comes as a NULL value or an empty array. @@ -1254,7 +1254,7 @@ function field_attach_delete(EntityInterface $entity) { $storages = array(); foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) { $field = field_info_field_by_id($instance['field_id']); - $field_id = $field['id']; + $field_id = $field['uuid']; $storages[$field['storage']['type']][$field_id] = $field_id; } @@ -1287,7 +1287,7 @@ function field_attach_delete_revision(EntityInterface $entity) { $storages = array(); foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) { $field = field_info_field_by_id($instance['field_id']); - $field_id = $field['id']; + $field_id = $field['uuid']; $storages[$field['storage']['type']][$field_id] = $field_id; } @@ -1549,11 +1549,17 @@ function field_attach_create_bundle($entity_type, $bundle) { * The new name of the bundle. */ function field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) { - db_update('field_config_instance') - ->fields(array('bundle' => $bundle_new)) - ->condition('entity_type', $entity_type) - ->condition('bundle', $bundle_old) - ->execute(); + $instances = field_read_instances(); + foreach ($instances as $id => $instance) { + if ($instance['entity_type'] == $entity_type && $instance['bundle'] == $bundle_old) { + $new_instance_id = $instance['entity_type'] . '.' . $bundle_new . '.' . $instance['field_name']; + config('field.instance.' . $instance['entity_type'] . '.' . $bundle_old . '.' . $instance['field_name'])->rename('field.instance.' . $new_instance_id); + config('field.instance.' . $instance['entity_type'] . '.' . $bundle_new . '.' . $instance['field_name']) + ->set('bundle', $bundle_new) + ->set('id', $new_instance_id) + ->save(); + } + } // Clear the cache. field_cache_clear(); @@ -1569,7 +1575,7 @@ function field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) { } /** - * Notifies field.module the a bundle was deleted. + * Notifies field.module that a bundle was deleted. * * This deletes the data for the field instances as well as the field instances * themselves. This function actually just marks the data and field instances as @@ -1582,14 +1588,18 @@ function field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) { * The entity type to which the bundle is bound. * @param $bundle * The bundle to delete. + * @param $field_cleanup + * If TRUE, the field will be deleted as well if its last instance is being + * deleted. If FALSE, it is the caller's responsibility to handle the case of + * fields left without instances. Defaults to TRUE. */ -function field_attach_delete_bundle($entity_type, $bundle) { +function field_attach_delete_bundle($entity_type, $bundle, $field_cleanup = TRUE) { // First, delete the instances themselves. field_read_instances() must be // used here since field_info_instances() does not return instances for // disabled entity types or bundles. $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_inactive' => 1)); foreach ($instances as $instance) { - field_delete_instance($instance); + field_delete_instance($instance, $field_cleanup); } // Clear the cache. diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc index f6ee8a2..0bbf81f 100644 --- a/core/modules/field/field.crud.inc +++ b/core/modules/field/field.crud.inc @@ -29,7 +29,7 @@ * field_create_instance() for that. * * @param $field - * A field definition array. The field_name and type properties are required. + * A field definition. The field_name and type properties are required. * Other properties, if omitted, will be given the following default values: * - cardinality: 1 * - locked: FALSE @@ -49,13 +49,20 @@ * hook_field_storage_info(). * * @return - * The $field array with the id property filled in. + * The $field entity. * * @throws Drupal\field\FieldException * * See: @link field Field API data structures @endlink. */ function field_create_field($field) { + + // Module developers can still pass in an array of properties + // into field_create_field(). + if (is_array($field)) { + $field = entity_create('field_entity', $field); + } + // Field name is required. if (empty($field['field_name'])) { throw new FieldException('Attempt to create an unnamed field.'); @@ -81,7 +88,7 @@ function field_create_field($field) { // We do not care about deleted fields. $prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE)); if (!empty($prior_field)) { - $message = $prior_field['active']? + $message = $prior_field['active'] ? t('Attempt to create field name %name which already exists and is active.', array('%name' => $field['field_name'])): t('Attempt to create field name %name which already exists, although it is inactive.', array('%name' => $field['field_name'])); throw new FieldException($message); @@ -96,16 +103,27 @@ function field_create_field($field) { } } - $field += array( + $defaults = array( 'entity_types' => array(), 'cardinality' => 1, 'translatable' => FALSE, - 'locked' => FALSE, 'settings' => array(), - 'storage' => array(), + 'bundles' => array(), + 'entity_types' => array(), + 'locked' => FALSE, 'deleted' => 0, + 'storage' => array(), + 'indexes' => array(), + 'foreign_keys' => array(), ); + // @todo This is set by entity_create right ? + foreach ($defaults as $key => $value) { + if (!isset($field[$key])) { + $field[$key] = $value; + } + } + // Check that the field type is known. $field_type = field_info_field_types($field['type']); if (!$field_type) { @@ -131,6 +149,9 @@ function field_create_field($field) { $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']); $field['storage']['module'] = $storage_type['module']; $field['storage']['active'] = 1; + $field['storage_type'] = $field['storage']['type']; + $field['storage_module'] = $storage_type['module']; + $field['storage_active'] = 1; // Collect storage information. module_load_install($field['module']); $schema = (array) module_invoke($field['module'], 'field_schema', $field); @@ -141,60 +162,34 @@ function field_create_field($field) { throw new FieldException(t('Illegal field type columns.')); } // 'foreign keys' are hardcoded in the field type. - $field['foreign keys'] = $schema['foreign keys']; + $field['foreign_keys'] = $schema['foreign keys']; // 'indexes' can be both hardcoded in the field type, and specified in the // incoming $field definition. - $field += array( - 'indexes' => array(), - ); $field['indexes'] += $schema['indexes']; - // The serialized 'data' column contains everything from $field that does not - // have its own column and is not automatically populated when the field is - // read. - $data = $field; - unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']); // Additionally, do not save the 'bundles' property populated by // field_info_field(). - unset($data['bundles']); - - $record = array( - 'field_name' => $field['field_name'], - 'type' => $field['type'], - 'module' => $field['module'], - 'active' => $field['active'], - 'storage_type' => $field['storage']['type'], - 'storage_module' => $field['storage']['module'], - 'storage_active' => $field['storage']['active'], - 'locked' => $field['locked'], - 'data' => $data, - 'cardinality' => $field['cardinality'], - 'translatable' => $field['translatable'], - 'deleted' => $field['deleted'], - ); + $field['bundles'] = array(); - // Store the field and get the id back. - drupal_write_record('field_config', $record); - $field['id'] = $record['id']; + // Save the configuration. + $field['id'] = $field['field_name']; + $field->save(); // Invoke hook_field_storage_create_field after the field is // complete (e.g. it has its id). try { - // Invoke hook_field_storage_create_field after - // drupal_write_record() sets the field id. + // Invoke hook_field_storage_create_field. module_invoke($storage_type['module'], 'field_storage_create_field', $field); } catch (Exception $e) { // If storage creation failed, remove the field_config record before // rethrowing the exception. - db_delete('field_config') - ->condition('id', $field['id']) - ->execute(); + entity_delete_multiple('field_entity', array($field['field_name'])); throw $e; } // Clear caches - field_cache_clear(TRUE); + field_cache_clear(); // Invoke external hooks after the cache is cleared for API consistency. module_invoke_all('field_create_field', $field); @@ -224,6 +219,32 @@ function field_create_field($field) { * @see field_create_field() */ function field_update_field($field) { + + // Module developers can still pass in an array of properties + // into field_update_field(). + if (is_array($field)) { + $field_loaded = entity_load('field_entity', $field['field_name']); + if (empty($field_loaded)) { + throw new FieldException('Attempt to update a non-existent field.'); + } + // Override settings + // @todo should we make updating a field completely different ? + foreach ($field as $key => $value) { + if (is_array($value)) { + if ($key == 'indexes') { + $field_loaded[$key] = $value; + } + else { + $field_loaded[$key] += $value; + } + } + else { + $field_loaded[$key] = $value; + } + } + $field = $field_loaded; + } + // Check that the specified field exists. $prior_field = field_read_field($field['field_name']); if (empty($prior_field)) { @@ -231,8 +252,7 @@ function field_update_field($field) { } // Use the prior field values for anything not specifically set by the new - // field to be sure that all values are set. - $field += $prior_field; + // field to be sure that all values are set. // @todo remove ? $field['settings'] += $prior_field['settings']; // Some updates are always disallowed. @@ -255,9 +275,9 @@ function field_update_field($field) { $field['columns'] = $schema['columns']; // 'indexes' can be both hardcoded in the field type, and specified in the // incoming $field definition. - $field += array( - 'indexes' => array(), - ); + if (!isset($field['indexes'])) { + $field['indexes'] = array(); + } $field['indexes'] += $schema['indexes']; $has_data = field_has_data($field); @@ -276,23 +296,15 @@ function field_update_field($field) { // Save the new field definition. @todo: refactor with // field_create_field. - // The serialized 'data' column contains everything from $field that does not - // have its own column and is not automatically populated when the field is - // read. - $data = $field; - unset($data['columns'], $data['field_name'], $data['type'], $data['locked'], $data['module'], $data['cardinality'], $data['active'], $data['deleted']); // Additionally, do not save the 'bundles' property populated by // field_info_field(). - unset($data['bundles']); + $field['bundles'] = array(); - $field['data'] = $data; - - // Store the field and create the id. - $primary_key = array('id'); - drupal_write_record('field_config', $field, $primary_key); + // Save the configuration. + $field->save(); // Clear caches - field_cache_clear(TRUE); + field_cache_clear(); // Invoke external hooks after the cache is cleared for API consistency. module_invoke_all('field_update_field', $field, $prior_field, $has_data); @@ -342,53 +354,38 @@ function field_read_field($field_name, $include_additional = array()) { * field ID, otherwise it is keyed by field name. */ function field_read_fields($params = array(), $include_additional = array()) { - $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC)); - $query->fields('fc'); - - // Turn the conditions into a query. - foreach ($params as $key => $value) { - // Allow filtering on the 'entity_type' and 'bundle' columns of the - // field_config_instance table. - if ($key == 'entity_type' || $key == 'bundle') { - if (empty($fci_join)) { - $fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id'); - } - $key = 'fci.' . $key; - } - else { - $key = 'fc.' . $key; - } + $fields = array(); - $query->condition($key, $value); + // Check if we need to retrieve deleted fields. + $include_deleted = (isset($include_additional['include_deleted']) && $include_additional['include_deleted']) || (isset($params['deleted']) && $params['deleted']); + if ($include_deleted) { + $deleted_fields = state()->get('field.field.deleted') ?: array(); } + // Add active and storage active parameters. if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) { - $query - ->condition('fc.active', 1) - ->condition('fc.storage_active', 1); + $params['active'] = 1; + $params['storage_active'] = 1; } - $include_deleted = (isset($include_additional['include_deleted']) && $include_additional['include_deleted']); - if (!$include_deleted) { - $query->condition('fc.deleted', 0); + + // Get configuration fields. + $config_fields = entity_load_multiple('field_entity'); + + // Merge deleted fields. + if (!empty($deleted_fields)) { + $config_fields += $deleted_fields; } - $fields = array(); - $results = $query->execute(); - foreach ($results as $record) { - $field = unserialize($record['data']); - $field['id'] = $record['id']; - $field['field_name'] = $record['field_name']; - $field['type'] = $record['type']; - $field['module'] = $record['module']; - $field['active'] = $record['active']; - $field['storage']['type'] = $record['storage_type']; - $field['storage']['module'] = $record['storage_module']; - $field['storage']['active'] = $record['storage_active']; - $field['locked'] = $record['locked']; - $field['cardinality'] = $record['cardinality']; - $field['translatable'] = $record['translatable']; - $field['deleted'] = $record['deleted']; + foreach ($config_fields as $field) { + // Conditions. + foreach ($params as $key => $value) { + if ($field[$key] != $value) { + continue 2; + } + } + + // Invoke read field. module_invoke_all('field_read_field', $field); // Populate storage information. @@ -399,7 +396,7 @@ function field_read_fields($params = array(), $include_additional = array()) { $field_name = $field['field_name']; if ($include_deleted) { - $field_name = $field['id']; + $field_name = $field['uuid']; } $fields[$field_name] = $field; } @@ -415,6 +412,7 @@ function field_read_fields($params = array(), $include_additional = array()) { function field_delete_field($field_name) { // Delete all non-deleted instances. $field = field_info_field($field_name); + if (isset($field['bundles'])) { foreach ($field['bundles'] as $entity_type => $bundles) { foreach ($bundles as $bundle) { @@ -427,14 +425,17 @@ function field_delete_field($field_name) { // Mark field data for deletion. module_invoke($field['storage']['module'], 'field_storage_delete_field', $field); - // Mark the field for deletion. - db_update('field_config') - ->fields(array('deleted' => 1)) - ->condition('field_name', $field_name) - ->execute(); + // Delete the configuration of this field and save the field configuration + // in the key_value table so we can use it later during field_purge_batch(). + // This makes sure a new field can be created immediately with the same name. + $deleted_fields = state()->get('field.field.deleted') ?: array(); + $field['deleted'] = TRUE; + $deleted_fields[$field['uuid']] = $field; + state()->set('field.field.deleted', $deleted_fields); + entity_delete_multiple('field_entity', array($field['field_name'])); // Clear the cache. - field_cache_clear(TRUE); + field_cache_clear(); module_invoke_all('field_delete_field', $field); } @@ -474,7 +475,14 @@ function field_delete_field($field_name) { * * See: @link field Field API data structures @endlink. */ -function field_create_instance(&$instance) { +function field_create_instance($instance) { + + // Module developers can still pass in an array of properties + // into field_create_instance(). + if (is_array($instance)) { + $instance = entity_create('field_instance', $instance); + } + $field = field_read_field($instance['field_name']); if (empty($field)) { throw new FieldException(t("Attempt to create an instance of a field @field_name that doesn't exist or is currently inactive.", array('@field_name' => $instance['field_name']))); @@ -492,7 +500,7 @@ function field_create_instance(&$instance) { } // Set the field id. - $instance['field_id'] = $field['id']; + $instance['field_id'] = $field['uuid']; // Note that we do *not* prevent creating a field on non-existing bundles, // because that would break the 'Body as field' upgrade for contrib @@ -542,6 +550,27 @@ function field_create_instance(&$instance) { * @see field_create_instance() */ function field_update_instance($instance) { + + // Module developers can still pass in an array of properties + // into field_update_instance(). + if (is_array($instance)) { + $instance_loaded = entity_load('field_instance', $instance['entity_type'] . '.' . $instance['bundle'] . '.' . $instance['field_name']); + if (empty($instance_loaded)) { + throw new FieldException('Attempt to update a non-existent instance.'); + } + // Override settings + // @todo should we make updating a instance completely different ? + foreach ($instance as $key => $value) { + if (is_array($value)) { + $instance_loaded[$key] += $value; + } + else { + $instance_loaded[$key] = $value; + } + } + $instance = $instance_loaded; + } + // Check that the specified field exists. $field = field_read_field($instance['field_name']); if (empty($field)) { @@ -555,10 +584,7 @@ function field_update_instance($instance) { throw new FieldException(t("Attempt to update an instance of field @field on bundle @bundle that doesn't exist.", array('@field' => $instance['field_name'], '@bundle' => $instance['bundle']))); } - $instance['id'] = $prior_instance['id']; - $instance['field_id'] = $prior_instance['field_id']; - - _field_write_instance($instance, TRUE); + _field_write_instance($instance); // Clear caches. field_cache_clear(); @@ -571,23 +597,13 @@ function field_update_instance($instance) { * * @param $instance * An instance structure. - * @param $update - * Whether this is a new or existing instance. */ -function _field_write_instance(&$instance, $update = FALSE) { +function _field_write_instance($instance) { $field = field_read_field($instance['field_name']); $field_type = field_info_field_types($field['type']); - // Temporary workaround to allow incoming $instance as arrays or classed - // objects. - // @todo remove once the external APIs have been converted to use - // FieldInstance objects. - if (is_object($instance) && get_class($instance) == 'Drupal\field\FieldInstance') { - $instance = $instance->getArray(); - } - // Set defaults. - $instance += array( + $defaults = array( 'settings' => array(), 'widget' => array(), 'required' => FALSE, @@ -595,10 +611,15 @@ function _field_write_instance(&$instance, $update = FALSE) { 'description' => '', 'deleted' => 0, ); + // @todo check if these are set by entity_create() (I guess so). + foreach ($defaults as $key => $value) { + if (!isset($instance[$key])) { + $instance[$key] = $value; + } + } // Set default instance settings. $instance['settings'] += field_info_instance_settings($field['type']); - // Set default widget and settings. $instance['widget'] += array( // TODO: what if no 'default_widget' specified ? @@ -615,30 +636,12 @@ function _field_write_instance(&$instance, $update = FALSE) { $instance['widget']['module'] = $widget_type['module']; $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']); - // The serialized 'data' column contains everything from $instance that does - // not have its own column and is not automatically populated when the - // instance is read. - $data = $instance; - unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']); - - $record = array( - 'field_id' => $instance['field_id'], - 'field_name' => $instance['field_name'], - 'entity_type' => $instance['entity_type'], - 'bundle' => $instance['bundle'], - 'data' => $data, - 'deleted' => $instance['deleted'], - ); - // We need to tell drupal_update_record() the primary keys to trigger an - // update. - if ($update) { - $record['id'] = $instance['id']; - drupal_write_record('field_config_instance', $record, array('id')); - } - else { - drupal_write_record('field_config_instance', $record); - $instance['id'] = $record['id']; + if (!isset($instance['id'])) { + $instance['id'] = $instance['entity_type'] . '.' . $instance['bundle'] . '.' . $instance['field_name']; } + + // Save into config. + $instance->save(); } /** @@ -673,8 +676,8 @@ function field_read_instance($entity_type, $field_name, $bundle, $include_additi * * @param $param * An array of properties to use in selecting a field instance. Valid keys - * include any column of the field_config_instance table. If NULL, all - * instances will be returned. + * include any property of the instance config object, except for data. + * If NULL, all instances will be returned. * @param $include_additional * The default behavior of this function is to not return field instances that * have been marked deleted, or whose field is inactive. Setting @@ -685,44 +688,66 @@ function field_read_instance($entity_type, $field_name, $bundle, $include_additi * An array of instances matching the arguments. */ function field_read_instances($params = array(), $include_additional = array()) { - $include_inactive = isset($include_additional['include_inactive']) && $include_additional['include_inactive']; - $include_deleted = isset($include_additional['include_deleted']) && $include_additional['include_deleted']; + $instances = array(); - $query = db_select('field_config_instance', 'fci', array('fetch' => PDO::FETCH_ASSOC)); - $query->join('field_config', 'fc', 'fc.id = fci.field_id'); - $query->fields('fci'); + $deleted_fields = state()->get('field.field.deleted'); + $include_inactive = isset($include_additional['include_inactive']) && $include_additional['include_inactive']; + $include_deleted = (isset($include_additional['include_deleted']) && $include_additional['include_deleted']) || (isset($params['deleted']) && $params['deleted']); - // Turn the conditions into a query. - foreach ($params as $key => $value) { - $query->condition('fci.' . $key, $value); + if ($include_deleted) { + $deleted_instances = state()->get('field.instance.deleted') ?: array(); } - if (!$include_inactive) { - $query - ->condition('fc.active', 1) - ->condition('fc.storage_active', 1); - } - if (!$include_deleted) { - $query->condition('fc.deleted', 0); - $query->condition('fci.deleted', 0); + + // Get configuration instances. + $config_instances = entity_load_multiple('field_instance'); + // Merge deleted instances. + if (!empty($deleted_instances)) { + $config_instances += $deleted_instances; } - $instances = array(); - $results = $query->execute(); + foreach ($config_instances as $instance) { + + $entity_info = entity_get_info($instance['entity_type']); + + // Get data from the field. If the field is marked as deleted, we + // need to get it from the state storage. + $field = entity_load('field_entity', $instance['field_name']); + if ($include_deleted) { + if (empty($field) && isset($deleted_fields[$instance['field_id']])) { + $field = $deleted_fields[$instance['field_id']]; + } + } + if (empty($field)) { + continue; + } + + // @todo do we really need this ? + $instance['active'] = $field['active']; + $instance['locked'] = $field['locked']; + $instance['type'] = $field['type']; + $instance['module'] = $field['module']; + $instance['storage_type'] = $field['storage']['type']; + $instance['storage_active'] = $field['storage']['active']; + $instance['storage_module'] = $field['storage']['module']; - foreach ($results as $record) { - // Filter out instances on unknown entity types (for instance because the - // module exposing them was disabled). - $entity_info = entity_get_info($record['entity_type']); if ($include_inactive || $entity_info) { - $instance = unserialize($record['data']); - $instance['id'] = $record['id']; - $instance['field_id'] = $record['field_id']; - $instance['field_name'] = $record['field_name']; - $instance['entity_type'] = $record['entity_type']; - $instance['bundle'] = $record['bundle']; - $instance['deleted'] = $record['deleted']; + // Conditions. + if (!$include_inactive) { + $params['active'] = 1; + $params['storage_active'] = 1; + } + if (!$include_deleted) { + $params['deleted'] = 0; + } + foreach ($params as $key => $value) { + if ($instance[$key] != $value) { + continue 2; + } + } + // Invoke read instance. module_invoke_all('field_read_instance', $instance); + $instances[] = $instance; } } @@ -740,13 +765,14 @@ function field_read_instances($params = array(), $include_additional = array()) * fields left without instances. Defaults to TRUE. */ function field_delete_instance($instance, $field_cleanup = TRUE) { - // Mark the field instance for deletion. - db_update('field_config_instance') - ->fields(array('deleted' => 1)) - ->condition('field_name', $instance['field_name']) - ->condition('entity_type', $instance['entity_type']) - ->condition('bundle', $instance['bundle']) - ->execute(); + + // Delete the configuration of this instance and save the configuration + // in the key_value table so we can use it later during field_purge_batch(). + $deleted_instances = state()->get('field.instance.deleted') ?: array(); + $instance['deleted'] = TRUE; + $deleted_instances[$instance['uuid']] = $instance; + state()->set('field.instance.deleted', $deleted_instances); + entity_delete_multiple('field_instance', array($instance['entity_type'] . '.' . $instance['bundle'] . '.' . $instance['field_name'])); // Clear the cache. field_cache_clear(); @@ -866,7 +892,7 @@ function field_purge_batch($batch_size) { $field = field_info_field_by_id($instance['field_id']); // Retrieve some entities. $query = $factory->get($entity_type) - ->condition('id:' . $field['id'] . '.deleted', 1) + ->condition('id:' . $field['uuid'] . '.deleted', 1) ->range(0, $batch_size); // If there's no bundle key, all results will have the same bundle. if (!empty($info[$entity_type]['entity_keys']['bundle'])) { @@ -884,7 +910,7 @@ function field_purge_batch($batch_size) { $ids->entity_id = $entity_id; $entities[$entity_id] = _field_create_entity_from_ids($ids); } - field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); + field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['uuid'], 'deleted' => 1)); foreach ($entities as $entity) { // Purge the data for the entity. field_purge_data($entity, $field, $instance); @@ -897,9 +923,9 @@ function field_purge_batch($batch_size) { } // Retrieve all deleted fields. Any that have no instances can be purged. - $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => 1)); - foreach ($fields as $field) { - $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1)); + $deleted_fields = state()->get('field.field.deleted') ?: array(); + foreach ($deleted_fields as $field) { + $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1)); if (empty($instances)) { field_purge_field($field); } @@ -946,14 +972,14 @@ function field_purge_data(EntityInterface $entity, $field, $instance) { * The instance record to purge. */ function field_purge_instance($instance) { - db_delete('field_config_instance') - ->condition('id', $instance['id']) - ->execute(); - // Notify the storage engine. $field = field_info_field_by_id($instance['field_id']); module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance); + $deleted_instances = state()->get('field.instance.deleted'); + unset($deleted_instances[$instance['uuid']]); + state()->set('field.instance.deleted', $deleted_instances); + // Clear the cache. field_info_cache_clear(); @@ -971,14 +997,14 @@ function field_purge_instance($instance) { * The field record to purge. */ function field_purge_field($field) { - $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1)); + $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1)); if (count($instances) > 0) { throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field['field_name']))); } - db_delete('field_config') - ->condition('id', $field['id']) - ->execute(); + $deleted_fields = state()->get('field.field.deleted'); + unset($deleted_fields[$field['uuid']]); + state()->set('field.field.deleted', $deleted_fields); // Notify the storage engine. module_invoke($field['storage']['module'], 'field_storage_purge_field', $field); diff --git a/core/modules/field/field.info b/core/modules/field/field.info index c74da0e..3c6c5fb 100644 --- a/core/modules/field/field.info +++ b/core/modules/field/field.info @@ -3,5 +3,4 @@ description = Field API to add fields to entities like nodes and users. package = Core version = VERSION core = 8.x -dependencies[] = field_sql_storage required = TRUE diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc index b422b47..4ec8bfe 100644 --- a/core/modules/field/field.info.inc +++ b/core/modules/field/field.info.inc @@ -5,7 +5,7 @@ * Field Info API, providing information about available fields and field types. */ -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\field\FieldInfo; /** diff --git a/core/modules/field/field.install b/core/modules/field/field.install index 695fd89..acd265d 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -5,162 +5,13 @@ * Install, update, and uninstall functions for the Field module. */ +use Drupal\Component\Uuid\Uuid; + /** * Implements hook_schema(). */ function field_schema() { - // Static (meta) tables. - $schema['field_config'] = array( - 'fields' => array( - 'id' => array( - 'type' => 'serial', - 'not null' => TRUE, - 'description' => 'The primary identifier for a field', - ), - 'field_name' => array( - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'description' => 'The name of this field. Non-deleted field names are unique, but multiple deleted fields can have the same name.', - ), - 'type' => array( - 'type' => 'varchar', - 'length' => 128, - 'not null' => TRUE, - 'description' => 'The type of this field.', - ), - 'module' => array( - 'type' => 'varchar', - 'length' => 128, - 'not null' => TRUE, - 'default' => '', - 'description' => 'The module that implements the field type.', - ), - 'active' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Boolean indicating whether the module that implements the field type is enabled.', - ), - 'storage_type' => array( - 'type' => 'varchar', - 'length' => 128, - 'not null' => TRUE, - 'description' => 'The storage backend for the field.', - ), - 'storage_module' => array( - 'type' => 'varchar', - 'length' => 128, - 'not null' => TRUE, - 'default' => '', - 'description' => 'The module that implements the storage backend.', - ), - 'storage_active' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Boolean indicating whether the module that implements the storage backend is enabled.', - ), - 'locked' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - 'description' => '@TODO', - ), - 'data' => array( - 'type' => 'blob', - 'size' => 'big', - 'not null' => TRUE, - 'serialize' => TRUE, - 'description' => 'Serialized data containing the field properties that do not warrant a dedicated column.', - ), - 'cardinality' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - 'translatable' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - 'deleted' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - ), - 'primary key' => array('id'), - 'indexes' => array( - 'field_name' => array('field_name'), - // Used by field_read_fields(). - 'active' => array('active'), - 'storage_active' => array('storage_active'), - 'deleted' => array('deleted'), - // Used by field_sync_field_status(). - 'module' => array('module'), - 'storage_module' => array('storage_module'), - 'type' => array('type'), - 'storage_type' => array('storage_type'), - ), - ); - $schema['field_config_instance'] = array( - 'fields' => array( - 'id' => array( - 'type' => 'serial', - 'not null' => TRUE, - 'description' => 'The primary identifier for a field instance', - ), - 'field_id' => array( - 'type' => 'int', - 'not null' => TRUE, - 'description' => 'The identifier of the field attached by this instance', - ), - 'field_name' => array( - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '' - ), - 'entity_type' => array( - 'type' => 'varchar', - 'length' => 32, - 'not null' => TRUE, - 'default' => '' - ), - 'bundle' => array( - 'type' => 'varchar', - 'length' => 128, - 'not null' => TRUE, - 'default' => '' - ), - 'data' => array( - 'type' => 'blob', - 'size' => 'big', - 'not null' => TRUE, - 'serialize' => TRUE, - ), - 'deleted' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - ), - ), - 'primary key' => array('id'), - 'indexes' => array( - // Used by field_delete_instance(). - 'field_name_bundle' => array('field_name', 'entity_type', 'bundle'), - // Used by field_read_instances(). - 'deleted' => array('deleted'), - ), - ); + $schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache'); $schema['cache_field']['description'] = 'Cache table for the Field module to store already built field informations.'; @@ -172,7 +23,7 @@ function field_schema() { * * @ingroup update_api */ -function _update_7000_field_create_field(&$field) { +function _update_7000_field_create_field($field) { // Merge in default values.` $field += array( 'entity_types' => array(), @@ -229,12 +80,25 @@ function _update_7000_field_create_field(&$field) { 'deleted' => (int) $field['deleted'], ); // We don't use drupal_write_record() here because it depends on the schema. - $field['id'] = db_insert('field_config') + $record['id'] = db_insert('field_config') ->fields($record) ->execute(); - // Create storage for the field. - field_sql_storage_field_storage_create_field($field); + // Extra keys - @todo clean this up. + $record['settings'] = $data['settings']; + $record['columns'] = $field['columns']; + $record['indexes'] = isset($data['indexes']) ? $data['indexes'] : array(); + if (!isset($record['foreign_keys'])) { + $record['foreign_keys'] = array(); + } + if (isset($data['foreign keys'])) { + $record['foreign_keys'] += $data['foreign keys']; + } + $record['storage'] = $data['storage']; + unset($record['data']); + field_sql_storage_field_storage_create_field((object) $record); + + return $record; } /** @@ -271,7 +135,6 @@ function _update_7000_field_delete_field($field_name) { ->execute(); } - /** * Deletes an instance and all its data of a field stored in SQL Storage. * @@ -382,15 +245,14 @@ function _update_7000_field_create_instance($field, &$instance) { */ /** - * Reassign all list.module fields to be controlled by options.module. + * Implements hook_update_dependencies(). */ -function field_update_8001() { - db_update('field_config') - ->fields(array( - 'module' => 'options', - )) - ->condition('module', 'list') - ->execute(); +function field_update_dependencies() { + // Convert to config after SQL storage has been updated. + $dependencies['field_sql_storage'][8000] = array( + 'field' => 8002, + ); + return $dependencies; } /** @@ -398,7 +260,7 @@ function field_update_8001() { * * @ingroup config_upgrade */ -function field_update_8002() { +function field_update_8001() { $displays = array(); module_load_install('entity'); @@ -442,7 +304,7 @@ function field_update_8002() { // Migration of 'extra_fields' display settings. Avoid calling // entity_get_info() by fetching the relevant variables directly in the - // cariables table. + // variable table. $variables = array_map('unserialize', db_query("SELECT name, value FROM {variable} WHERE name LIKE '%field_bundle_settings_%'")->fetchAllKeyed()); foreach ($variables as $variable_name => $variable_value) { if (preg_match('/field_bundle_settings_(.*)__(.*)/', $variable_name, $matches)) { @@ -484,6 +346,122 @@ function field_update_8002() { } /** + * Convert fields and instances to config. + */ +function field_update_8002() { + $manifest_ids = array('fields' => array(), 'instances' => array()); + + $deleted_fields = state()->get('field.field.deleted') ?: array(); + $deleted_instances = state()->get('field.instance.deleted') ?: array(); + + $field_ids = array(); + $fields = db_query("SELECT * FROM {field_config}")->fetchAll(PDO::FETCH_ASSOC); + foreach ($fields as $field) { + $field['data'] = unserialize($field['data']); + + // Keep old id for the field. + $old_id = $field['id']; + $field['id'] = $field['field_name']; + $field['settings'] = $field['data']['settings']; + + // @todo clean this up. + $field['storage'] = $field['data']['storage']; + if (!isset($field['indexes'])) { + $field['indexes'] = array(); + } + $field['foreign_keys'] = array(); + if (isset($field['data']['foreign keys'])) { + $field['foreign_keys'] += $field['data']['foreign keys']; + } + $schema = (array) module_invoke($field['module'], 'field_schema', (object) $field); + $schema += array('columns' => array(), 'indexes' => array()); + // 'columns' are hardcoded in the field type. + $field['columns'] = $schema['columns']; + // 'indexes' can be both hardcoded in the field type, and specified in the + // incoming $field definition. + $field['indexes'] += $schema['indexes']; + + // Remove data key. + unset($field['data']); + + // Reassign all list.module fields to be controlled by options.module. + if ($field['module'] == 'list') { + $field['module'] = 'options'; + } + + if (!$field['deleted']) { + $uuid = new Uuid(); + $uuid->generate(); + $config = config('field.field.' . $field['field_name']); + foreach ($field as $key => $value) { + $config->set($key, $value); + } + $config->set('uuid', $uuid->generate()); + $config->save(); + $manifest_ids['fields'][] = $field['field_name']; + } + else { + // @todo we actually need to store the entity config object there + // or should we dump the array in deleted fields (and instances below) + // as well and call entity_create() during field_purge_batch(). + $deleted_fields[$e_field['uuid']] = $field; + } + $field_ids[$old_id] = array( + 'id' => $config->get('uuid'), + ); + } + + $instances = db_query("SELECT * FROM {field_config_instance}")->fetchAll(PDO::FETCH_ASSOC); + foreach ($instances as $instance) { + $instance += unserialize($instance['data']); + unset($instance['data']); + + $config_id = $instance['entity_type'] . '.' . $instance['bundle'] . '.' . $instance['field_name']; + $instance['id'] = $config_id; + + // Map old field id to new UUID. + $old_id = $instance['field_id']; + $instance['field_id'] = $field_ids[$old_id]['id']; + + + if (!$instance['deleted']) { + $instance['widget'] = $instance['widget']; + unset($instance['widget']); + $uuid = new Uuid(); + $uuid->generate(); + $config = config('field.instance.' . $config_id); + $config->setData($instance); + $config->set('uuid', $uuid->generate()); + $config->save(); + + $manifest_ids['instances'][] = $config_id; + } + else { + // @todo we actually need to store the entity config object there + // or should we dump the array in deleted instances (and fields above) + // as well and call entity_create() during field_purge_batch(). + $deleted_instances[$instance['uuid']] = $instance; + } + + // Update file_usage table in case this instance has a default image. + if (!empty($instance['settings']['default_image'])) { + db_update('file_usage') + ->fields(array('id' => $instance['field_id'])) + ->condition('fid', $instance['settings']['default_image']) + ->execute(); + } + } + + // Create the manifest files. + update_config_manifest_add('field.field', $manifest_ids['fields']); + update_config_manifest_add('field.instance', $manifest_ids['instances']); + + // Save the deleted fields and instances in state. + state()->set('field.field.deleted', $deleted_fields); + state()->set('field.instance.deleted', $deleted_instances); +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/field/field.module b/core/modules/field/field.module index a52d917..0796a71 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -334,7 +334,8 @@ function field_cron() { * required if there are any active fields of that type. */ function field_system_info_alter(&$info, $file, $type) { - if ($type == 'module' && module_hook($file->name, 'field_info')) { + // It's not safe to call field_read_fields during maintenance mode. + if ($type == 'module' && module_hook($file->name, 'field_info') && !defined('MAINTENANCE_MODE')) { $fields = field_read_fields(array('module' => $file->name), array('include_deleted' => TRUE)); if ($fields) { $info['required'] = TRUE; @@ -536,23 +537,41 @@ function field_modules_disabled($modules) { } /** - * Refreshes the 'active' and 'storage_active' columns for fields. + * Refreshes the 'active' and 'storage_active' values for fields. */ function field_sync_field_status() { - // Refresh the 'active' and 'storage_active' columns according to the current + + $deleted_fields = state()->get('field.field.deleted') ?: array(); + $fields = field_read_fields(array(), array('include_deleted' => 1 ,'include_inactive' => 1)); + // Refresh the 'active' and 'storage_active' values according to the current // set of enabled modules. $modules = array_keys(drupal_container()->get('module_handler')->getModuleList()); foreach ($modules as $module_name) { - field_associate_fields($module_name); + $fields = field_associate_fields($module_name, $fields); + } + + foreach ($fields as $id => $field) { + if (!in_array($field['module'], $modules)) { + $fields[$id]->active = 0; + } + if (!in_array($field['storage_module'], $modules)) { + $fields[$id]['storage_active'] = 0; + } } - db_update('field_config') - ->fields(array('active' => 0)) - ->condition('module', $modules, 'NOT IN') - ->execute(); - db_update('field_config') - ->fields(array('storage_active' => 0)) - ->condition('storage_module', $modules, 'NOT IN') - ->execute(); + + foreach ($fields as $id => $field) { + if (!$field['deleted']) { + $field->save(); + } + else { + $deleted_fields[$field['uuid']] = $field; + } + } + + // Save the deleted fields. + state()->set('field.field.deleted', $deleted_fields); + + field_cache_clear(); } /** @@ -560,24 +579,37 @@ function field_sync_field_status() { * * @param $module * The name of the module to update on. + * @param $fields + * A collection of fields. */ -function field_associate_fields($module) { +function field_associate_fields($module, $fields) { + // Associate field types. $field_types = (array) module_invoke($module, 'field_info'); + if ($field_types) { - db_update('field_config') - ->fields(array('module' => $module, 'active' => 1)) - ->condition('type', array_keys($field_types)) - ->execute(); + $field_types = array_keys($field_types); + foreach ($fields as $id => $field) { + if (in_array($field['type'], $field_types)) { + $fields[$id]->module = $module; + $fields[$id]->active = TRUE; + } + } } + // Associate storage backends. $storage_types = (array) module_invoke($module, 'field_storage_info'); if ($storage_types) { - db_update('field_config') - ->fields(array('storage_module' => $module, 'storage_active' => 1)) - ->condition('storage_type', array_keys($storage_types)) - ->execute(); + $storage_types = array_keys($storage_types); + foreach ($fields as $id => $field) { + if (in_array($field['storage_type'], $storage_types)) { + $fields[$id]->storage_module = $module; + $fields[$id]->storage_active = TRUE; + } + } } + + return $fields; } /** @@ -1011,7 +1043,7 @@ function field_get_items(EntityInterface $entity, $field_name, $langcode = NULL) * TRUE if the field has data for any entity; FALSE otherwise. */ function field_has_data($field) { - $field = field_info_field_by_id($field['id']); + $field = field_info_field_by_id($field['uuid']); $columns = array_keys($field['columns']); $factory = drupal_container()->get('entity.query'); foreach ($field['bundles'] as $entity_type => $bundle) { diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc index a9b33ac..d9b6479 100644 --- a/core/modules/field/field.multilingual.inc +++ b/core/modules/field/field.multilingual.inc @@ -208,7 +208,10 @@ function field_content_languages() { * TRUE if the field can be translated. */ function field_is_translatable($entity_type, $field) { - return $field['translatable'] && field_has_translation_handler($entity_type); + // See http://drupal.org/node/1862758#comment-7035586 + if (!empty($field)) { + return $field['translatable'] && field_has_translation_handler($entity_type); + } } /** diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc index 6c769cd..37f8221 100644 --- a/core/modules/field/field.views.inc +++ b/core/modules/field/field.views.inc @@ -72,8 +72,8 @@ function field_views_field_label($field_name) { foreach ($instances as $entity_name => $entity_type) { foreach ($entity_type as $bundle) { if (isset($bundle[$field_name])) { - $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]['label']] : 1; - $all_labels[$entity_name][$bundle[$field_name]['label']] = TRUE; + $label_counter[$bundle[$field_name]->label] = isset($label_counter[$bundle[$field_name]->label]) ? ++$label_counter[$bundle[$field_name]->label] : 1; + $all_labels[$entity_name][$bundle[$field_name]->label] = TRUE; } } } diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php index 7ff6850..9861dc3 100644 --- a/core/modules/field/lib/Drupal/field/FieldInfo.php +++ b/core/modules/field/lib/Drupal/field/FieldInfo.php @@ -142,17 +142,11 @@ public function getFieldMap() { $map = array(); - $query = db_select('field_config_instance', 'fci'); - $query->join('field_config', 'fc', 'fc.id = fci.field_id'); - $query->fields('fc', array('type')); - $query->fields('fci', array('field_name', 'entity_type', 'bundle')) - ->condition('fc.active', 1) - ->condition('fc.storage_active', 1) - ->condition('fc.deleted', 0) - ->condition('fci.deleted', 0); - foreach ($query->execute() as $row) { - $map[$row->field_name]['bundles'][$row->entity_type][] = $row->bundle; - $map[$row->field_name]['type'] = $row->type; + $instances = field_read_instances(); + foreach ($instances as $key => $instance) { + $map[$instance['field_name']]['bundles'][$instance['entity_type']][] = $instance['bundle']; + // @todo what is this type ?! + $map[$instance['field_name']]['type'] = $instance['type']; } // Save in "static" and persistent caches. @@ -181,7 +175,7 @@ public function getFields() { else { // Collect and prepare fields. foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) { - $this->fieldsById[$field['id']] = $this->prepareField($field); + $this->fieldsById[$field['uuid']] = $this->prepareField($field); } // Store in persistent cache. @@ -191,7 +185,7 @@ public function getFields() { // Fill the name/ID map. foreach ($this->fieldsById as $field) { if (!$field['deleted']) { - $this->fieldIdsByName[$field['field_name']] = $field['id']; + $this->fieldIdsByName[$field['field_name']] = $field['uuid']; } } @@ -229,7 +223,7 @@ public function getInstances($entity_type = NULL) { foreach (field_read_instances() as $instance) { $field = $this->getField($instance['field_name']); $instance = $this->prepareInstance($instance, $field['type']); - $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = new FieldInstance($instance); + $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance; } // Store in persistent cache. @@ -275,8 +269,8 @@ public function getField($field_name) { $field = $this->prepareField($field); // Save in the "static" cache. - $this->fieldsById[$field['id']] = $field; - $this->fieldIdsByName[$field['field_name']] = $field['id']; + $this->fieldsById[$field['uuid']] = $field; + $this->fieldIdsByName[$field['field_name']] = $field['uuid']; return $field; } @@ -309,14 +303,14 @@ public function getFieldById($field_id) { // bundle. // Cache miss: read from definition. - if ($fields = field_read_fields(array('id' => $field_id), array('include_deleted' => TRUE))) { + if ($fields = field_read_fields(array('uuid' => $field_id), array('include_deleted' => TRUE))) { $field = current($fields); $field = $this->prepareField($field); // Store in the static cache. - $this->fieldsById[$field['id']] = $field; + $this->fieldsById[$field['uuid']] = $field; if (!$field['deleted']) { - $this->fieldIdsByName[$field['field_name']] = $field['id']; + $this->fieldIdsByName[$field['field_name']] = $field['uuid']; } return $field; @@ -355,10 +349,10 @@ public function getBundleInstances($entity_type, $bundle) { // Extract the field definitions and save them in the "static" cache. foreach ($info['fields'] as $field) { - if (!isset($this->fieldsById[$field['id']])) { - $this->fieldsById[$field['id']] = $field; + if (!isset($this->fieldsById[$field['uuid']])) { + $this->fieldsById[$field['uuid']] = $field; if (!$field['deleted']) { - $this->fieldIdsByName[$field['field_name']] = $field['id']; + $this->fieldIdsByName[$field['field_name']] = $field['uuid']; } } } @@ -382,7 +376,7 @@ public function getBundleInstances($entity_type, $bundle) { // Collect the fields in the bundle. $params = array('entity_type' => $entity_type, 'bundle' => $bundle); - $fields = field_read_fields($params); + $fields = field_read_fields(); // This iterates on non-deleted instances, so deleted fields are kept out of // the persistent caches. @@ -390,14 +384,14 @@ public function getBundleInstances($entity_type, $bundle) { $field = $fields[$instance['field_name']]; $instance = $this->prepareInstance($instance, $field['type']); - $instances[$field['field_name']] = new FieldInstance($instance); + $instances[$field['field_name']] = $instance; // If the field is not in our global "static" list yet, add it. - if (!isset($this->fieldsById[$field['id']])) { + if (!isset($this->fieldsById[$field['uuid']])) { $field = $this->prepareField($field); - $this->fieldsById[$field['id']] = $field; - $this->fieldIdsByName[$field['field_name']] = $field['id']; + $this->fieldsById[$field['uuid']] = $field; + $this->fieldIdsByName[$field['field_name']] = $field['uuid']; } } @@ -413,6 +407,7 @@ public function getBundleInstances($entity_type, $bundle) { // The persistent cache additionally contains the definitions of the fields // involved in the bundle. + uasort($instances, array($this, '_orderInstances')); $cache = array( 'instances' => $instances, 'fields' => array() @@ -553,4 +548,11 @@ public function prepareExtraFields($extra_fields, $entity_type, $bundle) { return $result; } + + /** + * Helper function to sort the instances on the widget weight. + */ + function _orderInstances($a, $b) { + return ($a['widget']['weight'] < $b['widget']['weight']) ? -1 : 1; + } } diff --git a/core/modules/field/lib/Drupal/field/FieldInstance.php b/core/modules/field/lib/Drupal/field/FieldInstance.php deleted file mode 100644 index ba6ea44..0000000 --- a/core/modules/field/lib/Drupal/field/FieldInstance.php +++ /dev/null @@ -1,135 +0,0 @@ -definition = $definition; - } - - /** - * Returns the Widget plugin for the instance. - * - * @return Drupal\field\Plugin\Type\Widget\WidgetInterface - * The Widget plugin to be used for the instance. - */ - public function getWidget() { - if (empty($this->widget)) { - $widget_properties = $this->definition['widget']; - - // Let modules alter the widget properties. - $context = array( - 'entity_type' => $this->definition['entity_type'], - 'bundle' => $this->definition['bundle'], - 'field' => field_info_field($this->definition['field_name']), - 'instance' => $this, - ); - drupal_alter(array('field_widget_properties', 'field_widget_properties_' . $this->definition['entity_type']), $widget_properties, $context); - - $options = array( - 'instance' => $this, - 'type' => $widget_properties['type'], - 'settings' => $widget_properties['settings'], - 'weight' => $widget_properties['weight'], - ); - $this->widget = drupal_container()->get('plugin.manager.field.widget')->getInstance($options); - } - - return $this->widget; - } - - /** - * Implements ArrayAccess::offsetExists(). - */ - public function offsetExists($offset) { - return isset($this->definition[$offset]) || array_key_exists($offset, $this->definition); - } - - /** - * Implements ArrayAccess::offsetGet(). - */ - public function &offsetGet($offset) { - return $this->definition[$offset]; - } - - /** - * Implements ArrayAccess::offsetSet(). - */ - public function offsetSet($offset, $value) { - if (!isset($offset)) { - // Do nothing; $array[] syntax is not supported by this temporary wrapper. - return; - } - $this->definition[$offset] = $value; - - // If the widget or formatter properties changed, the corrsponding plugins - // need to be re-instanciated. - if ($offset == 'widget') { - unset($this->widget); - } - } - - /** - * Implements ArrayAccess::offsetUnset(). - */ - public function offsetUnset($offset) { - unset($this->definition[$offset]); - - // If the widget or formatter properties changed, the corrsponding plugins - // need to be re-instanciated. - if ($offset == 'widget') { - unset($this->widget); - } - } - - /** - * Returns the instance definition as a regular array. - * - * This is used as a temporary BC layer. - * @todo Remove once the external APIs have been converted to use - * FieldInstance objects. - * - * @return array - * The instance definition as a regular array. - */ - public function getArray() { - return $this->definition; - } - - /** - * Handles serialization of Drupal\field\FieldInstance objects. - */ - public function __sleep() { - return array('definition'); - } - -} diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php new file mode 100644 index 0000000..63d7505 --- /dev/null +++ b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php @@ -0,0 +1,46 @@ +get(); + field_create_instance($config); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importChange(). + */ + public function importChange($name, Config $new_config, Config $old_config) { + $config = $new_config->get(); + field_update_instance($config); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importDelete(). + */ + public function importDelete($name, Config $new_config, Config $old_config) { + $config = $old_config->get(); + // In case the field has been deleted, + // the instance will be deleted by then already. + if (!empty($config)) { + field_delete_instance((object) $config); + } + } + +} diff --git a/core/modules/field/lib/Drupal/field/FieldStorageController.php b/core/modules/field/lib/Drupal/field/FieldStorageController.php new file mode 100644 index 0000000..a86c39c --- /dev/null +++ b/core/modules/field/lib/Drupal/field/FieldStorageController.php @@ -0,0 +1,39 @@ +get()); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importChange(). + */ + public function importChange($name, Config $new_config, Config $old_config) { + field_update_field($new_config->get()); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importDelete(). + */ + public function importDelete($name, Config $new_config, Config $old_config) { + field_delete_field($old_config->get('field_name')); + } + +} diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldEntity.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldEntity.php new file mode 100644 index 0000000..8348d88 --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldEntity.php @@ -0,0 +1,219 @@ +{$offset}); + } + + /** + * Implements ArrayAccess::offsetGet(). + */ + public function &offsetGet($offset) { + return $this->{$offset}; + } + + /** + * Implements ArrayAccess::offsetSet(). + */ + public function offsetSet($offset, $value) { + $this->{$offset} = $value; + } + + /** + * Implements ArrayAccess::offsetUnset(). + */ + public function offsetUnset($offset) { + unset($this->{$offset}); + } + + /** + * Generate an a table id for deleted fields. + * + * When a field is a deleted, the tables are renamed to {field_data_field_id} + * and {field_revision_field_id}. To make sure we don't end up with table + * names longer than 64 characters, we hash the uuid and return the first + * 6 characters so we end up with a short unique id. + */ + function generate_table_id() { + return substr(hash('sha256', $this->uuid), 0, 6); + } + +} diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php new file mode 100644 index 0000000..9011190 --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php @@ -0,0 +1,196 @@ +widgetObject)) { + $widget_properties = $this->widget; + + // Let modules alter the widget properties. + $context = array( + 'entity_type' => $this->entity_type, + 'bundle' => $this->bundle, + 'field' => field_info_field($this->field_name), + 'instance' => $this, + ); + drupal_alter(array('field_widget_properties', 'field_widget_properties_' . $this->entity_type), $widget_properties, $context); + + $options = array( + 'instance' => $this, + 'type' => $widget_properties['type'], + 'settings' => $widget_properties['settings'], + 'weight' => $widget_properties['weight'], + ); + $this->widgetObject = drupal_container()->get('plugin.manager.field.widget')->getInstance($options); + } + + return $this->widgetObject; + } + + /** + * Implements ArrayAccess::offsetExists(). + */ + public function offsetExists($offset) { + return isset($this->{$offset}); + } + + /** + * Implements ArrayAccess::offsetGet(). + */ + public function &offsetGet($offset) { + return $this->{$offset}; + } + + /** + * Implements ArrayAccess::offsetSet(). + */ + public function offsetSet($offset, $value) { + $this->{$offset} = $value; + } + + /** + * Implements ArrayAccess::offsetUnset(). + */ + public function offsetUnset($offset) { + unset($this->{$offset}); + } + +} + 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 04a038d..e93ab96 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 @@ -10,7 +10,7 @@ use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\field\Plugin\PluginSettingsBase; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Base class for 'Field formatter' plugin implementations. diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php index 36693b0..4058810 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterInterface.php @@ -8,7 +8,7 @@ namespace Drupal\field\Plugin\Type\Formatter; use Drupal\Core\Entity\EntityInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\field\Plugin\PluginSettingsInterface; /** 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 c935c44..363d29b 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 @@ -13,7 +13,7 @@ use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\field\Plugin\Type\Formatter\FormatterLegacyDiscoveryDecorator; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Plugin type manager for field formatters. diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php index 12118f8..802a4a5 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php @@ -11,7 +11,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; use Drupal\field\Plugin\PluginSettingsBase; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Base class for 'Field widget' plugin implementations. diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php index c0ffc95..8711bbd 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php @@ -8,7 +8,7 @@ namespace Drupal\field\Plugin\Type\Widget; use Drupal\Core\Entity\EntityInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Interface definition for field widget plugins. diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/formatter/LegacyFormatter.php b/core/modules/field/lib/Drupal/field/Plugin/field/formatter/LegacyFormatter.php index 17c69fc..00857ef 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/field/formatter/LegacyFormatter.php +++ b/core/modules/field/lib/Drupal/field/Plugin/field/formatter/LegacyFormatter.php @@ -58,7 +58,7 @@ public function settingsSummary() { // properties directly from $instance. Put the actual properties we use // here. $instance = clone $this->instance; - $instance['display'][$this->viewMode] = array( + $instance->display[$this->viewMode] = array( 'type' => $this->getPluginId(), 'settings' => $this->getSettings(), 'label' => $this->label, diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php index 30836a3..bf97ca6 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -428,7 +428,7 @@ function fakeFieldInstance($formatter, $formatter_settings) { $field_type = field_info_field_types($field['type']); - return array( + return entity_create('field_instance', array( // Build a fake entity type and bundle. 'field_name' => $field_name, 'entity_type' => 'views_fake', @@ -455,7 +455,7 @@ function fakeFieldInstance($formatter, $formatter_settings) { 'label' => $field_name, 'description' => '', 'deleted' => 0, - ); + )); } /** diff --git a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php index c365961..1d46a83 100644 --- a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php @@ -7,6 +7,8 @@ namespace Drupal\field\Tests; +use Drupal\field\Plugin\Core\Entity\FieldInstance; + /** * Unit test class for field bulk delete and batch purge functionality. */ @@ -171,9 +173,9 @@ function testDeleteFieldInstance() { field_delete_instance($instance); // The instance still exists, deleted. - $instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); + $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); $this->assertEqual(count($instances), 1, 'There is one deleted instance'); - $this->assertEqual($instances[0]['bundle'], $bundle, 'The deleted instance is for the correct bundle'); + $this->assertEqual($instances[0]->bundle, $bundle, 'The deleted instance is for the correct bundle'); // There are 0 entities of this bundle with non-deleted data. $found = $factory->get('test_entity') @@ -198,7 +200,7 @@ function testDeleteFieldInstance() { $ids->entity_id = $entity_id; $entities[$entity_id] = _field_create_entity_from_ids($ids); } - field_attach_load($this->entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); + field_attach_load($this->entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['uuid'], 'deleted' => 1)); $this->assertEqual(count($found), 10, 'Correct number of entities found after deleting'); foreach ($entities as $id => $entity) { $this->assertEqual($this->entities[$id]->{$field['field_name']}, $entity->{$field['field_name']}, "Entity $id with deleted data loaded correctly"); @@ -254,19 +256,19 @@ function testPurgeInstance() { $this->checkHooksInvocations($hooks, $actual_hooks); // The instance still exists, deleted. - $instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); + $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); $this->assertEqual(count($instances), 1, 'There is one deleted instance'); // Purge the instance. field_purge_batch($batch_size); // The instance is gone. - $instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); + $instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); $this->assertEqual(count($instances), 0, 'The instance is gone'); // The field still exists, not deleted, because it has a second instance. - $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1, 'include_inactive' => 1)); - $this->assertTrue(isset($fields[$field['id']]), 'The field exists and is not deleted'); + $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => 1, 'include_inactive' => 1)); + $this->assertTrue(isset($fields[$field['uuid']]), 'The field exists and is not deleted'); } /** @@ -307,8 +309,8 @@ function testPurgeField() { field_purge_batch(0); // The field still exists, not deleted. - $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1)); - $this->assertTrue(isset($fields[$field['id']]) && !$fields[$field['id']]['deleted'], 'The field exists and is not deleted'); + $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => 1)); + $this->assertTrue(isset($fields[$field['uuid']]) && !$fields[$field['uuid']]->deleted, 'The field exists and is not deleted'); // Delete the second instance. $bundle = next($this->bundles); @@ -331,14 +333,14 @@ function testPurgeField() { $this->checkHooksInvocations($hooks, $actual_hooks); // The field still exists, deleted. - $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1)); - $this->assertTrue(isset($fields[$field['id']]) && $fields[$field['id']]['deleted'], 'The field exists and is deleted'); + $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => 1)); + $this->assertTrue(isset($fields[$field['uuid']]) && $fields[$field['uuid']]->deleted, 'The field exists and is deleted'); // Purge again to purge the instance and the field. field_purge_batch(0); // The field is gone. - $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1, 'include_inactive' => 1)); + $fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => 1, 'include_inactive' => 1)); $this->assertEqual(count($fields), 0, 'The field is purged.'); } } diff --git a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php index 1c539da..76d6c78 100644 --- a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php @@ -41,28 +41,27 @@ function testCreateField() { 'type' => 'test_field', ); field_test_memorize(); - $field_definition = field_create_field($field_definition); + $create_field = field_create_field($field_definition); $mem = field_test_memorize(); - $this->assertIdentical($mem['field_test_field_create_field'][0][0], $field_definition, 'hook_field_create_field() called with correct arguments.'); + $this->assertIdentical($mem['field_test_field_create_field'][0][0]->field_name, $field_definition['field_name'], 'hook_field_create_field() called with correct arguments.'); + $this->assertIdentical($mem['field_test_field_create_field'][0][0]->type, $field_definition['type'], 'hook_field_create_field() called with correct arguments.'); - // Read the raw record from the {field_config_instance} table. - $result = db_query('SELECT * FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name'])); - $record = $result->fetchAssoc(); - $record['data'] = unserialize($record['data']); + // Read the configuration. + $record = entity_load('field_entity', $field_definition['field_name']); // Ensure that basic properties are preserved. - $this->assertEqual($record['field_name'], $field_definition['field_name'], 'The field name is properly saved.'); - $this->assertEqual($record['type'], $field_definition['type'], 'The field type is properly saved.'); + $this->assertEqual($record->field_name, $field_definition['field_name'], 'The field name is properly saved.'); + $this->assertEqual($record->type, $field_definition['type'], 'The field type is properly saved.'); // Ensure that cardinality defaults to 1. - $this->assertEqual($record['cardinality'], 1, 'Cardinality defaults to 1.'); + $this->assertEqual($record->cardinality, 1, 'Cardinality defaults to 1.'); // Ensure that default settings are present. $field_type = field_info_field_types($field_definition['type']); - $this->assertIdentical($record['data']['settings'], $field_type['settings'], 'Default field settings have been written.'); + $this->assertEqual($record->settings, $field_type['settings'], 'Default field settings have been written.'); // Ensure that default storage was set. - $this->assertEqual($record['storage_type'], variable_get('field_storage_default'), 'The field type is properly saved.'); + $this->assertEqual($record->storage_type, variable_get('field_storage_default'), 'The field type is properly saved.'); // Guarantee that the name is unique. try { @@ -157,11 +156,10 @@ function testCreateField() { function testCreateFieldFail() { $field_name = 'duplicate'; $field_definition = array('field_name' => $field_name, 'type' => 'test_field', 'storage' => array('type' => 'field_test_storage_failure')); - $query = db_select('field_config')->condition('field_name', $field_name)->countQuery(); + $field = entity_load('field_entity', $field_name); - // The field does not appear in field_config. - $count = $query->execute()->fetchField(); - $this->assertEqual($count, 0, 'A field_config row for the field does not exist.'); + // The field does not exist. + $this->assertFalse($field, 'The field does not exist.'); // Try to create the field. try { @@ -172,9 +170,10 @@ function testCreateFieldFail() { $this->assertTrue(TRUE, 'Field creation (correctly) fails.'); } - // The field does not appear in field_config. - $count = $query->execute()->fetchField(); - $this->assertEqual($count, 0, 'A field_config row for the field does not exist.'); + // The field does not exist. + // $field = config('field.field.' . $field_name)->get(); + $field = entity_load('field_entity', $field_name); + $this->assertFalse($field, 'The field does not exist.'); } /** @@ -221,10 +220,11 @@ function testReadFields() { field_create_instance($instance_definition); // Check that criteria spanning over the field_config_instance table work. - $fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'bundle' => $instance_definition['bundle'])); + // @todo do we still want to support this ? + /*$fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'bundle' => $instance_definition['bundle'])); $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.'); $fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'field_name' => $instance_definition['field_name'])); - $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.'); + $this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');*/ } /** @@ -278,9 +278,9 @@ function testDeleteField() { // Create two fields (so we can test that only one is deleted). $this->field = array('field_name' => 'field_1', 'type' => 'test_field'); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->another_field = array('field_name' => 'field_2', 'type' => 'test_field'); - field_create_field($this->another_field); + $this->another_field = field_create_field($this->another_field); // Create instances for each. $this->instance_definition = array( @@ -303,8 +303,8 @@ function testDeleteField() { // Make sure that the field is marked as deleted when it is specifically // loaded. - $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE)); - $this->assertTrue(!empty($field['deleted']), 'A deleted field is marked for deletion.'); + $deleted_fields = state()->get('field.field.deleted'); + $this->assertTrue(isset($deleted_fields[$field['uuid']]), 'A deleted field is marked for deletion.'); // Make sure that this field's instance is marked as deleted when it is // specifically loaded. @@ -389,7 +389,7 @@ function testUpdateField() { 'type' => 'test_field', 'cardinality' => $cardinality, ); - $field_definition = field_create_field($field_definition); + field_create_field($field_definition); $instance = array( 'field_name' => 'field_update', 'entity_type' => 'test_entity', @@ -505,6 +505,6 @@ function _testActiveHelper($field_definition, $modules) { // Check that the field is active again after all modules have been // enabled. $field = field_read_field($field_name); - $this->assertTrue($field_definition <= $field, 'The field was was marked active.'); + $this->assertTrue($field_definition <= $field, 'The field was marked active.'); } } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php index bc1a380..394e493 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php @@ -37,11 +37,11 @@ function setUp() { $this->content_type_info = $this->drupalCreateContentType(); $this->content_type = $this->content_type_info->type; - $this->field = array( + $field = array( 'field_name' => 'test_view_field', 'type' => 'text', ); - field_create_field($this->field); + $this->field = field_create_field($field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'node', diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php index 89e07c6..8a9bcf6 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php @@ -35,7 +35,7 @@ function testFieldAttachView() { // Populate values to be displayed. $values = $this->_generateTestFieldValues($this->field['cardinality']); $entity_init->{$this->field_name}[$langcode] = $values; - $values_2 = $this->_generateTestFieldValues($this->field_2['cardinality']); + $values_2 = $this->_generateTestFieldValues($this->field_2->cardinality); $entity_init->{$this->field_name_2}[$langcode] = $values_2; // Simple formatter, label displayed. @@ -61,7 +61,7 @@ function testFieldAttachView() { 'test_formatter_setting' => $formatter_setting_2, ), ); - $display->setComponent($this->field_2['field_name'], $display_options_2); + $display->setComponent($this->field_2->field_name, $display_options_2); // View all fields. field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); @@ -73,7 +73,7 @@ function testFieldAttachView() { $this->content = $output; $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); } - $this->assertRaw($this->instance_2['label'], "Second field's label is displayed."); + $this->assertRaw($this->instance_2->label, "Second field's label is displayed."); foreach ($values_2 as $delta => $value) { $this->content = $output; $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); @@ -88,7 +88,7 @@ function testFieldAttachView() { $this->content = $output; $this->assertNoRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); } - $this->assertRaw($this->instance_2['label'], "Second field's label is displayed."); + $this->assertRaw($this->instance_2->label, "Second field's label is displayed."); foreach ($values_2 as $delta => $value) { $this->content = $output; $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); @@ -187,7 +187,7 @@ function testFieldAttachPrepareViewMultiple() { field_test_create_bundle('test_bundle_2'); $formatter_setting = $this->randomName(); $this->instance2 = $this->instance; - $this->instance2['bundle'] = 'test_bundle_2'; + $this->instance2->bundle = 'test_bundle_2'; field_create_instance($this->instance2); $display_2 = entity_get_display('test_entity', 'test_bundle_2', 'full') @@ -348,7 +348,7 @@ function testFieldAttachValidate() { // Set up all values of the second field to generate errors. $values_2 = array(); - for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) { + for ($delta = 0; $delta < $this->field_2->cardinality; $delta++) { $values_2[$delta]['value'] = -1; } $entity->{$this->field_name_2}[$langcode] = $values_2; @@ -397,7 +397,7 @@ function testFieldAttachValidate() { $this->assertEqual(count($errors[$this->field_name_2][$langcode]), 0, 'No extraneous errors set for second field'); // Check that cardinality is validated. - $entity->{$this->field_name_2}[$langcode] = $this->_generateTestFieldValues($this->field_2['cardinality'] + 1); + $entity->{$this->field_name_2}[$langcode] = $this->_generateTestFieldValues($this->field_2->cardinality + 1); // When validating all fields. try { field_attach_validate($entity); @@ -435,12 +435,12 @@ function testFieldAttachForm() { field_attach_form($entity, $form, $form_state); $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}"); - $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}"); + $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2->label, "Second field's form title is {$this->instance_2->label}"); for ($delta = 0; $delta < $this->field['cardinality']; $delta++) { // field_test_widget uses 'textfield' $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield"); } - for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) { + for ($delta = 0; $delta < $this->field_2->cardinality; $delta++) { // field_test_widget uses 'textfield' $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield"); } @@ -452,8 +452,8 @@ function testFieldAttachForm() { field_attach_form($entity, $form, $form_state, NULL, $options); $this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form'); - $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}"); - for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) { + $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2->label, "Second field's form title is {$this->instance_2->label}"); + for ($delta = 0; $delta < $this->field_2->cardinality; $delta++) { // field_test_widget uses 'textfield' $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield"); } @@ -492,11 +492,11 @@ function testFieldAttachExtractFormValues() { // Second field. $values_2 = array(); $weights_2 = array(); - for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) { + for ($delta = 0; $delta < $this->field_2->cardinality; $delta++) { $values_2[$delta]['value'] = mt_rand(1, 127); // Assign random weight. do { - $weight = mt_rand(0, $this->field_2['cardinality']); + $weight = mt_rand(0, $this->field_2->cardinality); } while (in_array($weight, $weights_2)); $weights_2[$delta] = $weight; $values_2[$delta]['_weight'] = $weight; diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php index 5ae3610..2c0f182 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php @@ -112,7 +112,7 @@ function testFieldAttachLoadMultiple() { $field_names[$i] = 'field_' . $i; $field = array('field_name' => $field_names[$i], 'type' => 'test_field'); $field = field_create_field($field); - $field_ids[$i] = $field['id']; + $field_ids[$i] = $field['uuid']; foreach ($field_bundles_map[$i] as $bundle) { $instance = array( 'field_name' => $field_names[$i], @@ -231,7 +231,7 @@ function testFieldStorageDetailsAlter() { 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', ); - field_create_instance($instance); + $instance = field_create_instance($instance); $field = field_info_field($instance['field_name']); $instance = field_info_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']); @@ -248,7 +248,7 @@ function testFieldStorageDetailsAlter() { // Test current and revision storage details together because the columns // are the same. - foreach ((array) $field['columns'] as $column_name => $attributes) { + foreach ($field['columns'] as $column_name => $attributes) { $this->assertEqual($details[FIELD_LOAD_CURRENT]['moon'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'moon[FIELD_LOAD_CURRENT]'))); $this->assertEqual($details[FIELD_LOAD_REVISION]['mars'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'mars[FIELD_LOAD_REVISION]'))); } @@ -437,8 +437,8 @@ function testFieldAttachCreateRenameBundle() { field_test_create_bundle($new_bundle); // Add an instance to that bundle. - $this->instance['bundle'] = $new_bundle; - field_create_instance($this->instance); + $this->instance_definition['bundle'] = $new_bundle; + $this->instance = field_create_instance($this->instance_definition); // Save an entity with data in the field. $entity = field_test_create_entity(0, 0, $this->instance['bundle']); @@ -476,8 +476,8 @@ function testFieldAttachDeleteBundle() { field_test_create_bundle($new_bundle); // Add an instance to that bundle. - $this->instance['bundle'] = $new_bundle; - field_create_instance($this->instance); + $this->instance_definition['bundle'] = $new_bundle; + $this->instance = field_create_instance($this->instance_definition); // Create a second field for the test bundle $field_name = drupal_strtolower($this->randomName() . '_field_name'); @@ -494,7 +494,10 @@ function testFieldAttachDeleteBundle() { 'widget' => array( 'type' => 'test_field_widget', 'settings' => array( - 'size' => mt_rand(0, 255)))); + 'size' => mt_rand(0, 255) + ) + ) + ); field_create_instance($instance); // Save an entity with data for both fields diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachTestBase.php index 9d15ba2..71dc336 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachTestBase.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachTestBase.php @@ -34,11 +34,12 @@ function createFieldWithInstance($suffix = '') { $field = 'field' . $suffix; $field_id = 'field_id' . $suffix; $instance = 'instance' . $suffix; + $instance_definition = 'instance_definition' . $suffix; $this->$field_name = drupal_strtolower($this->randomName() . '_field_name' . $suffix); $this->$field = array('field_name' => $this->$field_name, 'type' => 'test_field', 'cardinality' => 4); $this->$field = field_create_field($this->$field); - $this->$field_id = $this->{$field}['id']; + $this->$field_id = $this->{$field}->uuid; $this->$instance = array( 'field_name' => $this->$field_name, 'entity_type' => 'test_entity', @@ -57,6 +58,7 @@ function createFieldWithInstance($suffix = '') { ) ) ); - field_create_instance($this->$instance); + $this->$instance_definition = $this->$instance; + $this->$instance = field_create_instance($this->$instance); } } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php new file mode 100644 index 0000000..e161b5c --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php @@ -0,0 +1,69 @@ + 'Field config change tests', + 'description' => 'Update field and instances during config change method invocation.', + 'group' => 'Field API', + ); + } + + function setUp() { + parent::setUp(); + + $this->instance_manifest = 'manifest.field.instance'; + $this->instance_name = 'field.instance.node.test_import.field_test_import'; + $this->drupalCreateContentType(array('type' => 'test_import', 'name' => 'Test import')); + + $admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access')); + $this->drupalLogin($admin_user); + } + + /** + * Test importing changes. + */ + function testImportChange() { + + // Assert default test import. + $this->drupalGet('node/add/test_import'); + $this->assertRaw('Test import field'); + + // Change label. + $active = $this->container->get('config.storage'); + $staging = $this->container->get('config.storage.staging'); + $manifest = $active->read($this->instance_manifest); + $instance = $active->read($this->instance_name); + $instance['label'] = 'Test update import field'; + $staging->write($this->instance_name, $instance); + $staging->write($this->instance_manifest, $manifest); + + // Import. + config_import(); + + // Assert updated label. + $this->drupalGet('node/add/test_import'); + $this->assertText('Test update import field'); + } +} diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php new file mode 100644 index 0000000..6bda93f --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php @@ -0,0 +1,87 @@ + 'Field config create tests', + 'description' => 'Create field and instances during config create method invocation.', + 'group' => 'Field API', + ); + } + + function setUp() { + parent::setUp(); + + $this->field_test_import_staging = 'field.field.field_test_import_staging'; + $this->instance_test_import_staging = 'field.instance.node.test_import.field_test_import_staging'; + $this->field_manifest = 'manifest.field.field'; + $this->instance_manifest = 'manifest.field.instance'; + $this->drupalCreateContentType(array('type' => 'test_import', 'name' => 'Test import')); + + $admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access')); + $this->drupalLogin($admin_user); + } + + /** + * Test importing new fields. + */ + function testImportCreate() { + + // Assert default test import. + $this->drupalGet('node/add/test_import'); + $this->assertNoText('Test import field'); + + // Enable field_test_config module and assert the test import + // field and instance is available on the Test content type. + // This tests creating fields and instances that are provided + // by a module. + module_enable(array('field_test_config')); + $this->drupalGet('node/add/test_import'); + $this->assertText('Test import field'); + $module_path = drupal_get_path('module', 'field_test_config'); + + // Copy another field and instance to the staging directory + // on the Test content type and run config_import() to test + // importing from the staging directory. + $active = $this->container->get('config.storage'); + $staging = $this->container->get('config.storage.staging'); + $field_manifest = $active->read($this->field_manifest); + $instance_manifest = $active->read($this->instance_manifest); + + // Copy the files. + $copied = file_unmanaged_copy($module_path .'/staging/' . $this->field_test_import_staging . '.yml', 'public://config_staging/' . $this->field_test_import_staging . '.yml'); + $this->assertTrue($copied); + $copied = file_unmanaged_copy($module_path .'/staging/' . $this->instance_test_import_staging . '.yml', 'public://config_staging/' . $this->instance_test_import_staging . '.yml'); + $this->assertTrue($copied); + + // Add to manifest. + $field_manifest['field_test_import_staging'] = array('name' => $this->field_test_import_staging); + $instance_manifest['node.test_import.field_test_import_staging'] = array('name' => $this->instance_test_import_staging); + + // Write to manifest and new config. + $staging->write($this->field_manifest, $field_manifest); + $staging->write($this->instance_manifest, $instance_manifest); + + // Import. + config_import(); + + // Assert the staging field is there. + $this->drupalGet('node/add/test_import'); + $this->assertText('Import from staging'); + } +} diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php new file mode 100644 index 0000000..1a54deb --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php @@ -0,0 +1,100 @@ + 'Field config delete tests', + 'description' => 'Delete field and instances during config delete method invocation.', + 'group' => 'Field API', + ); + } + + function setUp() { + parent::setUp(); + + $this->body_field_name = 'field.field.body'; + $this->test_import_field_name = 'field.field.test_import'; + $this->body_instance_name = 'field.instance.node.test_import.body'; + $this->test_import_instance_name = 'field.instance.node.test_import.field_test_import'; + $this->field_manifest = 'manifest.field.field'; + $this->instance_manifest = 'manifest.field.instance'; + $this->drupalCreateContentType(array('type' => 'test_import', 'name' => 'Test import')); + + $admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access')); + $this->drupalLogin($admin_user); + } + + /** + * Test importing deletions. + */ + function testImportDelete() { + + $body_field = field_info_field('body'); + $field_test_import = field_info_field('field_test_import'); + + // Assert default test import. + $this->drupalGet('node/add/test_import'); + $this->assertRaw('Test import field'); + $this->assertRaw('Body'); + + // Delete body field and instance, the test import instance + // from the manifest. + $active = $this->container->get('config.storage'); + $staging = $this->container->get('config.storage.staging'); + $field_manifest = $active->read($this->field_manifest); + $instance_manifest = $active->read($this->instance_manifest); + unset($field_manifest['body']); + unset($instance_manifest['node.test_import.body']); + unset($instance_manifest['node.test_import.field_test_import']); + $staging->write($this->field_manifest, $field_manifest); + $staging->write($this->instance_manifest, $instance_manifest); + + // Import. + config_import(); + + // Assert the field and instance are gone from the form. + $this->drupalGet('node/add/test_import'); + $this->assertNoText('Test import field'); + $this->assertNoText('Body'); + + // Check that body and import field are in state of deleted fields. + $deleted_fields = state()->get('field.field.deleted') ?: array(); + $this->assertTrue(isset($deleted_fields[$body_field['uuid']])); + $this->assertTrue(isset($deleted_fields[$field_test_import->uuid])); + + // Run purge_batch(). + field_purge_batch(10); + + // Check that the deleted fields are removed from state. + $deleted_fields = state()->get('field.field.deleted') ?: array(); + $this->assertTrue(empty($deleted_fields), 'Fields are deleted'); + + // Check all config files are gone. + $active = $this->container->get('config.storage'); + $this->assertIdentical($active->listAll($this->body_field_name), array()); + $this->assertIdentical($active->listAll($this->test_import_field_name), array()); + $this->assertIdentical($active->listAll($this->body_instance_name), array()); + $this->assertIdentical($active->listAll($this->test_import_instance_name), array()); + } +} diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php index 3115851..5b3c5ab 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php @@ -65,18 +65,18 @@ function testFieldInfo() { 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'test_field', ); - field_create_field($field); + $field = field_create_field($field); $fields = field_info_fields(); $this->assertEqual(count($fields), count($core_fields) + 1, 'One new field exists'); - $this->assertEqual($fields[$field['field_name']]['field_name'], $field['field_name'], 'info fields contains field name'); - $this->assertEqual($fields[$field['field_name']]['type'], $field['type'], 'info fields contains field type'); - $this->assertEqual($fields[$field['field_name']]['module'], 'field_test', 'info fields contains field module'); + $this->assertEqual($fields[$field['field_name']]->field_name, $field['field_name'], 'info fields contains field name'); + $this->assertEqual($fields[$field['field_name']]->type, $field['type'], 'info fields contains field type'); + $this->assertEqual($fields[$field['field_name']]->module, 'field_test', 'info fields contains field module'); $settings = array('test_field_setting' => 'dummy test string'); foreach ($settings as $key => $val) { - $this->assertEqual($fields[$field['field_name']]['settings'][$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val))); + $this->assertEqual($fields[$field['field_name']]->settings[$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val))); } - $this->assertEqual($fields[$field['field_name']]['cardinality'], 1, 'info fields contains cardinality 1'); - $this->assertEqual($fields[$field['field_name']]['active'], 1, 'info fields contains active 1'); + $this->assertEqual($fields[$field['field_name']]->cardinality, 1, 'info fields contains cardinality 1'); + $this->assertEqual($fields[$field['field_name']]->active, 1, 'info fields contains active 1'); // Create an instance, verify that it shows up $instance = array( @@ -90,8 +90,11 @@ function testFieldInfo() { 'widget' => array( 'type' => 'test_field_widget', 'settings' => array( - 'test_setting' => 999))); - field_create_instance($instance); + 'test_setting' => 999 + ) + ) + ); + $instance = field_create_instance($instance); $info = entity_get_info('test_entity'); $instances = field_info_instances('test_entity', $instance['bundle']); @@ -143,13 +146,9 @@ function testFieldPrepare() { // Simulate a stored field definition missing a field setting (e.g. a // third-party module adding a new field setting has been enabled, and // existing fields do not know the setting yet). - $data = db_query('SELECT data FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name']))->fetchField(); - $data = unserialize($data); - $data['settings'] = array(); - db_update('field_config') - ->fields(array('data' => serialize($data))) - ->condition('field_name', $field_definition['field_name']) - ->execute(); + $field = entity_load('field_entity', $field_definition['field_name']); + $field['settings'] = array(); + field_update_field($field); field_cache_clear(); @@ -158,7 +157,7 @@ function testFieldPrepare() { // Check that all expected settings are in place. $field_type = field_info_field_types($field_definition['type']); - $this->assertIdentical($field['settings'], $field_type['settings'], 'All expected default field settings are present.'); + $this->assertEqual($field['settings'], $field_type['settings'], 'All expected default field settings are present.'); } /** @@ -180,25 +179,18 @@ function testInstancePrepare() { // Simulate a stored instance definition missing various settings (e.g. a // third-party module adding instance or widget settings has been enabled, // but existing instances do not know the new settings). - $data = db_query('SELECT data FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $instance_definition['field_name'], ':bundle' => $instance_definition['bundle']))->fetchField(); - $data = unserialize($data); - $data['settings'] = array(); - $data['widget']['settings'] = 'unavailable_widget'; - $data['widget']['settings'] = array(); - db_update('field_config_instance') - ->fields(array('data' => serialize($data))) - ->condition('field_name', $instance_definition['field_name']) - ->condition('bundle', $instance_definition['bundle']) - ->execute(); - - field_cache_clear(); + $instance = entity_load('field_instance', $instance_definition['entity_type'] . '.' . $instance_definition['bundle'] . '.' . $instance_definition['field_name']); + $instance['settings'] = array(); + $instance['widget']['settings'] = 'unavailable_widget'; + $instance['widget']['settings'] = array(); + field_update_instance($instance); // Read the instance back. $instance = field_info_instance($instance_definition['entity_type'], $instance_definition['field_name'], $instance_definition['bundle']); // Check that all expected instance settings are in place. $field_type = field_info_field_types($field_definition['type']); - $this->assertIdentical($instance['settings'], $field_type['instance_settings'] , 'All expected instance settings are present.'); + $this->assertEqual($instance['settings'], $field_type['instance_settings'] , 'All expected instance settings are present.'); // Check that the default widget is used and expected settings are in place. $widget = $instance->getWidget(); diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php index 90fcc05..a6a3504 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php @@ -8,6 +8,7 @@ namespace Drupal\field\Tests; use Drupal\field\FieldException; +use Drupal\field\Plugin\Core\Entity\FieldInstance; class FieldInstanceCrudTest extends FieldTestBase { @@ -35,7 +36,7 @@ function setUp() { 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'test_field', ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance_definition = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -55,26 +56,24 @@ function setUp() { function testCreateFieldInstance() { field_create_instance($this->instance_definition); - // Read the raw record from the {field_config_instance} table. - $result = db_query('SELECT * FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $this->instance_definition['field_name'], ':bundle' => $this->instance_definition['bundle'])); - $record = $result->fetchAssoc(); - $record['data'] = unserialize($record['data']); + // Read the configuration. + $instance = entity_load('field_instance', $this->instance_definition['entity_type'] . '.' . $this->instance_definition['bundle'] . '.' . $this->instance_definition['field_name']); $field_type = field_info_field_types($this->field['type']); $widget_type = field_info_widget_types($field_type['default_widget']); // Check that the ID key is filled in. - $this->assertIdentical($record['id'], $this->instance_definition['id'], 'The instance id is filled in'); + //$this->assertIdentical($record['id'], $this->instance_definition['id'], 'The instance id is filled in'); // Check that default values are set. - $this->assertIdentical($record['data']['required'], FALSE, 'Required defaults to false.'); - $this->assertIdentical($record['data']['label'], $this->instance_definition['field_name'], 'Label defaults to field name.'); - $this->assertIdentical($record['data']['description'], '', 'Description defaults to empty string.'); - $this->assertIdentical($record['data']['widget']['type'], $field_type['default_widget'], 'Default widget has been written.'); + $this->assertEqual($instance['required'], FALSE, 'Required defaults to false.'); + $this->assertIdentical($instance['label'], $this->instance_definition['field_name'], 'Label defaults to field name.'); + $this->assertIdentical($instance['description'], '', 'Description defaults to empty string.'); + $this->assertIdentical($instance['widget']['type'], $field_type['default_widget'], 'Default widget has been written.'); // Check that default settings are set. - $this->assertIdentical($record['data']['settings'], $field_type['instance_settings'] , 'Default instance settings have been written.'); - $this->assertIdentical($record['data']['widget']['settings'], $widget_type['settings'] , 'Default widget settings have been written.'); + $this->assertEqual($instance['settings'], $field_type['instance_settings'] , 'Default instance settings have been written.'); + $this->assertIdentical($instance['widget']['settings'], $widget_type['settings'] , 'Default widget settings have been written.'); // Guarantee that the field/bundle combination is unique. try { @@ -139,7 +138,9 @@ function testReadFieldInstance() { // Read the instance back. $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); - $this->assertTrue($this->instance_definition == $instance, 'The field was properly read.'); + $this->assertTrue($this->instance_definition['field_name'] == $instance['field_name'], 'The field was properly read.'); + $this->assertTrue($this->instance_definition['entity_type'] == $instance['entity_type'], 'The field was properly read.'); + $this->assertTrue($this->instance_definition['bundle'] == $instance['bundle'], 'The field was properly read.'); } /** @@ -159,10 +160,10 @@ function testUpdateFieldInstance() { field_update_instance($instance); $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); - $this->assertEqual($instance['required'], $instance_new['required'], '"required" change is saved'); - $this->assertEqual($instance['label'], $instance_new['label'], '"label" change is saved'); - $this->assertEqual($instance['description'], $instance_new['description'], '"description" change is saved'); - $this->assertEqual($instance['widget']['settings']['test_widget_setting'], $instance_new['widget']['settings']['test_widget_setting'], 'Widget setting change is saved'); + $this->assertEqual($instance['required'], $instance_new->required, '"required" change is saved'); + $this->assertEqual($instance['label'], $instance_new->label, '"label" change is saved'); + $this->assertEqual($instance['description'], $instance_new->description, '"description" change is saved'); + $this->assertEqual($instance['widget']['settings']['test_widget_setting'], $instance_new->widget_settings['settings']['test_widget_setting'], 'Widget setting change is saved'); $this->assertEqual($instance['widget']['weight'], $instance_new['widget']['weight'], 'Widget weight change is saved'); // Check that changing the widget type updates the default settings. @@ -213,7 +214,9 @@ function testDeleteFieldInstance() { // Make sure the field is deleted when its last instance is deleted. field_delete_instance($another_instance); - $field = field_read_field($another_instance['field_name'], array('include_deleted' => TRUE)); - $this->assertTrue(!empty($field['deleted']), 'A deleted field is marked for deletion after all its instances have been marked for deletion.'); + $deleted_fields = state()->get('field.field.deleted'); + $this->assertTrue(isset($deleted_fields[$another_instance['field_id']]), 'A deleted field is marked for deletion.'); + $field = field_read_field(array('field_name' => $another_instance['field_name'])); + $this->assertFalse($field, 'The field marked to be deleted is not found anymore in the configuration.'); } } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldItemUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldItemUnitTestBase.php index e201fb5..dd9b6a8 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldItemUnitTestBase.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldItemUnitTestBase.php @@ -24,8 +24,6 @@ class FieldItemUnitTestBase extends DrupalUnitTestBase { public function setUp() { parent::setUp(); $this->installSchema('system', 'sequences'); - $this->installSchema('field', 'field_config'); - $this->installSchema('field', 'field_config_instance'); $this->installSchema('entity_test', 'entity_test'); } diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php index 2f5dbee..a1ab806 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php @@ -57,7 +57,7 @@ function testFieldFormSingle() { $this->field = $this->field_single; $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -123,7 +123,7 @@ function testFieldFormDefaultValue() { $this->instance['field_name'] = $this->field_name; $default = rand(1, 127); $this->instance['default_value'] = array(array('value' => $default)); - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -147,7 +147,7 @@ function testFieldFormSingleRequired() { $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; $this->instance['required'] = TRUE; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -185,7 +185,7 @@ function testFieldFormUnlimited() { $this->field = $this->field_unlimited; $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -265,7 +265,7 @@ function testFieldFormMultivalueWithRequiredRadio() { $this->field = $this->field_unlimited; $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -307,7 +307,7 @@ function testFieldFormJSAddMore() { $this->field = $this->field_unlimited; $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -367,7 +367,7 @@ function testFieldFormMultipleWidget() { $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; $this->instance['widget']['type'] = 'test_field_widget_multiple'; - field_create_field($this->field); + $this->field = field_create_field($this->field); field_create_instance($this->instance); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -406,7 +406,7 @@ function testFieldFormAccess() { $field_name = $field['field_name']; $instance = $this->instance; $instance['field_name'] = $field_name; - field_create_field($field); + $this->field = field_create_field($field); field_create_instance($instance); // Create a field with no edit access - see field_test_field_access(). diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php index f2ada97..11401a4 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php @@ -47,6 +47,7 @@ function setUp() { ); field_create_field($field); $this->field = field_read_field($this->field_name); + $this->field_definition = $field; $instance = array( 'field_name' => $this->field_name, @@ -55,6 +56,7 @@ function setUp() { ); field_create_instance($instance); $this->instance = field_read_instance('test_entity', $this->field_name, 'test_bundle'); + $this->instance_definition = $instance; for ($i = 0; $i < 3; ++$i) { $language = new Language(array( @@ -71,7 +73,7 @@ function setUp() { function testFieldAvailableLanguages() { // Test 'translatable' fieldable info. field_test_entity_info_translatable('test_entity', FALSE); - $field = $this->field; + $field = clone($this->field); $field['field_name'] .= '_untranslatable'; // Enable field translations for the entity. @@ -245,9 +247,9 @@ function testTranslatableFieldSaveLoad() { // Test default values. $field_name_default = drupal_strtolower($this->randomName() . '_field_name'); - $field = $this->field; + $field = $this->field_definition; $field['field_name'] = $field_name_default; - $instance = $this->instance; + $instance = $this->instance_definition; $instance['field_name'] = $field_name_default; $default = rand(1, 127); $instance['default_value'] = array(array('value' => $default)); @@ -312,7 +314,7 @@ function testFieldDisplayLanguage() { 'entity_type' => $entity_type, 'bundle' => 'test_bundle', ); - field_create_instance($instance); + $this->instance = field_create_instance($instance); $entity = field_test_create_entity(1, 1, $this->instance['bundle']); $instances = field_info_instances($entity_type, $this->instance['bundle']); diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php index 1c8d3f5..80c06d9 100644 --- a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php @@ -62,10 +62,10 @@ protected function setUp() { $edit[$field['field_name']][LANGUAGE_NOT_SPECIFIED][0]['value'] = $this->randomName(8); } for ($j = 0; $j < 5; $j++) { - $edit[$this->fields[3]['field_name']][LANGUAGE_NOT_SPECIFIED][$j]['value'] = $this->randomName(8); + $edit[$this->fields[3]->field_name][LANGUAGE_NOT_SPECIFIED][$j]['value'] = $this->randomName(8); } // Set this field to be empty. - $edit[$this->fields[4]['field_name']] = array(LANGUAGE_NOT_SPECIFIED => array(0 => array('value' => NULL))); + $edit[$this->fields[4]->field_name] = array(LANGUAGE_NOT_SPECIFIED => array(0 => array('value' => NULL))); $this->nodes[$i] = $this->drupalCreateNode($edit); } @@ -114,8 +114,8 @@ public function _testSimpleFieldRender() { public function _testFormatterSimpleFieldRender() { $view = views_get_view('test_view_fieldapi'); $this->prepareView($view); - $view->displayHandlers->get('default')->options['fields'][$this->fields[0]['field_name']]['type'] = 'text_trimmed'; - $view->displayHandlers->get('default')->options['fields'][$this->fields[0]['field_name']]['settings'] = array( + $view->displayHandlers->get('default')->options['fields'][$this->fields[0]->field_name]['type'] = 'text_trimmed'; + $view->displayHandlers->get('default')->options['fields'][$this->fields[0]->field_name]['settings'] = array( 'trim_length' => 3, ); $this->executeView($view); @@ -123,14 +123,14 @@ public function _testFormatterSimpleFieldRender() { // Take sure that the formatter works as expected. // @TODO: actually there should be a specific formatter. for ($i = 0; $i < 2; $i++) { - $rendered_field = $view->style_plugin->get_field($i, $this->fields[0]['field_name']); + $rendered_field = $view->style_plugin->get_field($i, $this->fields[0]->field_name); $this->assertEqual(strlen($rendered_field), 3); } } public function _testMultipleFieldRender() { $view = views_get_view('test_view_fieldapi'); - $field_name = $this->fields[3]['field_name']; + $field_name = $this->fields[3]->field_name; // Test delta limit. $this->prepareView($view); @@ -150,7 +150,7 @@ public function _testMultipleFieldRender() { } // Test that an empty field is rendered without error. - $rendered_field = $view->style_plugin->get_field(4, $this->fields[4]['field_name']); + $rendered_field = $view->style_plugin->get_field(4, $this->fields[4]->field_name); $view->destroy(); diff --git a/core/modules/field/tests/modules/field_test/field_test.field.inc b/core/modules/field/tests/modules/field_test/field_test.field.inc index 7166f4b..28f2b55 100644 --- a/core/modules/field/tests/modules/field_test/field_test.field.inc +++ b/core/modules/field/tests/modules/field_test/field_test.field.inc @@ -77,7 +77,7 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan foreach ($items as $id => $item) { // To keep the test non-intrusive, only act for instances with the // test_hook_field_load setting explicitly set to TRUE. - if (!empty($instances[$id]['settings']['test_hook_field_load'])) { + if (!empty($instances[$id]->settings['test_hook_field_load'])) { foreach ($item as $delta => $value) { // Don't add anything on empty values. if ($value) { diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index 03094dd..82661ed 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -96,7 +96,7 @@ function field_test_field_test_op_multiple($entity_type, $entities, $field, $ins // language. To verify this we try to access all the passed data structures // by entity id. If they are grouped correctly, one entity, one instance and // one array of items should be available for each entity id. - $field_name = $instances[$id]['field_name']; + $field_name = $instances[$id]->field_name; $result[$id] = array($langcode => hash('sha256', serialize(array($entity_type, $entity, $field_name, $langcode, $items[$id])))); } return $result; @@ -217,7 +217,7 @@ function field_test_field_attach_view_alter(&$output, $context) { */ function field_test_field_widget_properties_alter(&$widget, $context) { // Make the alter_test_text field 42 characters for nodes and comments. - if (in_array($context['entity_type'], array('node', 'comment')) && ($context['field']['field_name'] == 'alter_test_text')) { + if (in_array($context['entity_type'], array('node', 'comment')) && ($context['field']->field_name == 'alter_test_text')) { $widget['settings']['size'] = 42; } } @@ -227,7 +227,7 @@ function field_test_field_widget_properties_alter(&$widget, $context) { */ function field_test_field_widget_properties_user_alter(&$widget, $context) { // Always use buttons for the alter_test_options field on user forms. - if ($context['field']['field_name'] == 'alter_test_options') { + if ($context['field']->field_name == 'alter_test_options') { $widget['type'] = 'options_buttons'; } } @@ -236,7 +236,7 @@ function field_test_field_widget_properties_user_alter(&$widget, $context) { * Implements hook_field_widget_form_alter(). */ function field_test_field_widget_form_alter(&$element, &$form_state, $context) { - switch ($context['field']['field_name']) { + switch ($context['field']->field_name) { case 'alter_test_text': drupal_set_message('Field size: ' . $context['instance']->getWidget()->getSetting('size')); break; diff --git a/core/modules/field/tests/modules/field_test/field_test.storage.inc b/core/modules/field/tests/modules/field_test/field_test.storage.inc index a53b941..067e07d 100644 --- a/core/modules/field/tests/modules/field_test/field_test.storage.inc +++ b/core/modules/field/tests/modules/field_test/field_test.storage.inc @@ -89,7 +89,7 @@ function field_test_field_storage_load($entity_type, $entities, $age, $fields, $ foreach ($fields as $field_id => $ids) { $field = field_info_field_by_id($field_id); $field_name = $field['field_name']; - $field_data = $data[$field['id']]; + $field_data = $data[$field['uuid']]; $sub_table = $load_current ? 'current' : 'revisions'; $delta_count = array(); foreach ($field_data[$sub_table] as $row) { @@ -206,7 +206,7 @@ function field_test_field_storage_delete(EntityInterface $entity, $fields) { function field_test_field_storage_purge(EntityInterface $entity, $field, $instance) { $data = _field_test_storage_data(); - $field_data = &$data[$field['id']]; + $field_data = &$data[$field['uuid']]; foreach (array('current', 'revisions') as $sub_table) { foreach ($field_data[$sub_table] as $key => $row) { if ($row->type == $entity->entityType() && $row->entity_id == $entity->id()) { @@ -249,7 +249,7 @@ function field_test_field_storage_query($field_id, $conditions, $count, &$cursor $field = field_info_field_by_id($field_id); $field_columns = array_keys($field['columns']); - $field_data = $data[$field['id']]; + $field_data = $data[$field['uuid']]; $sub_table = $load_current ? 'current' : 'revisions'; // We need to sort records by entity type and entity id. usort($field_data[$sub_table], '_field_test_field_storage_query_sort_helper'); @@ -267,7 +267,7 @@ function field_test_field_storage_query($field_id, $conditions, $count, &$cursor break; } - if ($row->field_id == $field['id']) { + if ($row->field_id == $field['uuid']) { $match = TRUE; $condition_deleted = FALSE; // Add conditions. @@ -372,7 +372,7 @@ function field_test_field_storage_create_field($field) { $data = _field_test_storage_data(); - $data[$field['id']] = array( + $data[$field['uuid']] = array( 'current' => array(), 'revisions' => array(), ); @@ -386,7 +386,7 @@ function field_test_field_storage_create_field($field) { function field_test_field_storage_delete_field($field) { $data = _field_test_storage_data(); - $field_data = &$data[$field['id']]; + $field_data = &$data[$field['uuid']]; foreach (array('current', 'revisions') as $sub_table) { foreach ($field_data[$sub_table] as &$row) { $row->deleted = TRUE; @@ -403,7 +403,7 @@ function field_test_field_storage_delete_instance($instance) { $data = _field_test_storage_data(); $field = field_info_field($instance['field_name']); - $field_data = &$data[$field['id']]; + $field_data = &$data[$field['uuid']]; foreach (array('current', 'revisions') as $sub_table) { foreach ($field_data[$sub_table] as &$row) { if ($row->bundle == $instance['bundle']) { @@ -431,9 +431,9 @@ function field_test_field_attach_rename_bundle($bundle_old, $bundle_new) { // We need to account for deleted or inactive fields and instances. $instances = field_read_instances(array('bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE)); foreach ($instances as $field_name => $instance) { - $field = field_info_field_by_id($instance['field_id']); - if ($field['storage']['type'] == 'field_test_storage') { - $field_data = &$data[$field['id']]; + $field = field_info_field_by_id($instance['uuid']); + if ($field && $field['storage']['type'] == 'field_test_storage') { + $field_data = &$data[$field['uuid']]; foreach (array('current', 'revisions') as $sub_table) { foreach ($field_data[$sub_table] as &$row) { if ($row->bundle == $bundle_old) { @@ -454,9 +454,9 @@ function field_test_field_attach_delete_bundle($entity_type, $bundle, $instances $data = _field_test_storage_data(); foreach ($instances as $field_name => $instance) { - $field = field_info_field($field_name); - if ($field['storage']['type'] == 'field_test_storage') { - $field_data = &$data[$field['id']]; + $field = field_info_field($instance['field_name']); + if ($field && $field['storage']['type'] == 'field_test_storage') { + $field_data = &$data[$field['uuid']]; foreach (array('current', 'revisions') as $sub_table) { foreach ($field_data[$sub_table] as &$row) { if ($row->bundle == $bundle_old) { diff --git a/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 new file mode 100644 index 0000000..45afef5 --- /dev/null +++ b/core/modules/field/tests/modules/field_test_config/config/field.field.field_test_import.yml @@ -0,0 +1,49 @@ +id: field_test_import +uuid: fb38277f-1fd4-49d5-8d09-9d7037fdcce9 +field_name: field_test_import +type: text +translatable: false +entity_types: { } +cardinality: '1' +locked: false +settings: + max_length: '255' +module: text +active: 1 +deleted: 0 +storage_type: field_sql_storage +storage_module: field_sql_storage +storage_active: 1 +storage: + type: field_sql_storage + settings: { } + module: field_sql_storage + active: 1 + details: + sql: + FIELD_LOAD_CURRENT: + field_data_field_test_import: + value: field_test_import_value + format: field_test_import_format + FIELD_LOAD_REVISION: + field_revision_field_test_import: + value: field_test_import_value + format: field_test_import_format +columns: + value: + type: varchar + length: '255' + 'not null': false + format: + type: varchar + length: 255 + 'not null': false +'foreign_keys': + format: + table: filter_format + columns: + format: format +indexes: + format: + - format +langcode: und diff --git a/core/modules/field/tests/modules/field_test_config/config/field.instance.node.test_import.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.instance.node.test_import.field_test_import.yml new file mode 100644 index 0000000..3b1da8b --- /dev/null +++ b/core/modules/field/tests/modules/field_test_config/config/field.instance.node.test_import.field_test_import.yml @@ -0,0 +1,22 @@ +id: node.test_import.field_test_import +uuid: 392b4e9d-6157-412e-9603-3d622512f498 +field_name: field_test_import +entity_type: node +bundle: test_import +label: 'Test import field' +widget: + weight: '-2' + type: text_textfield + module: text + active: 0 + settings: + size: '60' +field_id: fb38277f-1fd4-49d5-8d09-9d7037fdcce9 +settings: + text_processing: '0' + user_register_form: false +required: 0 +description: '' +deleted: 0 +default_value: null +langcode: und diff --git a/core/modules/field/tests/modules/field_test_config/field_test_config.info b/core/modules/field/tests/modules/field_test_config/field_test_config.info new file mode 100644 index 0000000..49b0509 --- /dev/null +++ b/core/modules/field/tests/modules/field_test_config/field_test_config.info @@ -0,0 +1,6 @@ +name = "Field API configuration tests" +description = "Support module for the Field API configuration tests." +core = 8.x +package = Testing +version = VERSION +hidden = TRUE diff --git a/core/modules/field/tests/modules/field_test_config/field_test_config.module b/core/modules/field/tests/modules/field_test_config/field_test_config.module new file mode 100644 index 0000000..e208464 --- /dev/null +++ b/core/modules/field/tests/modules/field_test_config/field_test_config.module @@ -0,0 +1,6 @@ + TRUE, 'include_inactive' => TRUE)); - drupal_load('module', 'field_sql_storage'); + // It's not safe to call field_read_fields() during maintenance mode. + if (!defined('MAINTENANCE_MODE')) { + $fields = entity_load_multiple('field_entity'); foreach ($fields as $field) { if ($field['storage']['type'] == 'field_sql_storage') { - $schema += _field_sql_storage_schema($field); + $schema += _field_sql_storage_schema((object) $field); } } } + return $schema; } @@ -113,8 +114,8 @@ function field_sql_storage_update_8000(&$sandbox) { // Update schema. foreach ($fields as $field) { - $data_table = _field_sql_storage_tablename($field); - $revision_table = _field_sql_storage_revision_tablename($field); + $data_table = _field_sql_storage_tablename((object) $field); + $revision_table = _field_sql_storage_revision_tablename((object) $field); $table_info = array($data_table => $primary_key_data, $revision_table => $primary_key_revision); foreach ($table_info as $table => $primary_key) { diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module index accca35..29bfcf3 100644 --- a/core/modules/field_sql_storage/field_sql_storage.module +++ b/core/modules/field_sql_storage/field_sql_storage.module @@ -45,7 +45,7 @@ function field_sql_storage_field_storage_info() { */ function _field_sql_storage_tablename($field) { if ($field['deleted']) { - return "field_deleted_data_{$field['id']}"; + return "field_deleted_data_" . $field->generate_table_id(); } else { return "field_data_{$field['field_name']}"; @@ -63,7 +63,7 @@ function _field_sql_storage_tablename($field) { */ function _field_sql_storage_revision_tablename($field) { if ($field['deleted']) { - return "field_deleted_revision_{$field['id']}"; + return "field_deleted_revision_" . $field->generate_table_id(); } else { return "field_revision_{$field['field_name']}"; @@ -178,7 +178,13 @@ function _field_sql_storage_schema($field) { ), ); - $field += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array()); + $schema_properties = array('columns' => array(), 'indexes' => array(), 'foreign keys' => array()); + foreach ($schema_properties as $key => $value) { + if (!isset($field->data[$key])) { + $field->data[$key] = $value; + } + } + // Add field columns. foreach ($field['columns'] as $column_name => $attributes) { $real_name = _field_sql_storage_columnname($field['field_name'], $column_name); @@ -204,7 +210,7 @@ function _field_sql_storage_schema($field) { } // Add foreign keys. - foreach ($field['foreign keys'] as $specifier => $specification) { + foreach ($field['foreign_keys'] as $specifier => $specification) { $real_name = _field_sql_storage_indexname($field['field_name'], $specifier); $current['foreign keys'][$real_name]['table'] = $specification['table']; foreach ($specification['columns'] as $column => $referenced) { diff --git a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php index e79757e..0707bfc 100644 --- a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php +++ b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php @@ -413,7 +413,7 @@ function testFieldStorageDetails() { // Test current and revision storage details together because the columns // are the same. - foreach ((array) $this->field['columns'] as $column_name => $attributes) { + foreach ($this->field['columns'] as $column_name => $attributes) { $storage_column_name = _field_sql_storage_columnname($this->field['field_name'], $column_name); $this->assertEqual($details[FIELD_LOAD_CURRENT][$current][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $current))); $this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision))); @@ -431,8 +431,8 @@ function testFieldSqlStorageForeignKeys() { // Retrieve the field and instance with field_info and verify the foreign // keys are in place. $field = field_info_field($field_name); - $this->assertEqual($field['foreign keys']['format']['table'], 'filter_format', 'Foreign key table name preserved through CRUD'); - $this->assertEqual($field['foreign keys']['format']['columns']['format'], 'format', 'Foreign key column name preserved through CRUD'); + $this->assertEqual($field['foreign_keys']['format']['table'], 'filter_format', 'Foreign key table name preserved through CRUD'); + $this->assertEqual($field['foreign_keys']['format']['columns']['format'], 'format', 'Foreign key column name preserved through CRUD'); // Now grab the SQL schema and verify that too. $schema = drupal_get_schema(_field_sql_storage_tablename($field)); $this->assertEqual(count($schema['foreign keys']), 1, t("There is 1 foreign key in the schema")); diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc index 566959b..d44bac9 100644 --- a/core/modules/field_ui/field_ui.admin.inc +++ b/core/modules/field_ui/field_ui.admin.inc @@ -5,7 +5,7 @@ * Administrative interface for custom field type creation. */ -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\field_ui\FieldOverview; use Drupal\field_ui\DisplayOverview; @@ -615,7 +615,9 @@ function field_ui_field_settings_form_submit($form, &$form_state) { $instance = field_info_instance($entity_type, $field['field_name'], $bundle); // Update the field. - $field = array_merge($field, $field_values); + foreach ($field_values as $key => $value) { + $field->{$key} = $value; + } try { field_update_field($field); @@ -865,7 +867,7 @@ function field_ui_field_edit_form($form, &$form_state, $instance) { ); $form['instance']['widget']['active'] = array( '#type' => 'value', - '#value' => !empty($field['instance']['widget']['active']) ? 1 : 0, + '#value' => !empty($instance['widget']['active']) ? 1 : 0, // straight bug ? ); // Add additional field instance settings from the field module. @@ -936,7 +938,10 @@ function field_ui_default_value_widget($field, $instance, &$form, &$form_state) // Insert the widget. Since we do not use the "official" instance definition, // the whole flow cannot use field_invoke_method(). - $items = (array) $instance['default_value']; + $items = array(); + if (!empty($instance['default_value'])) { + $items = (array) $instance['default_value']; + } $element += $instance->getWidget()->form($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); return $element; @@ -1007,7 +1012,7 @@ function field_ui_field_edit_form_submit($form, &$form_state) { // Merge incoming values into the instance. foreach ($form_state['values']['instance'] as $key => $value) { - $instance[$key] = $value; + $instance->$key = $value; } field_update_instance($instance); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php index 925caef..011fd92 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php @@ -159,7 +159,7 @@ public function buildForm(array $form, array &$form_state) { '#links' => $links, ); - if (!empty($instance['locked'])) { + if (!empty($instance->locked)) { $table[$name]['operations'] = array('#value' => t('Locked')); $table[$name]['#attributes']['class'][] = 'menu-disabled'; } @@ -570,7 +570,7 @@ public function submitForm(array &$form, array &$form_state) { // Create the field and instance. try { - field_create_field($field); + $field = field_create_field($field); field_create_instance($instance); // Make sure the field is displayed in the 'default' view mode (using diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php index 45de66e..ee421d6 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php @@ -180,7 +180,7 @@ function testNonInitializedFields() { // Check that no settings have been set for the 'teaser' mode. $instance = field_info_instance('node', 'field_test', $this->type); - $this->assertFalse(isset($instance['display']['teaser'])); + $this->assertFalse(isset($instance->display['teaser'])); // Check that the field appears as 'hidden' on the 'Manage display' page // for the 'teaser' mode. diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc index e3a7d7c..63b60c7 100644 --- a/core/modules/file/file.field.inc +++ b/core/modules/file/file.field.inc @@ -768,7 +768,7 @@ function theme_file_upload_help($variables) { * fid, FALSE if it doesn't. */ function file_field_find_file_reference_column($field) { - foreach ($field['foreign keys'] as $data) { + foreach ($field['foreign_keys'] as $data) { if ($data['table'] == 'file_managed') { foreach ($data['columns'] as $field_column => $column) { if ($column == 'fid') { diff --git a/core/modules/file/file.install b/core/modules/file/file.install index 27a2438..472f7e5 100644 --- a/core/modules/file/file.install +++ b/core/modules/file/file.install @@ -125,8 +125,8 @@ function file_schema() { ), 'id' => array( 'description' => 'The primary key of the object using the file.', - 'type' => 'int', - 'unsigned' => TRUE, + 'type' => 'varchar', + 'length' => 64, 'not null' => TRUE, 'default' => 0, ), @@ -234,6 +234,21 @@ function file_requirements($phase) { } /** + * Implements hook_update_dependencies(). + */ +function file_update_dependencies() { + // The update hook to convert the id column in the column table needs to be + // the first one because user update hooks will be called during system + // update hooks due to other dependencies and the user picture conversion + // might need to save a default image and the field it's stored in, does + // not have an integer id anymore. + $dependencies['system'][8001] = array( + 'file' => 8001, + ); + return $dependencies; +} + +/** * Converts default_file_main variable to config. * * @ingroup config_upgrade @@ -245,3 +260,17 @@ function file_update_8000() { 'file_icon_directory'=>'icon.directory', )); } + +/** + * Convert the id column in file_usage to store UUID's. + */ +function file_update_8001() { + $spec = array( + 'description' => 'The primary key of the object using the file.', + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'default' => '', + ); + db_change_field('file_usage', 'id', 'id', $spec); +} diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install index b1e63de..3173cfb 100644 --- a/core/modules/forum/forum.install +++ b/core/modules/forum/forum.install @@ -22,10 +22,6 @@ function forum_install() { * Implements hook_enable(). */ function forum_enable() { - // If we enable forum at the same time as taxonomy we need to call - // field_associate_fields() as otherwise the field won't be enabled until - // hook modules_enabled is called which takes place after hook_enable events. - field_associate_fields('taxonomy'); // Create the forum vocabulary if it does not exist. // @todo Change Forum module so forum.settings can contain the vocabulary's @@ -55,7 +51,7 @@ function forum_enable() { } // Create the 'taxonomy_forums' field if it doesn't already exist. - if (!field_info_field('taxonomy_forums')) { + if (!field_read_field('taxonomy_forums', array('include_inactive' => TRUE))) { $field = array( 'field_name' => 'taxonomy_forums', 'type' => 'taxonomy_term_reference', diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc index 11152ae..16f8d21 100644 --- a/core/modules/image/image.field.inc +++ b/core/modules/image/image.field.inc @@ -232,8 +232,8 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $ if (empty($items[$id])) { $fid = 0; // Use the default for the instance if one is available. - if (!empty($instances[$id]['settings']['default_image'])) { - $fid = $instances[$id]['settings']['default_image']; + if (!empty($instances[$id]->settings['default_image'])) { + $fid = $instances[$id]->settings['default_image']; } // Otherwise, use the default for the field. elseif (!empty($field['settings']['default_image'])) { diff --git a/core/modules/image/image.module b/core/modules/image/image.module index d7b02d0..b8f6c58 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -427,12 +427,12 @@ function image_field_update_field($field, $prior_field, $has_data) { if ($file_new) { $file_new->status = FILE_STATUS_PERMANENT; $file_new->save(); - file_usage()->add($file_new, 'image', 'default_image', $field['id']); + file_usage()->add($file_new, 'image', 'default_image', $field['uuid']); } // Is there an old file? if ($fid_old && ($file_old = file_load($fid_old))) { - file_usage()->delete($file_old, 'image', 'default_image', $field['id']); + file_usage()->delete($file_old, 'image', 'default_image', $field['uuid']); } } @@ -495,11 +495,11 @@ function image_field_update_instance($instance, $prior_instance) { if ($file_new) { $file_new->status = FILE_STATUS_PERMANENT; $file_new->save(); - file_usage()->add($file_new, 'image', 'default_image', $instance['id']); + file_usage()->add($file_new, 'image', 'default_image', $instance['uuid']); } // Delete the old file, if present. if ($fid_old && ($file_old = file_load($fid_old))) { - file_usage()->delete($file_old, 'image', 'default_image', $instance['id']); + file_usage()->delete($file_old, 'image', 'default_image', $instance['uuid']); } } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php index 7c42a5b..a361ca7 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -146,8 +146,8 @@ function testImageFieldSettings() { $widget_settings = array( 'preview_image_style' => 'medium', ); - $field = $this->createImageField($field_name, 'article', array(), $instance_settings, $widget_settings); - $field['deleted'] = 0; + $this->createImageField($field_name, 'article', array(), $instance_settings, $widget_settings); + $field = field_info_field($field_name); $table = _field_sql_storage_tablename($field); $schema = drupal_get_schema($table, TRUE); $instance = field_info_instance('node', $field_name, 'article'); diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php index a608873..e3a952f 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php @@ -48,7 +48,7 @@ function testURLValidation() { 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'link', ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -63,7 +63,7 @@ function testURLValidation() { ), ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], array( 'type' => 'link', @@ -116,7 +116,7 @@ function testLinkTitle() { 'field_name' => drupal_strtolower($this->randomName()), 'type' => 'link', ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -132,7 +132,7 @@ function testLinkTitle() { ), ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], array( 'type' => 'link', @@ -226,7 +226,7 @@ function testLinkFormatter() { 'type' => 'link', 'cardinality' => 2, ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -362,7 +362,7 @@ function testLinkSeparateFormatter() { 'type' => 'link', 'cardinality' => 2, ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', diff --git a/core/modules/link/link.module b/core/modules/link/link.module index f8ee409..25799df 100644 --- a/core/modules/link/link.module +++ b/core/modules/link/link.module @@ -289,7 +289,7 @@ function link_field_formatter_settings_form($field, $instance, $view_mode, $form * Implements hook_field_formatter_settings_form(). */ function link_field_formatter_settings_summary($field, $instance, $view_mode) { - $display = $instance['display'][$view_mode]; + $display = $instance->display[$view_mode]; $settings = $display['settings']; $summary = array(); diff --git a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php index addc5c0..24b8b8b 100644 --- a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php @@ -30,8 +30,6 @@ protected function setUp() { $this->installSchema('node', 'node_type'); $this->installSchema('node', 'node'); $this->installSchema('node', 'node_revision'); - $this->installSchema('field', 'field_config'); - $this->installSchema('field', 'field_config_instance'); } /** diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php index 925828c..79969c9 100644 --- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php +++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php @@ -52,7 +52,7 @@ function testNumberDecimalField() { 'precision' => 8, 'scale' => 4, 'decimal_separator' => '.', ) ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -63,11 +63,6 @@ function testNumberDecimalField() { 'placeholder' => '0.00' ), ), - 'display' => array( - 'default' => array( - 'type' => 'number_decimal', - ), - ), ); field_create_instance($this->instance); entity_get_display('test_entity', 'test_bundle', 'default') diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php index e715f55..a48de2f 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php @@ -46,6 +46,7 @@ function setUp() { 'allowed_values' => array(1 => 'One', 2 => 'Two', 3 => 'Three'), ), ); + $this->field_definition = $this->field; $this->field = field_create_field($this->field); $this->instance = array( @@ -110,18 +111,16 @@ function testUpdateAllowedValues() { // Options are reset when a new field with the same name is created. field_delete_field($this->field_name); - unset($this->field['id']); - $this->field['settings']['allowed_values'] = array(1 => 'One', 2 => 'Two', 3 => 'Three'); - $this->field = field_create_field($this->field); + $field = field_create_field($this->field_definition); $this->instance = array( - 'field_name' => $this->field_name, + 'field_name' => $field['field_name'], 'entity_type' => 'entity_test', 'bundle' => 'entity_test', 'widget' => array( 'type' => 'options_buttons', ), ); - $this->instance = field_create_instance($this->instance); + field_create_instance($this->instance); $entity = entity_create('entity_test', array()); $form = entity_get_form($entity); $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists'); diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php index 023f012..6615f9d 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php @@ -523,7 +523,7 @@ function testOnOffCheckbox() { t('Display setting checkbox is available') ); $this->assertFieldChecked( - 'edit-instance-widget-settings-display-label', + 'edit-instance-widget-settings-settings-display-label', t('Display settings checkbox checked') ); $this->assertFieldByXPath( diff --git a/core/modules/options/options.module b/core/modules/options/options.module index 793b07e..77d75a4 100644 --- a/core/modules/options/options.module +++ b/core/modules/options/options.module @@ -252,7 +252,7 @@ function options_field_update_field($field, $prior_field, $has_data) { function options_allowed_values($field, $instance = NULL, EntityInterface $entity = NULL) { $allowed_values = &drupal_static(__FUNCTION__, array()); - if (!isset($allowed_values[$field['id']])) { + if (!isset($allowed_values[$field['uuid']])) { $function = $field['settings']['allowed_values_function']; // If $cacheable is FALSE, then the allowed values are not statically // cached. See options_test_dynamic_values_callback() for an example of @@ -266,14 +266,14 @@ function options_allowed_values($field, $instance = NULL, EntityInterface $entit } if ($cacheable) { - $allowed_values[$field['id']] = $values; + $allowed_values[$field['uuid']] = $values; } else { return $values; } } - return $allowed_values[$field['id']]; + return $allowed_values[$field['uuid']]; } /** @@ -388,7 +388,7 @@ function options_field_update_forbid($field, $prior_field, $has_data) { */ function _options_values_in_use($field, $values) { if ($values) { - $field = field_info_field_by_id($field['id']); + $field = field_info_field_by_id($field['uuid']); $factory = drupal_container()->get('entity.query'); foreach ($field['bundles'] as $entity_type => $bundle) { $result = $factory->get($entity_type) @@ -477,6 +477,9 @@ function options_field_widget_info() { function options_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { // Abstract over the actual field columns, to allow different field types to // reuse those widgets. + + // Reset internal pointer since we're dealing with objects now. + reset($field['columns']); $value_key = key($field['columns']); $type = str_replace('options_', '', $instance['widget']['type']); diff --git a/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php b/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php index fb7019e..33802db 100644 --- a/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php +++ b/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php @@ -57,7 +57,6 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('field', array('field_config', 'field_config_instance')); $this->installSchema('entity_test', array('entity_test_mulrev', 'entity_test_mulrev_property_revision', 'entity_test_mulrev_property_data')); // Auto-create a field for testing. diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php index 3aeab60..c4efde8 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php @@ -108,10 +108,7 @@ function testEnableModulesInstall() { */ function testEnableModulesInstallContainer() { // Install Node module. - // @todo field_sql_storage and field should technically not be necessary - // for an entity query. $this->enableModules(array('field_sql_storage', 'field', 'node')); - $this->installSchema('field', array('field_config', 'field_config_instance')); $this->installSchema('node', array('node_type', 'node')); // Perform an entity query against node. diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/SelectComplexTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/SelectComplexTest.php index c0f181a..a997a34 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/SelectComplexTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/SelectComplexTest.php @@ -27,11 +27,6 @@ public static function getInfo() { ); } - function setUp() { - parent::setUp(); - $this->installSchema('field', array('field_config', 'field_config_instance')); - } - /** * Tests simple JOIN statements. */ diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryAggregateTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryAggregateTest.php index b957675..d18321a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryAggregateTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryAggregateTest.php @@ -58,8 +58,6 @@ protected function setUp() { parent::setUp(); $this->installSchema('user', 'users'); $this->installSchema('system', 'sequences'); - $this->installSchema('field', 'field_config'); - $this->installSchema('field', 'field_config_instance'); $this->installSchema('entity_test', 'entity_test'); $this->entityStorageController = $this->container->get('plugin.manager.entity')->getStorageController('entity_test'); diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUriTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUriTest.php index 487fc43..6845a7d 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUriTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUriTest.php @@ -33,7 +33,6 @@ protected function setUp() { parent::setUp(); $this->installSchema('system', array('variable', 'url_alias')); - $this->installSchema('field', array('field_config', 'field_config_instance')); $this->installSchema('entity_test', array('entity_test')); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php index c0de21b..b57bf65 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php @@ -71,7 +71,7 @@ public function testEntityDisplayUpgrade() { // Check that the display key in the instance data was removed. $body_instance = field_info_instance('node', 'body', 'article'); - $this->assertTrue(!isset($body_instance['display'])); + $this->assertTrue(!isset($body_instance->display)); // Check that the 'language' extra field is configured as expected. $expected = array( @@ -87,4 +87,16 @@ public function testEntityDisplayUpgrade() { $this->assertEqual($displays['teaser']['content']['language'], $expected['teaser']); } + /** + * Tests upgrade of fields and instances to config. + */ + function testFieldUpgradeToConfig() { + $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.')); + + // Assert the body field and instance on the article are converted. + $body_field = field_info_field('body'); + $this->assertNotNull($body_field, 'The body field has been found.'); + $body_field_instance = field_info_instance('node', 'body', 'article'); + $this->assertNotNull($body_field_instance, 'The body field instance on the article content type has been found.'); + } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php index 04070c9..23eb3da 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php @@ -51,7 +51,7 @@ public function testUserPictureUpgrade() { // Check file usage for the default image. $usage = file_usage()->listUsage($file); $field = field_info_field('user_picture'); - $this->assertEqual(1, $usage['image']['default_image'][$field['id']]); + $this->assertTrue(isset($usage['image']['default_image'][$field['uuid']])); $this->assertEqual($instance['settings']['max_resolution'], '800x800', 'User picture maximum resolution has been migrated.'); $this->assertEqual($instance['settings']['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.'); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php index 3d28ec0..7c0de9a 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php @@ -57,7 +57,7 @@ function setUp() { 'type' => 'options_select', ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('node', 'article', 'default') ->setComponent('taxonomy_' . $this->vocabulary->id(), array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php index 8c5571c..aab02ff 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php @@ -123,7 +123,7 @@ function testTaxonomyTermFieldMultipleVocabularies() { // Verify that field and instance settings are correct. $field_info = field_info_field($this->field_name); - $this->assertEqual(count($field_info['settings']['allowed_values']), 1, 'Only one vocabulary is allowed for the field.'); + $this->assertEqual(count($field_info->settings['allowed_values']), 1, 'Only one vocabulary is allowed for the field.'); // The widget should still be displayed. $this->drupalGet('test-entity/add/test_bundle'); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php index d5de5fa..ff4e250 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php @@ -53,7 +53,7 @@ function setUp() { ), ) ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field_name, 'entity_type' => 'test_entity', @@ -62,7 +62,7 @@ function setUp() { 'type' => 'options_select', ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field_name, array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php index 93cc8d4..fca5b52 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php @@ -49,7 +49,7 @@ function setUp() { 'type' => 'options_select', ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('node', 'article', 'default') ->setComponent($this->instance['field_name'], array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php index ea73152..c1098c7 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php @@ -50,7 +50,7 @@ function setUp() { 'type' => 'options_select', ), ); - field_create_instance($this->instance); + $this->instance = field_create_instance($this->instance); entity_get_display('node', 'article', 'default') ->setComponent('taxonomy_' . $this->vocabulary->id(), array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php index d73302b..e969c15 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/VocabularyUnitTest.php @@ -176,7 +176,7 @@ function testUninstallReinstall() { // removed when the module is uninstalled. $this->field_name = drupal_strtolower($this->randomName() . '_field_name'); $this->field = array('field_name' => $this->field_name, 'type' => 'text', 'cardinality' => 4); - $this->field = field_create_field($this->field); + field_create_field($this->field); $this->instance = array( 'field_name' => $this->field_name, 'entity_type' => 'taxonomy_term', @@ -196,7 +196,6 @@ function testUninstallReinstall() { // an instance of this field on the same bundle name should be successful. $this->vocabulary->enforceIsNew(); taxonomy_vocabulary_save($this->vocabulary); - unset($this->field['id']); field_create_field($this->field); field_create_instance($this->instance); } diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php index f8c585b..bdb99c4 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php @@ -57,7 +57,7 @@ function testTextFieldValidation() { 'max_length' => $max_length, ) ); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', @@ -102,7 +102,7 @@ function _testTextfieldWidgets($field_type, $widget_type) { $entity_type = 'test_entity'; $this->field_name = drupal_strtolower($this->randomName()); $this->field = array('field_name' => $this->field_name, 'type' => $field_type); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field_name, 'entity_type' => 'test_entity', @@ -165,7 +165,7 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) { $entity_type = 'test_entity'; $this->field_name = drupal_strtolower($this->randomName()); $this->field = array('field_name' => $this->field_name, 'type' => $field_type); - field_create_field($this->field); + $this->field = field_create_field($this->field); $this->instance = array( 'field_name' => $this->field_name, 'entity_type' => 'test_entity', diff --git a/core/modules/text/text.module b/core/modules/text/text.module index 07c962e..15a1395 100644 --- a/core/modules/text/text.module +++ b/core/modules/text/text.module @@ -178,7 +178,7 @@ function text_field_load($entity_type, $entities, $field, $instances, $langcode, foreach ($items[$id] as $delta => $item) { // Only process items with a cacheable format, the rest will be handled // by formatters if needed. - if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) { + if (empty($instances[$id]->settings['text_processing']) || filter_format_allowcache($item['format'])) { $items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $item, 'value') : ''; if ($field['type'] == 'text_with_summary') { $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($instances[$id], $langcode, $item, 'summary') : ''; diff --git a/core/modules/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc index 0e2316b..fb6b79f 100644 --- a/core/modules/translation_entity/translation_entity.admin.inc +++ b/core/modules/translation_entity/translation_entity.admin.inc @@ -6,7 +6,8 @@ */ use Drupal\Core\Entity\EntityInterface; -use Drupal\field\FieldInstance; +use Drupal\field\Plugin\Core\Entity\FieldEntity; +use Drupal\field\Plugin\Core\Entity\FieldInstance; /** * Returns a form element to configure field synchronization. @@ -19,7 +20,7 @@ * @return array * A form element to configure field synchronization. */ -function translation_entity_field_sync_widget(array $field, FieldInstance $instance) { +function translation_entity_field_sync_widget(FieldEntity $field, FieldInstance $instance) { $element = array(); if (!empty($field['settings']['column_groups']) && count($field['settings']['column_groups']) > 1) { diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php index 38ca376..9d24e34 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php @@ -199,7 +199,7 @@ function testRegistrationWithUserFields() { 'field_name' => 'test_user_field', 'cardinality' => 1, ); - field_create_field($field); + $field = field_create_field($field); $instance = array( 'field_name' => 'test_user_field', 'entity_type' => 'user', @@ -208,7 +208,7 @@ function testRegistrationWithUserFields() { 'required' => TRUE, 'settings' => array('user_register_form' => FALSE), ); - field_create_instance($instance); + $instance = field_create_instance($instance); // Check that the field does not appear on the registration form. $this->drupalGet('user/register'); diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 10e429c..45edc81 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -315,10 +315,6 @@ function user_install_picture_field() { 'uri_scheme' => 'public', 'default_image' => FALSE, ), - 'storage' => array( - 'type' => 'field_sql_storage', - 'settings' => array(), - ), ); $field = field_create_field($field); @@ -717,7 +713,7 @@ function user_update_8011() { 'settings' => array(), ), ); - _update_7000_field_create_field($field); + $field = _update_7000_field_create_field($field); $instance = array( 'field_name' => 'user_picture', diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php index 5d2b524..172678d 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php @@ -27,7 +27,6 @@ */ protected function setUpFixtures() { $this->installSchema('user', array('users', 'users_roles', 'role_permission')); - $this->installSchema('field', array('field_config', 'field_config_instance')); $this->installConfig(array('user')); parent::setUpFixtures(); diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php index 6416193..b6fe584 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php @@ -66,7 +66,7 @@ function setUp() { ), ), ); - field_create_field($this->tag_field); + $this->tag_field = field_create_field($this->tag_field); // Create an instance of the tag field on one of the content types, and // configure it to display an autocomplete widget. diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install index 85c818c..6ac26fb 100644 --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -155,11 +155,11 @@ function standard_install() { 'type' => 'image', 'cardinality' => 1, 'locked' => FALSE, - 'indexes' => array('fid' => array('fid')), 'settings' => array( 'uri_scheme' => 'public', 'default_image' => FALSE, ), + 'indexes' => array('fid' => array('fid')), 'storage' => array( 'type' => 'field_sql_storage', 'settings' => array(),