I need someone to help me migrate the phpnuke site www.asclepios.com.br to drupal.
First of all, i need to keep all users (i have few)
Then I need to keep all web_links and downloads (what are the equivalent modules in drupal??)
after that all stories
If possible I would like to keep all statistics

After that is done, I will need to migrate some modules that were customized for me. But this is a second fase of the project.

If you can help me, please reply.
I already tried the php2drupal that already exists, but I am having difficult to migrate

Thanks

Comments

aamato’s picture

make your bid

VM’s picture

I'd contact the person who wrote this script: http://drupal.org/node/498

_____________________________________________________________________
My posts & comments are usually dripping with sarcasm.
If you ask nicely I'll give you a towel : )

VValdo’s picture

I'd contact the person who wrote this script: http://drupal.org/node/498

That would be me, although I really heavily modified an existing script. I use the Drupal 5.0 API as much as possible but there are some older parts that are straight DB manipulation that should probably be updated...

W

VValdo’s picture

Oh, and as for weblinks and downloads-- your best bet is to use the CCK and CCK "links" field module to create custom content types for your download files as well as your links.

I wrote a custom addition to the script to move my web links over. To use, you first have to set up a custom content type with CCK. Here's a slightly-modified export of my "mylinks" content type that you can maybe import with CCK and play with:

$content[type]  = array (
  'name' => 'My Links',
  'type' => 'mylink',
  'description' => 'External links',
  'title_label' => 'Link Name',
  'body_label' => '',
  'min_word_count' => '0',
  'help' => '',
  'node_options' => 
  array (
    'status' => true,
    'promote' => false,
    'sticky' => false,
    'revision' => false,
  ),
  'comment' => '2',
  'old_type' => 'mylink',
  'orig_type' => '',
  'module' => 'node',
  'custom' => '1',
  'modified' => '1',
  'locked' => '0',
);
$content[fields]  = array (
  0 => 
  array (
    'widget_type' => 'text',
    'label' => 'Description',
    'weight' => '-1',
    'rows' => '3',
    'description' => 'Please describe this link-- what is it?',
    'default_value_widget' => 
    array (
      'field_description' => 
      array (
        0 => 
        array (
          'value' => '',
        ),
      ),
    ),
    'default_value_php' => '',
    'group' => false,
    'required' => '1',
    'multiple' => '0',
    'text_processing' => '0',
    'max_length' => '300',
    'allowed_values' => '',
    'allowed_values_php' => '',
    'field_name' => 'field_description',
    'field_type' => 'text',
    'module' => 'text',
    'default_value' => 
    array (
      0 => 
      array (
        'value' => '',
      ),
    ),
  ),
  1 => 
  array (
    'widget_type' => 'link',
    'label' => 'mylink',
    'weight' => '0',
    'description' => 'Enter the link',
    'default_value_widget' => 
    array (
      'field_mylink' => 
      array (
        0 => 
        array (
          'url' => '',
          'title' => '',
        ),
      ),
    ),
    'default_value_php' => '',
    'group' => false,
    'required' => '1',
    'multiple' => '0',
    'title' => 'required',
    'title_value' => '',
    'display' => 
    array (
      'url_cutoff' => '80',
    ),
    'attributes' => 
    array (
      'target' => '_blank',
      'rel' => '',
      'class' => '',
    ),
    'field_name' => 'field_mylink',
    'field_type' => 'link',
    'module' => 'link',
  ),
);

Pretty simple content type.

Now here's some code (which I hereby release under the GPLv2) you can try... hope this works, as I haven't tried it in months. I believe it can also filter out links with bad URLs and can remove duplicate links as well (keeping the most recently added link when there are duplicates). See more below.

If you want to migrate the link's *categories*, you will also need to manually pre-create the link category terms as taxonomy terms via the Administration menu. If you don't know what all the categories are that you'll need to create, the first (commented out) bit of code below will spit out all the categories in your phpnuke site along with their category id (or "cid"). Its best to create the terms in Drupal in the same the order they appear in phpnuke so that you can determine the offset between the cid and the newly created term id. The script below should then be able to use that offset (in my case it was only +1) to re-associate the old categories to the new terms.

