home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (xmlrpcs.inc)

This example Drupal source code file (xmlrpcs.inc) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

args, array, error, function, if, method, methodname, ok, php, return, xml, xmlrpc, xmlrpc_error, xmlrpc_server

The xmlrpcs.inc Drupal example source code

<?php
// $Id: xmlrpcs.inc,v 1.42 2010/10/02 01:22:41 dries Exp $

/**
 * @file
 * Provides API for defining and handling XML-RPC requests.
 */

/**
 * Invokes XML-RPC methods on this server.
 *
 * @param array $callbacks
 *   Array of external XML-RPC method names with the callbacks they map to.
 */
function xmlrpc_server($callbacks) {
  $xmlrpc_server = new stdClass();
  // Define built-in XML-RPC method names
  $defaults = array(
    'system.multicall' => 'xmlrpc_server_multicall',
    array(
      'system.methodSignature',
      'xmlrpc_server_method_signature',
      array('array', 'string'),
      'Returns an array describing the return type and required parameters of a method.',
    ),
    array(
      'system.getCapabilities',
      'xmlrpc_server_get_capabilities',
      array('struct'),
      'Returns a struct describing the XML-RPC specifications supported by this server.',
    ),
    array(
      'system.listMethods',
      'xmlrpc_server_list_methods',
      array('array'),
      'Returns an array of available methods on this server.',
    ),
    array(
      'system.methodHelp',
      'xmlrpc_server_method_help',
      array('string', 'string'),
      'Returns a documentation string for the specified method.',
    ),
  );
  // We build an array of all method names by combining the built-ins
  // with those defined by modules implementing the _xmlrpc hook.
  // Built-in methods are overridable.
  $callbacks = array_merge($defaults, (array) $callbacks);
  drupal_alter('xmlrpc', $callbacks);
  foreach ($callbacks as $key => $callback) {
    // we could check for is_array($callback)
    if (is_int($key)) {
      $method = $callback[0];
      $xmlrpc_server->callbacks[$method] = $callback[1];
      $xmlrpc_server->signatures[$method] = $callback[2];
      $xmlrpc_server->help[$method] = $callback[3];
    }
    else {
      $xmlrpc_server->callbacks[$key] = $callback;
      $xmlrpc_server->signatures[$key] = '';
      $xmlrpc_server->help[$key] = '';
    }
  }

  $data = file_get_contents('php://input');
  if (!$data) {
    print 'XML-RPC server accepts POST requests only.';
    drupal_exit();
  }
  $xmlrpc_server->message = xmlrpc_message($data);
  if (!xmlrpc_message_parse($xmlrpc_server->message)) {
    xmlrpc_server_error(-32700, t('Parse error. Request not well formed.'));
  }
  if ($xmlrpc_server->message->messagetype != 'methodCall') {
    xmlrpc_server_error(-32600, t('Server error. Invalid XML-RPC. Request must be a methodCall.'));
  }
  if (!isset($xmlrpc_server->message->params)) {
    $xmlrpc_server->message->params = array();
  }
  xmlrpc_server_set($xmlrpc_server);
  $result = xmlrpc_server_call($xmlrpc_server, $xmlrpc_server->message->methodname, $xmlrpc_server->message->params);

  if (is_object($result) && !empty($result->is_error)) {
    xmlrpc_server_error($result);
  }
  // Encode the result
  $r = xmlrpc_value($result);
  // Create the XML
  $xml = '
<methodResponse>
  <params>
  <param>
    <value>' . xmlrpc_value_get_xml($r) . '</value>
  </param>
  </params>
</methodResponse>

';
  // Send it
  xmlrpc_server_output($xml);
}

/**
 * Throws an XML-RPC error.
 *
 * @param $error
 *   An error object or integer error code.
 * @param $message
 *   (optional) The description of the error. Used only if an integer error
 *   code was passed in.
 */
