This is a rather complex issue, with a simple solution.

I have just startet to use Mailhandler, and are creating nodes from mails. I'm setting cck fields, and most of the time it's no problem, however yesterday I had real troubles setting an optionwidget value from mailhandler submit. After some debugging I find an interesting and inconsistence problem, which can cause troubles for other modules. The problem lies in the nature of node submit handling in mailhandler. Compared to node.module, where a new node is based on a form array, the mailhandler creates an object of the node. In node.module the conversion of the node form array to a node object is done in $node = node_submit($node). This is not the case for mailhandler, and I suppose other modules.The problem is that mailhandler is calling both node_validate and node_submit with an object, and the content.module is handling these calls the same way; calling some_field_widget ($op = 'pocess form values') in _content_widget_invoke. Therefore this task is done twice, and in the case with the optionwidget module, which are manipulating the $items reference array, the new values are remembered, when an object is sent as argument. In difference to normal node submit, where an array is checked with node_validate. On line 639 in content.module this check is_object($node) actually sets the new variables from some_field_widget, and the next time this function is called there are already manipulated values in the $node->field_some_field variable. I don't know if this is an issue with the Mailhandler module, which should not call node_validate with an object. However I do have a simple fix for this issue in optionwidget.

On line 167:

      	$items = content_transpose_array_rows_cols(array('value' => $values));

Here is the $items array converted. The value syntax of custom submit to optionwidget is array('key' => 'some value'). But if the $items array already is converted we get an empty $items array, cause this function could be called twice.

The simple solution:
Replace the above line with:

      if (!empty($values)){
      	$items = content_transpose_array_rows_cols(array('value' => $values));
      }

Then the converstion is done only when no values are found - the array is already transposed by node_validate.

This opens/solves another issue to: Why not use the same syntax for adding content as other cck components? As mentioned above the optionwidget allows you to add items to fields by adding $node->filed_some_fiels -> array('key'=>'some_value') to the node object before node_submit, when i.e. nodereference and other components have this syntax: $node->filed_some_fiels -> array(array('value'=>'some_value')). With the above tweak it is actually possible to add values to optionwidget fields this way to, cause this is the format content_transpose_array_rows_cols tranpose the 'key' array to. Therefore by checking if $values has values, we don't reset the $items array when no 'key' array is found.

Ok, hope this is some kind of understandable. An issue which is not that easy to explain.

Comments

marcp’s picture

I'm having the same problem -- using mailhandler and wanting to set some CCK fields in my custom module's hook_mailhandler(). I hadn't gotten as far as you in debugging this. Did you come up with another solution other than patching optionwidgets.module?

karens’s picture

Status: Active » Closed (won't fix)

The D5 version is no longer being supported. Sorry.