Steps to reproduce:

1. Start to create an Article node ranting about the current President. Add a tag michele-obama-wears-combat-boots.
2. Preview the node.
3. Think better of it, and navigate away before saving the node.
4. Explain to the FBI guys who show up at your door to arrest you for defaming the first lady that actually it is the fault of a spikey-haired Belgian guy, not yourself, because you never meant to create that tag.

taxonomy_autocomplete_validate() calls taxonomy_term_save() for all terms that do not exist yet. I understand why it does: It needs to transform the form data to match what the field expects, which requires a tid, and also probably because of previous long-standing issues in which free-tagging terms did not work well with node preview. However, form validation (I thought) should not have any permanent side effects, and in this case it does. Questions:

1. Is it common in core for form validation to have side effects in the db?
2. If not, I'm wondering if we can find a way to avoid it in this case. Too tired to think about it myself right now.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anonymous’s picture

I kinda know about this problem, and Barry's assessment of the problem is accurate.

(And if the FBI does show up, just show them the cover of the New Yorker 21 July 2008.)

And I'm too tired to comment further, so I am going to have to come back to it after coffee and not on Sunday.

catch’s picture

Subscribing.

bjaspan’s picture

Priority: Normal » Critical
Status: Active » Needs review
FileSize
3.79 KB

Here's my first attempt at a solution. It seems pretty straightforward, I have no idea if it is a total kludge or a clever solution. :)

We really need an issue status of "testbot, please try this" so we don't have to embarrass ourselves my setting CNR when it isn't really ready. :-)

bjaspan’s picture

Priority: Critical » Normal

Didn't mean to set critical at this time.

Status: Needs review » Needs work

The last submitted patch, taxonomy-freetag-validation-826028-3.patch, failed testing.

bjaspan’s picture

Status: Needs work » Needs review
FileSize
4.21 KB

Ooops. Small fix.

bjaspan’s picture

Added explanatory comment and did some minor cleanup.

bjaspan’s picture

Bump, in hopes of catching a review. :-)

yched’s picture

missed that one. subscribe

what happens with the patch when the user enters several non-preexistent terms before previewing ?

Anonymous’s picture

