summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwebchick <webchick@24967.no-reply.drupal.org>2012-01-21 09:52:47 -0800
committerwebchick <webchick@24967.no-reply.drupal.org>2012-01-21 09:52:47 -0800
commit0736fbb14bb42e0e8c9d6583501fa93ea7ad58c2 (patch)
treeecbac92847a44bcdd782494059b21ced568ede22
parenta75b69734c216a404b57446ec939283eb6ab162d (diff)
downloadbrdo-0736fbb14bb42e0e8c9d6583501fa93ea7ad58c2.tar.gz
brdo-0736fbb14bb42e0e8c9d6583501fa93ea7ad58c2.tar.bz2
Issue #1371938 by yched, Everett Zufelt, xjm, casey: Fixed hook_field_delete() no longer invoked during field_purge_data().
-rw-r--r--modules/field/field.attach.inc9
-rw-r--r--modules/field/tests/field.test111
-rw-r--r--modules/field/tests/field_test.field.inc30
-rw-r--r--modules/field/tests/field_test.module24
4 files changed, 129 insertions, 45 deletions
diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc
index 45a2cb334..bd2934b48 100644
--- a/modules/field/field.attach.inc
+++ b/modules/field/field.attach.inc
@@ -194,8 +194,10 @@ function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $opti
// Iterate through the instances and collect results.
$return = array();
foreach ($instances as $instance) {
- $field_name = $instance['field_name'];
- $field = field_info_field($field_name);
+ // field_info_field() is not available for deleted fields, so use
+ // field_info_field_by_id().
+ $field = field_info_field_by_id($instance['field_id']);
+ $field_name = $field['field_name'];
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
if (function_exists($function)) {
// Determine the list of languages to iterate on.
@@ -703,7 +705,8 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
}
// Invoke field-type module's hook_field_load().
- _field_invoke_multiple('load', $entity_type, $queried_entities, $age, $options);
+ $null = NULL;
+ _field_invoke_multiple('load', $entity_type, $queried_entities, $age, $null, $options);
// Invoke hook_field_attach_load(): let other modules act on loading the
// entitiy.
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index aacef3d2b..657f1f364 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -2990,22 +2990,54 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
*/
function _generateStubEntities($entity_type, $entities, $field_name = NULL) {
$stubs = array();
- foreach ($entities as $entity) {
+ foreach ($entities as $id => $entity) {
$stub = entity_create_stub_entity($entity_type, entity_extract_ids($entity_type, $entity));
if (isset($field_name)) {
$stub->{$field_name} = $entity->{$field_name};
}
- $stubs[] = $stub;
+ $stubs[$id] = $stub;
}
return $stubs;
}
+ /**
+ * Tests that the expected hooks have been invoked on the expected entities.
+ *
+ * @param $expected_hooks
+ * An array keyed by hook name, with one entry per expected invocation.
+ * Each entry is the value of the "$entity" parameter the hook is expected
+ * to have been passed.
+ * @param $actual_hooks
+ * The array of actual hook invocations recorded by field_test_memorize().
+ */
+ function checkHooksInvocations($expected_hooks, $actual_hooks) {
+ foreach ($expected_hooks as $hook => $invocations) {
+ $actual_invocations = $actual_hooks[$hook];
+
+ // Check that the number of invocations is correct.
+ $this->assertEqual(count($actual_invocations), count($invocations), "$hook() was called the expected number of times.");
+
+ // Check that the hook was called for each expected argument.
+ foreach ($invocations as $argument) {
+ $found = FALSE;
+ foreach ($actual_invocations as $actual_arguments) {
+ if ($actual_arguments[1] == $argument) {
+ $found = TRUE;
+ break;
+ }
+ }
+ $this->assertTrue($found, "$hook() was called on expected argument");
+ }
+ }
+ }
+
function setUp() {
parent::setUp('field_test');
- // Clean up data from previous test cases.
$this->fields = array();
$this->instances = array();
+ $this->entities = array();
+ $this->entities_by_bundles = array();
// Create two bundles.
$this->bundles = array('bb_1' => 'bb_1', 'bb_2' => 'bb_2');
@@ -3041,7 +3073,10 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
foreach ($this->fields as $field) {
$entity->{$field['field_name']}[LANGUAGE_NONE] = $this->_generateTestFieldValues($field['cardinality']);
}
+
$this->entities[$id] = $entity;
+ // Also keep track of the entities per bundle.
+ $this->entities_by_bundles[$bundle][$id] = $entity;
field_attach_insert($this->entity_type, $entity);
$id++;
}
@@ -3106,6 +3141,7 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
* instance is deleted.
*/
function testPurgeInstance() {
+ // Start recording hook invocations.
field_test_memorize();
$bundle = reset($this->bundles);
@@ -3120,7 +3156,7 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
$this->assertEqual(count($mem), 0, 'No field hooks were called');
$batch_size = 2;
- for ($count = 8; $count >= 0; $count -= 2) {
+ for ($count = 8; $count >= 0; $count -= $batch_size) {
// Purge two entities.
field_purge_batch($batch_size);
@@ -3134,19 +3170,21 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
$this->assertEqual($count ? count($found['test_entity']) : count($found), $count, 'Correct number of entities found after purging 2');
}
- // hook_field_delete() was called on a pseudo-entity for each entity. Each
- // pseudo entity has a $field property that matches the original entity,
- // but no others.
- $mem = field_test_memorize();
- $this->assertEqual(count($mem['field_test_field_delete']), 10, 'hook_field_delete was called for the right number of entities');
- $stubs = $this->_generateStubEntities($this->entity_type, $this->entities, $field['field_name']);
- $count = count($stubs);
- foreach ($mem['field_test_field_delete'] as $args) {
- $entity = $args[1];
- $this->assertEqual($stubs[$entity->ftid], $entity, 'hook_field_delete() called with the correct stub');
- unset($stubs[$entity->ftid]);
+ // Check hooks invocations.
+ // - hook_field_load() (multiple hook) should have been called on all
+ // entities by pairs of two.
+ // - hook_field_delete() should have been called once for each entity in the
+ // bundle.
+ $actual_hooks = field_test_memorize();
+ $hooks = array();
+ $stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
+ foreach (array_chunk($stubs, $batch_size, TRUE) as $chunk) {
+ $hooks['field_test_field_load'][] = $chunk;
+ }
+ foreach ($stubs as $stub) {
+ $hooks['field_test_field_delete'][] = $stub;
}
- $this->assertEqual(count($stubs), $count-10, 'hook_field_delete was called with each entity once');
+ $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));
@@ -3169,15 +3207,37 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
* instances are deleted and purged.
*/
function testPurgeField() {
+ // Start recording hook invocations.
+ field_test_memorize();
+
$field = reset($this->fields);
// Delete the first instance.
- $instance = field_info_instance($this->entity_type, $field['field_name'], 'bb_1');
+ $bundle = reset($this->bundles);
+ $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
+ // Assert that hook_field_delete() was not called yet.
+ $mem = field_test_memorize();
+ $this->assertEqual(count($mem), 0, 'No field hooks were called.');
+
// Purge the data.
field_purge_batch(10);
+ // Check hooks invocations.
+ // - hook_field_load() (multiple hook) should have been called once, for all
+ // entities in the bundle.
+ // - hook_field_delete() should have been called once for each entity in the
+ // bundle.
+ $actual_hooks = field_test_memorize();
+ $hooks = array();
+ $stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
+ $hooks['field_test_field_load'][] = $stubs;
+ foreach ($stubs as $stub) {
+ $hooks['field_test_field_delete'][] = $stub;
+ }
+ $this->checkHooksInvocations($hooks, $actual_hooks);
+
// Purge again to purge the instance.
field_purge_batch(0);
@@ -3186,12 +3246,27 @@ class FieldBulkDeleteTestCase extends FieldTestCase {
$this->assertTrue(isset($fields[$field['id']]) && !$fields[$field['id']]['deleted'], 'The field exists and is not deleted');
// Delete the second instance.
- $instance = field_info_instance($this->entity_type, $field['field_name'], 'bb_2');
+ $bundle = next($this->bundles);
+ $instance = field_info_instance($this->entity_type, $field['field_name'], $bundle);
field_delete_instance($instance);
+ // Assert that hook_field_delete() was not called yet.
+ $mem = field_test_memorize();
+ $this->assertEqual(count($mem), 0, 'No field hooks were called.');
+
// Purge the data.
field_purge_batch(10);
+ // Check hooks invocations (same as above, for the 2nd bundle).
+ $actual_hooks = field_test_memorize();
+ $hooks = array();
+ $stubs = $this->_generateStubEntities($this->entity_type, $this->entities_by_bundles[$bundle], $field['field_name']);
+ $hooks['field_test_field_load'][] = $stubs;
+ foreach ($stubs as $stub) {
+ $hooks['field_test_field_delete'][] = $stub;
+ }
+ $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');
diff --git a/modules/field/tests/field_test.field.inc b/modules/field/tests/field_test.field.inc
index 6d03855c6..cc76a998d 100644
--- a/modules/field/tests/field_test.field.inc
+++ b/modules/field/tests/field_test.field.inc
@@ -58,6 +58,9 @@ function field_test_field_update_forbid($field, $prior_field, $has_data) {
* Implements hook_field_load().
*/
function field_test_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+ $args = func_get_args();
+ field_test_memorize(__FUNCTION__, $args);
+
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.
@@ -73,12 +76,39 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan
}
/**
+ * Implements hook_field_insert().
+ */
+function field_test_field_insert($entity_type, $entity, $field, $instance, $items) {
+ $args = func_get_args();
+ field_test_memorize(__FUNCTION__, $args);
+}
+
+/**
+ * Implements hook_field_update().
+ */
+function field_test_field_update($entity_type, $entity, $field, $instance, $items) {
+ $args = func_get_args();
+ field_test_memorize(__FUNCTION__, $args);
+}
+
+/**
+ * Implements hook_field_delete().
+ */
+function field_test_field_delete($entity_type, $entity, $field, $instance, $items) {
+ $args = func_get_args();
+ field_test_memorize(__FUNCTION__, $args);
+}
+
+/**
* Implements hook_field_validate().
*
* Possible error codes:
* - 'field_test_invalid': The value is invalid.
*/
function field_test_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+ $args = func_get_args();
+ field_test_memorize(__FUNCTION__, $args);
+
foreach ($items as $delta => $item) {
if ($item['value'] == -1) {
$errors[$field['field_name']][$langcode][$delta][] = array(
diff --git a/modules/field/tests/field_test.module b/modules/field/tests/field_test.module
index 4a87b060e..0015cd905 100644
--- a/modules/field/tests/field_test.module
+++ b/modules/field/tests/field_test.module
@@ -183,30 +183,6 @@ function field_test_field_create_field($field) {
}
/**
- * Memorize calls to hook_field_insert().
- */
-function field_test_field_insert($entity_type, $entity, $field, $instance, $items) {
- $args = func_get_args();
- field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
- * Memorize calls to hook_field_update().
- */
-function field_test_field_update($entity_type, $entity, $field, $instance, $items) {
- $args = func_get_args();
- field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
- * Memorize calls to hook_field_delete().
- */
-function field_test_field_delete($entity_type, $entity, $field, $instance, $items) {
- $args = func_get_args();
- field_test_memorize(__FUNCTION__, $args);
-}
-
-/**
* Implements hook_entity_query_alter().
*/
function field_test_entity_query_alter(&$query) {