Last updated April 6, 2010. Created by DartonW on September 22, 2009.
Edited by heyrocker. Log in to edit this page.
Services 6.x-2.x-dev on Drupal 6.14. Uses the XML-RPC for PHP library at http://phpxmlrpc.sourceforge.net/. Thanks to clues from http://drupal.org/node/303285 and the services tester, it includes some code for populating CCK fields ("field_publication", "field_byline", etc.). This is pre-production code for importing articles to a newspaper website, designed to run on the command line. I just left the parseXML() function as an example.
<?php
require('./xmlrpc-3.0.0.beta/lib/xmlrpc.inc');
$username = "username";
$pass = "password";
$domain = "example.com";
$publication = "The Daily Drupal";
$servicehost = "example.com";
$servicepath = "services/xmlrpc";
$sessid = "";
$uid = 0;
$xmlpath = "/path/to/xml";
$processdir = "/path/to/processed";
$successdir = "$processdir/success";
$failuredir = "$processdir/failure";
// Make initial connection to get a session ID
$m = new xmlrpcmsg('system.connect', array());
$c = new xmlrpc_client($servicepath, $servicehost, 80);
$c->return_type = "phpvals";
$r = &$c->send($m);
if(!$r->faultCode()){
$v = $r->value();
$sessid = ($v['sessid']);
}else{
die("An error occurred on system.connect: ".$r->faultString()."\n");
}
// Using the session ID from the first connection, log in to the server
$m = new xmlrpcmsg("user.login",
array(
new xmlrpcval($sessid),
new xmlrpcval($username),
new xmlrpcval($pass))
);
// If login is successful, user object and a new sessid will be returned
$r = &$c->send($m);
if(!$r->faultCode()){
$v = $r->value();
// Only need uid for our purposes
$uid = $v['user']['uid'];
$sessid = $v['sessid'];
}else{
die("An error occurred on user.login: ".$r->faultString()."\n");
}
// Open the XML directory and iterate files
$dir_handle = @opendir($xmlpath) or die("Unable to open $xmlpath\n");
while ($file = readdir($dir_handle))
{
// Only get files named *.xml
if(end(explode(".", $file)) != "xml")
continue;
// Ignore parsing errors for now and continue
libxml_use_internal_errors(true);
$xmldoc = simplexml_load_file("$xmlpath/$file");
if(!$xmldoc){
rename("$xmlpath/$file", "$failuredir/$file");
continue;
}
// Pass the XML to be parsed and get back a PHP node structure
$node = parseXML(&$xmldoc);
// Call the service to create the node
$nid = createNode($sessid, &$node);
// Move file to success or failure directory
if($nid > 0){
rename("$xmlpath/$file", "$successdir/$file");
print "Node $nid created.\n";
}
else{
rename("$xmlpath/$file", "$failuredir/$file");
}
}
closedir($dir_handle);
function parseXML($xmldoc){
global $publication;
// Initialize array container for node data
$node = array();
$node["publication"] = $publication;
$node["type"] = "story";
$node["format"] = 2;
$tmp = $xmldoc->xpath("//meta[@name='feed.doc.name']");
$node["filename"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='feed.doc.id']");
$node["docid"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='cms.section']");
$node["section"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='cms.category']");
$node["category"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='cms.release']");
$node["releasedate"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='cms.expire']");
$node["expiredate"] = trim($tmp[0]['content']);
$tmp = $xmldoc->xpath("//meta[@name='position.rank']");
$node["positionrank"] = trim($tmp[0]['value']);
$tmp = $xmldoc->xpath("//pubdata");
$node["positionsection"] = trim($tmp[0]['position.section']);
$node["positionsequence"] = trim($tmp[0]['position.sequence']);
$node["pubdataname"] = trim($tmp[0]['name']);
$node["headline"] = $xmldoc->body->{'body.head'}->hedline->hl1;
$node["subhead"] = $xmldoc->body->{'body.head'}->hedline->hl2;
$node["byline"] = $xmldoc->body->{'body.head'}->byline->person;
$node["bylinecredit"] = $xmldoc->body->{'body.head'}->bylinecredit->site;
// Try to access the body in different ways to account for screwy XML
$tmp = $xmldoc->body->{'body.content'};
foreach($tmp->children() as $element){
if($element->getName() !== "media")
$node["body"] .= $element->asXML();
}
if($node["body"] === "")
$node["body"] = $xmldoc->body->{'body.content'};
// Ampersands are encoded but need to be unencoded for other HTML characters
$node["body"] = preg_replace("/&/", "&", $node["body"]);
return $node;
}
// Handle node.save and CCK fields
function createNode($sessid, $node){
global $c, $uid, $username;
$edit = new xmlrpcval(
array(
"uid" => new xmlrpcval($uid, "int"),
"name" => new xmlrpcval($username),
"type" => new xmlrpcval($node["type"]),
"format" => new xmlrpcval($node["format"], "int"),
"title" => new xmlrpcval($node["headline"]),
"body" => new xmlrpcval($node["body"]),
"field_publication" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["publication"])), "struct")), "array"),
"field_byline" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["byline"])), "struct")), "array"),
"field_section" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["section"])), "struct")), "array"),
"field_category" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["category"])), "struct")), "array")
),
"struct"
);
$m = new xmlrpcmsg("node.save",
array(
new xmlrpcval($sessid),
$edit
)
);
$r = &$c->send($m);
if(!$r->faultCode()){
$nid = $r->value();
return $nid;
}else{
print ("An error occurred on node.save: ".$r->faultString()."\n");
$nid = 0;
return $nid;
}
}
?>
Comments
Has anyone had luck with this
Has anyone had luck with this using drupal 6.15 and services 6.2 beta1 (I tried dev 6.2 as well but the same problem)? I have essentially replicated this, except of course not using the cck fields.
I had to remove $sessid from user.login msg too as it would not work with it, otherwise it's the same.
I did open an issue (http://drupal.org/node/708508) with services, but I began to wonder if the problem is within the client?
did you set the
did you set the authentication module to 'Key authentication' and check the 'Use sessid' box in your services settings?
I can get past the user.login function but am stuck at node.save. I was getting a fatal error that looked like I didn't have xmlrpc enabled in my php install but found that I didn't have Node Service enabled - I enabled that and the errors went away. But it is still not creating the node. I dumped the data to make sure I was sending the required data. Does anyone have any insight?
Taxonomy
I'm trying to get taxonomy (predefined selection) terms with the node.save, but i seem not to do it right. Any directions on putting it in the right datastructure?
--
d-Media Web Professionals
http://d-media.nl
was trying to figure that out too
this is what worked for me yesterday using Services 6.x-2.0:
<?php"taxonomy" => new xmlrpcval(
array(
$node['vid'] => new xmlrpcval(
array(
new xmlrpcval($node['tid'],'int')
),
'array'),
),
'struct'),
?>
where $node['vid'] is the vocabulary id and $node['tid'] is the term id
this was for a single select non-tag vocabulary
Haven't tested this yet...
Haven't tested this yet... but seems right to me. I switched from an implementation with services to a in drupal solution where i was able to insert directly
--
d-Media Web Professionals
http://d-media.nl
Taxonomy tag on node.save
How to update a taxonomy tag name in node object using node.save via xmlrpc?
user.save based on the above script
Services 6.x-2.2 on Drupal 6.16. This code creates a user and changes that user's roles. (With thanks to the original author who saved me half a day's work)
<?php
require('./xmlrpc-3.0.0.beta/lib/xmlrpc.inc');
/*
Example client program to change user settings.
Install Services
Enable modules: Services, Key Authentication, XMLRPC Server, System Service and User Service.
Configuration:
Services: in admin/build/services/settings
set 'Authentication module:' to 'Key Authentication'
uncheck 'Use Keys'
check 'Use sessid'
Permissions (for the Services user role): in admin/user/permissions
under 'system_service module':
check 'get available services'
check 'log a system message from remote'
under 'user module':
check 'administer permissions' (actually roles)
check 'administer users'
under 'user_service module':
check 'create new users'
check 'get any user data'
check 'get own user data'
check 'update any user data'
check 'update own user data'
Check: in admin/build/services/browse check that the servers (XMLRPC) and services (system, user) are available.
Note: other than 2 => "authenticated user", the role ids and names are specific to your Drupal application,
and will need changing.
*/
/**
* Convert the user structure to an XML-RPC structure.
*
* @param $user the user data structure.
* @return the XML-RPC data structure.
*/
function user_to_xmlrpc($user) {
$xmlrpc = array();
// might not have a uid yet
if ($user['uid']) {
$xmlrpc['uid'] = new xmlrpcval($user['uid'], "int");
}
$xmlrpc['name'] = new xmlrpcval($user['name']);
if ($user['pass']) {
$xmlrpc['pass'] = new xmlrpcval($user['pass']);
}
$xmlrpc['mail'] = new xmlrpcval($user['mail']);
$xmlrpc['status'] = new xmlrpcval($user['status'], "int");
$xmlrpc['timezone'] = new xmlrpcval($user['timezone'], "int");
$xmlrpc['language'] = new xmlrpcval($user['language']);
if ($user['roles']) {
$roles = array();
foreach($user['roles'] as $role_id => $role_name) {
$roles[$role_id] = new xmlrpcval($role_name);
}
$xmlrpc['roles'] = new xmlrpcval($roles, "struct");
}
return new xmlrpcval($xmlrpc, "struct");
}
/**
* Get the roles we want to set.
*
* @return the roles.
*/
function get_roles() {
return array(
2 => 'authenticated user',
11 => 'editore',
21 => 'banca',
31 => 'imprenditore'
);
}
print("Example XML-RPC client for Drupal Services\n");
$service_host = "dev.autonomous-sandbox"; // set to the actual domain (this is a local domain)
$service_path = "services/xmlrpc";
$session_id = "";
$username = "external"; // XML-RPC user
$password = "external"; // XML-RPC password
$uid = 0;
$created_uid = 50; // previously created uid (from a previous run of the script) otherwise use -1
$created_user = NULL;
// make initial connection and get the session id
$message = new xmlrpcmsg('system.connect', array());
$client = new xmlrpc_client($service_path, $service_host, 80);
$client->return_type = "phpvals";
print("Connecting to: ". $service_host ."/". $service_path ."\n");
$result = &$client->send($message);
if (!$result->faultCode()) {
$value = $result->value();
$session_id = $value['sessid'];
}
else {
die("An error occurred on system.connect: ". $result->faultCode() .": ". $result->faultString() ."\n");
}
// log in to the server using the session id
$message = new xmlrpcmsg("user.login",
array(
new xmlrpcval($session_id),
new xmlrpcval($username),
new xmlrpcval($password)
)
);
print("Logging in as: ". $username ."\n");
// if login is successful, user object and a new session id will be returned
$result = &$client->send($message);
if (!$result->faultCode()) {
$value = $result->value();
// Only need uid for our purposes
$uid = $value['user']['uid'];
$session_id = $value['sessid'];
}
else {
die("An error occurred on user.login: ". $result->faultCode() .": ". $result->faultString() ."\n");
}
print("Logged in uid is: ". $uid ."\n");
//
// test examples - check if a user exists, if not create it, then set a (known role)
//
// check if the created user id exists, if not create it
$message = new xmlrpcmsg("user.get",
array(
new xmlrpcval($session_id),
new xmlrpcval($created_uid)
)
);
// if user.get is successful, user object will be returned
$result = &$client->send($message);
if (!$result->faultCode()) {
$created_user = $result->value();
$created_uid = $created_user['uid'];
print("Found user: ". print_r($created_user, TRUE). "\n");
unset($created_user['pass']); // remove the password
}
else {
// assume the fault is caused by the user not existing
$created_user = array(
'name' => 'created_user',
'pass' => 'created_user',
'mail' => 'created_user@example.com',
'status' => 1,
'timezone' => 7200, // GMT + 2
'language' => 'it',
'roles' => get_roles()
);
$message = new xmlrpcmsg("user.save",
array(
new xmlrpcval($session_id),
user_to_xmlrpc($created_user)
)
);
// if user.save is successful, user id will be returned
$result = &$client->send($message);
if (!$result->faultCode()) {
$created_uid = $result->value();
print("Created user: ". print_r($created_user, TRUE) ."\n");
$message = new xmlrpcmsg("user.get",
array(
new xmlrpcval($session_id),
new xmlrpcval($created_uid)
)
);
// if user.get is successful, user object will be returned
$result = &$client->send($message);
if (!$result->faultCode()) {
$created_user = $result->value();
print("Retrieved user(". $created_uid ."): ". print_r($created_user, TRUE). "\n");
unset($created_user['pass']); // remove the password
}
else {
die("An error occurred on user.get(". $created_uid ."): ". $result->faultCode() .": ". $result->faultString() ."\n");
}
}
else {
die("An error occurred on user.save: ". $result->faultCode() .": ". $result->faultString() ."\n");
}
}
//
// end test examples
//
// logout from the connection
$message = new xmlrpcmsg("user.logout",
array(
new xmlrpcval($session_id)
)
);
print("Logging out\n");
$result = &$client->send($message);
if (!$result->faultCode()) {
// $value = $result->value();
}
else {
die("An error occurred on user.logout: ". $result->faultCode() .": ". $result->faultString() ."\n");
}
?>
Più imparo, più dubito. The more I learn, the more I doubt.