Does anyone have an example php or mysql script that can create everything that is need to make a new node work properly with when using Drupal 4.7? The new vid column is breaking all of my previous methods for direct importing of content. I can get the content out of the various custom apps without too much pain, just getting into drupal is causing problems.

Comments

nevets’s picture

Here is a stripped down version of some code I have used in 4.7 for creating a node from code. You will need to modify as noted in the comments

<?php
                global $user;

		$node = new StdClass();
		// Information for base node
		$node->type = 'content type';  // *** This needs to be a valid content type
		$node->uid = $user->uid;

		// Optional - Useful if you want the create date/time to reflect something other than now
		// $node->created = ** Valid unix time stamp

		$node->status = 1;  // Set to 0 if you do not want the content published
		$node->promote = 0;  // Set to 1 if you do not want the content promoted to the front page
		$node->sticky = 0;  // Set to 1 if you do not want the content sticky
		$node->title = 'This is the title for the content';
		$node->body = 'The body of the node';
		$node->teaser = 'The teaser of the node';

		node_save($node);
		$nid = $node->nid;
?>
biohabit’s picture

How would you incorporate a script interating over a csv file using PHP?

toddgator’s picture

Did you ever get the code to import a CSV file into nodes? I need to get mine into flexinodes and I am stumped!

-Todd

http://www.toddalbert.com

biohabit’s picture

Have you taken a look at the node_import module? It is CVS and it should work with flexinode. The problem I'm running into is I want to directly insert nodes from scripts that run outside drupal and I've made it a little further but not a complete solution.

toddgator’s picture

I'm not having luck with node_import, although it claims to do exactly what I need. It is not working in 4.7, though.

The reason that I asked is that I figured that if you had this working, I might be able to run a script to insert my nodes. I only have to do this once, but I have over 6,000 nodes to insert from an older database.

Good luck!
-Todd

http://www.toddalbert.com

michaelangela’s picture

Just adding that I have had partial success with node_import using the CVS version with 4.7.2. It's not consistent, but it is working. I am only using it with flexinodes though. 2 out of 3 flexinodes area able to import (so far) but one type that I have just won't import at all through the standard UI. So I have been using the raw format and that has been working... still testing...

I may have to check out this kind of code though... might be more useful to deal with it directly.

For CSV files though, node_import uses http://php.net/fgetcsv. There is quite a bit about CSV and PHP on Google.

HTH
--------------------
Michael
http://michaelangela.name

pwolanin’s picture

I've thought about trying to do this using PHPmyadmin (which can import CSV) to put my data in a table in the database. Then within Drupal I could do an SQL query to get all the rows (or a subset of rows) from that table and run a loop where each iteration adds a node as per above. When done, just drop that table or delete the rows that have already been processed.

---
Work: BioRAFT

somebodysysop’s picture

Excellent. Thanks for the post. One small question: How do I say that this node belongs to a particular category?

Thanks!

<?php
                global $user;

        $node = new StdClass();
        // Information for base node
        $node->type = 'content type';  // *** This needs to be a valid content type
        $node->uid = $user->uid;

        // Optional - Useful if you want the create date/time to reflect something other than now
        // $node->created = ** Valid unix time stamp

        $node->status = 1;  // Set to 0 if you do not want the content published
        $node->promote = 0;  // Set to 1 if you do not want the content promoted to the front page
        $node->sticky = 0;  // Set to 1 if you do not want the content sticky
        $node->title = 'This is the title for the content';
        $node->body = 'The body of the node';
        $node->teaser = 'The teaser of the node';

        node_save($node);
        $nid = $node->nid;
?>
nevets’s picture

Before the call to node_save($node) add

$edit->taxonomy[] = 1;  // Replace 1 with the tid you want to use

or if you want to assign multiple categories you can use

$edit->taxonomy = array(1, 2, 3);  // Replacing 1,2 and 3 with the tids you want to use (note you can use fewer or more tids)
L0rne’s picture

I've been trying to get nodes to save with taxonomy information, but it isn't working for me. I checked the database to be sure I'm using the correct tid; the node is created fine, but has no taxonomy information.

This seems to almost work (the taxonomy link shows up on the page that previews the node teaser immediately after node creation, but the link is not there when I view the node from anywhere else):

$term = new StdClass();
$term->tid = "236";

$node->category[236] = $term;

node_save($node);

Any advice will be greatfully recieved

- L0rne

- L0rne

pwolanin’s picture

are you using the category module or the core taxonomy module?

---
Work: BioRAFT

L0rne’s picture

Oh, sorry, the code I posted should have read:

$term = new StdClass();
$term->tid = "236";

$node->taxonomy[236] = $term;

node_save($node);

The "$node->category[236]" thing was something I was testing.

To answer your question in a more direct way, I am using the category module.

- L0rne

- L0rne

nevets’s picture

When editing, taxonomy is just an array of tids, so your code would read

<?php
$node->taxonomy[] = 236;

node_save($node);
?>
L0rne’s picture

Odd! That was the first thing I tried. I tried it again, but it's not working.

The taxonomy bit of the node object looks like this just before node_save:

[taxonomy] => Array ( [0] => 236 )

This is a newly created node object. Is there anything special I need to do to initialize the taxonomy property? What else might I be doing wrong?

Thank you for the input!

- L0rne

- L0rne

nevets’s picture

Are you setting anything other than taxonomy? I ask because you show only a partial example, creating a node object with only the taxonomy field will have no effect.

L0rne’s picture

Here's a more complete account of what is happening.