function xmlrpc_server_error($error, $message = FALSE) {
  if ($message && !is_object($error)) {
    $error = xmlrpc_error($error, $message);
  }
  xmlrpc_server_output(xmlrpc_error_get_xml($error));
}

/**
 * Sends XML-RPC output to the browser.
 *
 * @param string $xml
 *   XML to send to the browser.
 */
function xmlrpc_server_output($xml) {
  $xml = '<?xml version="1.0"?>' . "\n" . $xml;
  drupal_add_http_header('Content-Length', strlen($xml));
  drupal_add_http_header('Content-Type', 'text/xml');
  echo $xml;
  drupal_exit();
}

/**
 * Stores a copy of an XML-RPC request temporarily.
 *
 * @param object $xmlrpc_server
 *   (optional) Request object created by xmlrpc_server(). Omit to leave the
 *   previous server object saved.
 *
 * @return
 *   The latest stored request.
 *
 * @see xmlrpc_server_get()
 */
function xmlrpc_server_set($xmlrpc_server = NULL) {
  static $server;
  if (!isset($server)) {
    $server = $xmlrpc_server;
  }
  return $server;
}

/**
 * Retrieves the latest stored XML-RPC request.
 *
 * @return object
 *   The stored request.
 *
 * @see xmlrpc_server_set()
 */
function xmlrpc_server_get() {
  return xmlrpc_server_set();
}

/**
 * Dispatches an XML-RPC request and any parameters to the appropriate handler.
 *
 * @param object $xmlrpc_server
 *   Object containing information about this XML-RPC server, the methods it
 *   provides, their signatures, etc.
 * @param string $methodname
 *   The external XML-RPC method name; e.g., 'system.methodHelp'.
 * @param array $args
 *   Array containing any parameters that are to be sent along with the request.
 *
 * @return
 *   The results of the call.
 */
function xmlrpc_server_call($xmlrpc_server, $methodname, $args) {
  // Make sure parameters are in an array
  if ($args && !is_array($args)) {
    $args = array($args);
  }
  // Has this method been mapped to a Drupal function by us or by modules?
  if (!isset($xmlrpc_server->callbacks[$methodname])) {
    return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $xmlrpc_server->message->methodname)));
  }
  $method = $xmlrpc_server->callbacks[$methodname];
  $signature = $xmlrpc_server->signatures[$methodname];

  // If the method has a signature, validate the request against the signature
  if (is_array($signature)) {
    $ok = TRUE;
    $return_type = array_shift($signature);
    // Check the number of arguments
    if (count($args) != count($signature)) {
      return xmlrpc_error(-32602, t('Server error. Wrong number of method parameters.'));
    }
    // Check the argument types
    foreach ($signature as $key => $type) {
      $arg = $args[$key];
      switch ($type) {
        case 'int':
        case 'i4':
          if (is_array($arg) || !is_int($arg)) {
            $ok = FALSE;
          }
          break;

        case 'base64':
        case 'string':
          if (!is_string($arg)) {
            $ok = FALSE;
          }
          break;

        case 'boolean':
          if ($arg !== FALSE && $arg !== TRUE) {
            $ok = FALSE;
          }
          break;

        case 'float':
        case 'double':
          if (!is_float($arg)) {
            $ok = FALSE;
          }
          break;

        case 'date':
        case 'dateTime.iso8601':
          if (!$arg->is_date) {
            $ok = FALSE;
          }
          break;
      }
      if (!$ok) {
        return xmlrpc_error(-32602, t('Server error. Invalid method parameters.'));
      }
    }
  }

  if (!function_exists($method)) {
    return xmlrpc_error(-32601, t('Server error. Requested function @method does not exist.', array("@method" => $method)));
  }
  // Call the mapped function
  return call_user_func_array($method, $args);
}

/**
 * Dispatches multiple XML-RPC requests.
 *
 * @param array $methodcalls
 *   An array of XML-RPC requests to make. Each request is an array with the
 *   following elements:
 *   - methodName: Name of the method to invoke.
 *   - params: Parameters to pass to the method.
 *
 * @return
 *   An array of the results of each request.
 *
 * @see xmlrpc_server_call()
 */
