Critical failures using drupal_execute() on nodes with CCK fields
| Project: | Content Construction Kit (CCK) |
| Version: | 6.x-2.5 |
| Component: | General |
| Category: | bug report |
| Priority: | critical |
| Assigned: | Unassigned |
| Status: | closed |
Jump to:
I created new "content type".
I created new "group one".
One text field in "group one"
Save was without problem.
I export new content type.
Delete new content type.
I tried import as "create new"
OK - The content fields table content_type_test has been created.
OK - The content type test has been added.
OK - Created field txt field one.
Error - The field txt field one (field_txt_field_one) was added to the content type test, but an error has occured updating the field settings.
Error - Please check the errors displayed for more details.
Error - An illegal choice has been detected. Please contact the site administrator.
Error - The default value is invalid.
I havent set default value.
Is this bug ?
$content[type] = array (
'name' => 'test',
'type' => 'test',
'description' => '',
'title_label' => 'test',
'body_label' => 'Body',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'promote' => true,
'sticky' => false,
'revision' => false,
),
'comment' => '2',
'old_type' => 'test',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
);
$content[groups] = array (
0 =>
array (
'label' => 'group one',
'settings' =>
array (
'form' =>
array (
'style' => 'fieldset',
'description' => '',
),
'display' =>
array (
'description' => '',
'teaser' => NULL,
'full' => NULL,
'label' => NULL,
),
),
'weight' => '0',
'group_name' => 'group_group_one',
),
);
$content[fields] = array (
0 =>
array (
'widget_type' => 'text',
'label' => 'txt field one',
'weight' => '0',
'rows' => '1',
'description' => '',
'field_txt_field_one' =>
array (
0 =>
array (
'value' => '',
),
),
'default_value_php' => '',
'group' => 'group_group_one',
'required' => '1',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_txt_field_one',
'field_type' => 'text',
'module' => 'text',
'default_value' =>
array (
0 =>
array (
'value' => '',
),
),
),
);

