Transmitting nodes between Drupal sites

The need

As discussed on g.d.o, over a year ago, in Templates or XSLT: How to structure data transfers and client-side content generation? incorporating a format for data exchange is unresolved in Drupal (no easy array/object to Json and back, no standard array/object to XML and back for easy Ajax-Drupal invokation).

The need

As discussed on g.d.o, over a year ago, in Templates or XSLT: How to structure data transfers and client-side content generation? incorporating a format for data exchange is unresolved in Drupal (no easy array/object to Json and back, no standard array/object to XML and back for easy Ajax-Drupal invokation).

So I need to do this now, and my obvious choice is SOA XML, at this stage of the 21st century. However, the lack of being sure of PHP 5 support means having to support PHP 4 XML libraries… prefer to wait till there is a basic standard.

Won’t dither around with that.

OK, so if I isolate the serialization/unserialization part, it can be replaced with javascript templates/JSON/XML/XSLT or whatever standard way the Drupal community arrives at.

So what to do to implement it now?

I’m gonna use XML-RPC for the transmission, and I’m gonna use good ole PHP serialize()/unserialize() (array to and from ASCII string) to transmit and receive nodes (we will leave authentication/security issues to one side for the sake of simplicity).

Checking out serialize()/unserialize()

So the PHP Cookbook gives some examples, which could be rendered like this:


$pantry = array('sugar' => '2 lbs.','butter' => '3 sticks');
$pantry_s = serialize($pantry);
echo $pantry_s;
$p = unserialize($pantry_s);
print_r($p);

And this gives:

a:2:{s:5:"sugar";s:6:"2 lbs.";s:6:"butter";s:8:"3 sticks";}

Array
(
[sugar] => 2 lbs.
[butter] => 3 sticks
)

Let’s try that with a node:

Title: This is a page node

Body: In viverra aliquet turpis. Sed at urna pretium diam congue mollis. Duis tempor. Nullam ornare, elit eu imperdiet luctus, eros felis varius sapien, eget venenatis mauris tellus a eros. Mauris a enim. Aenean non ipsum. Nulla facilisi. Nam rutrum, justo a rutrum adipiscing, eros dolor placerat erat, ac suscipit enim pede non nulla. Vestibulum id mi. Praesent placerat scelerisque elit. Sed venenatis. Suspendisse lacinia. Vivamus fermentum. Nullam blandit, quam consequat iaculis faucibus, sem ipsum aliquet diam, nec pharetra lectus risus at sapien. Mauris nec purus quis magna pharetra sollicitudin. Fusce tellus orci, mollis non, adipiscing a, pulvinar et, lacus. Nulla diam.

Name: victorkane

Taxonomy: bungee jumping, Company, Inc,. funny

etc., etc., etc.,

Using the following code:

$page = node_load(33044);
$p_s = serialize($page);
print $p_s;

gives us:

