Issues

ZF-6445: Zend_XmlRpc_Value should support the 64 bits integer data type

Description

The Zend_XmlRpc_Value class should support the a 64 bits integer data type.

Suggestion:

Add new constant to Zend_XmlRpc_Value class.


const XMLRPC_TYPE_I8 = 'i8';

Add the new constant to the switch in the getXmlRpcValue() method (search for self::XMLRPC_TYPE_I8)


switch ($type) {
    case self::AUTO_DETECT_TYPE:
        // Auto detect the XML-RPC native type from the PHP type of $value
        return self::_phpVarToNativeXmlRpc($value);

    case self::XML_STRING:
        // Parse the XML string given in $value and get the XML-RPC value in it
        return self::_xmlStringToNativeXmlRpc($value);

    case self::XMLRPC_TYPE_I4:
        // fall through to the next case
    case self::XMLRPC_TYPE_INTEGER:
        return new Zend_XmlRpc_Value_Integer($value);

    case self::XMLRPC_TYPE_DOUBLE:
        return new Zend_XmlRpc_Value_Double($value);

    case self::XMLRPC_TYPE_BOOLEAN:
        return new Zend_XmlRpc_Value_Boolean($value);

    case self::XMLRPC_TYPE_I8:
    case self::XMLRPC_TYPE_STRING:
        return new Zend_XmlRpc_Value_String($value);

    case self::XMLRPC_TYPE_BASE64:
        return new Zend_XmlRpc_Value_Base64($value);

    case self::XMLRPC_TYPE_NIL:
        return new Zend_XmlRpc_Value_Nil();

    case self::XMLRPC_TYPE_DATETIME:
        return new Zend_XmlRpc_Value_DateTime($value);

    case self::XMLRPC_TYPE_ARRAY:
        return new Zend_XmlRpc_Value_Array($value);

    case self::XMLRPC_TYPE_STRUCT:
        return new Zend_XmlRpc_Value_Struct($value);

    default:
        throw new Zend_XmlRpc_Value_Exception('Given type is not a '. __CLASS__ .' constant');
}

Add the new constant to the switch in the _xmlStringToNativeXmlRpc() method (search for self::XMLRPC_TYPE_I8)


switch ($type) {
    // All valid and known XML-RPC native values
    case self::XMLRPC_TYPE_I4:
        // Fall through to the next case
    case self::XMLRPC_TYPE_INTEGER:
        $xmlrpc_val = new Zend_XmlRpc_Value_Integer($value);
        break;
    case self::XMLRPC_TYPE_DOUBLE:
        $xmlrpc_val = new Zend_XmlRpc_Value_Double($value);
        break;
    case self::XMLRPC_TYPE_BOOLEAN:
        $xmlrpc_val = new Zend_XmlRpc_Value_Boolean($value);
        break;
    case self::XMLRPC_TYPE_I8:
    case self::XMLRPC_TYPE_STRING:
        $xmlrpc_val = new Zend_XmlRpc_Value_String($value);
        break;
    case self::XMLRPC_TYPE_DATETIME:  // The value should already be in a iso8601 format
        $xmlrpc_val = new Zend_XmlRpc_Value_DateTime($value);
        break;
    case self::XMLRPC_TYPE_BASE64:    // The value should already be base64 encoded
        $xmlrpc_val = new Zend_XmlRpc_Value_Base64($value ,true);
        break;
    case self::XMLRPC_TYPE_NIL:    // The value should always be NULL
        $xmlrpc_val = new Zend_XmlRpc_Value_Nil();
        break;
    case self::XMLRPC_TYPE_ARRAY:
        // If the XML is valid, $value must be an SimpleXML element and contain the  tag
        if (!$value instanceof SimpleXMLElement) {
            throw new Zend_XmlRpc_Value_Exception('XML string is invalid for XML-RPC native '. self::XMLRPC_TYPE_ARRAY .' type');
        } 

        // PHP 5.2.4 introduced a regression in how empty($xml->value) 
        // returns; need to look for the item specifically
        $data = null;
        foreach ($value->children() as $key => $value) {
            if ('data' == $key) {
                $data = $value;
                break;
            }
        }
        
        if (null === $data) {
            throw new Zend_XmlRpc_Value_Exception('Invalid XML for XML-RPC native '. self::XMLRPC_TYPE_ARRAY .' type: ARRAY tag must contain DATA tag');
        }
        $values = array();
        // Parse all the elements of the array from the XML string
        // (simple xml element) to Zend_XmlRpc_Value objects
        foreach ($data->value as $element) {
            $values[] = self::_xmlStringToNativeXmlRpc($element);
        }
        $xmlrpc_val = new Zend_XmlRpc_Value_Array($values);
        break;
    case self::XMLRPC_TYPE_STRUCT:
        // If the XML is valid, $value must be an SimpleXML
        if ((!$value instanceof SimpleXMLElement)) {
            throw new Zend_XmlRpc_Value_Exception('XML string is invalid for XML-RPC native '. self::XMLRPC_TYPE_STRUCT .' type');
        }
        $values = array();
        // Parse all the memebers of the struct from the XML string
        // (simple xml element) to Zend_XmlRpc_Value objects
        foreach ($value->member as $member) {
            // @todo? If a member doesn't have a  tag, we don't add it to the struct
            // Maybe we want to throw an exception here ?
            if ((!$member->value instanceof SimpleXMLElement)) {
                continue;
                //throw new Zend_XmlRpc_Value_Exception('Member of the '. self::XMLRPC_TYPE_STRUCT .' XML-RPC native type must contain a VALUE tag');
            }
            $values[(string)$member->name] = self::_xmlStringToNativeXmlRpc($member->value);
        }
        $xmlrpc_val = new Zend_XmlRpc_Value_Struct($values);
        break;
    default:
        throw new Zend_XmlRpc_Value_Exception('Value type \''. $type .'\' parsed from the XML string is not a known XML-RPC native type');
        break;
}

Thank you.

Comments

Hi,

I ran in to the same "problem" and solved it along the same lines. But instead of casting i8 to string use a (new) Zend_XmlRpc_Value_BigInteger I have attached a diff last svn version.

Patch to support BigInts in the xmlrpc client.

Michiel, the patch looks good. Could you provide some tests for the marshaling?

Please make sure you sign a CLA too so that we can accept your patches: http://framework.zend.com/community/contribute

Fixed in r17933. Handles as well as the non-standard Apache XML/RPC extension (http://ws.apache.org/xmlrpc/)

Zend_XmlRpc_Value_BigInteger has been refactored due to some major bugs. See ZF-8898 for more details.