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-2006 Sergio Carvalho
35
* @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
36
* @version    CVS: $Id: Datetime.php 308613 2011-02-23 19:16:47Z 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/Backend/Php/Value/Scalar.php';
45
// }}}
46
 
47
/**
48
 * XML_RPC datetime value class. Instances of this class represent datetime scalars in XML_RPC
49
 *
50
 * To work on a compatible way with the xmlrpcext backend, we introduce a particular "nativeValue" which is
51
 * a standard class (stdclass) with three public properties :
52
 * scalar => the iso8601 date string
53
 * timestamp => the corresponding timestamp (int)
54
 * xmlrpc_type => 'datetime'
55
 *
56
 * The constructor can be called with a iso8601 string, with a timestamp or with a such object
57
 *
58
 * @category   XML
59
 * @package    XML_RPC2
60
 * @author     Sergio Carvalho <sergio.carvalho@portugalmail.com>
61
 * @copyright  2004-2006 Sergio Carvalho
62
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
63
 * @link       http://pear.php.net/package/XML_RPC2
64
 */
65
class XML_RPC2_Backend_Php_Value_Datetime extends XML_RPC2_Backend_Php_Value
66
{
67
 
68
    // {{{ constructor
69
 
70
    /**
71
     * Constructor. Will build a new XML_RPC2_Backend_Php_Value_Datetime with the given value
72
     *
73
     * The provided value can be an int, which will be interpreted as a Unix timestamp, or
74
     * a string in iso8601 format, or a "stdclass native value"
75
     *
76
     * @param mixed $nativeValue a timestamp, an iso8601 date or a "stdclass native value"
77
     * @see http://www.w3.org/TR/NOTE-datetime
78
     */
79
    public function __construct($nativeValue)
80
    {
81
        if ((!is_int($nativeValue)) and (!is_float($nativeValue)) and (!is_string($nativeValue)) and (!is_object($nativeValue))) {
82
            throw new XML_RPC2_InvalidTypeException(sprintf('Cannot create XML_RPC2_Backend_Php_Value_Datetime from type \'%s\'.', gettype($nativeValue)));
83
        }
84
        if ((is_object($nativeValue)) &&(strtolower(get_class($nativeValue)) == 'stdclass') && (isset($nativeValue->xmlrpc_type))) {
85
            $scalar = $nativeValue->scalar;
86
            $timestamp = $nativeValue->timestamp;
87
        } else {
88
            if ((is_int($nativeValue)) or (is_float($nativeValue))) {
89
                $scalar = XML_RPC2_Backend_Php_Value_Datetime::_timestampToIso8601($nativeValue);
90
                $timestamp = (int) $nativeValue;
91
            } elseif (is_string($nativeValue)) {
92
                $scalar= $nativeValue;
93
                $timestamp = (int) XML_RPC2_Backend_Php_Value_Datetime::_iso8601ToTimestamp($nativeValue);
94
            } else {
95
                throw new XML_RPC2_InvalidTypeException(sprintf('Cannot create XML_RPC2_Backend_Php_Value_Datetime from type \'%s\'.', gettype($nativeValue)));
96
            }
97
        }
98
        $tmp              = new stdclass();
99
        $tmp->scalar      = $scalar;
100
        $tmp->timestamp   = $timestamp;
101
        $tmp->xmlrpc_type = 'datetime';
102
        $this->setNativeValue($tmp);
103
    }
104
 
105
    // }}}
106
    // {{{ _iso8601ToTimestamp()
107
 
108
    /**
109
     * Convert a iso8601 datetime string into timestamp
110
     *
111
     * @param string $datetime iso8601 datetime
112
     * @return int corresponding timestamp
113
     */
114
    private static function _iso8601ToTimestamp($datetime)
115
    {
116
        if (!preg_match('/([0-9]{4})(-?([0-9]{2})(-?([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?/', $datetime, $matches)) {
117
            throw new XML_RPC2_InvalidDateFormatException(sprintf('Provided date \'%s\' is not ISO-8601.', $datetime));
118
        }
119
        $year           = $matches[1];
120
        $month          = array_key_exists(3, $matches) ? $matches[3] : 1;
121
        $day            = array_key_exists(5, $matches) ? $matches[5] : 1;
122
        $hour           = array_key_exists(7, $matches) ? $matches[7] : 0;
123
        $minutes        = array_key_exists(8, $matches) ? $matches[8] : 0;
124
        $seconds        = array_key_exists(10, $matches) ? $matches[10] : 0;
125
        $milliseconds   = array_key_exists(12, $matches) ? ((double) ('0.' . $matches[12])) : 0;
126
        if (array_key_exists(13, $matches)) {
127
            if ($matches[13] == 'Z') {
128
                $tzSeconds = 0;
129
            } else {
130
                $tmp = ($matches[15] == '-') ? -1 : 1;
131
                $tzSeconds = $tmp * (((int) $matches[16]) * 3600 + ((int) $matches[17]) * 60);
132
            }
133
        } else {
134
            $tzSeconds = 0;
135
        }
136
        if (class_exists('DateTime')) {
137
            $result = new DateTime();
138
            $result->setDate($year, $month, $day);
139
            $result->setTime($hour, $minutes, $seconds);
140
            $result = $result->getTimestamp();
141
            if ($milliseconds==0) return $result;
142
            return ((float) $result) + $milliseconds/1000;
143
        } else {
144
            $result = ((double) @mktime($hour, $minutes, $seconds, $month, $day, $year, 0)) +
145
                      ((double) $milliseconds) -
146
                      ((double) $tzSeconds);
147
            if ($milliseconds==0) return ((int) $result);
148
            return $result;
149
        }
150
    }
151
 
152
    // }}}
153
    // {{{ _timestampToIso8601()
154
 
155
    /**
156
     * Convert a timestamp into an iso8601 datetime
157
     *
158
     * @param int $timestamp timestamp
159
     * @return string iso8601 datetim
160
     */
161
    private static function _timestampToIso8601($timestamp)
162
    {
163
        return strftime('%Y%m%dT%H:%M:%S', (int) $timestamp);
164
    }
165
 
166
    // }}}
167
    // {{{ decode()
168
 
169
    /**
170
     * Decode transport XML and set the instance value accordingly
171
     *
172
     * @param mixed The encoded XML-RPC value,
173
     */
174
    public static function decode($xml)
175
    {
176
        // TODO Remove reparsing of XML fragment, when SimpleXML proves more solid. Currently it segfaults when
177
        // xpath is used both in an element and in one of its children
178
        $xml = simplexml_load_string($xml->asXML());
179
        $value = $xml->xpath('/value/dateTime.iso8601/text()');
180
        if (!array_key_exists(0, $value)) {
181
            $value = $xml->xpath('/value/text()');
182
        }
183
        // Emulate xmlrpcext results (to be able to switch from a backend to another)
184
        $result              = new stdclass();
185
        $result->scalar      = (string) $value[0];
186
        $result->timestamp   = (int) XML_RPC2_Backend_Php_Value_Datetime::_iso8601ToTimestamp((string) $value[0]);
187
        $result->xmlrpc_type = 'datetime';
188
        return $result;
189
    }
190
 
191
    // }}}
192
    // {{{ encode()
193
 
194
    /**
195
     * Encode the instance into XML, for transport
196
     *
197
     * @return string The encoded XML-RPC value,
198
     */
199
    public function encode()
200
    {
201
        $native = $this->getNativeValue();
202
        return '<dateTime.iso8601>' . $native->scalar . '</dateTime.iso8601>';
203
    }
204
 
205
    // }}}
206
 
207
}
208
 
209
?>