I am importing content files using import_html. The stuff I am editing is in import_html.module. I found the place in the code where the node object is created, and added a few things just before node_save:

		  drupal_set_message(t("setting node to published and promoted"));

		  $node->status = 1;
		  $node->promote = 1; 
		  $node->sticky = 0;

		  $node->taxonomy[] = 236;

		  node_save($node);

Everything works fine, except the taxonomy. From what you have told me, and from what I have found elsewhere on this site, this should work. There must be something I am missing. I wonder if my taxonomy value is being over-writen somewhere else?

- L0rne

- L0rne

nevets’s picture

$node->type needs to be set to the type of content you are creating and the vocabulary for term 236 needs to include that type.

L0rne’s picture

The node type is being set to "page", and this type has been added to the types for the vocabulary. I am able to add other pages to this term, using the usual interface.

Does it matter that I am using the Category module?

- L0rne

- L0rne

nevets’s picture

It is possible it matters that you are using the Category module since $node->taxonomy[] applies to the taxonomy module. So if you are talking about values for the Category module this will not work, that would be different code (what it would look like I do not know).

L0rne’s picture

Having the Category module active does seem to be my problem. Here is my work-around:

  • De-activate the Category module and all of it's related modules.
  • Run the script to assign nodes to taxonomy terms.
  • Activate the Category module and related modules.

It seems that the taxonomy terms are brought over into Category when Category is activated, possibly thanks to category_legacy.

This worked for me because I'm doing one-time import stuff; I am certainly interested in a nice way to work with the Category module directly.

- L0rne

L0rne’s picture

I just revisited this for another project. I'm not sure if it was the same last time, but my problem this time was solved by ensuring that my document type was allowed in the vocabulary (container) that I was using. The taxonomy is now being added to the node with the Category module active.

nevets asked me if i had this set properly more than a year ago...

- L0rne

- L0rne

somebodysysop’s picture

This looks like it will add taxonomy from the vocabulary table:

$edit->taxonomy[] = 1; // Replace 1 with the tid you want to use

But, suppose I want to add category ids from the category table (from the category module)?

biohabit’s picture

Does anyone have an example of how to import fields into CCK created tables?

tormu’s picture

This is how I've imported nodes when using CCK-generated node types with bodies and teasers:

$node->body = '';
$node->field_body[0]['value'] = $body;
$node->field_body[0]['format'] = 4; //bbcode = 4
$node->teaser = '';
$node->field_teaser[0]['value'] = $teaser;
$node->field_teaser[0]['format'] = 4; //bbcode = 4
$node->field_main_image[0]['value']  = $image;

This is for checking a checkbox-typed field named "frontpage_topstory", the only option being "topstory":
$array = array(0 => array("value" => "topstory"), "keys" => array(1 => 1));
$node->field_frontpage_topstory = $array;
rich.yumul’s picture

Here's a snippet of how to do bulk import of nodes with a command line script.

A 'sig' is a special interest group node type that I created with CCK for use as the group home page in Organic Groups.

I put this script in the same directory as the drupal installation, so all the includes, etc. would work.

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

/*
for my purposes, I just put the node items in an array in the script, 
but it could be refactored to read node info from a CSV or text file.
*/
# array of states
$states = array(
  'Alaska',
  'Alabama',
  'Arizona',
  'Arkansas',
  'California',
  'Colorado',
  'Connecticut',
  'Delaware',
  'Florida',
  'Georgia',
  'etc...');

foreach ($states as $item) {
  echo "processing $item\n";

  $node = new StdClass();

  $node->type = 'sig';
  $node->uid = 1;
  $node->status = 1;
  $node->promote = 0;
  $node->sticky = 1;
  $node->title = $item;
  $node->body = 'Portal for ' . $item . ' athletes';
  $node->teaser = 'Portal for ' . $item . ' athletes';
  $node->field_group_type = array(array('value' => 'Location') );
  $node->og_public = 1;
  $node->og_description = $item . ' Athletes';
  $node->og_selective = 0;
  $node->og_register = 0;
  $node->og_directory = 1;
  $node->validated = 1;

  node_save($node);
}


?>

HTH!

Rich Yumul
www.sagetree.com

somebodysysop’s picture

Your example shows how to add a group node using node_save. But, do you know how to add a node to a group using node_save? That is, if I'm creating a "page" node, and I wish to add it to Group A using node_save, how do I code that? The following won't work:

  $title = 'Test Title';
  $body = 'Test Body';
  $gid = 323;
  $group = node_load($gid);
  $groupName = $group->title;

  $node = new stdClass();
  $node = array();
  $node['type'] = 'brix';
  $node['uid'] = 1;
  $node['title'] = $title;
  $node['body'] = $body;
  $node['og_groups'][0] = $gid;
  $node['og_groups_names'][0] = $groupName;

  if ($node = node_submit($node)) {
    node_save($node);
  }

Any ideas? Thanks!

chavalina’s picture

Should I create a module to place and run this code?
Thanks and sorry for my poor English.

tormu’s picture

I imported all the nodes by just making the code into a normal drupal page and just selecting PHP as the input format.

rezareza’s picture

exemple :


require "../db2.php";
$reponse = mysql_query("SELECT * FROM 2008_aggregator_item ORDER BY RAND() DESC LIMIT 1");

