I'm using Commerce, but this problem doesn't appear to be specific to that.
If a rule is provided only in code (in my case by commerce_tax) and I want to import some changes to that rule using the UI, when I import a string the same machine name, I would expect for that rule to be moved from code into the database, but that doesn't appear to happen. Instead, only the rules cache gets updated - so the overwritten rule appears to work correctly but as soon as the cache expires (drush cc all for example) the rule reverts back to the default stored in code.
Also interesting is the rule's status never changes from "default" at any point.
I should also explain that this problem has come about from building the commerce implementation on a development site then by attempting to deploy to live. I would usually use features, but the rules are provided initially by the commerce module so can't be exported into a feature. I would use features overrides but rules doesn't seem to support that and I get syntax errors in the exportables.
Comment | File | Size | Author |
---|---|---|---|
#9 | 2027717-9-status-of-imported-config-plus-test.patch | 7.9 KB | TR |
#9 | 2027717-9-status-of-imported-config-test-only.patch | 5.68 KB | TR |
#5 | 2027717-5-status-of-imported-config.patch | 2.22 KB | TR |
Comments
Comment #1
generalredneckI'm trying to write an upgrade for an action plugin that I made and I'm having the same problem using the export function and then trying to use the import function... Something like:
This is crude but I wanted to see if it could be done before I got too deep. I would expect the same behavior Angry Dan expected in that an imported rule with the same name as an existing rule would be overridden.
Suggestions?
Comment #2
rlmumfordI'm going to mark this as a critical error, as it can cause seemingly random, often severe changes in a sites behaviour.
This is a bug in the import form. It imports the new code, copies the rule id from the existing rule to the new rule but doesn't copy the status so that rules that were 'Default' before stay default. This means that when caches clear the imported configuration is completely lost!
The patch makes sure that the config status gets updated when the import form is submitted.
N.B. Comment #1 is a completely seperate issue I think.
Comment #3
rlmumfordComment #4
TR CreditAttribution: TR commentedRetesting ...
Still waiting for someone to review this patch and verify it works to fix the problem ...
I would also be nice to have some clear instructions for reproducing the problem, as right now the conditions under which this arises are not clear at all ...
Comment #5
TR CreditAttribution: TR commentedIn #4 I said it wasn't clear how to reproduce this. I don't know what I meant by that, as this seems pretty clear and reproducible to me now from just the information in the original post. It doesn't have anything to do with Commerce, so you can ignore that part of the original post.
To summarize the problem, if you have an existing rule provided by code (status will be 'Default'), and you import a rule with the same name using the import form and check the overwrite checkbox, the expectation is that this rule will now have the new imported values and have status 'Overridden', and you will be able to revert it back to the code-provided values using the revert link. What happens instead is that the existing rule DOES get temporarily changed in memory, but clearing the cache will improperly revert it back to the code-provided values. Additionally, even though this rule has been changed in memory, it shows a (wrong) status of 'Default' therefore you don't have a revert link to use ...
But the patch in #2 isn't the solution - it doesn't do the correct thing. (BTW this is one of the reasons why we should have tests for every feature).
The attached patch fixes this properly, but still needs tests.
TL;DR:
The status of the rules configuration is stored as a bitmask. There are four possible values, as defined in entity.module:
Now, the patch in #2 indicates that we should COPY the status of the existing configuration and use that same status for the imported configuration:
This is WRONG. Consider what happens if the existing configuration is ENTITY_IN_CODE. When overwriting this existing configuration, the imported configuration should be set to ENTITY_OVERRIDDEN and not remain as ENTITY_IN_CODE (which is what a simple copy would do).
Instead of a simple copy, what we should be doing is setting the ENTITY_CUSTOM bit in the existing status before we copy it:
If we set this bit, then the before/after statuses change the way we want them to:
(Note that for the last two cases, the patch in #2 will work, but for the first case it fails exactly the same way it did before that patch.)
The remaining question is what to do with existing configurations that have the status ENTITY_FIXED. Should we allow these to be overwritten on import? Note that we don't allow editing or deleting or enabling or disabling or reverting if the status is ENTITY_FIXED. I would argue that we shouldn't allow overwriting on import either - the import should fail in the validation function.
New patch attached which has been manually tested to fix the problem and work in all the above cases, but we still need tests to ensure the import sets the status as expected and to ensure that future patches don't break this functionality.
Comment #6
TR CreditAttribution: TR commentedHere's a test that demonstrates the bug - this should FAIL without the patch from #5.
Comment #8
TR CreditAttribution: TR commentedNow the fix from #5 combined with the test from #6. This should succeed.
Comment #9
TR CreditAttribution: TR commentedSlight change needed - test user didn't have correct permissions.
Once again, here is the test-only patch which should fail, and the test-plus-fix patch which should run green.
Comment #11
TR CreditAttribution: TR commentedCommitted.