#808534: file_get_file_references() is completely broken. From: Damien Tournoud --- .../field_sql_storage/field_sql_storage.module | 25 +++++------ file/tests/file.test | 46 ++++++++++++++++++-- simpletest/tests/entity_query.test | 17 +++++++ 3 files changed, 69 insertions(+), 19 deletions(-) diff --git modules/field/modules/field_sql_storage/field_sql_storage.module modules/field/modules/field_sql_storage/field_sql_storage.module index 4cfbc1f..2f8f1b2 100644 --- modules/field/modules/field_sql_storage/field_sql_storage.module +++ modules/field/modules/field_sql_storage/field_sql_storage.module @@ -358,6 +358,9 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi */ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fields) { list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); + if (!isset($vid)) { + $vid = $id; + } $etid = _field_sql_storage_etid($entity_type); foreach ($fields as $field_id) { @@ -380,14 +383,12 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel ->condition('entity_id', $id) ->condition('language', $languages, 'IN') ->execute(); - if (isset($vid)) { - db_delete($revision_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->condition('revision_id', $vid) - ->condition('language', $languages, 'IN') - ->execute(); - } + db_delete($revision_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->condition('revision_id', $vid) + ->condition('language', $languages, 'IN') + ->execute(); } } @@ -398,9 +399,7 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel $columns[] = _field_sql_storage_columnname($field_name, $column); } $query = db_insert($table_name)->fields($columns); - if (isset($vid)) { - $revision_query = db_insert($revision_name)->fields($columns); - } + $revision_query = db_insert($revision_name)->fields($columns); foreach ($field_languages as $langcode) { $items = (array) $entity->{$field_name}[$langcode]; @@ -433,9 +432,7 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel // Execute the query if we have values to insert. if ($do_insert) { $query->execute(); - if (isset($vid)) { - $revision_query->execute(); - } + $revision_query->execute(); } } } diff --git modules/file/tests/file.test modules/file/tests/file.test index 8e59558..5cf99b4 100644 --- modules/file/tests/file.test +++ modules/file/tests/file.test @@ -14,7 +14,7 @@ class FileFieldTestCase extends DrupalWebTestCase { function setUp() { parent::setUp('file'); - $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content')); + $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content')); $this->drupalLogin($this->admin_user); } @@ -55,11 +55,31 @@ class FileFieldTestCase extends DrupalWebTestCase { $field['settings'] = array_merge($field['settings'], $field_settings); field_create_field($field); + $this->attachFileField($name, 'node', $type_name, $instance_settings, $widget_settings); + } + + /** + * Attach a file field to an entity. + * + * @param $name + * The name of the new field (all lowercase), exclude the "field_" prefix. + * @param $entity_type + * The entity type this field will be added to. + * @param $bundle + * The bundle this field will be added to. + * @param $field_settings + * A list of field settings that will be added to the defaults. + * @param $instance_settings + * A list of instance settings that will be added to the instance defaults. + * @param $widget_settings + * A list of widget settings that will be added to the widget defaults. + */ + function attachFileField($name, $entity_type, $bundle, $instance_settings = array(), $widget_settings = array()) { $instance = array( - 'field_name' => $field['field_name'], - 'entity_type' => 'node', + 'field_name' => $name, 'label' => $name, - 'bundle' => $type_name, + 'entity_type' => $entity_type, + 'bundle' => $bundle, 'required' => !empty($instance_settings['required']), 'settings' => array(), 'widget' => array( @@ -212,6 +232,9 @@ class FileFieldRevisionTestCase extends FileFieldTestCase { $field = field_info_field($field_name); $instance = field_info_instance('node', $field_name, $type_name); + // Attach the same fields to users. + $this->attachFileField($field_name, 'user', 'user'); + $test_file = $this->getTestFile('text'); // Create a new node with the uploaded file. @@ -265,8 +288,21 @@ class FileFieldRevisionTestCase extends FileFieldTestCase { $this->assertFileEntryExists($node_file_r3, t('Second file entry is still available after deleting second revision, since it is being used by the third revision.')); $this->assertFileIsPermanent($node_file_r3, t('Second file entry is still permanent after deleting second revision, since it is being used by the third revision.')); - // Delete the third revision and check that the file is deleted also. + // Attach the second file to a user. + $user = $this->drupalCreateUser(); + $edit = array(); + $edit[$field_name][LANGUAGE_NONE][0] = (array) $node_file_r3; + user_save($user, $edit); + $this->drupalGet('user/' . $user->uid . '/edit'); + + // Delete the third revision and check that the file is not deleted yet. $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete')); + $this->assertFileExists($node_file_r3, t('Second file is still available after deleting third revision, since it is being used by the user.')); + $this->assertFileEntryExists($node_file_r3, t('Second file entry is still available after deleting third revision, since it is being used by the user.')); + $this->assertFileIsPermanent($node_file_r3, t('Second file entry is still permanent after deleting third revision, since it is being used by the user.')); + + // Delete the user and check that the file is also deleted. + user_delete($user->uid); // TODO: This seems like a bug in File API. Clearing the stat cache should // not be necessary here. The file really is deleted, but stream wrappers // doesn't seem to think so unless we clear the PHP file stat() cache. diff --git modules/simpletest/tests/entity_query.test modules/simpletest/tests/entity_query.test index a9cf0c9..fe717fe 100644 --- modules/simpletest/tests/entity_query.test +++ modules/simpletest/tests/entity_query.test @@ -248,6 +248,23 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { array('test_entity', 101), ), t('Test revision age.')); + // Test that fields attached to the non-revision supporting entity + // 'test_entity_bundle_key' are reachable in FIELD_LOAD_REVISION. + $query = new EntityFieldQuery(); + $query + ->fieldCondition($this->fields[0], 'value', 100, '<') + ->age(FIELD_LOAD_REVISION); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + array('test_entity', 1), + array('test_entity', 2), + array('test_entity', 3), + array('test_entity', 4), + ), t('Test that fields are reachable from FIELD_LOAD_REVISION even for non-revision entities.')); + // Test entity sort by entity_id. $query = new EntityFieldQuery(); $query