$donnees = mysql_fetch_array($reponse);
$titre = $donnees['title'];
$body = $donnees['description'];
$randy = rand(1, 2449);
$url = "http://laurent.gandhi.free.fr/400x400/the$randy.jpg";
$teaser = "<h1>YO !</h1><br><br><img src='$url'>";
echo "$titre<br>$body<br>$teaser";
                global $user;

        $node = new StdClass();
        // Information for base node
        $node->type = 'messagepublic';  // *** This needs to be a valid content type
        $node->uid = $user->uid;

        // Optional - Useful if you want the create date/time to reflect something other than now
        // $node->created = ** Valid unix time stamp

        $node->status = 1;  // Set to 0 if you do not want the content published
        $node->promote = 1;  // Set to 1 if you do not want the content promoted to the front page
        $node->sticky = 0;  // Set to 1 if you do not want the content sticky
        $node->title = $titre;
        $node->body = $body;
        $node->teaser = $teaser;
        $node->format = 1;
        $node->language 'fr';


        node_save($node);
        $nid = $node->nid;
rezareza’s picture

here an exemple to add bloggersearch

put this in a news block will auto updated


require "../db2.php";


$reponse = mysql_query("SELECT * FROM 2008_aggregator_item ORDER BY RAND() DESC LIMIT 1");
$donnees = mysql_fetch_array($reponse);

$lelink1 = $donnees['link'];
$titre1 = $donnees['title'];
$body1 = $donnees['description'];
$randy = rand(1, 2449);
$url = "http://laurent.gandhi.free.fr/400x400/the$randy.jpg";
$teaser1 = "<h1>YO !</h1><br><br><img src='$url'>";

$xml = simplexml_load_file("http://blogsearch.google.fr/blogsearch_feeds?hl=fr&lr=&q=$titre1&ie=utf-8&num=5&output=rss");

$xmldone = $xml->channel->item[0]->title."<br />";
$xmldone1 = $xml->channel->item[0]->link."<br />";
$xmldone2 = $xml->channel->item[0]->description."<br />";

$xmldonea = $xml->channel->item[1]->title."<br />";
$xmldone1a = $xml->channel->item[1]->link."<br />";
$xmldone2a = $xml->channel->item[1]->description."<br />";

$xmldoneaz = $xml->channel->item[2]->title."<br />";
$xmldone1az = $xml->channel->item[2]->link."<br />";
$xmldone2az = $xml->channel->item[2]->description."<br />";

$xmldoneae = $xml->channel->item[3]->title."<br />";
$xmldone1ae = $xml->channel->item[3]->link."<br />";
$xmldone2ae = $xml->channel->item[3]->description."<br />";

$xmldonear = $xml->channel->item[4]->title."<br />";
$xmldone1ar = $xml->channel->item[4]->link."<br />";
$xmldone2ar = $xml->channel->item[4]->description."<br />";

$body2 = "$teaser1<br><br>$body1<br><br>Voir la suite sur le site d'origine : <a href='$lelink1'>HOP LA</a><br><br>Référencement de cette article : <br>$xmldone $xmldone1 $xmldone2 <br> $xmldonea $xmldone1a $xmldone2a <br> $xmldoneaz $xmldone1az $xmldone2az <br> $xmldoneae $xmldone1ae $xmldone2ae <br> $xmldonear $xmldone1ar $xmldone2ar";
                global $user;

        $node = new StdClass();
        // Information for base node
        $node->type = 'messagepublic';  // *** This needs to be a valid content type
        $node->uid = $user->uid;

        // Optional - Useful if you want the create date/time to reflect something other than now
        // $node->created = ** Valid unix time stamp

        $node->status = 1;  // Set to 0 if you do not want the content published
        $node->promote = 1;  // Set to 0 if you do not want the content promoted to the front page
        $node->sticky = 0;  // Set to 1 if you do not want the content sticky
        $node->title = $titre1;
        $node->body = $body2;
        $node->teaser = $teaser1;
        $node->language = 'fr';
        $node->comment = '2';
        node_save($node);
        $nid = $node->nid;
daniel.hunt’s picture

*bump* for subscription

designerbrent’s picture

bump2 for subscription

jeffvogelsang’s picture

Hi all,

I made use of the information on this page and on others. I wanted to give back my completed script in case it helps others. This work for me on Drupal 5 importing hundreds of records.

// Written by Victor Kane - victorkane at awebfactory dot com dot ar
// *** This script affects your database
//
// Edits by Jeff Vogelsang - jeffvogelsang at pqa dot com

// CONFIGURATION

// Change the value below to TRUE when you want to run the script After running,
// immediately change back to FALSE in order to prevent accidentally executing
// this script twice.
// NOTE: I find the best way to do this is to leave it false. When you are ready
// to execute, set to this variable to true, and then click Preview. The script
// will execute, but will not be saved with the value set to true. This prevents
// accidentally saving the script with the value set to true. Also, it prevents
// the unfortunate situation where the cron job runs while it's set to true,
// and you get double imports.
$active = false; 