#1
Note: I tried import the same again and second time was OK.
I have next example
* The content fields table content_type_bb has been created.
* The content type first has been added.
* Added field bb.
* The field bb (field_bb) was added to the content type first, but an error has occured updating the field settings.
Please check the errors displayed for more details.
* An error has occured adding the field date (field_date).
Please check the errors displayed for more details.
* An illegal choice has been detected. Please contact the site administrator.
* The default value is invalid.
$content[type] = array (
'name' => 'first',
'type' => 'bb',
'description' => '',
'title_label' => 'Title',
'body_label' => '',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => false,
'promote' => false,
'sticky' => false,
'revision' => false,
),
'comment' => '2',
'old_type' => 'bb',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
);
$content[groups] = array (
0 =>
array (
'label' => 'aa',
'settings' =>
array (
'form' =>
array (
'style' => 'fieldset',
'description' => '',
),
'display' =>
array (
'description' => '',
'teaser' => NULL,
'full' => NULL,
'label' => NULL,
),
),
'weight' => '0',
'group_name' => 'group_aa',
),
);
$content[fields] = array (
0 =>
array (
'widget_type' => 'text',
'label' => 'bb',
'weight' => '0',
'rows' => '1',
'description' => '',
'field_bb' =>
array (
0 =>
array (
'value' => '',
),
),
'default_value_php' => '',
'group' => 'group_aa',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_bb',
'field_type' => 'text',
'module' => 'text',
'default_value' =>
array (
0 =>
array (
'value' => '',
),
),
),
1 =>
array (
'widget_type' => 'date_select',
'label' => 'date',
'weight' => '0',
'select_day' => '1',
'select_month' => '1',
'select_year' => '1',
'years_back' => '3',
'years_forward' => '3',
'increment' => '1',
'description' => '',
'group' => 'group_aa',
'required' => '0',
'multiple' => '0',
'granularity' =>
array (
'Y' => 'Y',
'M' => 'M',
'D' => 'D',
),
'todate' => 'optional',
'input_format' => 'site-wide',
'input_format_custom' => '',
'output_format_date' => 'd.m.Y - H:i',
'output_format_zone' => '',
'output_format_custom' => '',
'output_format_date_long' => 'l, j F, Y - H:i',
'output_format_zone_long' => '',
'output_format_custom_long' => '',
'output_format_date_medium' => 'j F, Y - H:i',
'output_format_zone_medium' => '',
'output_format_custom_medium' => '',
'output_format_date_short' => 'd.m.Y - H:i',
'output_format_zone_short' => '',
'output_format_custom_short' => '',
'tz_handling' => 'none',
'field_timezone' => 'Africa/Algiers',
'field_name' => 'field_date',
'field_type' => 'date',
'module' => 'date',
),
);
#2
Same problem here, with this code:
$content[type] = array ('name' => 'Issue',
'type' => 'issue',
'description' => '',
'title_label' => 'Title',
'body_label' => 'Body',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'promote' => false,
'sticky' => false,
'revision' => false,
),
'comment' => '0',
'event_nodeapi' => 'never',
'forward_display_' => '1',
'image_attach' => '1',
'upload' => '1',
'old_type' => 'issue',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
'location_maxnum' => '0',
'location_defaultnum' => '0',
'location_weight' => '9',
'location_collapsible' => 1,
'location_collapsed' => 1,
'location_addanother' => 0,
'location_name' => '',
'location_street' => '',
'location_city' => '0',
'location_province' => '0',
'location_postal_code' => '0',
'location_country' => '1',
);
#3
webchick/sirkitree here. We had this issue as well... CCK 5.x-1.5.
We created a content type manually and then to test, simply exported the type, deleted it, and re-imported it (no other changes). The content type (shown below) consists of a node reference field (Artist), an image field (photo) and two text fields (photographer first/last name).
When importing back, the nodereference field (which was listed first) was created, but it said there were errors with the field settings when importing it back in. All other fields after that failed.
In desperation, we merely tried re-ordering the fields in the export so that the two text fields were added first, followed by the noderef/image field -- the only change we did was re-order the fields and re-number their indexes appropriately -- and LO AND BEHOLD it worked! Woah. Go figure.
No time to debug this further, but here's the before/after dump which might help.
Before (errors-o-plenty):
<?php$content[type] = array (
'name' => 'Official photo',
'type' => 'official_photo',
'description' => 'Upload official pictures.',
'title_label' => 'Title',
'body_label' => 'Caption',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'promote' => false,
'sticky' => false,
'revision' => false,
'moderate' => false,
),
'fivestar' => 0,
'fivestar_unvote' => 0,
'fivestar_stars' => 5,
'fivestar_style' => 'default',
'fivestar_position_teaser' => 'hidden',
'fivestar_position' => 'below',
'comment' => 2,
'comment_type' => 'comment',
'comment_view' => 'node_comments',
'privatemsg_link' =>
array (
'node' => false,
'teaser' => false,
'comment' => false,
),
'community_tags_display' => 1,
'old_type' => 'official_photo',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
);
$content[fields] = array (
0 =>
array (
'widget_type' => 'nodereference_autocomplete',
'label' => 'Artist',
'weight' => '-4',
'description' => '',
'default_value_widget' =>
array (
'field_artist' =>
array (
0 =>
array (
'node_name' => '',
),
1 =>
array (
'node_name' => '',
),
2 =>
array (
'node_name' => '',
),
),
),
'default_value_php' => '',
'required' => '1',
'multiple' => '1',
'referenceable_types' =>
array (
'artist' => true,
0 => 1,
'blog' => false,
'comment' => false,
'forum' => false,
'official_photo' => false,
'page' => false,
'photo' => false,
'poll' => false,
'forum_reply' => false,
'story' => false,
'fan' => false,
'album' => false,
'label' => false,
'landing_page' => false,
'review' => false,
'track' => false,
'video' => false,
'video_mashup' => false,
),
'advanced_view' => '--',
'advanced_view_args' => '',
'field_name' => 'field_artist',
'field_type' => 'nodereference',
'module' => 'nodereference',
'default_value' =>
array (
0 =>
array (
),
),
),
1 =>
array (
'widget_type' => 'image',
'label' => 'Photo',
'weight' => '0',
'max_resolution' => '1600x1600',
'image_path' => 'offcial_photos',
'custom_alt' => 0,
'custom_title' => 0,
'description' => 'Your photo size cannot be larger than 1 MB. If your photo is larger than 1 MB, you will receive a "photo is required" error message. If this happens, please resize your photo and resubmit.',
'required' => '1',
'multiple' => '0',
'field_name' => 'field_photo',
'field_type' => 'image',
'module' => 'imagefield',
),
2 =>
array (
'widget_type' => 'text',
'label' => 'Photographer First Name',
'weight' => '1',
'rows' => '1',
'description' => '',
'default_value_widget' =>
array (
'field_photographer_first' =>
array (
0 =>
array (
'value' => '',
),
),
),
'default_value_php' => '',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_photographer_first',
'field_type' => 'text',
'module' => 'text',
),
3 =>
array (
'widget_type' => 'text',
'label' => 'Photographer Last Name',
'weight' => '2',
'rows' => '1',
'description' => '',
'default_value_widget' =>
array (
'field_photographer_last' =>
array (
0 =>
array (
'value' => '',
),
),
),
'default_value_php' => '',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_photographer_last',
'field_type' => 'text',
'module' => 'text',
),
);
?>
After (works):
<?php
$content[type] = array (
'name' => 'Official photo',
'type' => 'official_photo',
'description' => 'Upload official pictures.',
'title_label' => 'Title',
'body_label' => 'Caption',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'promote' => false,
'sticky' => false,
'revision' => false,
'moderate' => false,
),
'fivestar' => 0,
'fivestar_unvote' => 0,
'fivestar_stars' => 5,
'fivestar_style' => 'default',
'fivestar_position_teaser' => 'hidden',
'fivestar_position' => 'below',
'comment' => 2,
'comment_type' => 'comment',
'comment_view' => 'node_comments',
'privatemsg_link' =>
array (
'node' => false,
'teaser' => false,
'comment' => false,
),
'community_tags_display' => 1,
'old_type' => 'official_photo',
'orig_type' => '',
'module' => 'node',
'custom' => '1',
'modified' => '1',
'locked' => '0',
);
$content[fields] = array (
0 =>
array (
'widget_type' => 'text',
'label' => 'Photographer First Name',
'weight' => '1',
'rows' => '1',
'description' => '',
'default_value_widget' =>
array (
'field_photographer_first' =>
array (
0 =>
array (
'value' => '',
),
),
),
'default_value_php' => '',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_photographer_first',
'field_type' => 'text',
'module' => 'text',
),
1 =>
array (
'widget_type' => 'text',
'label' => 'Photographer Last Name',
'weight' => '2',
'rows' => '1',
'description' => '',
'default_value_widget' =>
array (
'field_photographer_last' =>
array (
0 =>
array (
'value' => '',
),
),
),
'default_value_php' => '',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_photographer_last',
'field_type' => 'text',
'module' => 'text',
),
2 =>
array (
'widget_type' => 'nodereference_autocomplete',
'label' => 'Artist',
'weight' => '-4',
'description' => '',
'default_value_widget' =>
array (
'field_artist' =>
array (
0 =>
array (
'node_name' => '',
),
1 =>
array (
'node_name' => '',
),
2 =>
array (
'node_name' => '',
),
),
),
'default_value_php' => '',
'required' => '1',
'multiple' => '1',
'referenceable_types' =>
array (
'artist' => true,
0 => 1,
'blog' => false,
'comment' => false,
'forum' => false,
'official_photo' => false,
'page' => false,
'photo' => false,
'poll' => false,
'forum_reply' => false,
'story' => false,
'fan' => false,
'album' => false,
'label' => false,
'landing_page' => false,
'review' => false,
'track' => false,
'video' => false,
'video_mashup' => false,
),
'advanced_view' => '--',
'advanced_view_args' => '',
'field_name' => 'field_artist',
'field_type' => 'nodereference',
'module' => 'nodereference',
'default_value' =>
array (
0 =>
array (
),
),
),
3 =>
array (
'widget_type' => 'image',
'label' => 'Photo',
'weight' => '0',
'max_resolution' => '1600x1600',
'image_path' => 'offcial_photos',
'custom_alt' => 0,
'custom_title' => 0,
'description' => 'Your photo size cannot be larger than 1 MB. If your photo is larger than 1 MB, you will receive a "photo is required" error message. If this happens, please resize your photo and resubmit.',
'required' => '1',
'multiple' => '0',
'field_name' => 'field_photo',
'field_type' => 'image',
'module' => 'imagefield',
),
);
?>
#4
Btw, I just marked http://drupal.org/node/134921 a duplicate of this, but that one mentions this error also caused by fields as '' that should be 0.
#5
subscribing.
#6
I have been doing quite extensive testing on content_copy.module and tracked down the root cause of these problems.
Import/export ops rely on drupal_execute to find and run the required forms. However in many cases the programmatic execution of forms is broken. Why so? Because many forms rely on PHP includes that happen somewhere else in the modules, starting with Node and CCK. BUT, this could apply to ANY module that provides any component to node forms...
So this is an endemic problem... It can be fixed by looking at your watchdog log to see which forms fail and adding the missing includes somewhere in your own code. At the very least here is what I do in my custom app:
include_once ('./'. drupal_get_path('module', 'node' ) . '/content_types.inc';
include_once ('./'. drupal_get_path('module', 'content') . '/content_admin.inc');
include_once ('./'. drupal_get_path('module', 'views' ) . '/views_cache.inc');
... includes for other modules, per watchdog errors ...
If anyone can suggest a good way to fix programmatic form execution, maybe this could still make it into D6.
#7
I ran into this problem myself. Your workaround is actually part of the documented usage from the author. Check out:
http://groups.drupal.org/node/5272
As a helper I can recommend replacing
$values['macro'] = /** YOUR CCK EXPORT DUMP HERE **/with
$filename = /** YOUR PATH GOES HERE **/$values['macro'] = file_get_contents($filename);
This keeps your imports nice and clean in a separate file. Filename convention? Perhaps my_content_type.content
#8
I have been experiencing this "The default value is invalid" on the export of a module rather then importing them. I have been able to manually generate the export file, and then apply the fix to the import process. I was wondering if anyone knew of a way to fix the problem in the export process because it has been quite annoying having to manually generate the export files.
#9
subscribe
#10
#3
Look at this: http://drupal.org/node/216295
#11
Reposting my comment from another Import/Export issue that was marked as fixed:
http://drupal.org/node/168526#comment-764486
#12
just trying to import a pile of types using latest cck 5.x-1.7 and i am still getting these errors on some of my imports:
# The field Retailer (field_retailer) was added to the content type Publisher Retailer, but an error has occured updating the field settings.Please check the errors displayed for more details.
# An error has occured adding the field Affiliate (field_affiliate).
Please check the errors displayed for more details.
# An error has occured adding the field Rank (field_rank).
Please check the errors displayed for more details.
.
.
.
i guess there is no solution yet?
#13
as mentioned here i tried simply re-submitting - that doesn't work.
i also tried re-arranging fields: moved noderefs to after text fields (index in $content[fields] array was left untouched however) and this DOES work. I am sure it is not the correct fix; but possibly just having export order fields differently would help??
#14
changed status since i don't see any patch posted here
#15
The patch is here: http://drupal.org/node/128038#comment-527467
Unfortunately it is hard to turn it into a .patch file, since we could have different includes depending on what contrib modules are used. If you could think of a way to package a patch to take care of this issue, feel free.
#16
ok, thanks..but that isn't a patch.. it is just a statement of an understanding of the issue.
not sure why you would set this as being a patch - then people will think the issue is solved and won't be as likely to look for a solution.
#17
It is a patch because it is solution recipe. Even if not packaged into a single file.
#18
Since i am pretty sure this issue has not been addressed yet here is a work around for importing CCK types. As far as i can tell the main issue is with nodereference fields and specifically their ordering in the export file (they need to come last, after other fields). This is mentioned above in #3 and post is correct except that they mention they also re-indexed the field array - this isn't necessary.
I used the following code partially pulled from the group posting listed in #7 above and added code to re-arrange the fields in the export field array. I then re-assembled the $content['macro'] and used that as my new import. The following is code from a module install file which ran on a folder of 17 cck export files (one file for each type) - 4 of these would not import correctly due to noderef fields. Using this install update routine they all imported correctly.
hope this helps and i hope someone can come up with a ptch to fix the content_copy export routine.
/**
* Programmatically create CCK fields and types using the content copy module
* @param $type string
* content type to create, defaults to new type, if type exists, only fields will be added
* @param $macro array
* exported array from content types -> export. If file is not specified, macro will be used
* @param $file string
* path to file containing content copy exported macro data structure. no escaping needed.
*/
function base_create_content($type = '<create>', $macro = '', $file = '') {
if(!module_exists("content_copy")){
drupal_set_message('Programmatically creating CCK fields requires the Content Copy module. Exiting.');
return;
}
$values = array();
$values['type_name'] = $type;
//get macro import data, prefer file first
if($file){
if(file_exists($file)){
$values['macro'] = file_get_contents($file);
}
else{
drupal_set_message('Unable to read input file for import. Exiting.');
return;
}
}
elseif($macro){
$values['macro'] = $macro;
}
// convert macro to real PHP array and then check if type already exists
eval($values['macro']);
if (db_table_exists('content_type_'. $content['type']['type'])) return;
//include required files
include_once './'. drupal_get_path('module', 'node') .'/content_types.inc';
include_once('./'. drupal_get_path('module', 'content') .'/content_admin.inc');
// reorder fields so that noderefs are last
foreach ($content['fields'] as $key => $field) {
if ($field['widget_type'] == "nodereference_select") {
unset ($content['fields'][$key]);
$content['fields'][] = $field;
}
}
$typestr = var_export($content['type'], true);
$groupsstr = var_export($content['groups'], true);
$fieldsstr = var_export($content['fields'], true);
// convert back to string representation of macro
$values['macro'] = <<<CONTENT
\$content['type'] = $typestr;
\$content['groups'] = $groupsstr;
\$content['fields'] = $fieldsstr;
CONTENT;
//import content by executing content copy import form and passing macro
drupal_execute("content_copy_import_form", $values);
}
// just so that i can force build of CCK Types without uninstalling/re-installing
function csearch_tweaks_update_1() {
$ret = array();
// add CCK types
$path = drupal_get_path('module', 'csearch_tweaks') . "/cck_types";
$cck_types = glob($path . "/*.txt");
foreach ($cck_types as $type) {
base_create_content('<create>', '', $type);
}
return $ret;
}
Peter Lindstrom
LiquidCMS - Content Management Solution Experts
#19
liquidcms, thanks for that code. that is awesome.
I am having another strange problem though... not sure why but I have one specific option_select field that causes the same errors node reference fields were causing if not at bottom of array. moving the optoin_select to the bottom just before the noderef fields fixes the problem... perhaps this means the problem is not specifically isolated to noderef fields... do we know what is CAUSING this problem in the first place?
#20
I haven't looked into the field code enough to what the root problem is here - i think the post referenced in #7 discusses it a bit.
i guess shouldn't be too hard to modify my code to move select lists to the bottom as well.
#21
quick note liquidcms, in your foreach loop above where you are reordering noderef fields, it should include nodereference_autocomplete fields this:
if ($field['widget_type'] == "nodereference_select" || $field['widget_type'] == "nodereference_autocomplete") {I couldn't figure out why the code wasn't working for me, and that was why, because I use autocomplete noderef fields! You wouldn't have noticed this had you been using just the _select variety.
Also, if anyone is having FURTHER issues, you could try also adding || $field['widget_type'] == "options_select" after the autocomplete in the line above, as this seems to occasionally fail imports as well *scratch head*
#22
so, i don't understant, we have patch or not?
#23
i also have error with importing content type.
next code don't work:
<?php
$content['type'] = array(
// i have a type, but it's not important
);
$content['groups'] = array(
// i have a group, but it's not important
);
// next, vary important
$content['fields'] = array (
0 =>
array (
'widget_type' => 'text',
'label' => 'Issues',
'weight' => '0',
'rows' => '7',
'description' => 'Input the Issues concerning the Change Request',
'field_issues' =>
array (
0 =>
array (
'value' => '',
),
),
'default_value_php' => '',
'group' => 'group_more',
'required' => '0',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_issues',
'field_type' => 'text',
'module' => 'text',
'default_value' =>
array (
0 =>
array (
'value' => '',
),
),
),
1 =>
array (
'widget_type' => 'options_buttons',
'label' => 'Status',
'weight' => '0',
'description' => 'Status reflects progress in time of the Change Request development',
'field_status_3' =>
array (
'key' => false,
),
'default_value_php' => '',
'group' => false,
'required' => '1',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => 'In Work
Frozen for Reviews
Frozen and Approved ',
'allowed_values_php' => '',
'field_name' => 'field_status_3',
'field_type' => 'text',
'module' => 'text, optionwidgets',
),
2 =>
array (
'widget_type' => 'text',
'label' => 'DescriptionText ',
'weight' => '1',
'rows' => '7',
'description' => 'Enter the general description of the Change Request',
'field_descriptiontext' =>
array (
0 =>
array (
'value' => '',
),
),
'default_value_php' => '',
'group' => false,
'required' => '1',
'multiple' => '0',
'text_processing' => '0',
'max_length' => '',
'allowed_values' => '',
'allowed_values_php' => '',
'field_name' => 'field_descriptiontext',
'field_type' => 'text',
'module' => 'text',
),
);
?>
But, if i set array $content['fields'][1] (where 'widget_type' => 'options_buttons') to top array $content['fields'] - it's work.
I use next code:
<?php
foreach($content as $key1 => $fields) {
foreach($fields as $key2 => $value) {
if ($value['widget_type'] == "options_buttons" && $key2 != 0) {
$temp = array();
$temp = $content[$key1][$key2];
unset ($content[$key1][$key2]);
array_unshift($content[$key1], $temp);
}
}
print "<pre>";
print_r ($content['fields']);
print "<pre />";
}
?>
#24
there's no patch atm. just an alternative wrapper method (above) that works.
#25
There is no patch, so fix that first. I started digging into this.
There are a slew of problems here, some related to the fact that programmatically submitting forms does not create exactly the same form arrays and structures that you get when you do them normally.
1) One problem is the same one I ran into in D6 #283985: Content copy destroys field settings -- something really funky happens to arrays somewhere and numeric values become boolean values and then break.
2) One problem is that the program is trying to do validation on the default value widget, which is a form (with its own sub-validation) within a form, and it is just too complex to work right in all cases. If that validation fails, all further processing stops, and all later fields get skipped.
3) One problem may be missing include files, as noted somewhere above, but I didn't actually see that problem.
So lots of problems, needing lots of fixes. I think one take-away is that drupal_execute() still has lots of potential problems because of the complexity of the way forms can work.
I fixed #1 in the D6 version by force-feeding the field values to the form, so we may need a similar fix in D5.
The 'illegal choice' and 'That post cannot be referenced' errors seem to be coming from #2, the validation of the default value widget, and we can get around those by skipping that validation on programmatic forms. I'm trying to decide if that's a safe decision to make, but if we're doing this via Content Copy it is definitely safe because the original value was validated when the field was originally created -- we're just copying those values into the export.
As I said, I haven't actually run into a place where #3 was a problem, so I'm not going to worry about that yet.
Anyway, still digging...
#26
Marking #160660: Node Reference export/import problems - This post can't be referenced as a duplicate.
#27
Marking #288848: import not saving widget_settings correctly (if 0?) as a duplicate.
#28
Marking #284467: Nodereference referenceable file export/import fails as a duplicate.
#29
Marking #114346: This post can't be referenced as a duplicate.
#30
Marking #268999: Problems exporting content type with userreference field as a duplicate.
#31
Marking #235190: validation error when importing content type with date field as a duplicate.
#32
Marking #214115: Illegal choice 0 in ... element. on Importing (Date element) - An illegal choice has been detected. as a duplicate.
#33
Marking #186874: Import loses 'Default Value' Settings as a duplicate.
#34
Marking #263507: bad loading of defaults from the cck number type causes new nodes to (silently) not be saved., #142286: cck field prevents node creation with drupal_execute, and #185505: node_submit (drupal_execute) scrambles data if node_load called in 'insert' operation as likely duplicates -- all related to problems using drupal_execute() on nodes with CCK fields.
#35
Renaming this to reflect the big issue, Content Copy is just one of the implementations of drupal_execute() that is having trouble.
#36
Another issue caused by the default value widget processing is #232425: Help nodereference work with node_import.
#37
I tracked down the problem where array values get switched from numeric to boolean, and it is in the expand_checkboxes() function, which sets the value to
<?phpisset($value[$key])
?>
It looks like this doesn't happen if #value is already set, only if we're letting the the form builder retrieve the values, so I think pre-setting the values with $field and $node values will avoid that.
So, it looks like a couple fixes will take care of most or all of the problems:
1) Skip default value widget processing in the field settings form if the form is #programmed so the form doesn't try to validate the default value element.
2) Force-feed form values to drupal_execute() anytime there are checkboxes in the form (which is probably most of the time).
The last problem has come up a lot in the above issues, and that is when an unexpected value gets sent to nodereference module as a reference -- an array is sent instead of a number or the array has the wrong structure, or whatever. We're going to fix what we're sending in Content Copy but it's complicated and it's easy to see why custom code might get it wrong, so I think we could add a little error-trapping to nodereference to bail out without so much noise (and without stopping all further processing of the form). And userreference could use a similar fix.
#38
Wow, that's a lot of duplicates. So what could be the best approach to a fix that would cover them all?
Is there anything else to fix, besides adding the proper includes, per #6?
#39
I'm committing a series of fixes to help the problems with drupal_execute.
1) Backport content_field_instance_collapse() and content_field_instance_expand() into content_crud.inc to make it easier to send (collapsed) field values to drupal_execute(). (Only applies to D5)
2) Use content_field_instance_collapse() to send form values in the Content Copy export to be sure we get the original field values for checkboxes instead of the true/false values we will get otherwise. (Done in both D5 and D6)
3) Alter _content_admin_form() to provide the raw widget default values as well as the default value widget so programmed forms will have those values available. You can't tell when you construct the form if it's a programmed form or not, so we will always have to create the default value widget, but we don't always have to use it. This will also get the default values into the Content Copy export in a way that Content Copy import can pick them up (Done in both D5 and D6)
4) Alter the _content_admin_form() validation to unset the default value widget and skip the default value widget processing if it's a programmed form. Since we are now provided the actual default value (not just the default value widget) in the export, we can safely pick it up in the import. (Done in both D5 and D6)
5) Go back to nodereference and userreference validation and check for $form['#programmed'] and silently fix or ignore some problems.
These changes will get Content Copy working correctly -- it will export and import all values, including default values, and will do so without encountering any errors from the default value widget processing.
These changes should also take care of most problems trying to programmatically create fields, including trying to do so from profiles. That part is not tested, but should work right now.
Anyone trying to use drupal_execute() in other places should try to provide values rather than hope that they will be successfully discovered, using a method similar to what is used in Content Copy -- retrieve the $field value and collapse it into a form_values array using content_field_instance_collapse(), then make whatever changes are needed and send that array to drupal_execute. Someone should write up some instructions on that sometime.
#40
More notes:
The odd behavior noted before where you won't get nodereference errors if you re-arrange the fields is because of a core bug, #260934: Static caching: cannot call drupal_validate_form on the same form more than once, which is still unfixed in D7. That bug causes all validation to be skipped for all fields except the first one you export/import. So when you push the nodereference field down the list, it never gets validated at all.
When that bug gets fixed, the original problems would have come back no matter what order you put things in, except that I think I've gotten them mostly worked out of the system.
I've still not run into any places where includes are needed, though. I need an example of when that became an issue.
#41
Wow great work and explanations KarenS.
#42
Anybody have references/links to CCK export/import in D6? Sorry if this is wrong place to post, but I've googled around and haven't found much for D6.
Thanks for any guidance.
#43
Looks like this is fixed now ?
#44
All done except for trying to see if nodereference validation could be more forgiving, which I was going to try to go back and do. But we don't seem to be getting error reports now, so hopefully, yes, this is fixed :)
#45
Automatically closed -- issue fixed for two weeks with no activity.
#46
I had all kinds of problems trying to programatically create nodes containing autocomplete nodereference fields via drupal_execute. I was looping through a table in an external DB, then building a node and executing drupal_execute for each record. The CCK fields would only get validated during the first call to drupal_execute. Wrapping everything in the Batch API solved the problem for me.
#47
I think it's breaking nod reference imports. I have an import script that worked some months ago - god knows why but is broken using latest drupal /cck - this is what I pass to drupal_execute:
<?php["field_updateon"]=>
array(2) {
[0]=>
array(1) {
["nid"]=>
array(1) {
["nid"]=>
string(8) "[nid:63]"
}
}
["nid"]=>
array(1) {
["nid"]=>
string(2) "63"
}
}
?>
It gives a log error
#48
Well I found a way of disabling all form validation. Here it is:
<?php
function _drupal_execute($form_id, &$form_state) {
$args = func_get_args();
$form = call_user_func_array('drupal_retrieve_form', $args);
$form['#post'] = $form_state['values'];
form_set_error(NULL, '', TRUE); // reset all form errors
drupal_prepare_form($form_id, $form, $form_state);
_drupal_process_form($form_id, $form, $form_state);
}
function _drupal_process_form($form_id, &$form, &$form_state) {
$form_state['values'] = array();
$form = form_builder($form_id, $form, $form_state);
// Only process the form if it is programmed or the form_id coming
// from the POST data is set and matches the current form_id.
if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {
_drupal_validate_form($form_id, $form, $form_state);
// form_clean_id() maintains a cache of element IDs it has seen,
// so it can prevent duplicates. We want to be sure we reset that
// cache when a form is processed, so scenerios that result in
// the form being built behind the scenes and again for the
// browser don't increment all the element IDs needlessly.
form_clean_id(NULL, TRUE);
if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) {
$form_state['redirect'] = NULL;
form_execute_handlers('submit', $form, $form_state);
// We'll clear out the cached copies of the form and its stored data
// here, as we've finished with them. The in-memory copies are still
// here, though.
if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
cache_clear_all('form_'. $form_state['values']['form_build_id'], 'cache_form');
cache_clear_all('storage_'. $form_state['values']['form_build_id'], 'cache_form');
}
// If batches were set in the submit handlers, we process them now,
// possibly ending execution. We make sure we do not react to the batch
// that is already being processed (if a batch operation performs a
// drupal_execute).
if ($batch =& batch_get() && !isset($batch['current_set'])) {
// The batch uses its own copies of $form and $form_state for
// late execution of submit handers and post-batch redirection.
$batch['form'] = $form;
$batch['form_state'] = $form_state;
$batch['progressive'] = !$form['#programmed'];
batch_process();
// Execution continues only for programmatic forms.
// For 'regular' forms, we get redirected to the batch processing
// page. Form redirection will be handled in _batch_finished(),
// after the batch is processed.
}
// If no submit handlers have populated the $form_state['storage']
// bundle, and the $form_state['rebuild'] flag has not been set,
// we're finished and should redirect to a new destination page
// if one has been set (and a fresh, unpopulated copy of the form
// if one hasn't). If the form was called by drupal_execute(),
// however, we'll skip this and let the calling function examine
// the resulting $form_state bundle itself.
if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
drupal_redirect_form($form, $form_state['redirect']);
}
}
}
}
function _drupal_validate_form($form_id, $form, &$form_state) {
// If the session token was set by drupal_prepare_form(), ensure that it
// matches the current user's session.
if (isset($form['#token'])) {
if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
// Setting this error will cause the form to fail validation.
form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
}
}
// _form_validate($form, $form_state, $form_id);
}
?>
Now calling _drupal_execute instead of drupal_execute skips any validation. Wonder what problems that may bring though.
#49
For reference - I found the problem in the end: 18n rewrites messed up the import in my case. Hope it helps someone else.
#50
I upgraded views today, and this problem suddenly occurred for me. I am using a views generated select list in one of my content types and it is unexpectedly broken, and trying to edit it generates the same 'this post can't be referenced.' error.