Symptoms

Currently, whenever a decision is updated through the pattern

  $node = node_load(NID);
  // Do something with node, such $node->promote = 1
  node_save($node);

all the settings are lost. Its a problem, because this pattern is used quite a lot by both contrib and core modules. Below are some relatively contrived steps to reproduce the problem using only core and decisions:

  1. Enable the Trigger module
  2. Go to admin/build/trigger/comments (Administer -> Site building -> Triggers, and then the local task Comments)
  3. Add the "Save post" actions to the trigger "Trigger: After saving a new comment"
  4. Create a new Decisions node
  5. Add a comment to it

Expected result: No change to the decision node, as the only action we've assigned is the Save post one.

Actual result: The node is now marked as closed, and every settings made in the Decision settings fieldset are gone.

A more realistic scenario would be: install both the Views and Views Bulk Operations modules, go to the new administration page provided by Views Bulk Operations (located at admin/content/node2), choose a decision node and one of the available actions, such as "Promote post to frontpage", apply ... and observe that all the settings are lost.

What's going on
Currently, both decisions_inserts and decisions_updates assumes that their values come from a form submission, and thus use the values as they would appear in a form api submit callback.

The problem is that decisions_form sets '#tree' => TRUE on the settings fieldset, which means that the values in the submit callback are stored in a settings array ; decisions_load puts them straight in the node object though.
A concrete example: decisions_load puts the algorithm in $node->algorithm, but the value at the submit stage and thus used by decisions_update is $node->settings['algorithm'].

This obviously breaks if the node passed to decisions_update is just the object returned by decisions_load, and not a node object coming from the form.

Possible solution
I'm attaching a patch that makes decisions_load also put all the values in the $node->settings array, pretty much like they would be in a form api submit callback. This means that the node object becomes a bit heavier memory-wise, because some informations is stored twice: that could be avoided by unsetting the original properties of the object once they're in the settings array, but it also means changing a lot of code all around.

The patch also slightly tweaks decisions_insert / decisions_update to make them check the format of both startdate and enddate, to avoid unnecessary timestamp => array => timestamp conversions.

Just in case: This isn't the same as #514562: Allow creating decisions programatically. That issue deals with providing default values to make it easier to create decisions node from scratch, this issue deals with preserving existing settings set on a node.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

DeFr’s picture

Attaching patch mentioned above.

DeFr’s picture

I've been thinking a bit more about the problem, and thus here come a completely different approach to solving this issue, that's probably cleaner.

As stated in the original comment, the problem is that due to the '#tree' => TRUE property in decisions_form, the shape of the node values isn't the same in the form submit callback and in decisions_load. Instead of patching decisions_load to make it load the values in both place like patch in #1 does, this patch simply overhaul decisions_form a bit, to make it output the variables directly in $node.

DeFr’s picture

Priority: Normal » Major

Bumping to major, as this bug can cause some sort of dataloss.