// Bootstrap Drupal
include_once "includes/bootstrap.inc";
include_once("includes/common.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// CSV file containing the data to import.
// For simplicity I place this in the root of the Drupal
// site and remove it when done.
$data_archive = 'mn1.csv';

// Content information... This is the CCK type data you wish to import to.
// It needs to match exactly your created content type information.
$content_type = 'eis_meeting_notes';
$content_name = 'EIS Meeting Notes';

// Check for the script being enabled, and for appropriate permissions.
if ($active) {
    if (user_access("administer content types")) {
        insert_content($content_type, $data_archive);
    } else {
        print "You don't have permission to administer content types.";
    }
  } else {
        print "Variable active is set to false.";
}

function insert_content ($content_type, $data_archive) {
	// Open the CSV file read only.
    $handle = fopen($data_archive, "r");
	// Read the headers from the first line.
    $theHeaders = fgetcsv ($handle);
	// Keep count of how many lines we have processed.
    $lineno = 0;
    while ($line = fgetcsv ($handle)) {
        $output = '';
    $valueno = 0;
    $lineno++;
    $output .= '<ul>Line: '. $lineno;
    $observaciones = '';
    foreach ($line as $value) {
      if ($value) {
        $output .= '<li>'.$theHeaders[$valueno].': '.$value.'</li>';
        $observaciones .= '<li>'.$theHeaders[$valueno].': '.$value.'</li>';
      }
      $valueno++;
    }
    $output .= '</ul>';

    // Create new node
    $node = array();
	// Node is of type $content_type/$content_name
    $node['type'] = $content_type;
    $node['name'] = $content_name;
	// Formats on CCK nodes apply to fields, so no format set here.
    $node['format'] = 0;
	// Enable read/write comments.
    $node['comment'] = 2;
	// Published
    $node['status'] = 1;
	// Not promoted to front page.
    $node['promote'] = 0;
	// Not sticky.
    $node['sticky'] = 0;
	// Create a log entry for the first revision.
    $log = 'Imported from csv.' . date('g:i:s a');
    $node['log'] = $log;

    // Node fields here, mapped to CSV file data.
    $node['title'] = $line[1];
    $node['created'] = $line[4];
    $node['name'] = $line[7];
    $node['uid'] = $line[8];

    // CCK fields here, mapped to CSV file data.
	// For each, we set the value, and the desired input/output format.
	// In this case, format 4 is a non-html-filtering input type.
	
	$node['field_eis_action_items'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[16],
	            'format' => 4
	        )
	);

	$node['field_eis_agenda'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[14],
	            'format' => 4
	        )
	);

	$node['field_eis_attendees'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[9],
	            'format' => 4,
	        )
	);

	$node['field_eis_meeting_date'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[10]
	        )
	);

	$node['field_eis_notes'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[22],
	            'format' => 4
	        )
	);

	$node['field_eis_open_issues'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[20],
	            'format' => 4
	        )
	);

	$node['field_eis_purpose'] = array
	(
	    0 => array
	        (
	            'value' =>  $line[12],
	            'format' => 4
	        )
	);

	$node['field_eis_requirements'] = array
	(
	    0 => array
	        (
	            'value' => $line[18],
	            'format' => 4
	        )
	);

	// Basic check for having a non-blank title.
	// Then submit/save node, and output the data we used for this node.
    if ($node['title']) {
      $node = (object)$node;
		// This is the unique TID from the taxonomy table. It can also be an array of values.
		// Set it here after we turn the node into an object...
		$node->taxonomy[] = 1;
      $node = node_submit($node);
      node_save($node);
      print $output;
    };
  }
}

---
Jeff Vogelsang
Senior Associate (Technical Architect, Developer)
Perrin Quarles Associates

dindon’s picture

Thanks for that script!! it's very usefull but i've got problem when i need to insert screenshot and attachment.

do you have any idea how to do it? the cck fieldimage handle the screenshot and upload module for attachment.

Regards,

tormu’s picture

Not sure if this helps all the way, but this is how I've added files to nodes when mass importing stuff - this is for Drupal 4.7.
This is AFTER node_save() in the code.


//Soundfile directory
$dir = "files";

//$files-array contains filenames and possible descriptions
if(!empty($files))
{
	$i = 0;
	foreach($files as $file)
	{
		$upload = new StdClass();
		$upload->fid = 'upload';
		$upload->filename = $file[0];
		$upload->filepath = $dir . '/' . $file[0];
		$upload->filemime = 'audio/mpeg';
		$upload->filesize = filesize($dir . '/' . $file[0]);
		$upload->description = $file[1];
		$upload->list = 1;
		$node->files = array();
		$node->files[$i] = $upload;
		$i++;
	}
	//This saves the looped files to the node that was just saved prior to this code.
	upload_save($node);
}


dindon’s picture

thanks!!

it works!

coupet’s picture

//$files-array contains filenames and possible descriptions

Please provide a sample $files array as described.

----
Darly

tormu’s picture

$files[0][0] = 'example_file_1.mp3';
$files[0][1] = 'Description for example_file_1';
$files[1][0] = 'example_file_2.mp3';
$files[1][1] = 'Description for example_file_2';
$files[2][0] = 'example_file_3.mp3';
$files[2][1] = 'Description for example_file_3';
coupet’s picture

@ Jery, great thanks! following may work alternatively.

  $files = array (
  array ('example_file_1.mp3', 'Description for example_file_1'),
  array ('example_file_2.mp3', 'Description for example_file_2'),
  array ('example_file_3.mp3', 'Description for example_file_3')
  );
  echo $files[0][0]; // display filename 1
  echo $files[0][1]; // display file description 1
  echo $files[1][0]; // display filename 2
  echo $files[1][1]; // display file description 2
  echo $files[2][0]; // display filename 3 
  echo $files[2][1]; // display file description 3

----
Darly

junedkazi’s picture

I am sorry if it is in wrong context . I am asuming this is a normal array of files .
I would suggest the use of foreach because as the contents of the array increases
there might be a problem .

  $files = array (
    'example_file_1.mp3' => 'Description for example_file_1',
    'example_file_2.mp3' => 'Description for example_file_2',
    'example_file_3.mp3' => 'Description for example_file_3',
  );
  foreach($files as $file => $file_description) {
    echo $file; //Display file
    echo $file_description; //Display file description
  }
  

Hope this helps .

JUNED KAZI
http://junedkazi.blogspot.com/

newdru’s picture

thanks for providing the code!

why do you both submit and save the node at the end?

the previous examples only save the node.. just curious!!

thanks

