Creating a node programmatically
Hi,
my module is using the insert hook to insert nodes of type question. now i wish to create nodes with out using a node form.
I am guessing i can just create a node object of type question programmatically , alter some of its propertys and then pass it to question_insert($node) to save it. i have found node_save but no method to freshly create node objects . i also found advice to use node_aggragator but i cant find it in the api.
Is this how i should create a node ?
What functions should i use to create the fresh node object ?
Once again thankyou for all the great help. :)

Hi, think node_save is what
Hi,
think node_save is what you want.
http://api.drupal.org/api/function/node_save/5
if you don't pass a node id node_save will assume you want to created a new node and do so.
this will invoke your hook_insert (and all other ones too) so your current hook_insert should be fine.
hope that helps
Tom
______________________________________________
http://teachyourselfdrupal.com
http://codelessons.com
Register your interest now & get 20% off all future orders @ both sites
Ahh, how do i get the node id for the newly saved node ?
Thank you for the quick reply.
can you also tell me, how do i get the node id for the newly saved node.
Once again thank you.
node id...
the node id is inserted directly in the node...
node_save($node); //insert or update
$nid = $node->nid;
P.
This is how i am programmatically creating the node objects
$node = new StdClass();
//creating a bare node
$node->type = 'answer';
//giving it type
$node->status = 1;
//give it a published staus
$node->title = "Step up to the FLava";
//gives title
$node->body = "Body Body body";
//gives body
node_save($node);
//save it and give it the rest of the attributes
Cool, glad you've sorted it
Cool,
glad you've sorted it and posted your "how to" here, i'm sure other users will be interested in this.
cheers
Tom
______________________________________________
http://teachyourselfdrupal.com
http://codelessons.com
Register your interest now & get 20% off all future orders @ both sites
node_submit()?
Shouldn't there be a
$node = node_submit($node)beforenode_save($node)?I use an array
What I normally do is use an array.
<?php
$node = array(
'title' => $title,
'uid' => $uid,
'body' => $body,
'promote' => 0,
etc...
);
if ($node = node_submit($node)) {
node_save($node);
}
?>
Dave
My site: http://www.unitorganizer.com/myblog
Just a quick addition that
Just a quick addition that cost me a couple of hours... Multiple cck terms are added as an array with an extra key ['value']. If the values are not hard coded you can add them in a foreach loop:
<?phpforeach ($the_array as $key => $value) {
$node->field_name[]['value'] = $value;
}
?>
Creating a node with drupal_execute
I am currently attempting to create a node in a php file that looks something like this:
include_once('includes/bootstrap.inc');
include_once('includes/common.inc');
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$node = new stdClass();
$node = array();
$node['type'] = 'nodetype';
$node['uid'] = 5;
//cck fields
$node['field_name'] = array(0 => array('value' => value,'format' => 4));
$node = node_submit($node);
node_save($node);
This works fine but I have read here: http://www.civicactions.com/blog/cck_import_and_update that one should be using drupal_execute() to insert a node, and in this instance I need to be able to tell if the form submitted properly, and using drupal_execute seems to be the only way to do so.
So I in trying code as seen at the link above, whenever I set the uid of the node and use drupal_execute I get a new node, from an anonymous user, not the specified uid.
An example of that:
$node = array('uid' => 5,'name' => 'name,'type' => 'contenttype',);
$values = array();
$values['title'] = 'title';
$values['promote'] = 1;
$values['status'] = 1;
$values['sticky'] = 0;
//have tried to set the uid in both $node and $values (as i've seen examples with both).
//$values['uid'] = 3;
//$values['uid'][0]['value'] = 3;
$values['field_somecckfield][0]['value'] = somecckvalue;
drupal_execute('contenttype_node_form', $values, $node);
Again this works, but I get an anonymous user, unelss I use
user_authenticate('user', 'pass);for the user I'd like the node assigned to (still ignores assigning the uid) which in this case won't work for my application. Is there a method to assign the uid using drupal_execute()?so .. ?
did you know what was wrong?
...
Try
$value['name'] = 'something';.Please quote the sentence.
There's node_validate(). I believe I saw a page in the handbooks that describe the process.
drupal_execute with anonymous users. A user_register example.
Drupal 5.7
I used drupal_execute() to create a partial user profile node when users register. I used form_alter to add a few additional fields to the registration form and to set custom form validation and submission functions on user_register. Everything worked well until I tried to set the "authored by" for the node. Originally, I kept getting the anonymous user as the author, despite trying every combination of name, author, uid on the $values and $node parameters.
I found if I gave the "anonymous users" role the permission to "administer nodes" then it would work, but this is NOT a permission you give to anonymous users. This told me it was a permissions issue, so I kept messing with it.
It seems some of the functions drupal_execute() hooks into (possibly node_submit, node_save, and/or others) use the global $user variable to determine the new node's author. When the user is registering they are still anonymous, so Drupal correctly assigns the anonymous user (uid = 0) to those nodes.
However, I setup a secondary submit function on registration and was able to do things just after the new user account was created. By the time drupal_execute() executed the user already had a new account (created via user_register_submit()), they just weren't logged in. I figured I could populate the global $user variable using a user_load plus the new user's name, execute drupal_execute, and then clear the $user variable. Essentially, temporarily login in the new user, creating their profile node as them, and then logging them out. Since the user must pass through user_validate to get this far I figure it's fairly safe to rely on the username they passed in. (Please let me know if you see any security issues with this whole technique, as I was hesitant to post this code if there's a vulnerability. I wasted about 3 hours working around the anonymous issue, so thought it was worth helping some folks avoid or help come up with a better solution)
In my system_custom.module, within a system_custom_form_alter() function, I call a secondary user_registration submit function
// set the form submit to call the regular user_register_submit() (from user.module)// and the user_register_submit_custom() (defined in this module)
$form['#submit'] = array(
'user_register_submit' => array(),
'user_register_submit_custom' => array()
);
The custom function, which executes after the regular user_register_submit() to programmatically save a node
function user_register_submit_custom($form_id, $form_values) {
global $user;
$user = user_load( array( 'name' => $form_values['name'] ) ); // load the new user into the $user variable, using their registration name
$node = array('type' => 'yourContentType'); // create a new node of type uprofile
// some sample CCK fields, as an example of the format for different field types
$values['field_fieldname1']['key'] = $form_values['register_value1']; // a select (dropdown) form element
$values['field_fieldname2'][0]['value'] = $form_values['register_value2']; // a textfield form element
$values['field_fieldname3']['keys'] = 1; // a checkbox element
$values['type'] = 'yourContentType'; // the node's type
$values['status'] = 1; // set the node's status to Published
$values['title'] = $form_values['name']."'s Profile"; // the node's title
$values['body'] = 'whatever body you might want, or else, leave blank'; // the body, not required
// $values['name'] = $form_values['name']; // set the author (i.e. name) of the node equal to the username just registered
$errs = drupal_execute('yourContentType_node_form', $values, (object) $node); // call the function to create the node, node_revisions, and CCK values for the uprofile node type
// if there were any validation errors, drupal_execute will return them, then you have a chance to do something
if (count($errs)) {
// optional code here
}
$user = drupal_anonymous_user(); // clear the temporary user credentials by setting it to the anonymous user settings
} // end of function user_register_submit_custom
Notes for various skill levels
$user = user_load( array( 'name' => $form_values['name'] ) )This is the step where we take the username provided during the registration and basically log that user in temporarily. This might not be such a good idea if you were already logged in$values['name'] = $form_values['name']. Unless you're already logged in as another user with proper credentials it didn't seem to care what was set here, which was my original problem. It seems to look at who's logged in, not who you say should be the author/owner.You can view the contents of the form's array by adding code like this to any of your custom modules
/*** Implementation of hook_form_validate().
*/
function yourContentType_node_form_validate($form_id, $form) {
print_r($form);
}
Suggestions, questions, and improvements are more than welcome.
OrangeCoat.com
I solve this problem
I meet the same problem as you.
according to you mentioned, becaue of the $user, we get uid = 0, so we can add these code
global $user;$user = user_load(array('uid') => $account->uid); // or $user = user_load(array('name') => $account->name);
then we get proper uid
unable to define user name with drupal_execute()
I'm trying to define the user name to a node created programmatically using drupal_execute() via cron, but it insists on inserting uid 0 for anonymous. I have confirmed the user name being passed actually exists in the system. Other fields like the node title are defined correctly as expected.
Any advice would be appreciated.
The only way I found to do
The only way I found to do this was to temporarily log the user in, as described in my post above. There may still be some security implications, but it works. The reason you keep getting 0 is because if you're not logged in then Drupal correctly adds the node as a user 0 (an anonymous visitor). The code above and my subsequent comments should explain how to do a temporary login and how to submit text, checkbox/radio, select/drop-down box, and node reference fields programatically with drupal_execute(). If this doesn't work for you then post some details of the issue or shoot me a message via the contact form on my profile.
Jim
OrangeCoat.com
no longer an issue for me
Thanks for your advice and offer to help.
I ended up doing something different, which made anonymously created nodes perfectly acceptable.
More comments regarding this topic can be found in this thread.
Thanks Ciallella for this
Thanks Ciallella for this helpful information.
Using 6.x could this be my error?...
I used your second block (only slight variation on Lullabot's Eaton article sited).
I did a simple passthru of some simple variables. I used the 'title'=>'drupal execute title' convention for putting in data (or 'when'=>'de when' if I thought the field length was limited).
I didn't know exactly where to make this happen, but I enabled the "Execute PHP" block and placed it in there and clicked the 'Execute' button.
I got the following warning:
Might this be an irregularity of my using 6.x, or might I have done something else wrong?
I looked a that line number and it is a tertiary expression as a functon parameter passing either $callback (if it isset) or $form_id. (This seems internal based on what I did or did not include in my drupal_execute() parameters...)
When I poked in Devel's Variable Editor I see that each content type has a variable: form_build_id_<contentype>
According to the warning it would seem that the 'contenttype_node_form' portion was in error.
In my little test content type, 'drupalnotes', I look in phpMyAdmin and see that the table is called 'content_type_drupalnotes', thus my code uses:
drupal_execute('drupalnotes_node_form', $values, $node);
Yes?
BTW, I am meticulously following the directions of this and Eaton article, and thus am creating $node as an array and passing it; however it is confusing to me that $node is said to be an object (http://drupal.org/node/49768) yet we are passing an array?
Thanks in advance.
--
Brad
Programmatic Node Example For Drupal 6
Yes, Drupal 6 came with changes to drupal_execute(). Likewise, CCK has changed to the point where a Drupal 6 specific example is necessary. This is modified from the basic code snippet shown in the D6 API to include CCK fields.
Drupal 6 Example Code
$form_state = array();
module_load_include('inc', 'node', 'node.pages'); // new for Drupal 6
$nodeTmp = array('type' => 'story'); // a variable holding the content type
$form_state['values']['type'] = 'story'; // the type of the node to be created
$form_state['values']['status'] = 1; // set the node's status to Published, or set to 0 for unpublished
$form_state['values']['title'] = 'Some Node Title Here'; // the node's title
$form_state['values']['body'] = 'whatever body you might want, or else, leave blank'; // the body, not required
// the username of the node's author, must be a valid user with access to create this node.
// Otherwise, see (http://drupal.org/node/178506#comment-726479) above about using user_load() to create nodes as any user, even when not logged in
$form_state['values']['name'] = 'someusername';
$form_state['values']['op'] = t('Save'); // this seems to be a required value
// CCK field examples for CCK in D6
$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
// call the function to create the node, node_revisions, and CCK values.
// Replace "story" with the name of your form / content type
$errs = drupal_execute('story_node_form', $form_state, (object) $nodeTmp);
// if there were any validation errors, drupal_execute will return them, then you have a chance to do something
if (count($errs)) {
// optional code here
}
If you compare the Drupal 5 example to the Drupal 6 example you'll notice quite a few differences.
<input type="radio" name="field_mycheckbox[value]"which translates to $form_state['values']['field_mycheckbox']['value'] as the array in PHP code.Hope this answers them questions.
OrangeCoat.com
Wow! Thanks!... but still not getting the CCK fields in D6?...
Hi OrangeCoat-Ciallella,
Thanks so much.
I (your code) did create the nodes.
I (your code) did create the related rows in the CCK table "content_type_mycontentype" (and I used "mycontentype" instead of "story" above that).
No errors were returned.
But the actual values that were placed in the cck table rows had NULLs for each field.
I could see them in my list View and when I linked to it, the Title and Body were great, and when I edited the other fields were available (but empty or default). I was able to successfully change those NULLs to other values and post those edits.
I didn't see any "text" example, so I assumed that was not a 6 change, and also used your "view source" tip, and confirmed that, so I entered:
$form_state['values']['field_mytext'][0]['value'] = 'de mytext test1'The first two were both drop-downs so I used your syntax there, but it failed.
My guess -- but I don't have the chops to find where this happens -- is that there are two separate SQL statements, one to insert the node record and one to insert the cck content type record, and because the problem is with the Values() or the parallel list of column names portions of the INSERT it still executed and the fields were set to the Default: NULL.
So close!...
Okay, I turned the DEVEL SQL echo on, so...
When I submit these CCK lines (which I believe adhere to your example):
$form_state['values']['field_source']['value'] = 1;$form_state['values']['field_context']['value'] = 3;
$form_state['values']['field_when'][0]['value'] = 'de when9';
Here is the CCK Table SQL that is successfully run:
INSERT INTO content_type_drupalnotes (vid, nid, field_source_value, field_context_value, field_when_value) VALUES (53, 53, NULL, NULL, NULL)Since the table name and column names in the SQL match perfectly (and the row is created) it would seem that the error is happening because the 1, 3, and 'de when9' values are not "translating" for some reason.
I am logged on as User1 and I supply the the "$form_state['values']['name']" for User1; and double-checked that every single permissions checkbox is checked for Administrator. I also tried disabling the "Node Privacy by Type" module (even though everything for that was checked for Administrator).
I am committed that if you (and/or others) help me break through this barrier I will meticulously document a "follow along" step-by-step tutorial all the way through a credible example to share with all! (Not that this thread, and this reply in particular, haven't been immensely helpful; my intent is to forestall others at my relative newbie level from needing to bother you mavens again.)
Thanks again for this, and thanks in advance for any additional help.
--
Brad
I could understand how the
I could understand how the drop-down value wouldn't validate / "translate" if the value being set isn't an option for the drop-down.
For instance, when I look at field_mydropdown's settings via /admin/content/node-type/story/fields/field_mydropdown/edit
under the Allowed values I have a keyed list
1|Jim2|Evan
3|Josie
Since the 3 is a valid value for this field it saves 3 in the database and when the node is rendered it shows "Josie" in the drop-down. My drop-down was actually of type "text", so this wasn't the best example because I was actually saving integer values, but it works fine because you can save integer values as text, but not vice versa.
Your text field syntax looks alright. I added text field and text area CCK widgets and looked at the HTML source and it appears the following would be the syntax.
$form_state['values']['field_mytextfield '][0]['value'] = 'some text';
$form_state['values']['field_mytextarea'][0]['value'] = 'some longer text';
If you enabled the text processing option for a text field or text area widget (i.e. you select "Filtered text (user selects input format)" instead of "Plain text") then you'd have to also set that filter value programatically like such:
$form_state['values']['field_mytextfield'][0]['format'] = 1; // set the text field's input format to 1 or "Filtered HTML"
$form_state['values']['field_mytextarea'][0]['format'] = 2; // set the text area's input format to 2 or "Full HTML"
Likewise, if you specify other widget options, like "Number of values:" then the syntax would change. My original example used the default settings of "Plain text" and no multiply values. It appears from the SQL statement you posted that you were using Plain text, so not sure that's the problem, but you might double check your widget settings and the HTML code.
Not sure what else to check because the original code I posted worked for the default "Story" content type in Drupal 6.2 and CCK 6.x-2.0-beta . If you want further verify the syntax Drupal is generating when you do a node/add/yourContentType you could create a form_validate or form_submit hook to print the $form_state and see what it's passing in just before it's saved to the database.
/**
* Implementation of hook_form_validate() for Drupal 6
*/
function yourContentType_node_form_validate($form, &$form_state) {
print_r($form_state);
}
// OR
/**
* Implementation of hook_form_submit() for Drupal 6
*/
function yourContentType_node_form_submit($form, &$form_state) {
print_r($form_state);
}
where you'd replace yourContentType with your content type name
How to populate a CCK Node Reference Field Programatically
An additional note about how to populate a CCK Node Reference form field as part of a programatically submitted node.
It seems when a CCK Node Reference form field is processed the processing function looks for the a token like [nid:#] (where # is a valid node id). The submitted value will probably be something like The Node's Title [nid: 3] but the processor ignores the title portion and uses the token to correctly store the nid in the database.
I had a node reference field called Tour and this format worked for adding a reference to node id
$values['field_tour'][0]['node_name'] = '[nid:'.$aValidNid.']'; // populate the node reference with a token like [nid:3]See my prior comment above for a full example, which shows example formats for programatically submitting text box values, select (drop-down) values, checkboxes (and radio buttons) values.
OrangeCoat.com
can you clarify?
i'm not sure i follow this example -
i have a node type of mls_listing, a reference field called field_mls which references a node type of mls_feed. i've tried a bagillion different ways of doing this but nothing seems to work. what exactly is supposed to go into the array index where you have 'node_name'? it seems like:
$values['field_mls'][0]['mls_feed'] = '[nid:' . $nid . ']';should work, but it's not... any suggestions?
thanks a lot!
arthur
If I remember correctly,
If I remember correctly, ['node_name'] is the required value used by the CCK node reference module.
In your case, I believe you'd use
$values['field_mls'][0]['node_name'] = '[nid:' . $nid . ']';where $nid should be the node id of the referenced node.
Look at the way a node reference field works normally on a /node/add/someType form. You'll notice as you type the name of a node it will search for the node by title and then ends up putting something like "The title of the Node Here [nid:123]" in the text field via AJAX
I assume the CCK node reference field just processes the string value in the form textfield and if it sees the pattern [nid:*] in the string it uses the number specified. So, technically I think you could set the value to 'Blah Blah Blah [nid:234] and it should still work still recognize node 234 as the referenced node.
OrangeCoat.com
Definitely solution is
Definitely solution is this:
drupal_execute()
There is a very good and useful article in Lullabot.com that was extremely useful to me.
http://www.lullabot.com
Here it is:
http://www.lullabot.com/articles/quick_and_dirty_cck_imports
Hope it is useful.
'name' not 'uid' for registered users.
I had a problem of newly created nodes created under uid of 0, or an anonymous user.
Initially I kept trying to insert the uid into the node. I ended up with inserting 'name' for the node after reading the example at a website. Somehow, that works but uid doesn't.
I used the following to insert the new node of custom content type.
global $user;
$node = array('type' => 'cont_sentitems', 'name' => $user->name);
$values['title'] = $subject;
$values['body'] = $body;
$values['recipients'] = $to_string;
drupal_execute('cont_sentitems_node_form', $values, $node);
Hope this benefits people who encounter the same problem as me and have yet to find a solution or ended up doing this another way.
so i've got all this down.
so i've got all this down. now suppose i wanted to included the taxonomy as well. how would i do that? i'm trying basically do an import of data that already matches to my current taxonomy...i haven't been able how i could add data to my node before posting in order to get it to post taxonomy data too.
It sounds like you're asking
It sounds like you're asking how to add taxonomy terms to a node programatically.
If so, I'd suggest trying the following. As an example, lets assume you have a node of type Book and you want to add to it a taxonomy term of "Fiction", where Fiction has a term ID (tid) of 22 and it part of the vocabulary "Book Type" with a vocabulary ID (vid) of 1. Also assume the vocabulary allows for multiple select and no free tagging.
If you go to the normal /node/add/book page you can look at the HTML source and see something like
<select name="taxonomy[1][]" multiple="multiple" ....<option value="22">Fiction</option>
or if you use print_r($node) on _nodeapi() hook or print_r($form_values) with a _validate() hook you'd see something like this
[taxonomy] => Array
(
[1] => Array
(
[22] => 22
)
)
So, without actually testing this I'm going to suggest the syntax to add a tag or tags to a node programatically for multiple select, no free tagging vocabulary would be
$values['taxonomy'][1][] = 22;OR
$values['taxonomy'][1][22] = 22;Again, where 1 = the vid of your vocabulary and 22 is the tid of your term.
I'm not sure if either or both of these would work, so this is just pointing you in a direction. Also, the syntax for free tagging or no multiple select could very well be different.
In general, if you look at the the "name" attribute of a form element on the /node/add/yourType page's HTML then it should provide insight into what to use following $values. Also, using print_r() within the _validate() _submit() or nodeapi() hooks should show you what the array of values looks like after Drupal has built it.
OrangeCoat.com
Thanks a lot,
Thanks a lot, orangecoat-ciallella, this is very usefull.
My question is: if i create several nodes at a time with this method and one of them have not passed validation( we have $err) but will the data be inserted in db or the process will be like if that was done by submitting node form(incorrect data is not inserted in db) and what will be with other nodes?
Thanks one more time!
According to the Drupal 5
According to the Drupal 5 API, drupal_execute is "the programmatic counterpart to drupal_get_form". The code for drupal_execute calls drupal_process_form, which calls validation functions and returns on errors. To to me that suggests if an error is encountered then no data would be inserted into the database, just like when validation fails through a regular node form.
If you want to test I'd suggest creating a form validate hook for the node type being submitted and generate a form error by calling form_set_error()
OrangeCoat.com