Using the "Manage Fields" screen, I've added an Image field to a taxonomy vocabulary (intending to display an image to appear at the top of taxonomy term listings at /taxonomy/term/%). This works, and displays the image as expected.
However, trying to save any subsequent edits to a term once an image has been attached results in the error: "Referencing to the file used in the {Taxonomy Image} field is not allowed." (where {Taxonomy Image} is the name of my image field).

Steps to reproduce:
1.) Fresh install of Drupal-alpha5
2.) Add a new image field to the default "Tags" vocabulary:
- Go to admin/structure/taxonomy/tags/fields
- Add new field as follows:
LABEL: Taxonomy Image
NAME: field_taxonomy_image
FIELD: Image
WIDGET: Image
- Click SAVE.
- On the following two screens, leave all default options and click SAVE FIELD SETTINGS then SAVE SETTINGS.
3.) Add a new term to the "Tags" vocabulary with an associated image:
- Go to admin/structure/taxonomy/tags/add
- Enter a name for the new term, select a Taxonomy Image, then click SAVE.

Viewing the term at /taxonomy/term/1 now looks ok, but if you try to edit the term at /taxonomy/term/1/edit (e.g. by adding a description) and then click save, you get the following warning message:
"Referencing to the file used in the Taxonomy Image field is not allowed."
and the edits cannot be saved.