fyi, this is a repost positioned incorrectly at bottom of thread

marcbe’s picture

Using the above script, I have managed to create new nodes of a CCK type I have made but some fields do not seem to get set correctly. I note that all simple "text field" are fine but nodes using a "select list" type do not work. Can someone please point me in the right direction? Aslo note that these two select lists fields that don't work are set to be "required". Maybe I need to set other parameters for these fields?

What I am currently using for these fields is:

$node['field_product_category'] = array  // product category
    (
        0 => array
            (
                'value' =>  'An allowed list item here',
                'format' => 3,	// unfiltered HTML format			
            )
    );

Thanks. The script that Jeff submitted is a great help.

marcbe’s picture

It seems that the value I'm trying to set is validated against the allowed list of values for that select list element. For some reason, the string I use does not match those in the enumeration.

Any ideas?

zigma’s picture

I have been looking for a script that can set complete set of values for a node through script.

Thank you very much.

adam640kb’s picture

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()?

isaac77’s picture

was having a similar problem. seems counter intuitive, but setting $newnode['name'] = $user->name; rather than $newnode['uid'] = $user->uid; seems to work.

i'm doing something similar to the following:


global $user;

$newnode = array();
$newnode['type'] = 'my_special_node';
$newnode['title'] = 'title here';
$newnode['name'] = $user->name;

node_validate($newnode);
$newnode= node_submit($newnode);
node_save($newnode);

use that as an example at your own risk, but it seems to be working for me. perhaps someone else knows of a better way?

Terix-1’s picture

There's a post in API documentation explaining this behaviour.

smcguinness’s picture

Thanks Jeff for the great script. I got it working and importing almost out of the box from what you had. However, when I started adding more and more fields and in a way piece mealing the process trying to debug it as I went, I came and hit a wall with the checkboxes in my node. I have devel and that outputs value=>1 which is in my database, however, when I try and import 1 from my csv it doesn't do it and actually puts in a 0 as if it hasn't been checked. Anyone know how to check a checkbox via php? Any help would be fantastic. This one thing is the only thing holding me up. Again, I would be half as far if it weren't for this script. Thanks.

Seth

jweedman’s picture

First off, thanks very much for your help here. It's saved me loads of time... or at least it's going to once I figure this last bit out.

You are using $node['created'] = $line[4]; to pass the created time of your content in the csv file over to Drupal's. What format is your "$line[4]" coming over in? After looking at the database (I'm using phpmyadmin) it looks like the created time for drupal is being stored in Unix format. Unfortunately, the date format in my csv file is not Unix. Howerver, using the php function - strtotime() - I'm converting it to Unix succesfully. Unfortunately, when I make the import into Drupal, The created time isn't being passed coreectly. It seems that it's being overwritten.

So just to recap the problem - I have content created in the past on my old site, and I'm trying to import that into Drupal, retaining the original date it was created. When I pass that date over through the csv file, it is being over written with the current date. Below is the php code I am using in place of your '$node['created'] = line[4]; Thanks for any suggestions you might have.

Code I'm using:


$node['created'] = strtotime(line[10]);

mradcliffe’s picture

strtotime() defaults to "now".

Try seeing what the value of $line[10] is and breaking it up into parts to pass through checkdate()? And make sure there's a $ in front of your variable name in the actual code.

jweedman’s picture

Thanks for your help so far.

The value of $line[10] is "2002-03-03 01:19:33". The value of - strtotime($line[10]) is "1015139973". I checked that in a Unix Time Calculator and it is spitting out the correct date. In my import script, I put an echo statement on $node['created'] to see what it is being stored as, and it prints "1015139973" as well. So the variable is being set to the correct Unix timecode (which is the format that drupal's database stores the content's created date), but when it is put into the database itself, it is putting the Unix Timecode for the current day (April 3rd, 2009)!

I'm kind of at a loss. I thought maybe it was over-writting the created date with the revision date, so I commented that part of the code as well.... to no avail. Any ideas? Thanks in advance.

-jweedman

mradcliffe’s picture

That's really strange. I have the following code for an old wordpress importer, which doesn't need strtotime, but it should set it a similar way. And it is the created field not the changed field that's being displayed as now() right?

After you use node_save(), what's the output of $node->created (probably now, but i'm wondering).

For reference, but not relevant...

    $node = new StdClass();

    $node->type = 'page';
    $node->uid = $users[$content['author']]->uid;
    $node->title = $content['title'];
    $node->body = str_replace('<!--more-->','<!--break-->',$content['body']);
    $node->teaser = node_teaser($node->body);
    if ($content['status'] == 'publish')
    {   
        $node->status = 1;
        $node->promote = 1;
    }   
    else
        $node->status = 0;
    $node->created = $content['created'];
    //$node->changed = $content['modified'];
    if ($content['comment'] == 'closed')
        $node->comment = 0;
    else
        $node->comment = 2;


    foreach ($content['categories'] as $cat)
    {   
        $node->taxonomy['tags'][1] .= $cat['name'].',';
    }   

    node_save($node);

jweedman’s picture

For anybody trying to import content, and can't figure out how to retain the original date (like me), let me save you days of frustration....

As you can see in Jeff's original post, his code both submits the node, and then saves it --- with node_submit() and node_save(). Well, I had a sneaking suspicion that $node['created'] was being overwritten or swapped out somewhere in one of these functions. So, "mradcliffe", your suspicions were right as well. If you look in the node_submit() function (list of functions here),

$node->created = !empty($node->date) ? strtotime($node->date) : time();

Bascially, if $node->date is NOT empty, make $node->created = $node->date. If it IS empty, set $node->create to time(), which uses now() by default!

