Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
4
 
5
// LICENSE AGREEMENT. If folded, press za here to unfold and read license {{{
6
 
7
/**
8
* +-----------------------------------------------------------------------------+
9
* | Copyright (c) 2004-2006 Sergio Goncalves Carvalho                                |
10
* +-----------------------------------------------------------------------------+
11
* | This file is part of XML_RPC2.                                              |
12
* |                                                                             |
13
* | XML_RPC2 is free software; you can redistribute it and/or modify            |
14
* | it under the terms of the GNU Lesser General Public License as published by |
15
* | the Free Software Foundation; either version 2.1 of the License, or         |
16
* | (at your option) any later version.                                         |
17
* |                                                                             |
18
* | XML_RPC2 is distributed in the hope that it will be useful,                 |
19
* | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
20
* | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
21
* | GNU Lesser General Public License for more details.                         |
22
* |                                                                             |
23
* | You should have received a copy of the GNU Lesser General Public License    |
24
* | along with XML_RPC2; if not, write to the Free Software                     |
25
* | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
26
* | 02111-1307 USA                                                              |
27
* +-----------------------------------------------------------------------------+
28
* | Author: Sergio Carvalho <sergio.carvalho@portugalmail.com>                  |
29
* +-----------------------------------------------------------------------------+
30
*
31
* @category   XML
32
* @package    XML_RPC2
33
* @author     Sergio Carvalho <sergio.carvalho@portugalmail.com>
34
* @copyright  2004-2005 Sergio Carvalho
35
* @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
36
* @version    CVS: $Id: Value.php 308633 2011-02-24 18:54:23Z sergiosgc $
37
* @link       http://pear.php.net/package/XML_RPC2
38
*/
39
 
40
// }}}
41
 
42
// dependencies {{{
43
require_once 'XML/RPC2/Exception.php';
44
require_once 'XML/RPC2/Value.php';
45
// }}}
46
 
47
/**
48
 * XML_RPC value abstract class. All XML_RPC value classes inherit from XML_RPC2_Value
49
 *
50
 * @category   XML
51
 * @package    XML_RPC2
52
 * @author     Sergio Carvalho <sergio.carvalho@portugalmail.com>
53
 * @copyright  2004-2005 Sergio Carvalho
54
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
55
 * @link       http://pear.php.net/package/XML_RPC2
56
 */