If you choose not to keep your categories, or if what I just typed sounded too complicated, you can just comment out anything having to do with categories/taxonomy/terms in the code below and don't worry about categories/terms for your migration.

--CODE BEGINS--

/*  add this to the migration script at http://bogdan.org.ua/wp-content/uploads/2007/08/phpnuke2drupal-5.x-0.02-w.tar.gz so it's executed last in the sequence of migrations.  You may need to comment/uncomment bits to taste */

	$n_links="{$nuke} . {$nuke_prefix}_links_links";
	$node_ltype = "mylink";

// ----------------------------------------------------------  LINKS  --------------------------------------------------
echo "DOING LINKS<p><p><p>";

/* this commented bit below is used to determine all the link categories in phpnuke and their associated id number.  It's for linking phpnuke categories to drupal taxonomy terms.  In my case, I took the phpnuke categories listed below and created them as taxonomy terms, which by chance happened to have an offset of 1.  Below, where I do the actual migration of the links, I add 1 from the category ID # to get the associated drupal term ID #.  None of this matters at all if you're not planning on doing any taxonomy when migrating your links.  In which case, just keep it commented it out (and then comment out the taxonomy stuff later on.)  */

/*
$result = db_query ("SELECT cid, title, cdescription FROM phpnuke.nuke_links_categories WHERE cid > 0 ");
while ($row = mysql_fetch_array($result)) {
$category[$row[0]]=$row[1];
echo "Cat # " .$row[0] . ":  " . $category[$row[0]]. "<BR>";
}
*/

/* the bit below removes all duplicate URLs from phpnuke db, keeping most recently added duplicate.  I believe i did this because there were occasions in which the same link appeared in multiple categories.  However, I later commented it out because I figured I may as well have links within multiple categories.  So I include the code here just for historical purposes.  */

/*
$result = db_query("select url,count(*) as n from $n_links group by url having n > 1");
while ($row = mysql_fetch_object($result)) 			
{
	// got duplicates.  Now prune the older ones.
	$badurl=$row->url; echo "cleaning badurl=$badurl<br>";
	$result2 = db_query("SELECT lid FROM $n_links WHERE url='$badurl' order by lid");

	    $count = mysql_num_rows($result2);
	    $del = 1;
	    while ($del < $count) {

		    $row2 = mysql_fetch_object($result2);
		        $aquery = "DELETE FROM $n_links WHERE lid=" . $row2->lid;
			 echo $aquery . "<br>";
			 $result3 = db_query($aquery);
			 $del++;
	    }
}

*/


/* now that our phpnuke database is clean, let's migrate the links.  Chuck any invalid URLs.  Again, assume the term and vocabulary are pre-made manually via taxonomy.  As I said, it so happens in my case that I can just add 1 from the CID (category ID) in phpnuke for the matching term ID in Drupal.  Your mileage may very well vary.  */

$result = mysql_query("SELECT $n_links.title, $n_links.cid, $n_links.url, $n_links.description, $n_links.date, $n_links.submitter, $n_links.name, $n_links.email FROM $n_links WHERE lid > 0");

