#808534: file_get_file_references() is completely broken.

From: Damien Tournoud <damien@commerceguys.com>


---
 .../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
