Data comparison conditions that utilize "is one of" currently trigger what appears to be an Ajax event that replaces the values list with a data selector. In order to tell the condition to compare the saved data with a list of predefined values, it is necessary to "trick" Rules and bypass this Ajax issue. In short, this is accomplished by choosing "equals", refreshing the browser window, and then selecting both "is one of" and your list of values.
I have tested this in a "save new content" rule and it appears to be repeatable. Here are the detailed steps to reproduce:
(Note, I also have Rules List Conditions installed, but I don't think that module is at play here.)
1. Create a new Reaction Rule and add event, "After saving new content of type [your content type name].
2. Add one or more Actions (e.g. send email).
3. Add a Condition.
4. Select "Data comparison" (default) and click Continue.
5. Select your data selector and click Continue.
6. Check "Negate".
The Operators available here are "equals" (default) or "is one of". Initially, while "equals" is selected, a list of values are visible. But for this condition to work, the data selector must *not* equal any of the listed values.
7. Select "is one of" operator.
When the operator is changed to "is one of", the values list is replaced with a data selector field. This appears to be an Ajax error of some kind, and instead it should continue to show a list of values, because selecting a data selector here will result in the condition failing. Instead, we want to be able to point the "is one of" operator to the list of values.
Note that changing the selected operator back to "equals" does not bring back the list of values, or effect any change. This is where we fool the code and get around what appears to be a bug.
8. Refresh your browser window.
Your browser will ask you if you really want to refresh the page. Because some or all of your selections made thus far are stored locally, go ahead and allow the page to refresh.
When the page refreshes, you now have both the "is one of" Value operator *and* the list of values. Drupal displays a warning at the top, "Data selector field is required. Missing configuration for parameter value." Ignore this warning.
9. With "is one of" selected, and your list of values selected (and Negate still checked) click Save.
Rules goes ahead and permits you to save this condition, and the condition will now tell the rule to fire if the saved value does not match any of the values contained in the list you selected in step 10.
Note: The bypass technique described above will only work while creating a new condition, and not while editing a condition.
Comment | File | Size | Author |
---|---|---|---|
#22 | 2281739-22.patch | 2.07 KB | TR |
| |||
#20 | rules-data_comparison_list_field_is_one_of_error-2281739-20.patch | 2.43 KB | ron_s |
#3 | Rules condition data comparison is one of bug (1-3) 1324pxw.jpg | 97.01 KB | silurius |
#3 | Rules condition data comparison is one of bug (4-6) 1485pxw.jpg | 157.6 KB | silurius |
Comments
Comment #1
silurius CreditAttribution: silurius commentedComment #2
silurius CreditAttribution: silurius commentedComment #3
silurius CreditAttribution: silurius commentedComment #4
Nicolas Bouteille CreditAttribution: Nicolas Bouteille commentedI have the same problem and I can't even seem to reproduce your bypass technique. Maybe this is not possible in 2.9 anymore for some reason :(
Comment #5
marcosdr CreditAttribution: marcosdr commentedJust to note: This method worked in Firefox but didn't work in Chrome
There is another issue which is if after saving the rule you then decide to change the selection you had for "is one of", when you go to edit the rule this will change to the data selector again and the trick mentioned above won't work this time, so you need to create the rule from scratch again.
This is a big bug as the data comparison is one of the most used conditions.
Comment #6
sketman CreditAttribution: sketman commentedThe same problem here and I am not able to reproduce the workaround described in #3...
Comment #7
kruser CreditAttribution: kruser commentedVery strange bug, I just ran into this too. The refresh workaround using firefox worked for me, but Chrome is a problem.
although when going back to edit the values, in either browser, it reverts back to the Data Selection and the refresh trick doesn't work anymore.
Comment #8
ogursoy CreditAttribution: ogursoy commentedConfirm this bug.
Comment #9
rollingnet CreditAttribution: rollingnet commentedThis is over 2 years and half major bug of rules, one of most used module of Drupal.
I think it's time to correct it, since it occur in a very used function, i.e. data comparison.
I can't give support for code, but I'm here to test patches so it can be finally closed.
Comment #10
gusantor CreditAttribution: gusantor commentedHello
this is also happening to me, using:
Drupal 7.39
Rules 7.x-2.9
Rules UI 7.x-2.9
I needed to use FF AND alter the form select control to allow MULTIPLE option selection
Comment #11
Anonymous (not verified) CreditAttribution: Anonymous commentedIf you need to compare if only one value is selected use condition: List contains item > item to compare.
Most likely works with multiple comparisons to "List contains item" and condition set "OR" between them:
List contains item: first
OR
---List contains item: third
---OR
------List contains item: seventh
This comparison works without bug described here.
Comment #12
ron_s CreditAttribution: ron_s commentedThis continues to be a serious bug with no solution. The workarounds mentioned for versions prior to 2.9 do not work.
Comment #13
ron_s CreditAttribution: ron_s commentedI have a patch for review. There might be a better way to include this, but the approach identifies the problem.
The issue is specifically for list fields when using the "is one of" option. When in this setting, the button to toggle back to selecting values disappears because
$info['type']
is no longer in the right format. The incoming type value islist<text>
, which means when the code in therules_condition_data_is_info_alter
function runs, thelist<text>
gets wrapped with anotherlist<>
. This creates an unrecognizable format oflist<list<text>>
.The attached patch looks for an incoming type with a format of
list<>
, and extracts the value if it exists. I also tested this on data comparison conditions that are not a list, and it works correctly.Please review and let me know your feedback, thanks.
Comment #14
TR CreditAttribution: TR commentedComment #15
ron_s CreditAttribution: ron_s commentedAfter further testing, I realized the rule was not being evaluated correctly. The problem is that the
'IN'
option assumes that$data
is a string. When comparing a list text field,$data
is an array.The attached patch checks if
$data
array is not empty, and one or more array values in$data
exists in the$value
array.Please review, thanks.
Comment #16
ron_s CreditAttribution: ron_s commentedChanging the title to reflect that list field data comparisons when using "is one of" do not work.
Comment #17
ron_s CreditAttribution: ron_s commentedSorry, have one further update. The
array_intersect
check needs to be acount
... cannot perform a boolean check on an array. See attached.Comment #18
hedrickbt CreditAttribution: hedrickbt as a volunteer commentedI was receiving the following error when my lists to be compared were tags. This would cause the rule to fail.
Recoverable fatal error: Object of class stdClass could not be converted to string
I don't know of a better way to resolve this, but I modified the patch to look for objects that both have 'tid' properties and in that case use array_uintersect comparing the tid values instead of array_intersect.
Comment #19
ron_s CreditAttribution: ron_s commentedI don't understand the issue you're identifying. Also the patch you created is not of the right format.
Two questions:
- Are you saying this patch created the error? Or you're attempting to incorporate a fix to a separate problem?
- What exactly is telling you it is an object? $data? $value?
Comment #20
ron_s CreditAttribution: ron_s commentedI ran a test, and your addition is not going to work in all cases. The code assumes
$value[0]
exists, which is not the case. The key for$value
is going to be the$tid
.Also while I don't necessarily mind using
array_uintersect
, the approach you've taken is going to miss some cases. It needs to account for -1, 0, and 1 in the result returns, otherwise it can potentially create unexpected errors.Instead of trying to be too fancy, there is a simpler, fool-proof way to handle this. See the attached patch.
Comment #21
TR CreditAttribution: TR commentedWe need test cases for the data_is condition to ensure that this and the related issue:
1) works properly
2) doesn't get accidentally broken by future changes
Comment #22
TR CreditAttribution: TR commentedHere's a re-roll of #20 - it didn't apply anymore because of other commits that have been made recently.
Comment #23
ron_s CreditAttribution: ron_s commentedPatch in #22 still applies cleanly to the latest 7.x-2.14 version.
Comment #24
ron_s CreditAttribution: ron_s commentedMoving back to needs review since I see it still needs tests, although have been using this in production environments for years.