while ($row = mysql_fetch_object($result))		
{
echo "checking $row->url ...";
if (valid_url($row->url)) {
	echo "VALID.  Processing...<br>";

		$row->description = addslashes(tidyhtml($row->description));
		$row->submitter = addslashes($row->submitter);
		$row->title = addslashes($row->title);
		$row->name = $row->name;
		$row->url = addslashes($row->url);
		$row->email = addslashes($row->email);
		$mynode = new StdClass;

		if (empty($row->description)) { $row->description = $row->title;}

		$mynode->title = $row->title;
		$mynode->type=$node_ltype;
		$mynode->uid = 0;  // all links were anonymous previously
		$mynode->name =  $row->name;
		$mynode->status=1;
		$mynode->comment=$comment;
		$mynode->promote=$promote;  // fix for actual import
		$mynode->timestamp = strtotime($row->date);
		$ts = strval(strtotime($row->date));
		$mynode->format = $review_format;
		$mynode->log = "Contributed by $row->name ($row->email)";
		unset($nid);
		if (!isset($urltable[strtolower($row->url)])) { // if the link node does not already exist...  add it.
		node_save($mynode);

		$nid=$mynode->nid;
		$querycheese = "INSERT INTO content_type_" . $node_ltype . " SET nid='$nid', vid='$nid', field_description_value='$row->description',  field_mylink_url='$row->url', field_mylink_title='$row->title', field_mylink_attributes='N;'";
		echo $querycheese . "<br>";
  		$result2 = db_query($querycheese);
   		$query99 = "UPDATE $d_nodes SET created=$ts, changed=$ts WHERE nid=$nid"; echo $query99; db_query($query99);
   
   		$urltable[strtolower($row->url)] = $nid;
 }

/* now, in this part of the migration, create the category/term relationship using taxonomy terms which you've conveniently pre-made.  Again, free to comment out if you're not using taxonomy. */

   		$tid = $row->cid+1;
$nid =  $urltable[strtolower($row->url)];
   
		if ($relationship[$nid][$tid] != 1) 
       		     {
$query99 = "INSERT INTO term_node (nid, tid) VALUES ($nid, $tid)";
echo $query99;
db_query($query99);
$relationship[$nid][$tid] = 1;
}

  		 echo "Done!<br>";
} else 
		{ echo "INVALID.  Skipped.<br>";}

}
echo "&lt;p&gt;&lt;p&gt;COMPLETED LINKS!";

--CODE ENDS--

The reason I didn't include this (and a few other bits) in phpnuke2drupal is that it required CCK, the link field, and pre-creating custom content types with specific field names, plus you have to pre-make the taxonomy categories to match your phpnuke link categories, so it wasn't "universal" enough to include in a general migration script.

Caveats: this isnt tested beyond my own personal use. I haven't really scoured through to make sure this will all work and am kinda going from memory Don't run on a DB that isn't thoroughly backed up. That's obvious I guess. This is messy programming. Inefficient and probably the "wrong way" to do it. But it worked for me, and was meant for one-time execution.

You also may want to change $promote to zero unless you want the new links to appear on the front page...

Good luck,

W

VValdo’s picture

Don't know if anyone is interested in the code, but I have a few moments to add my "migrate the reviews" code. I modified my own code to make it more generic, so hopefully I haven't introduced any bugs...

As before, here is my (slightly generic-afied) CCK 5.x structure I exported of the reviews node. As above, make sure you have CCK & the CCK link field module installed. Simply import this stuff as a first step.

$content[type]  = array (
  'name' => 'MYREVIEWS',
  'type' => 'myreviews',
  'description' => 'My Review',
  'title_label' => 'Product Name',
  'body_label' => '',
  'min_word_count' => '100',
  'help' => '',
  'node_options' => 
  array (
    'status' => true,
    'promote' => false,
    'sticky' => false,
    'revision' => false,
  ),
  'comment' => '2',
  'old_type' => 'myreviews',
  'orig_type' => '',
  'module' => 'node',
  'custom' => '1',
  'modified' => '1',
  'locked' => '0',
);
$content[fields]  = array (
  0 => 
  array (
    'widget_type' => 'text',
    'label' => 'Your Review',
    'weight' => '-1',
    'rows' => '25',
    'description' => '',
    'default_value_widget' => 
    array (
      'field_review' => 
      array (
        0 => 
        array (
          'value' => '',
        ),
      ),
    ),
    'field_review' => 
    array (
      0 => 
      array (
        'format' => 1,
      ),
    ),
    'default_value_php' => '',
    'group' => false,
    'required' => '1',
    'multiple' => '0',
    'text_processing' => '1',
    'max_length' => '',
    'allowed_values' => '',
    'allowed_values_php' => '',
    'field_name' => 'field_review',
    'field_type' => 'text',
    'module' => 'text',
    'default_value' => 
    array (
      0 => 
      array (
        'value' => '',
      ),
    ),
  ),
  1 => 
  array (
    'widget_type' => 'options_select',
    'label' => 'Rating',
    'weight' => '1',
    'description' => ' Rate from 1 to 10.  1 is terrible.  10 is the best ever.',
    'default_value_widget' => 
    array (
      'field_rating' => 
      array (
        'key' => false,
      ),
    ),
    'default_value_php' => '',
    'group' => false,
    'required' => '1',
    'multiple' => '0',
    'min' => '1',
    'max' => '10',
    'prefix' => '',
    'suffix' => '',
    'allowed_values' => '1
2
3
4
5
6
7
8
9
10',
    'allowed_values_php' => '',
    'field_name' => 'field_rating',
    'field_type' => 'number_decimal',
    'module' => 'number, optionwidgets',
  ),
  2 => 
  array (
    'widget_type' => 'link',
    'label' => 'link',
    'weight' => '2',
    'description' => '',
    'default_value_widget' => 
    array (
      'field_link' => 
      array (
        0 => 
        array (
          'url' => '',
          'title' => '',
        ),
      ),
    ),
    'default_value_php' => '',
    'group' => false,
    'required' => '0',
    'multiple' => '0',
    'title' => 'optional',
    'title_value' => '',
    'display' => 
    array (
      'url_cutoff' => '80',
    ),
    'attributes' => 
    array (
      'target' => '_blank',
      'rel' => '',
      'class' => '',
    ),
    'field_name' => 'field_link',
    'field_type' => 'link',
    'module' => 'link',
  ),
);