So even though I was assigning $node->created, it was being overwritten because I was NOT assigning $node->date to anything.

So all in all instead of setting $node->created = $line[10] like I did, you just have to set $node->date = $line[10]. Frustrating... but glad it's fixed. Thanks 'mradcliffe' for your help. Hope this saves someone some time!

-jweedman

coupet’s picture

          CREATE TABLE {node_example} (
            vid int(10) unsigned NOT NULL default '0',
            nid int(10) unsigned NOT NULL default '0',
            color varchar(255) NOT NULL default '',
            quantity int(10) unsigned NOT NULL default '0',
            PRIMARY KEY (vid, nid),
            KEY node_example_nid (nid)
          ) /*!40100 DEFAULT CHARACTER SET utf8 */;

Excellent thread, suggested comments on inserting from CSV into node_example table as described?
----
Darly

newdru’s picture

oops! this was meant to be threaded above to post: http://drupal.org/node/67887#comment-209250
i'll repost there for context

thanks for providing the code!

why do you both submit and save the node at the end?

the previous examples only save the node.. just curious!!

thanks

gurukripa’s picture

importing html book pages/files into Drupal

tough situation for me here..looking for this feature :) dunno if this is the right place to ask this..but I am using Drupal 5.1 and need this feature as i have several books in html and need to put it on my drupal site..and would like some automation there..so i can set rules for the page title or menu title etc..is something available ?
Help guys

mr.dale’s picture

Just seconding this request, I'm needing to import literally hundreds of html items into book pages. Used to be able to do it fairly easily with the book import module.

marcbe’s picture

I'd like to contribute back some tips I got while discussing with jeff (jjv).

1) The select list CCK item seems to do some string validation based on the valid list you gave. The way to import in those fields is to temporarily turn these fields as plain text fields AND remove any valid entries for that field. As Jeff said:

if you set your select list field in your cck node to be a plain text field, and then run the script, you'll get your data in. Then you can go back to the cck field and change it to a select list with your desired options. After you save the save the change the values that were already there as text will still be there and work in the select list

2) If you are unsure about the format of a given custom node you made using CCK, you can use the "devel" module to output the node structure. As Jeff puts it:

you can do a "dev load" and "dev render" on any node. This will cause Drupal to output the $node structure for that node type, and will help you set up the assignments that you see listed in my script.

Hope this helps some of you trying to import from external databases.

Regards

mwander’s picture

I have the script working well except that it is not writing the uid specified in the CSV. The uid is staying 0 (default). All of the other fields are updating. Any ideas?

Thanks!

Mitch

mwander’s picture

I resolved this with some help from various folks on IRC.

The existing function node_submit code was not recognizing that I was logged on as a user with administrator rights, It's not clear whether this problem happened because I was calling the function via PHP code or something relating to my implementation of Drupal 5.x.

Anyway, I created a new function node_submit_new that commented out the part of function node_submit that was causing me trouble. I only left the single line (i.e., did not comment it out) that replaced the uid. The parts that checked whether I was logged on as a user with correct permissions had to be commented out - at least for now (see below... just that part of the code).

Best regards,

Mitch

// $access = user_access('administer nodes');
// if ($access) {
// // Populate the "authored by" field.
// if ($account = user_load(array('name' => $node->name))) {
// $node->uid = $account->uid;
$node->uid =$user->uid;
// }
// else {
// $node->uid = 0;
// }

gurukripa’s picture

can someone suggest a module for this.. I couldnt follow this discussion on how to make scripts..i am a newbie..and am comfortable with modules..pls help.

leeksoup’s picture

It is designed to import static sites into Drupal using XSL filtering. See http://drupal.org/project/import_html

chastyti@groups.drupal.org’s picture

hi there gurukripa.. ;)

umm, so i am also a noob. well, yeah. thats the easiest way to describe it.

and no, in 5.x there isnt a functioning way to get most anything into drupal via the cms interface. maybe sql queries, no auto-magic modules have been switched over that i can see.

there were a few in 4.7x if that is what you are working with your saved. the modules i recall are/were- node import. the xml api, user and book imports.. a couple static html page imports (wgHTML appears to work in 5.x!!)
Who knows maybe these might work if youre not on 5 yet..

however nothing for custom data into the current drupal environment. :(
this forum thread looks to be the best link ive found so far.
------------------

anyways, what fromw i am gathering from the oblique comments about only "previewing" the changes and not actually submitting them, is that this code / script is to be executed as part of the normal "page" editing process. answering the desperately flocks with simple help on how to implement said script doesnt seem to be forthcoming. so....

when you create or edit a page. there is a content type box mid way down, filtered html, full html, or "gasp"; php!! youll see it.

i am guessing thats the magic with these "script" things :)
simply copy and paste the code from here into a new page.

change the stuff as indicated by the helpful internal documentation (inside the code),
and then execute it by "previewing it" in drupal (the code will still get called, executed, etc..

everybody seems to be gung-ho about it working and all that, so .... give it a try??? ;)
pay heed to the bit about leavin the execute option (or whatever the variable is called)
to false until youre ready. terrible things will happen if it gets ran twice. run it on a test database, yadda yadda.

editing this mystical script? dont worry. its normal plain old php source. - thats something youre gonna have to learn a little bit about if you dont already know the basics of syntax and stuff. for more info search for drupal and hell on here (drupal.org)

who needs no stinking handbooks! ;)
or, perhaps i am completely full of shi_ite.

umm, so i need to import a bunch of data too..
and it doesnt make sense to me to hang this code in a php file by itself.
and how could you preview your changes that way! ;)