57
abstract class XML_RPC2_Backend_Php_Value extends XML_RPC2_Value
58
{
59
    // {{{ properties
60
 
61
    /**
62
     * native value
63
     *
64
     * @var mixed
65
     */
66
    private $_nativeValue = null;
67
 
68
    // }}}
69
    // {{{ getNativeValue()
70
 
71
    /**
72
     * nativeValue property getter
73
     *
74
     * @return mixed The current nativeValue
75
     */
76
    public function getNativeValue()
77
    {
78
        return $this->_nativeValue;
79
    }
80
 
81
    // }}}
82
    // {{{ setNativeValue()
83
 
84
    /**
85
     * nativeValue setter
86
     *
87
     * @param mixed $value
88
     */
89
    protected function setNativeValue($value)
90
    {
91
        $this->_nativeValue = $value;
92
    }
93
 
94
    // }}}
95
    // {{{ createFromNative()
96
 
97
    /**
98
     * Choose a XML_RPC2_Value subclass appropriate for the
99
     * given value and create it.
100
     *
101
     * This method tries to find the most adequate XML-RPC datatype to hold
102
     * a given PHP native type. Note that distinguishing some datatypes may be
103
     * difficult:
104
     *  - Timestamps are represented by PHP integers, so an XML_RPC2_Value_Datetime is never returned
105
     *  - Indexed arrays and associative arrays are the same native PHP type. In this case:
106
     *    a) The array's indexes start at 0 or 1 and increase monotonically with step 1, or
107
     *    b) they do not
108
     *    in the first case, an XML_RPC2_Value_Array is returned. In the second, a XML_RPC2_Value_Struct is returned.
109
     *  - PHP Objects are serialized and represented in an XML_RPC2_Value_Base64
110
     *  - Integers fitting in a 32bit integer are encoded as regular xml-rpc integers
111
     *  - Integers larger than 32bit are encoded using the i8 xml-rpc extension
112
     *
113
     * Whenever native object automatic detection proves inaccurate, use XML_RPC2_Value::createFromNative providing
114
     * a valid explicit type as second argument
115
     *
116
     * the appropriate XML_RPC2_Value child class instead.
117
     *
118
     * @param mixed The native value
119
     * @param string The xml-rpc target encoding type, as per the xmlrpc spec (optional)
120
     * @throws XML_RPC2_InvalidTypeEncodeException When the native value has a type that can't be translated to XML_RPC
121
     * @return A new XML_RPC2_Value instance
122
     * @see XML_RPC_Client::__call
123
     * @see XML_RPC_Server
124
     */
125
    public static function createFromNative($nativeValue, $explicitType = null)
126
    {
127
        if (is_null($explicitType)) {
128
            switch (gettype($nativeValue)) {
129
                case 'boolean':
130
                    $explicitType = 'boolean';
131
                    break;
132
                case 'integer':
133
                    $explicitType = 'int';
134
                    break;
135
                case 'double':
136
                    $explicitType = 'double';
137
                    break;
138
                case 'string':
139
                    $explicitType = 'string';
140
                    break;
141
                case 'array':
142
                    $explicitType = 'array';
143
                    $keys = array_keys($nativeValue);
144
                    if (count($keys) > 0) {
145
                        if ($keys[0] !== 0 && ($keys[0] !== 1)) $explicitType = 'struct';
146
                        $i=0;
147
                        do {
148
                            $previous = $keys[$i];
149
                            $i++;
150
                            if (array_key_exists($i, $keys) && ($keys[$i] !== $keys[$i - 1] + 1)) $explicitType = 'struct';
151
                        } while (array_key_exists($i, $keys) && $explicitType == 'array');
152
                    }
153
                    break;
154
                case 'object':
155
                    if ((strtolower(get_class($nativeValue)) == 'stdclass') && (isset($nativeValue->xmlrpc_type))) {
156
                        // In this case, we have a "stdclass native value" (emulate xmlrpcext)
157
                        // the type 'base64' or 'datetime' is given by xmlrpc_type public property
158
                        $explicitType = $nativeValue->xmlrpc_type;
159
                    } else {
160
                        $nativeValue = serialize($nativeValue);
161
                        $explicitType = 'base64';
162
                    }
163
                    break;
164
                case 'resource':
165
                case 'NULL':
166
                case 'unknown type':
167
                    throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Impossible to encode value \'%s\' from type \'%s\'. No analogous type in XML_RPC.',
168
                        (string) $nativeValue,
169
                        gettype($nativeValue)));
170
                default:
171
                    throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Unexpected PHP native type returned by gettype: \'%s\', for value \'%s\'',
172
                        gettype($nativeValue),
173
                        (string) $nativeValue));
174
            }
175
        }
176
        $explicitType = ucfirst(strtolower($explicitType));
177
        switch ($explicitType) {
178
            case 'I8':
179
                require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
180
                return XML_RPC2_Backend_Php_Value_Scalar::createFromNative($nativeValue, 'Integer64');
181
                break;
182
            case 'I4':
183
            case 'Int':
184
            case 'Boolean':
185
            case 'Double':
186
            case 'String':
187
            case 'Nil':
188
                require_once 'XML/RPC2/Backend/Php/Value/Scalar.php';
189
                return XML_RPC2_Backend_Php_Value_Scalar::createFromNative($nativeValue);
190
                break;
191
            case 'Datetime.iso8601':
192
            case 'Datetime':
193
                require_once 'XML/RPC2/Backend/Php/Value/Datetime.php';
194
                return new XML_RPC2_Backend_Php_Value_Datetime($nativeValue);
195
                break;
196
            case 'Base64':
197
                require_once 'XML/RPC2/Backend/Php/Value/Base64.php';
198
                return new XML_RPC2_Backend_Php_Value_Base64($nativeValue);
199
                break;
200
            case 'Array':
201
                require_once 'XML/RPC2/Backend/Php/Value/Array.php';
202
                return new XML_RPC2_Backend_Php_Value_Array($nativeValue);
203
                break;
204
            case 'Struct':
205
                require_once 'XML/RPC2/Backend/Php/Value/Struct.php';
206
                return new XML_RPC2_Backend_Php_Value_Struct($nativeValue);
207
                break;
208
            default:
209
                throw new XML_RPC2_InvalidTypeEncodeException(sprintf('Unexpected explicit encoding type \'%s\'', $explicitType));
210
        }