And here is the reviews migration code using the previous content type. Add it to the phpnuke2drupal script (version .002 or whatever the latest was) so that it executes after it's done all the other migration steps.

Note: I haven't carefully reviewed the code- I'm basically copy/pasting from my migration script as it was run months ago with a few tweaks for clarity. If it doesn't work for you, you may need to tweak it a little bit. Post here if you have questions. I'll try to check in every so often...

I am GPLing this below as well. (v2).


/*  Migrate phpnuke review section to drupal custom cck nodes  by Waldo   */

/*  Set up some variables first */
$n_reviews="{$nuke} . {$nuke_prefix}_reviews";
$n_review_comments="{$nuke} . {$nuke_prefix}_reviews_comments";
$node_rtype = "myreviews";


$result = db_query("SELECT $n_reviews.url, $n_reviews.url_title, $n_reviews.id, $n_reviews.date, $n_reviews.title, $n_reviews.text, $n_reviews.reviewer AS name, $n_reviews.email, $n_reviews.url, $n_reviews.url_title, $n_reviews.score FROM $n_reviews WHERE $n_reviews.id > 0 ORDER BY $n_reviews.date");
  
while ($row = mysql_fetch_object($result)) 			
{

$row->text = addslashes(tidyhtml($row->text));
$row->title = addslashes($row->title);
$row->name = addslashes($row->name);
$row->url = addslashes($row->url);
$row->url_title = addslashes($row->url_title);
$row->email = addslashes($row->email);

// migrate attribution if available
$part1 = ""; $part2="";
if (!empty($row->email)) { $part1 = "<a href=\"mailto:$row->email\">"; $part2 = "</a>"; }
if (empty($row->name)) {$row->name = $row->email;};
if (!empty($row->name)) {
	$row->text .= "\n\n<b>Review Submitted by:</b> " . $part1 . $row->name . $part2 . " (unverified)"; }

unset($mynode);
$mynode = new StdClass;

#$mynode->nid=$nid;
#$mynode->vid=$nid;
$mynode->title = $row->title;
$mynode->type=$node_rtype;
$mynode->uid = 0;  // all myreviews were anonymous previously
$mynode->name =  $row->name;
$mynode->status=1;
#$mynode->created = time();
#$mynode->changed = time();
$mynode->comment=$comment;
$mynode->promote=$promote;  // fix for actual import
#$mynode->body =  
#$mynode->teaser = $row->title;
$mynode->timestamp = strtotime($row->date);
$ts = strval(strtotime($row->date));
$mynode->format = $review_format;
print_r($mynode);
node_save($mynode);


$nid=$mynode->nid;


$query99 = "UPDATE $d_nodes SET created=$ts, changed=$ts WHERE nid=$nid"; echo $query99; db_query($query99);

$result2 = db_query("INSERT INTO content_type_" . $node_rtype . " SET nid='$nid', vid='$nid', field_review_value='$row->text', field_rating_value = '$row->score', field_link_url='$row->url', field_link_title='$row->url_title', field_link_attributes='N;'");
$result3 = db_query("SELECT $n_review_comments.userid AS name, $n_review_comments.date, $n_review_comments.comments AS comment, $n_review_comments.score from $n_review_comments WHERE $n_review_comments.rid='$row->id' ORDER BY $n_review_comments.date");

while ($thiscomment = mysql_fetch_object($result3)) {

$myuser['name']=$thiscomment->name;
if (strcmp($thiscomment->name,"Anonymous") ==0) {$thiscomment->name="";}

$myuid=0;
#if ($commentor = user_load($myuser)) { $myuid=$commentor->uid;} else {$myuid=0;}  /// all review comments are anonymous.  Change this line to allow for actual users...

if ($thiscomment->score !=0)  { $thiscomment->comment .= "<p />\n\nMy score: $thiscomment->score.";}
$thiscomment->subject = "Re: $row->title";

unset($mycomment);

#$mycomment['pid']=0;
$mycomment['uid']=$myuid;
$mycomment['nid']=$nid;
$mycomment['name'] = addslashes($thiscomment->name);
$mycomment['subject'] = addslashes($thiscomment->subject);
$mycomment['comment'] = tidyhtml($thiscomment->comment);
#$mycomment['timestamp'] = strtotime($thiscomment->date);
print_r($mycomment);
echo "<p>saving comment from " . $thiscomment->name . " called " . $thiscomment->subject;

// drupal will insert the current date.  We want the original date.  Fix that. --Waldo

echo "fixing time $thiscomment->date to " . strtotime($thiscomment->date);

if ($comid = comment_save($mycomment)) { $query4 = "UPDATE $d_comments SET timestamp = " . strtotime($thiscomment->date) . " WHERE cid=$comid"; echo $query4; $result4=db_query($query4);}

// drupal will insert the current date as the changed date as as the last comment made in the NODE and comment statistics.  We want the original date.  Fix that. --Waldo
$query4 = "UPDATE $d_nodes SET changed = " . strtotime($thiscomment->date) . " WHERE nid=$nid"; echo $query4;  $result4=db_query($query4); 
$query4 = "UPDATE $d_comment_statistics SET last_comment_timestamp = " . strtotime($thiscomment->date) . " WHERE nid=$nid"; echo $query4; $result4=db_query($query4);	
								
}
}

