<?php
/**
* dom_xmlrpc_builder is a utility for building string representations of XML-RPC documents
* @package dom-xmlrpc
* @copyright (C) 2004 John Heinstein. All rights reserved
* @license http://www.gnu.org/copyleft/lesser.html LGPL License
* @author John Heinstein <johnkarl@nbnet.nb.ca>
* @link http://www.engageinteractive.com/dom_xmlrpc/ DOM XML-RPC Home Page
* DOM XML-RPC is Free Software
**/
if (!defined('DOM_XMLRPC_INCLUDE_PATH')) {
define('DOM_XMLRPC_INCLUDE_PATH', (dirname(__FILE__) . "/"));
}
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_constants.php');
/**
* A utility for building string representations of XML-RPC documents
*
* @package dom-xmlrpc
* @author John Heinstein <johnkarl@nbnet.nb.ca>
*/
class dom_xmlrpc_builder {
/** @var string The method type of the XML-RPC data, e.g., DOM_XMLRPC_TYPE_METHODRESPONSE */
var $methodType;
/** @var string The XML string representing the method params */
var $params = "";
/** @var string The type of object marshalling to be used, if this option is enabled */
var $objectMarshalling = DOM_XMLRPC_OBJECT_MARSHALLING_ANONYMOUS;
/**
* Invokes the ability to pass PHP objects in addition to basic native types such as int and string
* @param string The type of object marshalling to be invoked: either anonymous, named, or serialized
*/
function setObjectMarshalling($type) {
$type = strtolower($type);
switch ($type) {
case DOM_XMLRPC_OBJECT_MARSHALLING_ANONYMOUS: //default
case DOM_XMLRPC_OBJECT_MARSHALLING_NAMED:
case DOM_XMLRPC_OBJECT_MARSHALLING_SERIALIZED:
$this->objectMarshalling = $type;
break;
default:
XMLRPC_Client_Exception::raiseException(XMLRPC_CLIENT_RESPONSE_TYPE_ERR,
('Invalid object marshalling type: ' . $type));
}
} //setObjectMarshalling
/**
* Creates an XML-RPC representation of a scalar value (e.g. string, double, boolean)
* @param mixed The value to be converted to XML-RPC notation
* @param string The type of the value (will be autodetected if omitted)
* @return string An XML-RPC representation of the value
*/
function createScalar($value, $type = '') {
if ($type == '') {
$type = dom_xmlrpc_utilities::getScalarTypeFromValue($value);
}
switch ($type) {
case DOM_XMLRPC_TYPE_STRING:
if ($this->methodType == DOM_XMLRPC_TYPE_METHODRESPONSE) {
//htmlencode the string, because
//DOM XML-RPC server has decoded it
$value = htmlentities($value, ENT_QUOTES);
}
break;
case DOM_XMLRPC_TYPE_DOUBLE:
//ensure trailing .0 if it looks like an int
$value = '' . $value;
if (strpos($value, '.') === false) {
$value .= '.0';
}
break;
case DOM_XMLRPC_TYPE_BOOLEAN:
if (is_bool($value)) {
$value = ($value ? '1' : '0');
}
break;
case DOM_XMLRPC_TYPE_BASE64:
if (is_object($value)) {
$value = $value->getEncoded();
}
break;
case DOM_XMLRPC_TYPE_DATETIME:
if (is_object($value)) {
$value = $value->getDateTime_iso();
}
break;
}
return ("<value><$type>$value</$type></value>");
} //createScalar
/**
* Generates an XML-RPC param from the scalar and adds it to the method params
* @param mixed The value to be converted to XML-RPC notation
* @param string The type of the value (will be autodetected if omitted)
*/
function addScalar($value, $type = '') {
$this->params .= "\n\t\t<param>" . $this->createScalar($value, $type) . '</param>';
} //addScalar
/**
* Creates an XML-RPC representation of a PHP array
* @param array The array to be converted to XML-RPC notation
* @return string An XML-RPC representation of the array
*/
function createArray(&$myArray) {
$data = '<value><array><data>';
foreach ($myArray as $key => $value) {
$currDataItem =& $myArray[$key];
$currType = dom_xmlrpc_utilities::getTypeFromValue($currDataItem);
$data .= $this->create($currDataItem, $currType);
}
$data .= '</data></array></value>';
return $data;
} //createArray
/**
* Generates an XML-RPC param from the array and adds it to the method params
* @param array The array to be converted to XML-RPC notation
*/
function addArray($myArray) {
$this->addArrayByRef($myArray);
} //addArray
/**
* Generates an XML-RPC param from the array reference and adds it to the method params
* @param array The array reference to be converted to XML-RPC notation
*/
function addArrayByRef(&$myArray) { //can call with reference if deep copy is required
$this->params .= "\n\t\t<param>" . $this->createArray($myArray) . '</param>';
} //addArrayByRef
/**
* Creates an XML-RPC representation of a PHP object
* @param object The object to be converted to XML-RPC notation
* @return string An XML-RPC representation of the object
*/
function createObject(&$myObject) {
require_once('dom_xmlrpc_object.php');
if (get_class($myObject) == 'dom_xmlrpc_object') { //wrapper for xmlrpc object
$myObject =& $myObject->getObject(); //grab embedded object
}
switch($this->objectMarshalling){
case DOM_XMLRPC_OBJECT_MARSHALLING_ANONYMOUS:
//generic struct, one member for each
//object property, object type is discarded
$data = '<value><struct>';
foreach ($myObject as $key => $value) {
$currValue =& $myObject->$key;
$currType = dom_xmlrpc_utilities::getTypeFromValue($currValue);
$data .= $this->createMember($key, $currValue, $currType);
}
$data .= '</struct></value>';
break;
case DOM_XMLRPC_OBJECT_MARSHALLING_NAMED:
//struct with one member for each
//object property, object type is defined
//by an additional member (first in list) named
//"__phpobject__" whose value is a string
//containing the class type of the object
$data = '<value><struct>';
$data .= $this->createMember(DOM_XMLRPC_PHPOBJECT, get_class($myObject), DOM_XMLRPC_TYPE_STRING);
foreach ($myObject as $key => $value) {
$currValue =& $myObject->$key;
$currType = dom_xmlrpc_utilities::getTypeFromValue($currValue);
$data .= $this->createMember($key, $currValue, $currType);
}
$data .= '</struct></value>';
break;
case DOM_XMLRPC_OBJECT_MARSHALLING_SERIALIZED:
//serialized object, one member of type base64
//which is the serialized object, base64 encoded
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_base64.php');
$data = '<value><struct>';
$data .= $this->createMember(DOM_XMLRPC_PHPOBJECT, get_class($myObject), DOM_XMLRPC_TYPE_STRING);
$serialized =& serialize($myObject);
$currValue =& $this->createBase64($serialized);
$data .= $this->createMember(DOM_XMLRPC_SERIALIZED, $currValue, DOM_XMLRPC_TYPE_BASE64);
$data .= '</struct></value>';
break;
} // switch
return $data;
} //createObject
/**
* Generates an XML-RPC param from the object and adds it to the method params
* @param object The object to be converted to XML-RPC notation
*/
function addObject($myObject) {
$this->addObjectByRef($myObject);
}//addObject
/**
* Generates an XML-RPC param from the object reference and adds it to the method params
* @param object The object reference to be converted to XML-RPC notation
*/
function addObjectByRef(&$myObject) { //can call with reference if deep copy is required
$this->params .= "\n\t\t<param>" . $this->createObject($myObject) . '</param>';
}//addObjectByRef
/**
* Creates an XML-RPC representation of a struct
* @param mixed The struct to be converted to XML-RPC notation
* @return string An XML-RPC representation of the struct
*/
function createStruct(&$myStruct) {
require_once('dom_xmlrpc_object.php');
$className = get_class($myStruct);
//if struct is explicitly cast as an xmlrpc object
if ($className == 'dom_xmlrpc_object') {
$myObject =& $myStruct->getObject(); //grab embedded object
return $this->createObject($myObject);
}
else {
//wrapper for numeric indexed structs
//that are meant to be string indexed
if ($className == 'dom_xmlrpc_struct') {
$myStruct =& $myStruct->getStruct(); //grab embedded array
}
$isArrayNotObj = is_array($myStruct);
//if struct is an object and isn't anonymous
if ($isArrayNotObj && ($this->objectMarshalling != DOM_XMLRPC_OBJECT_MARSHALLING_ANONYMOUS)) {
return $this->createObject($myStruct);
}
else {
$data = '<value><struct>';
foreach ($myStruct as $key => $value) {
$isArrayNotObj ? ($currValue =& $myStruct[$key]) : ($currValue =& $value);
$currType = dom_xmlrpc_utilities::getTypeFromValue($currValue);
$data .= $this->createMember($key, $currValue, $currType);
}
$data .= '</struct></value>';
return $data;
}
}
} //createStruct
/**
* Generates an XML-RPC param from the struct and adds it to the method params
* @param mixed The struct to be converted to XML-RPC notation
*/
function addStruct($myStruct) {
$this->addStructByRef($myStruct);
} //addStruct
/**
* Generates an XML-RPC param from the struct reference and adds it to the method params
* @param mixed The struct reference to be converted to XML-RPC notation
*/
function addStructByRef(&$myStruct) { //can call with reference if deep copy is required
$this->params .= "\n\t\t<param>" . $this->createStruct($myStruct) . '</param>';
} //addStructRef
/**
* Creates an XML-RPC representation of a member
* @param mixed The member to be converted to XML-RPC notation
* @return string An XML-RPC representation of the member
*/
function createMember($name, &$value, $type) {
$data = '<member><name>' . $name . '</name>';
if ($type == '') {
$type = dom_xmlrpc_utilities::getScalarTypeFromValue($value);
}
$data .= $this->create($value, $type) . '</member>';
return $data;
} //createMember
/**
* Generates an XML-RPC param from the value and adds it to the method params
* @param mixed The value to be converted to XML-RPC notation
*/
function create(&$value, $type = '') {
$data = '';
if ($type == '') {
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_utilities.php');
$type = dom_xmlrpc_utilities::getTypeFromValue($value);
}
switch ($type) {
case DOM_XMLRPC_TYPE_STRING:
case DOM_XMLRPC_TYPE_INT:
case DOM_XMLRPC_TYPE_I4:
case DOM_XMLRPC_TYPE_DOUBLE:
case DOM_XMLRPC_TYPE_BOOLEAN:
case DOM_XMLRPC_TYPE_BASE64:
case DOM_XMLRPC_TYPE_DATETIME:
$data .= $this->createScalar($value, $type);
break;
case DOM_XMLRPC_TYPE_STRUCT:
$data .= $this->createStruct($value, $type);
break;
case DOM_XMLRPC_TYPE_ARRAY:
$data .= $this->createArray($value, $type);
break;
}
return $data;
} //create
/**
* Generates an XML-RPC param from the unspecified value
* @param mixed The value to be converted to XML-RPC notation
*/
function add($value, $type = '') {
$this->addByRef($value, $type);
} //add
/**
* Generates an XML-RPC param from the unspecified reference
* @param mixed The reference to be converted to XML-RPC notation
*/
function addByRef(&$value, $type = '') { //can call with reference if deep copy is required
$this->params .= "\n\t\t<param>" . $this->create($value, $type) . '</param>';
} //addByRef
/**
* Generates an XML-RPC param from list of values
*/
function addList() {
$total = func_num_args();
for ($i = 0; $i < $total; $i++) {
$this->add(func_get_arg($i));
}
} //addList
/**
* Creates a dom_xmlrpc_base64 object from the binary data
* @param mixed The binary data
* @return object The base64 encoded data
*/
function &createBase64($binaryData) {
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_base64.php');
$base64 = new dom_xmlrpc_base64();
$base64->fromBinary($binaryData);
return $base64;
} //createBase64
/**
* Creates a dom_xmlrpc_base64 object from the file
* @param string The file path
* @return object The base64 encoded data
*/
function &createBase64FromFile($fileName) {
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_base64.php');
$base64 = new dom_xmlrpc_base64();
$base64->fromFile($fileName);
return $base64;
} //createBase64FromFile
/**
* Creates a dom_xmlrpc_datetime_iso8601 object from the PHP time
* @param string The time
* @return object The dom_xmlrpc_datetime_iso8601 object
*/
function &createDateTimeISO($time) {
require_once(DOM_XMLRPC_INCLUDE_PATH . 'dom_xmlrpc_datetime_iso8601.php');
$isoDateTime = new dom_xmlrpc_datetime_iso8601($time);
return $isoDateTime;
} //createDateTimeISO
} //dom_xmlrpc_builder
?>