I have 2 fields (field_a nodereference and field_b text) in a multigroup (group_test). My multigroup can accept an unlimited # of values.
When I run the following test code only the first fieldgroup entry is saved (field_a = nid 391, field_b = test 1), the second entry is completely ignored:
require("modules/node/node.pages.inc");
$node = node_load(392);
$form_state['values'] = (array)$node;
$form_state['values']['field_a'][0]['nid'] = '391';
$form_state['values']['field_b'][0]['value'] = 'test 1';
$form_state['values']['field_a'][1]['nid'] = '391';
$form_state['values']['field_b'][1]['value'] = 'test 2';
$form_state['values']['op'] = 'Save';
drupal_execute('mynodetype_node_form',$form_state, $node);
A little investigation seems to indicate that the problem occurs somehow when drupal_prepare_form() runs (inside of drupal_execute()). The form prepared by drupal_prepare_form generates a group_test array with only as many delta entries as the node had before being edited.
You may wonder why use drupal_execute? The above code is just a simplified version of what the Services module uses to save nodes so I really need it to work. For reference, below is an exact copy of the relevant code from the Services module :
function node_service_save($edit) {
// Load the required includes for drupal_execute
module_load_include('inc', 'node', 'node.pages');
$nid = NULL;
$edit = (array) $edit;
if ($edit['nid']) {
$node = node_load($edit['nid']);
if ($node->nid) {
// Setup form_state.
$form_state = array();
$form_state['values'] = (array) $edit;
$form_state['values']['op'] = t('Save');
// Later on in the chain node_form seems to expect a copy of
// the old node object.
$form_state['node'] = (array) $node;
$ret = drupal_execute($node->type .'_node_form', $form_state, (object)$node);
// If the node is immediately reloaded after update, it will
// load the OLD cached version.
node_load(0, NULL, TRUE);
// Set $nid, so it can be returned
$nid = $node->nid;
}
else {
return services_error(t('Node not found'), 401);
}
}
else {
// If the submitted node has no author (for instance if it was
// created programmatically by hand) then set the currently logged
// in user as the author.
if (!$edit->uid) {
global $user;
$edit->uid = $user->uid;
}
// Setup form_state
$form_state = array();
$form_state['values'] = (array) $edit;
$form_state['values']['op'] = t('Save');
$ret = drupal_execute($edit['type'] .'_node_form', $form_state, (object)$edit);
// Fetch $nid out of $form_state
$nid = $form_state['nid'];
}
if ($errors = form_get_errors()) {
return services_error(implode("\n", $errors), 401);
}
return $nid;
}
Comments
Comment #1
azinck commentedThis might end up being a problem with the Services module. Please read the solution I posted here: #727108: node_service_save incompatibility with CCK multigroup
Comment #2
Anonymous (not verified) commentedHey azinck,
I'm having the exact same problem with adding multiple values programmatically into a multigroup field. But i'm not using the Services module at all. So I guess it's not an issue of the Service module.
Did you come up with a solution in the meantime? I tried to find the problem for some hours, with no success.
With normal CCK Fields i'm having no problems.
thanks in advance
Comment #3
karens commentedYou cannot use drupal_execute more than once in a single session, there is a core bug that misses validation processing if you do that. If you want to create multiple nodes in a single pass you need to use node_save().
There is a very very old issue about this on core, it still hasn't been fixed. But this is not a CCK bug.
Comment #4
azinck commentedHi jazzati,
Best of luck finding a solution. I did solve my problem and linked to the solution in comment #1. You could try emulating what Services does and add a copy of your new (edited) node, in array format, to $form_state['node']
so something like:
Here's another reference to pore over: #293663: Programmatically creating nodes with drupal_execute
Comment #5
Anonymous (not verified) commented@azinck
Thanks for your quick answer. Your solution actually worked!! I did follow the instructions in #293663: Programmatically creating nodes with drupal_execute and came out with the following:
now, as you suggested, i made the following change:
this works now perfectly with creating one node. But as KarenS said in comment #3, there seems to be a problem when creating multiple nodes with drupal_execute(). I call my nodeSave-Function in a recursive way so it is called several times to create a node together with all the nodes it references.
I'm going to try this with node_save to see if it does work.
thanks for your help.
Comment #6
Anonymous (not verified) commentedthe solution with "node_save" actually solved all problems. it's more a workaround rather than a fix.
Comment #8
dunx commentedOkay, I've spent too long trying to work out how to create 1000s of node that includes node references and eventually came across the answer here:
http://drupal.org/node/178506#comment-895418
Basically...
$form_state['values']['field_mydropdown']['value'] = 3; // a select (dropdown, where 3 is the "option" value saved to the db
$form_state['values']['field_myuserref'][0]['uid']['uid'] = 'someusername'; // a user reference example
$form_state['values']['field_mycheckbox']['value'] = 1; // a checkbox example
$form_state['values']['field_mynoderef'][0]['nid']['nid'] = '[nid:9]'; // a node reference example. In this case, 9 is referring to node 9
$form_state['values']['field_mynoderef'][1]['nid']['nid'] = '[nid:15]'; //etc...
Remember, you don't want to do this for any blank value, so no '[nid:]' values passed in.
I wanted to use drupal_execute as this is actually a migration script rather than a module. I didn't want to use node_save. As there's the caching issue with drupal_execute's validation, then you may also need the solution detailed here:
http://drupal.org/node/260934
Comment #9
johannesdr commentedHi, did anyone else have this problem.
Because adding
didn't work for me.
I am also using the services module and when a node has a multigroup only the first field in this group is added to the node.