O:8:"stdClass":25:{s:3:"nid";s:5:"33044";s:3:"vid";s:5:"34185";s:4:"type";s:4:"page";s:6:"status";s:1:"1";s:7:"created";s:10:"1187172116";s:7:"changed";s:10:"1187172116";s:7:"comment";s:1:"2";s:7:"promote";s:1:"0";s:6:"sticky";s:1:"0";s:18:"revision_timestamp";s:10:"1187172116";s:5:"title";s:19:"This is a page node";s:4:"body";s:677:"In viverra aliquet turpis. Sed at urna pretium diam congue mollis. Duis tempor. Nullam ornare, elit eu imperdiet luctus, eros felis varius sapien, eget venenatis mauris tellus a eros. Mauris a enim. Aenean non ipsum. Nulla facilisi. Nam rutrum, justo a rutrum adipiscing, eros dolor placerat erat, ac suscipit enim pede non nulla. Vestibulum id mi. Praesent placerat scelerisque elit. Sed venenatis. Suspendisse lacinia. Vivamus fermentum. Nullam blandit, quam consequat iaculis faucibus, sem ipsum aliquet diam, nec pharetra lectus risus at sapien. Mauris nec purus quis magna pharetra sollicitudin. Fusce tellus orci, mollis non, adipiscing a, pulvinar et, lacus. Nulla diam.";s:6:"teaser";s:549:"In viverra aliquet turpis. Sed at urna pretium diam congue mollis. Duis tempor. Nullam ornare, elit eu imperdiet luctus, eros felis varius sapien, eget venenatis mauris tellus a eros. Mauris a enim. Aenean non ipsum. Nulla facilisi. Nam rutrum, justo a rutrum adipiscing, eros dolor placerat erat, ac suscipit enim pede non nulla. Vestibulum id mi. Praesent placerat scelerisque elit. Sed venenatis. Suspendisse lacinia. Vivamus fermentum. Nullam blandit, quam consequat iaculis faucibus, sem ipsum aliquet diam, nec pharetra lectus risus at sapien.";s:3:"log";s:0:"";s:6:"format";s:1:"3";s:3:"uid";s:1:"2";s:4:"name";s:10:"victorkane";s:7:"picture";s:28:"files/pictures/picture-2.jpg";s:4:"data";s:112:"a:4:{s:18:"admin_compact_mode";b:1;s:7:"contact";i:1;s:14:"picture_delete";s:0:"";s:14:"picture_upload";s:0:"";}";s:1:"0";b:0;s:22:"last_comment_timestamp";s:10:"1187172116";s:17:"last_comment_name";N;s:13:"comment_count";s:1:"0";s:8:"taxonomy";a:3:{i:625;O:8:"stdClass":5:{s:3:"tid";s:3:"625";s:3:"vid";s:1:"9";s:4:"name";s:14:"bungee jumping";s:11:"description";s:0:"";s:6:"weight";s:1:"0";}i:626;O:8:"stdClass":5:{s:3:"tid";s:3:"626";s:3:"vid";s:1:"9";s:4:"name";s:13:"Company, Inc.";s:11:"description";s:0:"";s:6:"weight";s:1:"0";}i:624;O:8:"stdClass":5:{s:3:"tid";s:3:"624";s:3:"vid";s:1:"9";s:4:"name";s:5:"funny";s:11:"description";s:0:"";s:6:"weight";s:1:"0";}}s:5:"files";a:0:{}}

cool, sounds like something we could even encrypt and send to the mother lode. Unstandard as all heck, but it will work.

So, erm, how do we send stuff with XML-RPC from one Drupal site to another?

Well, good ole’ Matt Westgate and John K. VanDyk’s Pro Drupal Development should give us the answer to that, shouldn’t it?

And yes, Chapter 19 is entitled "XML-RPC"!

Test 1

So here is a "guess the lucky number" server and the code calling the server from another site, and the result:

Server module:

10) {
return xmlrpc_error(1, t('Your guess must be between 1 and 10.'));
}
$lucky_number = mt_rand(1, 10);
if ($guess == $lucky_number) {
return t('Your number matched!');
}
else {
return t('Sorry, the number was @num.', array('@num' => $lucky_number));
}
}

Client invocation from another Drupal site (use moshe weitzman‘s- devel module’s Execute php block to try it out real quick):


$lucky_number = xmlrpc('http://empleos.mentor/xmlrpc.php', 'xmlrpc_ssa.guessLuckyNumber', 5);
if (xmlrpc_error()) {
$error_num = xmlrpc_errno();
$error = xmlrpc_error();
print_r ($error);
}
echo $lucky_number;</code>

Result:

Sorry, the number was 8. 

Test 2 (Iteration 1)

So let’s transmit a node already.

New server:


$node -> title));
}

Result (success!):

Received This is a page node

Test 3 (Iteration 2)

So now the server is are going to actually write the node! (I won’t be mean and leave that as an "exercise to the reader" Cool ).

New server:


type) {
case 'page':
unset($node -> nid);
unset($node -> vid);
unset($node -> created);
unset($node -> changed);
unset($node -> revision_timestamp);
unset($node -> taxonomy);
$node = node_submit($node);
node_save($node);
break;
default:
break;
}
return t('Received @node_title', array('@node_title' => $node -> title . ' nid: ' . $node -> nid));
}

Same invocation. It just works! Simplified things with the unsetting of certain fields. Obviously, matching taxonomy nodes …. maybe next post?