Status: Needs review » Reviewed & tested by the community
+++ modules/taxonomy/taxonomy.module	14 Jun 2010 13:11:22 -0000
@@ -1357,28 +1370,23 @@ function taxonomy_autocomplete_validate(
-    $value = options_array_transpose(array('tid' => $values));

I like being rid of this. Was it doing anything useful anyway? I don't think it was.

+++ modules/taxonomy/taxonomy.module	14 Jun 2010 13:11:22 -0000
@@ -7,6 +7,18 @@
+define('TAXONOMY_FREETAG_AUTOCREATE', 'TAXONOMY_FREETAG_AUTOCREATE');

I'm not going to bikeshed he name of a constant. But if I were going to bikeshed, I'd drop the FREETAG. But I'm not.

Otherwise? I think the patch is good. My assessment: clever solution.

@yched: I tested the patch by using three tags that didn't exist yet. They were all created after saving. Previewing the node did not create the terms. All the terms were still in the order I typed them in the autocomplete widget after preview. The autocomplete widget in taxonomy term fields does not rely on term IDs for passing around its values until the values are saved--if I'm reading your concern correctly.

46 critical left. Go review some!

RTBC!

yched’s picture

The role of options_array_transpose() was to transform an array of $tids into the
array(... $delta => array('tid' => $tid) ... )
format expected for field values.

Definite +1 on removing it. I guess this was a remnant from when the 'taxo as field' widget code was split from optionwidgets, but here it's possible and indeed much better to directly build the array in the right format, which the patch does as a side effect of the general fix.

Patch looks good, so if bangpound is happy, then so am I.

bjaspan’s picture

Status: Reviewed & tested by the community » Needs work

As the author of the patch I'm no longer convinced it is right. As yched points out, it makes preview of new terms not work, and more importantly I'm suddenly getting some E_NOTICE errors. Working on it...

bjaspan’s picture

bjaspan’s picture

New patch. This makes free-tagging terms that do not yet exist show up in the preview as just a name, since they have no URI yet. It also turns out that rdf.module needed a patch because it also operates during preview assumes the terms exist.

If you press Preview twice on the same node you will get several warnings. That has nothing to do with this patch, and is fixed by #844388: Taxonomy terms disappear from node preview if previewed more than once.

bjaspan’s picture

Issue tags: +Needs tests
bjaspan’s picture

Status: Needs work » Needs review

Asking the testbot if there are other problems like the one in rdf.module...

yched’s picture

Hm, patch #14 only touches rdf.module ?

bjaspan’s picture

Odd, cvs diff is not doing what I expect. New patch.

moshe weitzman’s picture

Priority: Normal » Critical

Up priority due to FBI connection. And this is DB corruption IMO.

AaronBauman’s picture

yup, patch #18 works for me

sun’s picture

Status: Needs review » Needs work
+++ modules/taxonomy/taxonomy.module	4 Jul 2010 22:58:46 -0000
@@ -7,6 +7,18 @@
 /**
+ * The 'tid' for a free-tagging term created during entity field
+ * submission.
+ *
+ * Users can create new terms in a free-tagging vocabulary when
+ * submitting a taxonomy_autocomplete_widget. We store a term object
+ * whose tid is TAXONOMY_TERM_AUTOCREATE as a field data item
+ * during widget validation and then actually create the term if/when
+ * that field data item makes it to taxonomy_field_insert/update().
+ */
+define('TAXONOMY_TERM_AUTOCREATE', 'TAXONOMY_TERM_AUTOCREATE');

@@ -1142,21 +1154,21 @@ function taxonomy_field_schema($field) {
   foreach ($items as $delta => $item) {
-    if (!empty($item['tid'])) {
+    if (!empty($item['tid']) && $item['tid'] != TAXONOMY_TERM_AUTOCREATE) {
       $tids[] = $item['tid'];

um. That's a weird use of constants. Why don't we simply use a string 'new' or 'autocreate' or whatever, instead of this *heavy* indirection? Makes no sense to me.

At the very least, this could be a negative integer, since tid cannot be < 0...

Anything, else, please.

Powered by Dreditor.

yched’s picture

+++ modules/taxonomy/taxonomy.module	4 Jul 2010 22:58:46 -0000
@@ -1221,25 +1233,36 @@ function taxonomy_field_formatter_info()
 
+  // Terms whose tid is TAXONOMY_TERM_AUTOCREATE do not exist
+  // yet and $item['taxonomy_term'] is not set. Theme such terms as
+  // just their name.

Minor : in order to have previews look accurate (i.e with links where there will be links), we should IMO generate a link to a new 'taxonomy/temporary' page, which only displays some text saying 'No content, this term does not exist yet'.
I guess few people click on taxo term links in previews anyway (since it reloads the page and kills you edits, unless you use a middle-button click), while the overall appearance matters more.

+++ modules/taxonomy/taxonomy.module	4 Jul 2010 22:58:46 -0000
@@ -1298,6 +1323,10 @@ function taxonomy_field_formatter_prepar
+        // Terms to be created are not in $terms, but are still legitimate.
+        else if ($item['tid'] == TAXONOMY_TERM_AUTOCREATE) {
+          // Leave the item in place.
+        }
         // Otherwise, unset the instance value, since the term does not exist.
         else {
           unset($items[$id][$delta]);

empty else if clause looks odd ?

+++ modules/taxonomy/taxonomy.module	4 Jul 2010 22:58:46 -0000
@@ -1490,9 +1515,25 @@ function taxonomy_rdf_mapping() {
 function taxonomy_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
+  _taxonomy_term_autocreate($items);
+
+++ modules/taxonomy/taxonomy.module	4 Jul 2010 22:58:46 -0000
@@ -1513,6 +1554,8 @@ function taxonomy_field_insert($entity_t
 function taxonomy_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
+  _taxonomy_term_autocreate($items);
+

If something needs to be done in both 'insert' and 'update', then hook_field_presave() sounds like a better candidate - it's called before any of the two others, so execution order should be the same as in the current patch.
In which case, not sure this deserves a separate _taxonomy_term_autocreate() helper func ?

Other than that, the patch and the approach look good to me.

Powered by Dreditor.

bjaspan’s picture

Status: Needs work » Needs review
FileSize
9.72 KB

New patch.

1. Replaced TAXONOMY_TERM_AUTOCREATE with 'autocreate'. Refusing to bikeshed.
2. Converted _taxonomy_term_autocreate() into taxonomy_field_presave(), per #22.
3. Added tests.

re: a link for a non-existent term, I think it is debatable. A themer can make such new terms look like whatever they want. I suggest this as a non-critical followup issue.

re: the empty "else if" block. I know it looks odd, and it would be easy to write it the other way (change == to != and then put the body of the else clause in it), but I think the code is clearer and easier to understand the way I did it. Does anyone object strongly?

I discovered via my new test that taxonomy.module has static caching bugs. I'll file a separate issue.

bjaspan’s picture

Regarding linking for non-existent terms in preview, it turns out my current patch does what D6 did. From taxonomy_link():

        // Previewing free tagging terms; we don't link them because the
        // term-page might not exist yet.
        else {
          foreach ($term as $free_typed) {
            $typed_terms = drupal_explode_tags($free_typed);
            foreach ($typed_terms as $typed_term) {
              $links['taxonomy_preview_term_'. $typed_term] = array(
                'title' => $typed_term,
              );
            }
          }

So it seems clear we can leave it this way in D7 too.

yched’s picture

Status: Needs review » Reviewed & tested by the community

True. Looks good, then !

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to CVS HEAD.

Status: Fixed » Closed (fixed)
Issue tags: -Needs tests

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