review of node_factory.
| Project: | Node factory |
| Version: | 5.x-1.x-dev |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | clemens.tolboom |
| Status: | closed |
Jump to:
Saw your new module, and thought it useful to give you a review based on my successes and (mostly) failures with this area.
node_factory_set_noderef_value() expects the calling code to know the field type. This should be inside node_factory.module.
<?php
// Load the field info for this content type's field.
$field = content_fields($name, $edit['type']);
// Now $field['type'] contains the field type and you can set the data appropriately.
?>More importantly, the calling code may not know anything about the content type. There may be a new field on the content type which is "required". If we don't set this, then node_submit is going to fail. So your node_factory_save_node() should be interrogating cck and filling in the gaps.
Another issue I've encountered is path_auto. I haven't been able to get my own code to work with path_auto automatically creating alias. I'm sure there are /many/ issues like this: basically this led me to the conclusion that a module like this needs to get *really* serious about determining what the node form should look like by default - not just building up a best guess $edit.
Good luck.

#1
Thanks for this great hint!!!
I'll dive into this soon!
#2
I'm stuck with
<?php$field = content_fields($name, $edit['type']);
?>
What to do next? Looking at the content.module i found
- content_default_value( $node, $field, $items)
or
- content_handle( 'field', 'default value', $field)
but don't know what to do with them.
I hope you have some more feedback regarding cck.
Regards, Clemens
#3
Looks like you're on the right track and it's further than I've ventured. I've had a bit of a look and I'm not sure but perhaps you could try this approach:
-- Building a default cck form object for node_submit() --
1. Set up your basic $node
2. Pass it through to content_form($node) which should pass to all other cck fields to add form elements correctly.
3. This should give you all the faults you need to submit without errors...
Next steps?
If you want to let the user assign values to the cck fields of the node, you get stuck because different fields have different structures of storing data.
For example, here's the functions Ive been using:
<?php
/**
* Add node content.
* This is proving to be fragile. (Surprise, surprise)
*
* @param string $content_type, should match existing content types
* @param array $properties, with fields you need to explicitly set.
*
* Return a node.
*/
function install_create_content($content_type, $properties) {
global $user;
$default = array();
$default['type'] = $content_type;
$default['format'] = 0;
$default['comment'] = 2; // Enable read/write comments
$default['status'] = 1; // Published
$default['promote'] = 0; // Not promoted to front page.
$default['sticky'] = 0; // Not sticky.
$default['created'] = date('g:i:sA');
$default['log'] = 'Updated at ' . date('g:i:sA') . ' via lpimport' ;
$default['name'] = $user->name;
$default['uid'] = $user->uid;
foreach ($properties AS $property => $value) {
$field = content_fields($property, $content_type);
if (isset($field['field_name'])) {
switch ($field['type']) {
case 'cckmap':
$default[$property] = $value;
break;
case 'nodereference':
case 'userreference':
// @todo: make this support multiple entries?
$default[$property] = array(array('nid' => $value));
break;
default:
if (is_array($value)) {
// Uncertain.
$default[$property][] = $value;
}
else {
$default[$property] = array(array('value' => $value));
}
}
if ($field['widget']['type'] == 'options_select' && isset($default[$property][0]['value'])) {
if ($field['multiple']) {
foreach ($property[0] AS $v) {
$default[$property]['keys'][$value] = $value;
}
}
else {
$default[$property]['key'] = $default[$property][0]['value'];
}
//unset($default[$property][0]);
}
unset($properties[$property]);
}
}
// Should be doing node_prepare() or whatever its called here but I wasn't.
$node = array_merge($default, $properties);
$node = node_submit($node);
node_save($node);
return $node;
}
?>
Now. I let the user request a node type, and then everything else on properties.
so
<?phpinstall_create_content('mynodetype', array('title' => 'Surfing trip', 'body' => 'Great time...', 'holiday' = 99);
?>
So what happens is the node gets created with defaults. Then it goes through each field and tries match a name in $properties to a field name on the cck. So say 'holiday' is a node reference field to another node (nid 99). My function needs to check for nodereference fields and explicitly set the values correctly.
Note, if another property is
'status' => 0, this gets assigned near the end in the array_merge().Now my function is ok for the one site it's being used on but it's not flexible. Say if you used
content_form() to prepare a the formthen had another function called assign_property():<?php
// Pass a node in *array* form, a field/propery name, and a value.
// Property might be 'field_my_special_node_reference'
// Value might be 99
//
// This will require some recursive array function stuff
//
// UNTESTED, just a big guess
function assign_property($node, $property, $value) {
// Pseudocode
// The $property name should be at the base of the array.
// Walk the field until you find a leaf value.
// Replace that leaf value with $value
// If you can't find the property/value raise an error.
// Some weird fields might need a special handler. For example nodereference and userreference must have a different structure. But at the same time, you might be able to deduce the structure of any field with the right call to cck.
}
?>
Hope that helps, you seem intent on this so I figured giving you what little I know and let you do what you can.
#4
Thanks for this extensive example ... especially content_form and the content_fields loop ... hope to implement and test this week.
Thanks for your time and code sharing.
#5
I just played with some cck functions now so hope to implement the above suggestion and get rid of node_factory_set_noderef_value() function.
#6
module node_import has a special support inc for cck-fields. all kind of cck-fields including node_reference and numbers are handled.
#7
Are all remarks in this review implemented in the 1.0 beta release?
#8
I hope I translated it the right way. So it should be.
What's still lacking is the #231922: From [development] programmatic creation of node hints and tips
#9
Apart from other issues like #231922: From [development] programmatic creation of node and
node_prepareI hope I implemented these suggestions.#10
Automatically closed -- issue fixed for two weeks with no activity.
#11
Maybe I missed something, was the issue with path auto now also resolved? If not, pointers in the right direction would be great, and I will submit I can get working back to here of course