Download & Extend

Programmically assign parent when creating a node from script

Project:Node Hierarchy
Version:6.x-2.x-dev
Component:Documentation
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed (fixed)

Issue Summary

Hey,

I am writing a module that takes some content from a parent node, manipulates it, then adds the manipulated content to child nodes.

There is a lot of documentation/tutorials on how to create a node/modify a node/add stuff to cck/etc... with a script... but didnt really see any thing for this module.

How would I go about setting the parent of a node from a script?

Normal nodes are something like this:

<?php
// Construct the new node object.
$node = new stdClass();

// Your script will probably pull this information from a database.
$node->title = "My imported node";
$node->body = "The body of my imported node.\n\nAdditional Information";
$node->type = 'story';   // Your specified content type
$node->created = time();

CCK something like this:

<?php
$node
->field_text_field[0]['value'] = "value 1";
$node->field_text_field[1]['value'] = "2nd value";
$node->field_nodereference[0]['nid'] = 58;
?>

(on a side note... If anyone is interested, I got this code from here: http://acquia.com/blog/migrating-drupal-way-part-i-creating-node ).

How would I do this w/ node hierarchy?

Comments

#1

Soooo yeah, I just guessed and gave it a shot... and it worked :)

I decided to go w/ drupal_execute from this guide: http://thedrupalblog.com/programmatically-create-any-node-type-using-dru...

Here is what I came up with:

// create $form_state
$form_state = array();
$form_state['values'] = array(
    'title' => t('MyTitle ') .$i, // 'i' is just a counter, I have this in a loop.
    'body' => spin($string, false),
    'name' => $myuid, //this var is the user ID pulled from a database
    'parent' => $mynid,  //var is also pulled from a database, its the node id of the parent I want.
    'op' => t('Save'),
);

/* add CCK fields -- used later for cck fields
$form_state['values']['field_MYFIELD1'][0]['value'] = "blah";
$form_state['values']['field_MYFIELD2'][0]['value'] = "wee";
*/

// create $node
$node = (object) NULL;
$node->type = 'article';

// include node file, necessary for node generation
module_load_include('inc', 'node', 'node.pages');

// create node using drupal_execute
drupal_execute('article_node_form', $form_state, $node);

The 'parent' is what I used and set it as the nid.

Hope this helps someone :).

#2

Hi,

Just in case there is someone else that is using the 2.x branch (which is a lot better) here is what I came up with to create a new child when a node (of a certain type) is created.
If you know a better way of doing this please post a reply here.

/**
* hook_nodeapi
*/
function myModule_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if($op == 'insert' && $node->type == REPLACE_THIS_WITH_YOUR_NODE_TYPE) {
    global $user;

    $nid = @$node->nid;

    $plid = _nodehierarchy_get_node_mlid($nid);
    $nodehierarchy_menu_links = _nodehierarchy_default_menu_link($nid, $plid);
    $nodehierarchy_menu_links['hidden'] = FALSE;

    $nodehierarchy_old_menu_links = $nodehierarchy_menu_links;
    $nodehierarchy_old_menu_links['enabled'] = TRUE;
    unset($nodehierarchy_old_menu_links['hidden']);
    unset($nodehierarchy_old_menu_links['link_path']);
    $nodehierarchy_old_menu_links['link_title'] = '';
    $nodehierarchy_old_menu_links['expanded'] = '';
    $nodehierarchy_old_menu_links['description'] = '';
    $nodehierarchy_old_menu_links['customized'] = '';

    // This is the child node
    $std_node = new stdClass();
    $std_node->title = 'The node\'s title';
    $std_node->type = 'page';
    $std_node->uid = $user->uid;
    $std_node->nodehierarchy_menu_links[] = $nodehierarchy_menu_links;
    $std_node->nodehierarchy_old_menu_links[] = $nodehierarchy_old_menu_links;
    node_save($std_node);
  }
}

#3

The way I'm using this (w/ NH 1.2), I have a parent, which is created by users, and then they push a button (on a different page) and there parent is analysed and 100's of children are spit out.

Since I am also using batch api, I have to pass $nid (the parent nid) from previous functions.

function add_new_node($title, $myusername, $nid, $body, $descr, $refbox) {

/**
* Saving current user, then loading user w/ permissions to change author and pick parent nodes
* I have to do this because normal users don't have the permissions to set the author of a node.
* I want the children author to be the same as the parents author, even if someone else generates the children.
*
*/
global $user;
//save current user name
$current_user = $user -> name;
//load user with permissions to do everything on here
$user = user_load(array('name' => 'spincreator_donttouch'));
  $node = new StdClass();
  $node->type = 'auto_spun_article';
  $node->status = 1;
  $node->promote = 0;
  $node->format = 1;
  $node->title = $title;
  $node->name = $myusername; //used a username pulled from a query of the parent

// This is where I set the parent node id for the child... that simple
$node->parent = $nid;
  $node->field_spun_ref_box[0]['value'] = $refbox;
  $node->field_spun_desc[0]['value'] = $descr;
  $node->field_spun_article_body[0]['value'] = $body;
  $node = node_submit($node);
  if ($node->validated) {
    node_save($node);
  }
  //load old user back in
  $user = user_load(array('name' => $current_user));
}