we will see.
maybe some hekpful non-n00b would like to clear this up?

or maybe point us among the unenlightened to a link about including scripts
in pages/custom blocks whatever??

anyways.
back to drupal fun 4 me

xox
c

www.chastyti.com

googelybear’s picture

Hi guys,

how do you do achieve the same for comments (directly create a comment for a node, given its nid, not via the web interface, e.g. when the xml-rpc interface of the module is being called)? I saw that there is comment_save but this doesnt seem to call any hooks...

junedkazi’s picture

I am trying to insert path for the node but I anm not able to so.
This is what I have tried.

$node['path'] = "aboutus";

I have also tried it with

$values['path'] = "aboutus";

But it is not working.
Pls Help

JUNED KAZI
junedkazi@gmail.com

seancharles’s picture

Have you tried,

$node->path = 'aboutus';

instead... you have used array notation whereas my example is class->field notation... that's off the top of my head after a Double-Sausage and Egg breakfast so the E-numbers might be affecting me.
:)
Sean Charles

gnucifer’s picture

I spent the last few day importing data from an old (and terribly designed) access database into drupal. This thread helped me a great deal, fist I went with a more direct aproach inserting into the database through the drupal abstractation layer. This however was a bit messy, and you have to rewrite a lot of stuff that is essensially already in drupal, plus no modules gets a chance to hook in. Emulating form submission using the api really feels like the way to go (with nodes anyway). I made a script inspired by some in this thread:

(It's pretty specific for my needs, and not very pretty, but since those posted in this thread helped increase my understanding the process of submitting a node maybe this can be useful for others)

// Bootstrap Drupal
include_once "includes/bootstrap.inc";
include_once("includes/common.inc");
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// Import some useful functions for formating and importing data, nothing fancy
include_once('import_functions.php');

$active = FALSE;

if ($active && user_access("administer content types")) {
  print 'Great success!<br />';
  //Importing data from html table
  $data = get_table($import_data_folder . '/chat.html');

  // Quick and dirty cleanup
  $data = array_map('cleanup', $data);
  function cleanup( $line ) {
    $line = preg_replace('/&#\d*;/', ' ', $line);
    return array_map('trim', array_map('strip_tags', $line));
  }
  // Array mapping usernames in old database to user names in drupal database
  global $old_to_new;
    
  foreach($data as $line) {
    $skip = FALSE;
    $old_uname = current(explode(' ', $line[2]));
    
    // Checking just to be sure
    if(!isset($old_to_new[$old_uname])) {
      print('Warning: User: ' . $old_uname . ' missing in $old_to_new.<br/>');
      $skip = TRUE;
    }
    if(empty($line[1])) {
      die("This should never happen, time to panic..");
      //$skip = TRUE;
    }
    // We skip post if post to short or user unknown
    if(!$skip && strlen($line[1]) >= 100) {
      
      $node = new StdClass();
      $node->name = $old_to_new[$old_uname];
      $account = user_load(array('name' => $node->name));
      if(!$account){
        die('User: '. $node->name .' does not exist, check mapping for '. $old_uname .'.<br />');
      }
      // Assigned when calling node_submit (if $node->name is set), so not really necessary to set value here
      $node->uid = $account->uid;
      $node->type = 'nyhet';
      $node->created = olddate_to_unix_time($line[3]);
      $node->changed = $node->created;
      // Must set this so that created is not overwritten some where else
      $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
      $node->title =  mktitle(html_entity_decode($line[1]), 30);
      $node->body = $line[1];
      // Format set to filtered html
      $node->format = 1;
      $node->log = 'Importerad från HEABNET '. date('d/m-y H:m') .'.';
      // Status set to published
      $node->status = 1;
      // Promote to first page
      $node->promote = 1;
      $node->sticky = 0;
      $node->revision = 0;
      // Enable read/write comments
      $node->comment = 2;
      $node->pathauto_perform_alias = 1;
      
      print '<pre>';
      print '<em>Before submit:</em><br />';
      print_r($node);
      $node = node_submit($node);
      print '<em>After:</em><br />';
      print_r($node);
      print '</pre><hr />';
      //node_save($node);
      // Just testing, only need one post
      break;
    }
  }
}
else {
  print 'Script ' . __FILE__ . ' is not set to active, or access denied';
}

Some pitfalls:
Found out that if node->date is not set the following code in node_submit will result in the 'created' property losing its value:

$node->created = !empty($node->date) ? strtotime($node->date) : time();
coupet’s picture

missing import_functions.php

----
Darly

gnucifer’s picture

The script I posted was pretty specific for that particular import, as is the functions in "import_functions.php". Had to import data from 4 different tables (represented as 4 different node types in drupal) and thanks to thanks to the unbelievebly messy database they came from I had to make all kind of hacks for each import. Later found out about the node import module, but I could not have used it anyway as the data had to be sanitised while importing. It would be easier to write a nice looking script if one had nice looking data to start with, but I really should try to write a more generic script that also can handle messy imports. I posted it, quick and dirty as it was, mosty so that people could copy some relevant parts, even though most of whats in my scripts can be found in others in this thread.

summit’s picture

Hi,

This is a great script for batch-importing data from another database.
Anyone made sort of script for real time importing nodes from another database?
May be through rss or something like that?

I think of rssfeed on the "foreign" database to "post" the data
feedapi rss import to fetch the data into Drupal?

Thanks in advance for thinking about this!
Greetings,
Martijn

bachbach’s picture

thanks for this script
my script to import images in an image cck field :

$active = FLASE;

if($active){
	# upload files
	$nid = $node->nid;
	$uploads = array();
	for($files as $file){
		$upl = new StdClass();
        $upl->fid = 'upload';
        $upl->filename = $file['dest_path'];
        $upl->filepath = $file['src_path'];
        $upload->filemime = 'image/jpeg';
        $upl->filesize = $file['size'];
        //$upl->description = $file[1];
        $upl->list = 1;
		array_push($uploads, $upl);
	}
	
	$node->files = $uploads;
	upload_save($node);
	
	# save image fields
	$files = $node->files;
	$images = array();
	foreach($files as $file){
		array_push($images,array(
				'title' => $file->filename,
				'nid' => $nid,
				'fid' => $file->fid
			)
		);
	}
	$node->field_diaporama = $images;
	node_save($node);
}
bachbach’s picture

i can't delete this comment (this not previous)

alihammad’s picture

    
// over here you connect to your old database and retrieve the values like this till the end

      while ($row= mysql_fetch_array($resultwithlimit)) {

      $a1 = $row["YourTitlefield"];
      $a2 = $row["firstnameauthor"];
      $a3 = $row["lastnameauthor"];
      $a4 = $row["otherfield42"];
      $a5 = $row["themistfield"];
      $a6 = $row["body"];
      $a7 = $row["field2"];
      $a8 = $row["wordsvalley"];
      $a9 = $row["randomfield29"];



$mynode = array();

$mynode['title'] = "$a1";

$mynode['type'] = "yourcontenttype"; // all content types have names which are given at the time of the content type creation. visible at content types page when you drag your mouse over the list of content types

$mynode['name'] = "thenameoftheusersubmittingthepage";//not necessary

$mynode['body'] = "$a6"; // You can remove the body field from your content type if you want.

$mynode['status'] = 1;//stands for published=1 or unpublished=0 content

$mynode['uid'] = 121;//uid is user id, the user id 1 being the id of the one who makes first id after a drupal installation, uid 1 has all prvilleged, make sure your user id comes with all privileges,preferably use userid 1 to save yourself from the hassle.

$mynode['promote'] = 0; // promote =0 doesn't promote the content to the front page , whereas promote=1 promotes the content to the front page

$mynode['comment'] = '2'; // comment 0=off , comment 1=readonly, comment 2=allowed

$mynode['field_friendlytitle'] = array(array('value' => "$a4" ));// field_friendlytitle is the field I presumably created using cck for the content type. Notice how I am filling in the value for field_friendlytitle using array in an array. 

$mynode['field_firstnameauthor'] = array(array('value' => "$a2" ));
$mynode['field_lastnameauthor'] = array(array('value' => "$a3" ));
$mynode['field_fieldIcreatedwithcck'] = array(array( 'value' => "$a9"));
$mynode['field_fieldIcreatedwithcck1'] = array(array('value' => "$a8" ));
$mynode['field_fieldIcreatedwithcck2sjhdshjdj'] = array(array('value' => "$a7" ));

$mynode['format'] = '2'; // inputformat, format=0 means Filtered HTML,format=1 means PHP code , format=2 means Full HTML 


//You can also specify $mynode['nid'] followed by a number which will be the nid but I presume that it wont be of use to you at the moment. Not mentioning it will lead to a sequential auto generation whereas mentioning a static number will overwrite the old content each type you save the node!;




$mynode = node_submit($mynode);
node_save($mynode);

unset($mynode);

}

Ali Hammad Raza
WordsValley

summit’s picture

Hi,

I am looking for a solution to output many nodes related to the input of a matrix of fields (drupal 5).
Like a letter-template and a database with addresses. So every letter-instance can be personalized.

I would like to use a cck-multireference field with many instances and output them to as many nodes as instances there are.

Did anybody allready do this?
Will pieces of code stated here help?

Thanks a lot in advance for your reply!
greetings,
Martijn

jatboy’s picture

I saw some wonderful examples of how to create nodes. But I don't think that I read it any where I should run this code from? What directory? Because I tried running it from home directory and this is what i got:

PHP Fatal error: Call to undefined function node_submit() in whicn.h is basically complaining about the node_save function

alihammad’s picture

You can run this code from within any node be it a page or article. But you need to set the filter to allow php values for execution. By executing it from within a drupal node you have access to drupal api because the bootstrap loads all the basic drupal functions.

You can also create a module to run this code but for a beginner I believe it can be slightly complex.

Ali Hammad Raza
WordsValley.org

jatboy’s picture

saw some wonderful examples of how to create nodes. But I don't think that I read it any where I should run this code from? What directory? Because I tried running it from home directory and this is what i got:

PHP Fatal error: Call to undefined function node_submit() in whicn.h is basically complaining about the node_save function

junedkazi’s picture

jatbot ,

you will have to run this code from a custom module .
The tutorial of how to create a module is located here
http://drupal.org/node/508 .
Pld do let me know if this helps .

JUNED KAZI
http://junedkazi.blogspot.com/

tormu’s picture

You can also create a node with PHP input format and contain your code there. Just be sure you don't refresh the page again, since it will execute that code on every reload.

raff77’s picture

Hi I'm using the trying to enter in user data (which I have linked to a node) from another Joomla database to Drupal 6.

The user_save function can handle this, the problem I have is the serialized 'data' column. I'm unsure what it is needed for and what I should put in there. It seems to be a serialized array for the new node but there is extra info in there like '_error_element'. Is there a way of programmatically running a form (that a user would enter on the front end), this would make any migration much easier as we have already developed the form and its validation, why can't be just send data to the form?

If not can someone tell me what the 'data' column is used for?

Ronan

raff77’s picture