Searching drupal.org, I can see unresolved bug reports similar to this error under the filefield module queue (see http://drupal.org/node/441280 although that relates to nodes not terms), so I guess that this bug has remained during the inclusion of file fields in core. I'm tagging as critical because it makes the entire taxonomy term uneditable, which I count as a pretty major problem.

FWIW, this is running under XAMPP1.7.2 under Win Vista 64 bit.

Please let me know if there's any more information I can supply.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tanoshimi’s picture

Version: 7.0-alpha5 » 7.x-dev

Moving from 7.0-alpha5 to 7.x-dev (applies to both) since it seems that most of the bug-fixing attention seems only to be directed towards issues filed against the 7.x-dev version rather than the more general - 7.x issues -

eojthebrave’s picture

Subscribe, remembering to take a look at this later.

eojthebrave’s picture

It looks to me like the problem is line #973 of file.module

$references[$field_name] = field_attach_query($file_field['id'], array(array('fid', $file->fid)), array('limit' => FIELD_QUERY_NO_LIMIT, 'cursor' => &$cursor, 'age'=> $age));

Which occurs inside of file_get_file_references() which is called in a round about way when updating the term as it goes through and checks for file references.

Removing the $age parameter from the line above makes the problem go away. The documentation for field_attach_query() states that this parameter is for internal use only and that field_attach_query_revisions() should be used instead. Changing to that function doesn't fix anything however.

This is where my knowledge of what is going on here starts to break down.

Also, possibly worth noting is that changing the $age parameter from FIELD_LOAD_REVISION of FIELD_LOAD_CURRENT fixes the problem as well.

file_get_file_references() is never called in core using FIELD_LOAD_CURRENT though that is the default value of the $age parameter. Possible cleanup task here.

Finally, looks like media module ran into this problem as well. #739310: File References error

dhthwy’s picture

Check the relevant revision tables in your database. They're most likely empty, but they shouldn't be empty?

FIELD_LOAD_CURRENT works because it queries the base table. FIELD_LOAD_REVISION queries the revision table, which is empty, so field_attach_query() rightly returns an empty result and therefore the reference count ends up equaling 0 triggering the error tanoshimi is getting.

I hypothesis that the image module, more specifically image.field.inc, needs to write out to the revision table when new/existing image fields are saved/updated. I have yet to write any proof of concept code to demonstrate it does indeed solve the problem.

catch’s picture

Title: "Referencing to the file ... is not allowed" image field error prevents taxonomy terms from being saved. » file_get_references() is completely broken

    // Execute the query if we have values to insert.
    if ($do_insert) {
      $query->execute();
      if (isset($vid)) {
        $revision_query->execute();
      }
    }

field_sql_storage.module doesn't write to the revision table unless the entity supports revisions, so this is completely broken. file.module
likely needs to query first the current storage, then the revisions table, to see if either have references to the file.

If this wasn't such a nasty bug it ought to be a duplicate of or postponed on #353458: hook_file_references() was not designed for a highly flexible field storage or #780154: There is no listing API for field API.

dhthwy’s picture

+1 catch. After I looked into it further I realized my post in #4 was totally wrong.

catch's suggestion seems reasonable to me, should be an easy patch?

catch’s picture

I think we should actuall save revisions for all entities all the time for consistency, node revisions are a bit broken if you look at the details etc., but that's all Drupal 8 work, so for now doing the current query first ought indeed to be a fairly quick patch.

dhthwy’s picture

Status: Active » Needs review
FileSize
3.04 KB

catch, here's an idea. Revision tables seem to be always created (see below), even for entities that don't support revisions. So why not just write out a revision like you said, for consistency. Either way is going to be a kludge. I imagine if we change file_get_references we'd be ignoring the $age argument. Plus querying two tables (current + revision) which really sucks.

I'm not sure if this patch is going to work, but I figure I'd offer it up as an alternative. I mean it does fix the issue for me and it passes the few tests I've ran against it. But I have no idea if there are unintended side-effects with this approach. We'll see if it passes testbot.

snippet:

 function _field_sql_storage_schema($field) {

 // Construct the revision table. The primary key includes
  // revision_id but not entity_id so that multiple revision loads can
  // use the IN operator.
  $revision = $current;
  $revision['description'] = "Revision archive storage for {$deleted}field {$field['id']} ({$field['field_name']})";
  $revision['revision_id']['description'] = 'The entity revision id this data is attached to';
  $revision['primary key'] = array('etid', 'revision_id', 'deleted', 'delta', 'language');

  return array(
    _field_sql_storage_tablename($field) => $current,
    _field_sql_storage_revision_tablename($field) => $revision,
  );
}
catch’s picture

Status: Needs review » Needs work

I think that could cause issues for entities which we subsequently add revisions for (which I'm hoping to do in Drupal 8). And saving the field query doesn't justify the extra writes here IMO. Since hook_file_references() is going to be refactored in another, also critical issue, I'd suggest we just add the field query here, which is an easier change to revert in a refactor than changing field_sql_storage.module

dhthwy’s picture

Ah ok, well in that case shouldn't this wait until #780154: There is no listing API for field API is resolved?

catch’s picture

Works for me.

andypost’s picture

Damien Tournoud’s picture

Title: file_get_references() is completely broken » file_get_file_references() is completely broken

Retitling. It took me some time to find the correct function.

Damien Tournoud’s picture

I agree with #8: the storage should always store an entry in the revision table even if the entity doesn't support revisions. Sounds like a no-brainer to me.

Damien Tournoud’s picture

If we don't store an entry in the revision table for entities that doesn't support revision, you cannot possibly get all the fields that have or had a value, and Views will be affected by such a madness.

I really think the only possible route here is to change the storage and always store revisions. After all, we already do store two copies when the entity supports revisions.

chx’s picture

I concur. field sql storage as far as i can see has no notion of 'supporting revisions' or not, it always acts on both, storage_schema, update field, delete field, create field, the works. the only distinction is in storage write -- no vid, no record. that's easy to fix and hurts noone.

chx’s picture

Status: Needs work » Needs review
FileSize
2.06 KB

Status: Needs review » Needs work

The last submitted patch, revision.patch, failed testing.

dhthwy’s picture

FileSize
2.71 KB

reroll.

dhthwy’s picture

Status: Needs work » Needs review
aspilicious’s picture

Status: Needs review » Needs work
+++ modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -420,22 +419,18 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel
+    } ¶

trailing whitespace :)

Powered by Dreditor.

yched’s picture

I missed that one so far. Subscribe for now...

Damien Tournoud’s picture

Status: Needs work » Needs review
FileSize
3.76 KB

Added a low-level test that fields can be reached via FIELD_LOAD_REVISION even if they are attached to entities that don't support revisions.

Edit: and of course we cannot use 0 for the revision_id, because that's global to the entity type.

Damien Tournoud’s picture

FileSize
8.16 KB

Added a high level test in file.test: we try to attach the file to a user (an entity that doesn't support revisions) and see if it is works properly. This test properly fail when the patch to the SQL storage is not applied.

dhthwy’s picture

Looks good to me. I'd RTBC but I'm probably not the right person to RTBC this.

catch’s picture

Status: Needs review » Reviewed & tested by the community

No sure what I was smoking in #9, different storage based on revision support makes no sense anyway, patch looks good, adds and passes tests, RTBC.

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Looks good. Committed to CVS HEAD.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.