I stopped using drupal_execute because a) it sometimes hates on cck fields b) its kinda funky with batch api... (plus I noticed it doesnt have a D7 section in the api http://api.drupal.org/api/function/drupal_execute/6 ... )

I didnt even look at the 2.x version yet.... I didn't realize it was changed so much. Hmmm.... maybe I should look at it instead.

#4

I didnt even look at the 2.x version yet.... I didn't realize it was changed so much. Hmmm.... maybe I should look at it instead.

Before starting playing with it have a look at this patch first:#623300: SQL errors in the latest 2.x dev from 2009-Nov-01

Cheers

#5

Version:6.x-1.2» 6.x-1.3

Hi all,

I'm also attempting to create child nodes but it doesn't want to work. Here's the code snippet:

/////////// save sub node

$node = new stdClass();

$node->type = 'allgemein'; 
$node->title = $src_title . ' - Allgemein';
    $node->field_citydesk[0]['value'] = $maintext;

$node->parent  = $mainnid;

$node->created = time();
$node->changed = $node->created;
$node->status = 1;
$node->promote = 1;
$node->sticky = 0;
$node->format = 1;       // Filtered HTML
$node->uid = 1;          // UID of content owner

node_submit($node);
if ($node->validated) {
node_save($node);
}

The node gets created correctly except no parent is assigned.
Manually assigning the parent works fine.
$node->parent is set correctly prior to the call to node_save but turns up empty afterwards.

Guess I could work around it by writing to nodehierarchy directly but then I'd run into problems with URL alias which is supposed to assign an alias based on the parent name.

Tearing my hair out already here. Any views why this may not work?

EDIT: never mind, it needed the user_load piece.

#6

I'm using the latest 2.x dev, and I have tried andreiashu's pattern, but I can't get it to work.

Specifically, here's my code ($par_nid is a node ID loaded from the database):

<?php
$plid
= _nodehierarchy_get_node_mlid($par_nid);
$nodehierarchy_menu_links = _nodehierarchy_default_menu_link($par_nid, $plid);
$nodehierarchy_menu_links['hidden'] = FALSE;
$nodehierarchy_old_menu_links = $nodehierarchy_menu_links;
$nodehierarchy_old_menu_links['enabled'] = TRUE;
unset(
$nodehierarchy_old_menu_links['hidden']);
unset(
$nodehierarchy_old_menu_links['link_path']);
$nodehierarchy_old_menu_links['link_title'] = '';
$nodehierarchy_old_menu_links['expanded'] = '';
$nodehierarchy_old_menu_links['description'] = '';
$nodehierarchy_old_menu_links['customized'] = '';

$node->nodehierarchy_menu_links[] = $nodehierarchy_menu_links;
$node->nodehierarchy_old_menu_links[] = $nodehierarchy_old_menu_links;
?>

#7

Hi. Please has anyone been able to do this with latest 2.x? I could not get it to work too.

I tried both methods i.e #2 and #3

The breadcrumb is set though in the child. But the child is not linked to parent node, and hence does not show up under parent. Looks like there is still one more setting to do...

edit: Also was running it as admin, so permissions should be fine...

also tried:

....
$node->nodehierarchy_menu_links[0]['pnid'] = $pid;
$node->parent = $pid;

    node_save($node);

where $pid is nid of parent. Created breadcrumbs ok, but parent still not set....

#8

@zeezhao

Can you post the code you have working? I'm having the same problem as well using #2 except the breadcrumb doesn't even appear...

#9

as well, @zeezhao

Can you confirm that the children don't exist by going to the parent node and clicking on the 'Children' tab? I've had it happen where no default view has been set to view the children on the same node display as the parent.

#10

Version:6.x-1.3» 6.x-2.x-dev
Component:Documentation» Miscellaneous

I finally got this working on 2.x

Code below is based off of andreiashu's. Is tested and works...

<?php

//$nid is the parent nid from wherever you get it

global $user; //assuming you're logged in with the right permissions

$plid = _nodehierarchy_get_node_mlid($nid,true); //    <-------- Important don't forget the 'true'.

$node = new stdClass();
$node->type = 'subnodetype';
$node->title = 'title';
$node->created = time();
$node->changed = $node->created;
$node->status = 1;
$node->promote = 0;
$node->sticky = 0;
$node->format = 1;       // Filtered HTML
$node->name = $user->name;     // <----- use $user->name otherwise you get 'Anonymous'
$node->language='en';
node_submit($node);
node_save($node); // <--- Save the node now

$nodehierarchy_menu_links = _nodehierarchy_default_menu_link($nid, $plid);
$nodehierarchy_menu_links['pnid']=$nid;   // <----- Give the menu link the parent id
$nodehierarchy_menu_links['hidden'] = FALSE;
$nodehierarchy_menu_links['enabled'] = TRUE; //  <------ Make sure the menu link is enabled
 
//Is $nodehierarchy_old_menu_links necessary? Doesn't look like it...but keep it just for kicks
$nodehierarchy_old_menu_links = $nodehierarchy_menu_links;
$nodehierarchy_old_menu_links['enabled'] = TRUE;
unset(
$nodehierarchy_old_menu_links['hidden']);
unset(
$nodehierarchy_old_menu_links['link_path']);
$nodehierarchy_old_menu_links['link_title'] = '';
$nodehierarchy_old_menu_links['expanded'] = '';
$nodehierarchy_old_menu_links['description'] = '';
$nodehierarchy_old_menu_links['customized'] = '';

$node->nodehierarchy_menu_links[] = $nodehierarchy_menu_links;
$node->nodehierarchy_old_menu_links[] = $nodehierarchy_old_menu_links;

_nodehierarchy_save_node($node); // <---- Let nodeheirarchy do it's thing

?>

#11

Thanks for this! Will try it out.

I looked into what I was doing last night and these are the additional issues...:

1. The way I did it before actually created the children under the new parent, and was visible from the "Children" tab. but not showing up in the view. So had to do:
$node->nh_children_view_display = 'default';

2. Now after doing that, because the new parent was cloned in code, for some reason its view was pointing to view of node from which it was cloned, but still had correct children under its "Children" tab! So some settings were not right on the clone.

Hope you stuff clears it up for me. Thanks.

#12

Version:6.x-2.x-dev» 6.x-1.3
Component:Miscellaneous» Documentation

Make sure you add this:

$std_node->nodehierarchy_menu_links[0]['plid'] = $plid;
$std_node->nodehierarchy_menu_links[0]['pnid'] = $nid;

Should work.

#13

Thanks for all your help and comments. Got it to work eventually... As I was also cloning existing nodes, had to add some extra steps:
For cloned child:

.....
        //to ensure stuff from clone not carried forward
$node->nodehierarchy_menu_links = NULL;
$node->nodehierarchy_old_menu_links = NULL;

$plid = _nodehierarchy_get_node_mlid($pid, TRUE);
node_submit($node);
node_save($node);

$nodehierarchy_menu_links = _nodehierarchy_default_menu_link($pid, $plid);
$nodehierarchy_menu_links['pnid']= $pid;
$nodehierarchy_menu_links['hidden'] = FALSE;
$nodehierarchy_menu_links['enabled'] = TRUE;
$nodehierarchy_old_menu_links = $nodehierarchy_menu_links;
$nodehierarchy_old_menu_links['enabled'] = TRUE;
unset($nodehierarchy_old_menu_links['hidden']);
unset($nodehierarchy_old_menu_links['link_path']);
$nodehierarchy_old_menu_links['link_title'] = '';
$nodehierarchy_old_menu_links['expanded'] = '';
$nodehierarchy_old_menu_links['description'] = '';
$nodehierarchy_old_menu_links['customized'] = '';
$node->nodehierarchy_menu_links[] = $nodehierarchy_menu_links;
$node->nodehierarchy_old_menu_links[] = $nodehierarchy_old_menu_links;
_nodehierarchy_save_node($node);

For cloned parent, since it was also cloned from another parent node, and was not going to have any parent itself, I had to do:
.....
$node->nodehierarchy_menu_links = array();
$node->nodehierarchy_menu_links[0]['pnid'] = 0;
$node->nodehierarchy_menu_links[0]['plid'] = 0;
$node->nodehierarchy_menu_links[0]['mlid'] = 0;
$node->nodehierarchy_menu_links[0]['enabled'] = TRUE;
        node_save($node);
_nodehierarchy_save_node($node);
.........

#14

Version:6.x-1.3» 6.x-2.x-dev

#15

i can't say it enough
thankyou thankyou thankyou
i've spent alot of time trying to make this happen!! cheers.

#16

#13 works in D7 too!

Thank you! this saved me hours...

#17

Title:Programmically assign parent when creating a node from script in D6» Programmically assign parent when creating a node from script
Status:active» fixed

Made the title more ambiguous to hopefully steer future searchers.

#18

Status:fixed» closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.