211
    }
212
 
213
    // }}}
214
    // {{{ createFromDecode()
215
 
216
    /**
217
     * Decode an encoded value and build the applicable XML_RPC2_Value subclass
218
     *
219
     * @param SimpleXMLElement The encoded XML-RPC value
220
     * @return mixed the corresponding XML_RPC2_Value object
221
     */
222
    public static function createFromDecode($simpleXML)
223
    {
224
        // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
225
        // xpath is used both in an element and in one of its children
226
        $simpleXML = simplexml_load_string($simpleXML->asXML());
227
 
228
        $valueType = $simpleXML->xpath('./*');
229
        if (count($valueType) == 1) { // Usually we must check the node name
230
            $nodename = dom_import_simplexml($valueType[0])->nodeName;
231
            switch ($nodename) {
232
                case 'i8':
233
                    $nativeType = 'Integer64';
234
                    break;
235
                case 'i4':
236
                case 'int':
237
                    $nativeType = 'Integer';
238
                    break;
239
                case 'boolean':
240
                    $nativeType = 'Boolean';
241
                    break;
242
                case 'double':
243
                    $nativeType = 'Double';
244
                    break;
245
                case 'string':
246
                    $nativeType = 'String';
247
                    break;
248
                case 'dateTime.iso8601':
249
                    $nativeType = 'Datetime';
250
                    break;
251
                case 'base64':
252
                    $nativeType = 'Base64';
253
                    break;
254
                case 'array':
255
                    $nativeType = 'Array';
256
                    break;
257
                case 'struct':
258
                    $nativeType = 'Struct';
259
                    break;
260
                case 'nil':
261
                    $nativeType = 'Nil';
262
                    break;
263
                default:
264
                    throw new XML_RPC2_DecodeException(sprintf('Unable to decode XML-RPC value. Value type is not recognized \'%s\'', $nodename));
265
            }
266
        } elseif (count($valueType) == 0) { // Default type is string
267
            $nodename = null;
268
            $nativeType = 'String';
269
        } else {
270
            throw new XML_RPC2_DecodeException(sprintf('Unable to decode XML-RPC value. Value presented %s type nodes: %s.', count($valueType), $simpleXML->asXML()));
271
        }
272
        require_once(sprintf('XML/RPC2/Backend/Php/Value/%s.php', $nativeType));
273
        $nativeType = 'XML_RPC2_Backend_Php_Value_' . $nativeType;
274
        return self::createFromNative(@call_user_func(array($nativeType, 'decode'), $simpleXML), $nodename);
275
    }
276
 
277
    // }}}
278
    // {{{ encode()
279
 
280
    /**
281
     * Encode the instance into XML, for transport
282
     *
283
     * @return string The encoded XML-RPC value,
284
     */
285
     // Declaration commented because of: http://pear.php.net/bugs/bug.php?id=8499
286
//    public abstract function encode();
287
 
288
    // }}}
289
    // {{{ decode()
290
 
291
    /**
292
     * decode. Decode transport XML and set the instance value accordingly
293
     *
294
     * @param mixed The encoded XML-RPC value,
295
     */
296
     // Declaration commented because of: http://pear.php.net/bugs/bug.php?id=8499
297
//    public static abstract function decode($xml);
298
 
299
    // }}}
300
}
301
 
302
?>