Commit 55651cf3 authored by Dries's avatar Dries

Issue #1981314 by pcambra, aspilicious, andypost, swentel: Drop procedural...

Issue #1981314 by pcambra, aspilicious, andypost, swentel: Drop procedural usage of fields in field module.
parent 81b2685c
......@@ -1587,7 +1587,7 @@ function field_entity_bundle_delete($entity_type, $bundle) {
// entity types or bundles.
$instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_inactive' => TRUE));
foreach ($instances as $instance) {
field_delete_instance($instance);
$instance->delete();
}
// Clear the cache.
......
......@@ -24,89 +24,6 @@
* the Field API.
*/
/**
* Creates a field.
*
* This function does not bind the field to any bundle; use
* field_create_instance() for that.
*
* @param array $field
* 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
* - indexes: the field-type indexes, specified by the field type's
* hook_field_schema(). The indexes specified in $field are added
* to those default indexes. It is possible to override the
* definition of a field-type index by providing an index with the
* same name, or to remove it by redefining it as an empty array
* of columns. Overriding field-type indexes should be done
* carefully, for it might seriously affect the site's performance.
* - settings: each omitted setting is given the default value defined in
* hook_field_info().
* - storage:
* - type: the storage backend specified in the
* 'field.settings.default_storage' configuration.
* - settings: each omitted setting is given the default value specified in
* hook_field_storage_info().
*
* @return \Drupal\field\Plugin\Core\Entity\Field
* The field entity.
*
* @throws Drupal\field\FieldException
*
* @deprecated as of Drupal 8.0. Use
* entity_create('field_entity', $definition)->save().
*
* See: @link field Field API data structures @endlink.
*/
function field_create_field(array $field) {
$field = entity_create('field_entity', $field);
$field->save();
return $field;
}
/**
* Updates a field.
*
* Any module may forbid any update for any reason. For example, the
* field's storage module might forbid an update if it would change
* the storage schema while data for the field exists. A field type
* module might forbid an update if it would change existing data's
* semantics, or if there are external dependencies on field settings
* that cannot be updated.
*
* @param mixed $field
* Either the \Drupal\field\Plugin\Core\Entity\Field object to update, or a
* field array structure. If the latter, $field['field_name'] must provided;
* it identifies the field that will be updated to match this structure. Any
* other properties of the field that are not specified in $field will be left
* unchanged, so it is not necessary to pass in a fully populated $field
* structure.
*
* @throws Drupal\field\FieldException
*
* @deprecated as of Drupal 8.0. Use $field->save().
*
* @see field_create_field()
*/
function field_update_field($field) {
// Module developers can still pass in an array of properties.
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.');
}
// Merge incoming values.
foreach ($field as $key => $value) {
$field_loaded[$key] = $value;
}
$field = $field_loaded;
}
$field->save();
}
/**
* Reads a single field record directly from the database.
*
......@@ -161,103 +78,6 @@ function field_read_fields($conditions = array(), $include_additional = array())
return entity_load_multiple_by_properties('field_entity', $conditions);
}
/**
* Marks a field and its instances and data for deletion.
*
* @param $field_name
* The field name to delete.
*
* @deprecated as of Drupal 8.0. Use $field->delete().
*/
function field_delete_field($field_name) {
if ($field = field_info_field($field_name)) {
$field->delete();
}
}
/**
* Creates an instance of a field, binding it to a bundle.
*
* @param array $instance
* A field instance definition array. The field_name, entity_type and
* bundle properties are required. Other properties, if omitted,
* will be given the following default values:
* - label: the field name
* - description: empty string
* - required: FALSE
* - default_value_function: empty string
* - settings: each omitted setting is given the default value specified in
* hook_field_info().
* - widget:
* - type: the default widget specified in hook_field_info().
* - settings: each omitted setting is given the default value specified in
* hook_field_widget_info().
*
* @return \Drupal\field\Plugin\Core\Entity\FieldInstance
* The field instance entity.
*
* @throws Drupal\field\FieldException
*
* @deprecated as of Drupal 8.0. Use
* entity_create('field_instance', $definition)->save().
*
* See: @link field Field API data structures @endlink.
*/
function field_create_instance(array $instance) {
$instance = entity_create('field_instance', $instance);
$instance->save();
return $instance;
}
/**
* Updates an instance of a field.
*
* @param mixed $instance
* Either the \Drupal\field\Plugin\Core\Entity\FieldInstance to update, or an
* associative array representing an instance structure. If the latter, the
* required keys and values are:
* - entity_type: The type of the entity the field is attached to.
* - bundle: The bundle this field belongs to.
* - field_name: The name of an existing field.
* The other array elements represent properties of the instance, and all
* properties must be specified or their default values will be used (except
* internal-use properties, which are assigned automatically). To avoid losing
* the previously stored properties of the instance when making a change,
* first load the instance with field_info_instance(), then override the
* values you want to override, and finally save using this function. Example:
* @code
* // Fetch an instance info array.
* $instance_info = field_info_instance($entity_type, $field_name, $bundle_name);
* // Change a single property in the instance definition.
* $instance_info['definition']['required'] = TRUE;
* // Write the changed definition back.
* field_update_instance($instance_info['definition']);
* @endcode
*
* @throws Drupal\field\FieldException
*
* @deprecated as of Drupal 8.0. Use $instance->save().
*
* @see field_info_instance()
* @see field_create_instance()
*/
function field_update_instance($instance) {
// Module developers can still pass in an array of properties.
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.');
}
// Merge incoming values.
foreach ($instance as $key => $value) {
$instance_loaded[$key] = $value;
}
$instance = $instance_loaded;
}
$instance->save();
}
/**
* Reads a single instance record from the database.
*
......@@ -316,22 +136,6 @@ function field_read_instances($conditions = array(), $include_additional = array
return entity_load_multiple_by_properties('field_instance', $conditions);
}
/**
* Marks a field instance and its data for deletion.
*
* @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
* The field instance.
* @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.
*
* @deprecated as of Drupal 8.0. Use $instance->delete().
*/
function field_delete_instance(FieldInstance $instance, $field_cleanup = TRUE) {
$instance->delete($field_cleanup);
}
/**
* @} End of "defgroup field_crud".
*/
......
......@@ -75,8 +75,7 @@
* field_sql_storage.module, stores field data in the local SQL database.
*
* - @link field_purge Field API bulk data deletion @endlink: Cleans up after
* bulk deletion operations such as field_delete_field() and
* field_delete_instance().
* bulk deletion operations such as deletion of field or field_instance.
*
* - @link field_language Field language API @endlink: Provides native
* multilingual support for the Field API.
......
......@@ -37,7 +37,7 @@ function testActive() {
'type' => 'field_sql_storage',
),
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
// Test disabling and enabling:
// - the field type module,
......
......@@ -16,7 +16,40 @@
*/
class BulkDeleteTest extends FieldUnitTestBase {
protected $field;
/**
* The fields to use in this test.
*
* @var array
*/
protected $fields;
/**
* The entities to use in this test.
*
* @var array
*/
protected $entities;
/**
* The entities to use in this test, keyed by bundle.
*
* @var array
*/
protected $entities_by_bundles;
/**
* The bundles for the entities used in this test.
*
* @var array
*/
protected $bundles;
/**
* The entity type to be used in the test classes.
*
* @var array
*/
protected $entity_type = 'test_entity';
public static function getInfo() {
return array(
......@@ -37,8 +70,7 @@ public static function getInfo() {
* @param $field_name
* A field name whose data should be copied from $entities into the returned
* partial entities.
* @return
* An array of partial entities corresponding to $entities.
* @return array An array of partial entities corresponding to $entities.
*/
protected function convertToPartialEntities($entities, $field_name) {
$partial_entities = array();
......@@ -93,7 +125,6 @@ function setUp() {
parent::setUp();
$this->fields = array();
$this->instances = array();
$this->entities = array();
$this->entities_by_bundles = array();
......@@ -104,29 +135,37 @@ function setUp() {
}
// Create two fields.
$field = array('field_name' => 'bf_1', 'type' => 'test_field', 'cardinality' => 1);
$this->fields[] = field_create_field($field);
$field = array('field_name' => 'bf_2', 'type' => 'test_field', 'cardinality' => 4);
$this->fields[] = field_create_field($field);
$field = entity_create('field_entity', array(
'field_name' => 'bf_1',
'type' => 'test_field',
'cardinality' => 1
));
$field->save();
$this->fields[] = $field;
$field = entity_create('field_entity', array(
'field_name' => 'bf_2',
'type' => 'test_field',
'cardinality' => 4
));
$field->save();
$this->fields[] = $field;
// For each bundle, create an instance of each field, and 10
// entities with values for each field.
$id = 1;
$this->entity_type = 'test_entity';
foreach ($this->bundles as $bundle) {
foreach ($this->fields as $field) {
$instance = array(
'field_name' => $field['field_name'],
entity_create('field_instance', array(
'field_name' => $field->id(),
'entity_type' => $this->entity_type,
'bundle' => $bundle,
);
$this->instances[] = field_create_instance($instance);
))->save();
}
for ($i = 0; $i < 10; $i++) {
$entity = field_test_create_entity($id, $id, $bundle);
foreach ($this->fields as $field) {
$entity->{$field['field_name']}[Language::LANGCODE_NOT_SPECIFIED] = $this->_generateTestFieldValues($field['cardinality']);
$entity->{$field->id()}[Language::LANGCODE_NOT_SPECIFIED] = $this->_generateTestFieldValues($field->cardinality);
}
$entity->save();
$id++;
......@@ -144,14 +183,13 @@ function setUp() {
* the database and that the appropriate Field API functions can
* operate on the deleted data and instance.
*
* This tests how EntityFieldQuery interacts with
* field_delete_instance() and could be moved to FieldCrudTestCase,
* but depends on this class's setUp().
* This tests how EntityFieldQuery interacts with field instance deletion and
* could be moved to FieldCrudTestCase, but depends on this class's setUp().
*/
function testDeleteFieldInstance() {
$bundle = reset($this->bundles);
$field = reset($this->fields);
$field_name = $field['field_name'];
$field_name = $field->id();
$factory = \Drupal::service('entity.query');
// There are 10 entities of this bundle.
......@@ -161,11 +199,11 @@ function testDeleteFieldInstance() {
$this->assertEqual(count($found), 10, 'Correct number of entities found before deleting');
// Delete the instance.
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
$instance = field_info_instance($this->entity_type, $field->id(), $bundle);
$instance->delete();
// The instance still exists, deleted.
$instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$this->assertEqual(count($instances), 1, 'There is one deleted instance');
$this->assertEqual($instances[0]['bundle'], $bundle, 'The deleted instance is for the correct bundle');
......@@ -192,10 +230,10 @@ 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['uuid'], 'deleted' => TRUE));
field_attach_load($this->entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field->uuid, 'deleted' => TRUE));
$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");
$this->assertEqual($this->entities[$id]->{$field->id()}, $entity->{$field->id()}, "Entity $id with deleted data loaded correctly");
}
}
......@@ -211,8 +249,8 @@ function testPurgeInstance() {
$field = reset($this->fields);
// Delete the instance.
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
$instance = field_info_instance($this->entity_type, $field->id(), $bundle);
$instance->delete();
// No field hooks were called.
$mem = field_test_memorize();
......@@ -226,7 +264,7 @@ function testPurgeInstance() {
// There are $count deleted entities left.
$found = \Drupal::entityQuery('test_entity')
->condition('fttype', $bundle)
->condition($field['field_name'] . '.deleted', 1)
->condition($field->id() . '.deleted', 1)
->execute();
$this->assertEqual(count($found), $count, 'Correct number of entities found after purging 2');
}
......@@ -238,7 +276,7 @@ function testPurgeInstance() {
// bundle.
$actual_hooks = field_test_memorize();
$hooks = array();
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
foreach (array_chunk($entities, $batch_size, TRUE) as $chunk_entity) {
$hooks['field_test_field_load'][] = $chunk_entity;
}
......@@ -248,19 +286,19 @@ function testPurgeInstance() {
$this->checkHooksInvocations($hooks, $actual_hooks);
// The instance still exists, deleted.
$instances = field_read_instances(array('field_id' => $field['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$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['uuid'], 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$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('uuid' => $field['uuid']), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$this->assertTrue(isset($fields[$field['uuid']]), 'The field exists and is not deleted');
$fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$this->assertTrue(isset($fields[$field->uuid]), 'The field exists and is not deleted');
}
/**
......@@ -275,8 +313,8 @@ function testPurgeField() {
// Delete the first instance.
$bundle = reset($this->bundles);
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
$instance = field_info_instance($this->entity_type, $field->id(), $bundle);
$instance->delete();
// Assert that hook_field_delete() was not called yet.
$mem = field_test_memorize();
......@@ -292,7 +330,7 @@ function testPurgeField() {
// bundle.
$actual_hooks = field_test_memorize();
$hooks = array();
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
$hooks['field_test_field_load'][] = $entities;
$hooks['field_test_field_delete'] = $entities;
$this->checkHooksInvocations($hooks, $actual_hooks);
......@@ -301,13 +339,13 @@ function testPurgeField() {
field_purge_batch(0);
// The field still exists, not deleted.
$fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE));
$this->assertTrue(isset($fields[$field['uuid']]) && !$fields[$field['uuid']]->deleted, 'The field exists and is not deleted');
$fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE));
$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);
$instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
$instance = field_info_instance($this->entity_type, $field->id(), $bundle);
$instance->delete();
// Assert that hook_field_delete() was not called yet.
$mem = field_test_memorize();
......@@ -319,20 +357,21 @@ function testPurgeField() {
// Check hooks invocations (same as above, for the 2nd bundle).
$actual_hooks = field_test_memorize();
$hooks = array();
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field['field_name']);
$entities = $this->convertToPartialEntities($this->entities_by_bundles[$bundle], $field->id());
$hooks['field_test_field_load'][] = $entities;
$hooks['field_test_field_delete'] = $entities;
$this->checkHooksInvocations($hooks, $actual_hooks);
// The field still exists, deleted.
$fields = field_read_fields(array('uuid' => $field['uuid']), array('include_deleted' => TRUE));
$this->assertTrue(isset($fields[$field['uuid']]) && $fields[$field['uuid']]->deleted, 'The field exists and is deleted');
$fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE));
$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('uuid' => $field['uuid']), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$fields = field_read_fields(array('uuid' => $field->uuid), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
$this->assertEqual(count($fields), 0, 'The field is purged.');
}
}
......@@ -41,7 +41,8 @@ function testCreateField() {
'type' => 'test_field',
);
field_test_memorize();
$field = field_create_field($field_definition);
$field = entity_create('field_entity', $field_definition);
$field->save();
$mem = field_test_memorize();
$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.');
......@@ -67,7 +68,7 @@ function testCreateField() {
// Guarantee that the name is unique.
try {
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create two fields with the same name.'));
}
catch (FieldException $e) {
......@@ -79,7 +80,7 @@ function testCreateField() {
$field_definition = array(
'field_name' => 'field_1',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create a field with no type.'));
}
catch (FieldException $e) {
......@@ -91,7 +92,7 @@ function testCreateField() {
$field_definition = array(
'type' => 'test_field'
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create an unnamed field.'));
}
catch (FieldException $e) {
......@@ -104,7 +105,7 @@ function testCreateField() {
'field_name' => '2field_2',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create a field with a name starting with a digit.'));
}
catch (FieldException $e) {
......@@ -117,7 +118,7 @@ function testCreateField() {
'field_name' => 'field#_3',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create a field with a name containing an illegal character.'));
}
catch (FieldException $e) {
......@@ -130,7 +131,7 @@ function testCreateField() {
'field_name' => '_12345678901234567890123456789012',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create a field with a name longer than 32 characters.'));
}
catch (FieldException $e) {
......@@ -144,7 +145,7 @@ function testCreateField() {
'type' => 'test_field',
'field_name' => 'ftvid',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->fail(t('Cannot create a field bearing the name of an entity key.'));
}
catch (FieldException $e) {
......@@ -165,7 +166,7 @@ function testCreateFieldFail() {
// Try to create the field.
try {
$field = field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$this->assertTrue(FALSE, 'Field creation (correctly) fails.');
}
catch (\Exception $e) {
......@@ -185,7 +186,7 @@ function testReadField() {
'field_name' => 'field_1',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
// Read the field back.
$field = field_read_field($field_definition['field_name']);
......@@ -200,7 +201,7 @@ function testReadFields() {
'field_name' => 'field_1',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
// Check that 'single column' criteria works.
$fields = field_read_fields(array('field_name' => $field_definition['field_name']));
......@@ -218,7 +219,7 @@ function testReadFields() {
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
);
field_create_instance($instance_definition);
entity_create('field_instance', $instance_definition)->save();
}
/**
......@@ -230,7 +231,7 @@ function testFieldIndexes() {
'field_name' => 'field_1',
'type' => 'test_field',
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$field = field_read_field($field_definition['field_name']);
$schema = $field->getSchema();
$expected_indexes = array('value' => array('value'));
......@@ -245,7 +246,7 @@ function testFieldIndexes() {
'value' => array(),
),
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$field = field_read_field($field_definition['field_name']);
$schema = $field->getSchema();
$expected_indexes = array('value' => array());
......@@ -260,7 +261,7 @@ function testFieldIndexes() {
'value_2' => array('value'),
),
);
field_create_field($field_definition);
entity_create('field_entity', $field_definition)->save();
$field = field_read_field($field_definition['field_name']);
$schema = $field->getSchema();
$expected_indexes = array('value' => array('value'), 'value_2' => array('value'));
......@@ -275,9 +276,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);
entity_create('field_entity', $this->field)->save();
$this->another_field = array('field_name' => 'field_2', 'type' => 'test_field');
field_create_field($this->another_field);
entity_create('field_entity', $this->another_field)->save();
// Create instances for each.
$this->instance_definition = array(
......@@ -285,15 +286,15 @@ function testDeleteField() {
'entity_type' => 'test_entity',
'bundle' => 'test_bundle',
);
field_create_instance($this->