function xmlrpc_server_multicall($methodcalls) {
  // See http://www.xmlrpc.com/discuss/msgReader$1208
  $return = array();
  $xmlrpc_server = xmlrpc_server_get();
  foreach ($methodcalls as $call) {
    $ok = TRUE;
    if (!isset($call['methodName']) || !isset($call['params'])) {
      $result = xmlrpc_error(3, t('Invalid syntax for system.multicall.'));
      $ok = FALSE;
    }
    $method = $call['methodName'];
    $params = $call['params'];
    if ($method == 'system.multicall') {
      $result = xmlrpc_error(-32600, t('Recursive calls to system.multicall are forbidden.'));
    }
    elseif ($ok) {
      $result = xmlrpc_server_call($xmlrpc_server, $method, $params);
    }
    if (is_object($result) && !empty($result->is_error)) {
      $return[] = array(
        'faultCode' => $result->code,
        'faultString' => $result->message,
      );
    }
    else {
      $return[] = array($result);
    }
  }
  return $return;
}

/**
 * Lists the methods available on this XML-RPC server.
 *
 * XML-RPC method system.listMethods maps to this function.
 *
 * @return array
 *   Array of the names of methods available on this server.
 */
function xmlrpc_server_list_methods() {
  $xmlrpc_server = xmlrpc_server_get();
  return array_keys($xmlrpc_server->callbacks);
}

/**
 * Returns a list of the capabilities of this server.
 *
 * XML-RPC method system.getCapabilities maps to this function.
 *
 * @return array
 *   Array of server capabilities.
 *
 * @see http://groups.yahoo.com/group/xml-rpc/message/2897
 */
function xmlrpc_server_get_capabilities() {
  return array(
    'xmlrpc' => array(
      'specUrl' => 'http://www.xmlrpc.com/spec',
      'specVersion' => 1,
    ),
    'faults_interop' => array(
      'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
      'specVersion' => 20010516,
    ),
    'system.multicall' => array(
      'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
      'specVersion' => 1,
    ),
    'introspection' => array(
      'specUrl' => 'http://scripts.incutio.com/xmlrpc/introspection.html',
      'specVersion' => 1,
    ),
  );
}

/**
 * Returns the method signature of a function.
 *
 * This is the function mapped to the XML-RPC method system.methodSignature.
 *
 * A method signature is an array of the input and output types of a method. For
 * instance, the method signature of this function is array('array', 'string'),
 * because it takes an array and returns a string.
 *
 * @param string $methodname
 *   Name of method to return a method signature for.
 *
 * @return array
 *   An array of types representing the method signature of the function that
 *   $methodname maps to.
 */
function xmlrpc_server_method_signature($methodname) {
  $xmlrpc_server = xmlrpc_server_get();
  if (!isset($xmlrpc_server->callbacks[$methodname])) {
    return xmlrpc_error(-32601, t('Server error. Requested method @methodname not specified.', array("@methodname" => $methodname)));
  }
  if (!is_array($xmlrpc_server->signatures[$methodname])) {
    return xmlrpc_error(-32601, t('Server error. Requested method @methodname signature not specified.', array("@methodname" => $methodname)));
  }
  // We array of types
  $return = array();
  foreach ($xmlrpc_server->signatures[$methodname] as $type) {
    $return[] = $type;
  }
  return $return;
}

/**
 * Returns the help for an XML-RPC method.
 *
 * XML-RPC method system.methodHelp maps to this function.
 *
 * @param string $method
 *   Name of method for which we return a help string.
 *
 * @return string
 *   Help text for $method.
 */
function xmlrpc_server_method_help($method) {
  $xmlrpc_server = xmlrpc_server_get();
  return $xmlrpc_server->help[$method];
}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal xmlrpcs.inc source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.