If you import the reviews, you will notice that the reviews simply have the number 1-10 listed as the rating. I wanted to graphically show the rating with images-- that is, show the # of stars so that a rating of 1 looks like "*" and a rating of ten looks like "**********" (where asterisks are replaced by the star.jpg graphic).

To create a (very easy) custom display of the reviews, I first created a file at /sites/default/files/star.png which was literally a tiny star with a transparent background. I then created a template file in the /sites/all/themes/garland/ directory that I called node-myreviews.tpl.php, which has the following content:

<div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>">
    <?php if ($picture) {
      print $picture;
    }?>
    <?php if ($page == 0) { ?><h2 class="title"><a href="<?php print $node_url?>"><?php print $title?></a></h2><?php }; ?>
    <span class="submitted"><?php print $submitted?></span>
    <span class="taxonomy"><?php print $terms?></span>
    <div class="content">

<p /><b>Rating:</b><?php
  for ($counttt=1; ($counttt <= content_format('field_rating', $field_rating[0])); $counttt++)
{ echo "<img src=\"/sites/default/files/star.png\" alt=\"*\" />";  }  echo "(" . content_format('field_rating', $field_rating[0]) . "/10)";
?><p />

<b>Review:</b><p />
<?php print content_format('field_review', $field_review[0]); ?>

<?php
if ((content_format('field_link', $field_link[0]) != NULL)) {
   echo "<p /><b>Related Link</b>: <a href=\""; print content_format('field_link_url', $field_link_url[0]);  echo "\">";
         print content_format('field_link', $field_link[0]); echo "</a>";} ?>
    </div>
    <?php if ($links) { ?><div class="links">&raquo; <?php print $links?></div><?php }; ?>
  </div>

Hope this works for ya! Good luck,

W

WebbyWorker’s picture

Hi,

We would be interested talking with you about this project.

B

shah_waliuallah’s picture

Hi

How would i migrate the downloads module?

And also how do i keep my stats for each of the downloads?

If someone can migrate my site with a large downloads mod content and categories,im willing to pay

Thanks