|
1
|
|
|
<?php namespace Comodojo\Xmlrpc; |
|
2
|
|
|
|
|
3
|
|
|
use \Comodojo\Exception\XmlrpcException; |
|
4
|
|
|
use \XMLWriter; |
|
5
|
|
|
use \Exception; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* XML-RPC encoder |
|
9
|
|
|
* |
|
10
|
|
|
* Main features: |
|
11
|
|
|
* - support for <nil /> and <ex:nil /> |
|
12
|
|
|
* - implements true, XML compliant, HTML numeric entities conversion |
|
13
|
|
|
* - support for CDATA values |
|
14
|
|
|
* |
|
15
|
|
|
* @package Comodojo Spare Parts |
|
16
|
|
|
* @author Marco Giovinazzi <[email protected]> |
|
17
|
|
|
* @license MIT |
|
18
|
|
|
* |
|
19
|
|
|
* LICENSE: |
|
20
|
|
|
* |
|
21
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
22
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
23
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
24
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
25
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
26
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
27
|
|
|
* THE SOFTWARE. |
|
28
|
|
|
*/ |
|
29
|
|
|
|
|
30
|
|
|
class XmlrpcEncoder { |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* Request/Response encoding |
|
34
|
|
|
* |
|
35
|
|
|
* @var string |
|
36
|
|
|
*/ |
|
37
|
|
|
private $encoding; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* References of special values (base64, datetime, cdata) |
|
41
|
|
|
* |
|
42
|
|
|
* @var array |
|
43
|
|
|
*/ |
|
44
|
|
|
private $special_types = array(); |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* ex:nil switch (for apache rpc compatibility) |
|
48
|
|
|
* |
|
49
|
|
|
* @var bool |
|
50
|
|
|
*/ |
|
51
|
|
|
private $use_ex_nil = false; |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Constructor method |
|
55
|
|
|
*/ |
|
56
|
27 |
|
final public function __construct() { |
|
57
|
|
|
|
|
58
|
27 |
|
$this->encoding = defined("XMLRPC_DEFAULT_ENCODING") ? strtolower(XMLRPC_DEFAULT_ENCODING) : 'utf-8'; |
|
59
|
|
|
|
|
60
|
27 |
|
} |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* Set encoding |
|
64
|
|
|
* |
|
65
|
|
|
* @param string $encoding |
|
66
|
|
|
* |
|
67
|
|
|
* @return \Comodojo\Xmlrpc\XmlrpcEncoder |
|
68
|
|
|
*/ |
|
69
|
|
|
final public function setEncoding($encoding) { |
|
70
|
|
|
|
|
71
|
|
|
$this->encoding = $encoding; |
|
72
|
|
|
|
|
73
|
|
|
return $this; |
|
74
|
|
|
|
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* Get encoding |
|
79
|
|
|
* |
|
80
|
|
|
* @return string |
|
81
|
|
|
*/ |
|
82
|
|
|
final public function getEncoding() { |
|
83
|
|
|
|
|
84
|
|
|
return $this->encoding; |
|
85
|
|
|
|
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* Handle base64 and datetime values |
|
90
|
|
|
* |
|
91
|
|
|
* @param mixed $value The referenced value |
|
92
|
|
|
* @param string $type The type of value |
|
93
|
|
|
* |
|
94
|
|
|
* @return \Comodojo\Xmlrpc\XmlrpcEncoder |
|
95
|
|
|
*/ |
|
96
|
6 |
|
final public function setValueType(&$value, $type) { |
|
97
|
|
|
|
|
98
|
6 |
|
if ( empty($value) || !in_array(strtolower($type), array("base64", "datetime", "cdata")) ) throw new XmlrpcException("Invalid value type"); |
|
99
|
|
|
|
|
100
|
6 |
|
$this->special_types[$value] = strtolower($type); |
|
101
|
|
|
|
|
102
|
6 |
|
return $this; |
|
103
|
|
|
|
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* Use <ex:nil /> instead of <nil /> (apache xmlrpc compliant) |
|
108
|
|
|
* |
|
109
|
|
|
* @param bool $mode |
|
110
|
|
|
* |
|
111
|
|
|
* @return \Comodojo\Xmlrpc\XmlrpcEncoder |
|
112
|
|
|
*/ |
|
113
|
3 |
|
final public function useExNil($mode = true) { |
|
114
|
|
|
|
|
115
|
3 |
|
$this->use_ex_nil = filter_var($mode, FILTER_VALIDATE_BOOLEAN); |
|
116
|
|
|
|
|
117
|
3 |
|
return $this; |
|
118
|
|
|
|
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* Encode an xmlrpc response |
|
123
|
|
|
* |
|
124
|
|
|
* It expects a scalar, array or NULL as $data and will try to encode it as a valid xmlrpc response. |
|
125
|
|
|
* |
|
126
|
|
|
* @param mixed $data |
|
127
|
|
|
* |
|
128
|
|
|
* @return string xmlrpc formatted response |
|
129
|
|
|
* |
|
130
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
131
|
|
|
* @throws \Exception |
|
132
|
|
|
*/ |
|
133
|
6 |
|
public function encodeResponse($data) { |
|
134
|
|
|
|
|
135
|
6 |
|
$xml = new XMLWriter(); |
|
136
|
|
|
|
|
137
|
6 |
|
$xml->openMemory(); |
|
138
|
|
|
|
|
139
|
6 |
|
$xml->setIndent(false); |
|
140
|
|
|
|
|
141
|
6 |
|
$xml->startDocument('1.0', $this->encoding); |
|
142
|
|
|
|
|
143
|
6 |
|
$xml->startElement("methodResponse"); |
|
144
|
|
|
|
|
145
|
6 |
|
$xml->startElement("params"); |
|
146
|
|
|
|
|
147
|
6 |
|
$xml->startElement("param"); |
|
148
|
|
|
|
|
149
|
6 |
|
$xml->startElement("value"); |
|
150
|
|
|
|
|
151
|
|
|
try { |
|
152
|
|
|
|
|
153
|
6 |
|
$this->encodeValue($xml, $data); |
|
154
|
|
|
|
|
155
|
2 |
|
} catch (XmlrpcException $xe) { |
|
156
|
|
|
|
|
157
|
|
|
throw $xe; |
|
158
|
|
|
|
|
159
|
|
|
} catch (Exception $e) { |
|
160
|
|
|
|
|
161
|
|
|
throw $e; |
|
162
|
|
|
|
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
6 |
|
$xml->endElement(); |
|
166
|
|
|
|
|
167
|
6 |
|
$xml->endElement(); |
|
168
|
|
|
|
|
169
|
6 |
|
$xml->endElement(); |
|
170
|
|
|
|
|
171
|
6 |
|
$xml->endElement(); |
|
172
|
|
|
|
|
173
|
6 |
|
$xml->endDocument(); |
|
174
|
|
|
|
|
175
|
6 |
|
return trim($xml->outputMemory()); |
|
176
|
|
|
|
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Encode an xmlrpc call |
|
181
|
|
|
* |
|
182
|
|
|
* It expects an array of values as $data and will try to encode it as a valid xmlrpc call. |
|
183
|
|
|
* |
|
184
|
|
|
* @param string $method |
|
185
|
|
|
* @param array $data |
|
186
|
|
|
* |
|
187
|
|
|
* @return string xmlrpc formatted call |
|
188
|
|
|
* |
|
189
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
190
|
|
|
* @throws \Exception |
|
191
|
|
|
*/ |
|
192
|
18 |
|
public function encodeCall($method, $data = array()) { |
|
193
|
|
|
|
|
194
|
18 |
|
$xml = new XMLWriter(); |
|
195
|
|
|
|
|
196
|
18 |
|
$xml->openMemory(); |
|
197
|
|
|
|
|
198
|
18 |
|
$xml->setIndent(false); |
|
199
|
|
|
|
|
200
|
18 |
|
$xml->startDocument('1.0', $this->encoding); |
|
201
|
|
|
|
|
202
|
18 |
|
$xml->startElement("methodCall"); |
|
203
|
|
|
|
|
204
|
18 |
|
$xml->writeElement("methodName", trim($method)); |
|
205
|
|
|
|
|
206
|
18 |
|
$xml->startElement("params"); |
|
207
|
|
|
|
|
208
|
|
|
try { |
|
209
|
|
|
|
|
210
|
18 |
|
foreach ( $data as $d ) { |
|
211
|
|
|
|
|
212
|
15 |
|
$xml->startElement("param"); |
|
213
|
|
|
|
|
214
|
15 |
|
$xml->startElement("value"); |
|
215
|
|
|
|
|
216
|
15 |
|
$this->encodeValue($xml, $d); |
|
217
|
|
|
|
|
218
|
15 |
|
$xml->endElement(); |
|
219
|
|
|
|
|
220
|
17 |
|
$xml->endElement(); |
|
221
|
|
|
|
|
222
|
6 |
|
} |
|
223
|
|
|
|
|
224
|
6 |
|
} catch (XmlrpcException $xe) { |
|
225
|
|
|
|
|
226
|
|
|
throw $xe; |
|
227
|
|
|
|
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
18 |
|
$xml->endElement(); |
|
231
|
|
|
|
|
232
|
18 |
|
$xml->endElement(); |
|
233
|
|
|
|
|
234
|
18 |
|
$xml->endDocument(); |
|
235
|
|
|
|
|
236
|
18 |
|
return trim($xml->outputMemory()); |
|
237
|
|
|
|
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Encode an xmlrpc multicall |
|
242
|
|
|
* |
|
243
|
|
|
* It expects in input a key->val array where key |
|
244
|
|
|
* represent the method and val the parameters. |
|
245
|
|
|
* |
|
246
|
|
|
* @param array $data |
|
247
|
|
|
* |
|
248
|
|
|
* @return string xmlrpc formatted call |
|
249
|
|
|
* |
|
250
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
251
|
|
|
* @throws \Exception |
|
252
|
|
|
*/ |
|
253
|
6 |
|
public function encodeMulticall($data) { |
|
254
|
|
|
|
|
255
|
6 |
|
$packed_requests = array(); |
|
256
|
|
|
|
|
257
|
6 |
|
foreach ( $data as $methodName => $params ) { |
|
258
|
|
|
|
|
259
|
6 |
|
if ( is_int($methodName) && count($params) == 2 ) { |
|
260
|
|
|
|
|
261
|
3 |
|
array_push($packed_requests, array( |
|
262
|
3 |
|
"methodName" => $params[0], |
|
263
|
3 |
|
"params" => $params[1] |
|
264
|
1 |
|
)); |
|
265
|
|
|
|
|
266
|
1 |
|
} else { |
|
267
|
|
|
|
|
268
|
3 |
|
array_push($packed_requests, array( |
|
269
|
3 |
|
"methodName" => $methodName, |
|
270
|
4 |
|
"params" => $params |
|
271
|
1 |
|
)); |
|
272
|
|
|
|
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
2 |
|
} |
|
276
|
|
|
|
|
277
|
6 |
|
return $this->encodeCall("system.multicall", array($packed_requests)); |
|
278
|
|
|
|
|
279
|
|
|
} |
|
280
|
|
|
|
|
281
|
|
|
/** |
|
282
|
|
|
* Encode an xmlrpc error |
|
283
|
|
|
* |
|
284
|
|
|
* @param int $error_code |
|
285
|
|
|
* @param string $error_message |
|
286
|
|
|
* |
|
287
|
|
|
* @return string xmlrpc formatted error |
|
288
|
|
|
*/ |
|
289
|
3 |
|
public function encodeError($error_code, $error_message) { |
|
290
|
|
|
|
|
291
|
3 |
|
$payload = '<?xml version="1.0" encoding="'.$this->encoding.'"?>'; |
|
292
|
3 |
|
$payload .= "<methodResponse>"; |
|
293
|
3 |
|
$payload .= $this->encodeFault($error_code, $error_message); |
|
294
|
3 |
|
$payload .= "</methodResponse>"; |
|
295
|
|
|
|
|
296
|
3 |
|
return $payload; |
|
297
|
|
|
|
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
/** |
|
301
|
|
|
* Encode an xmlrpc fault (without full xml document body) |
|
302
|
|
|
* |
|
303
|
|
|
* @param int $error_code |
|
304
|
|
|
* @param string $error_message |
|
305
|
|
|
* |
|
306
|
|
|
* @return string xmlrpc formatted error |
|
307
|
|
|
*/ |
|
308
|
3 |
|
private function encodeFault($error_code, $error_message) { |
|
309
|
|
|
|
|
310
|
3 |
|
$value = htmlentities($error_message, ENT_QUOTES, $this->encoding, false); |
|
311
|
|
|
|
|
312
|
3 |
|
$string = preg_replace_callback('/&([a-zA-Z][a-zA-Z0-9]+);/S', 'self::numericEntities', $value); |
|
313
|
|
|
|
|
314
|
3 |
|
$payload = "<fault>"; |
|
315
|
3 |
|
$payload .= "<value>"; |
|
316
|
3 |
|
$payload .= "<struct>"; |
|
317
|
3 |
|
$payload .= "<member>"; |
|
318
|
3 |
|
$payload .= "<name>faultCode</name>"; |
|
319
|
3 |
|
$payload .= "<value><int>".$error_code."</int></value>"; |
|
320
|
3 |
|
$payload .= "</member>"; |
|
321
|
3 |
|
$payload .= "<member>"; |
|
322
|
3 |
|
$payload .= "<name>faultString</name>"; |
|
323
|
3 |
|
$payload .= "<value><string>".$string."</string></value>"; |
|
324
|
3 |
|
$payload .= "</member>"; |
|
325
|
3 |
|
$payload .= "</struct>"; |
|
326
|
3 |
|
$payload .= "</value>"; |
|
327
|
3 |
|
$payload .= "</fault>"; |
|
328
|
|
|
|
|
329
|
3 |
|
return $payload; |
|
330
|
|
|
|
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
/** |
|
334
|
|
|
* Encode a value using XMLWriter object $xml |
|
335
|
|
|
* |
|
336
|
|
|
* @param XMLWriter $xml |
|
337
|
|
|
* @param mixed $value |
|
338
|
|
|
* |
|
339
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
340
|
|
|
*/ |
|
341
|
21 |
|
private function encodeValue(XMLWriter $xml, $value) { |
|
342
|
|
|
|
|
343
|
21 |
|
if ( $value === null ) $xml->writeRaw($this->use_ex_nil === true ? '<ex:nil />' : '<nil />'); |
|
344
|
|
|
|
|
345
|
21 |
|
else if ( is_array($value) ) { |
|
346
|
|
|
|
|
347
|
12 |
|
if ( !self::catchStruct($value) ) $this->encodeArray($xml, $value); |
|
348
|
|
|
|
|
349
|
11 |
|
else $this->encodeStruct($xml, $value); |
|
350
|
|
|
|
|
351
|
21 |
|
} else if ( @array_key_exists($value, $this->special_types) ) { |
|
352
|
|
|
|
|
353
|
6 |
|
switch ( $this->special_types[$value] ) { |
|
354
|
|
|
|
|
355
|
6 |
|
case 'base64': |
|
|
|
|
|
|
356
|
|
|
|
|
357
|
3 |
|
$xml->writeElement("base64", $value); |
|
358
|
|
|
|
|
359
|
3 |
|
break; |
|
360
|
|
|
|
|
361
|
3 |
|
case 'datetime': |
|
|
|
|
|
|
362
|
|
|
|
|
363
|
|
|
$xml->writeElement("dateTime.iso8601", self::timestampToIso8601Time($value)); |
|
364
|
|
|
|
|
365
|
|
|
break; |
|
366
|
|
|
|
|
367
|
3 |
|
case 'cdata': |
|
|
|
|
|
|
368
|
|
|
|
|
369
|
3 |
|
$xml->writeCData($value); |
|
370
|
|
|
|
|
371
|
5 |
|
break; |
|
372
|
|
|
|
|
373
|
2 |
|
} |
|
374
|
|
|
|
|
375
|
21 |
|
} else if ( is_bool($value) ) { |
|
376
|
|
|
|
|
377
|
3 |
|
$xml->writeElement("boolean", $value ? 1 : 0); |
|
378
|
|
|
|
|
379
|
21 |
|
} else if ( is_double($value) ) { |
|
380
|
|
|
|
|
381
|
|
|
$xml->writeElement("double", $value); |
|
382
|
|
|
|
|
383
|
21 |
|
} else if ( is_integer($value) ) { |
|
384
|
|
|
|
|
385
|
3 |
|
$xml->writeElement("int", $value); |
|
386
|
|
|
|
|
387
|
21 |
|
} else if ( is_object($value) ) { |
|
388
|
|
|
|
|
389
|
|
|
$this->encodeObject($xml, $value); |
|
390
|
|
|
|
|
391
|
21 |
|
} else if ( is_string($value) ) { |
|
392
|
|
|
|
|
393
|
21 |
|
$value = htmlentities($value, ENT_QUOTES, $this->encoding, false); |
|
394
|
|
|
|
|
395
|
21 |
|
$string = preg_replace_callback('/&([a-zA-Z][a-zA-Z0-9]+);/S', 'self::numericEntities', $value); |
|
396
|
|
|
|
|
397
|
21 |
|
$xml->writeRaw("<string>".$string."</string>"); |
|
398
|
|
|
|
|
399
|
7 |
|
} else throw new XmlrpcException("Unknown type for encoding"); |
|
400
|
|
|
|
|
401
|
21 |
|
} |
|
402
|
|
|
|
|
403
|
|
|
/** |
|
404
|
|
|
* Encode an array using XMLWriter object $xml |
|
405
|
|
|
* |
|
406
|
|
|
* @param XMLWriter $xml |
|
407
|
|
|
* @param mixed $value |
|
408
|
|
|
*/ |
|
409
|
12 |
|
private function encodeArray(XMLWriter $xml, $value) { |
|
410
|
|
|
|
|
411
|
12 |
|
$xml->startElement("array"); |
|
412
|
|
|
|
|
413
|
12 |
|
$xml->startElement("data"); |
|
414
|
|
|
|
|
415
|
12 |
|
foreach ( $value as $entry ) { |
|
416
|
|
|
|
|
417
|
12 |
|
$xml->startElement("value"); |
|
418
|
|
|
|
|
419
|
12 |
|
$this->encodeValue($xml, $entry); |
|
420
|
|
|
|
|
421
|
12 |
|
$xml->endElement(); |
|
422
|
|
|
|
|
423
|
4 |
|
} |
|
424
|
|
|
|
|
425
|
12 |
|
$xml->endElement(); |
|
426
|
|
|
|
|
427
|
12 |
|
$xml->endElement(); |
|
428
|
|
|
|
|
429
|
12 |
|
} |
|
430
|
|
|
|
|
431
|
|
|
/** |
|
432
|
|
|
* Encode an object using XMLWriter object $xml |
|
433
|
|
|
* |
|
434
|
|
|
* @param XMLWriter $xml |
|
435
|
|
|
* @param mixed $value |
|
436
|
|
|
* |
|
437
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
438
|
|
|
*/ |
|
439
|
|
|
private function encodeObject(XMLWriter $xml, $value) { |
|
440
|
|
|
|
|
441
|
|
|
if ( $value instanceof \DateTime ) $xml->writeElement("dateTime.iso8601", self::timestampToIso8601Time($value->format('U'))); |
|
442
|
|
|
|
|
443
|
|
|
else throw new XmlrpcException("Unknown type for encoding"); |
|
444
|
|
|
|
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
|
/** |
|
448
|
|
|
* Encode a struct using XMLWriter object $xml |
|
449
|
|
|
* |
|
450
|
|
|
* @param XMLWriter $xml |
|
451
|
|
|
* @param mixed $value |
|
452
|
|
|
* |
|
453
|
|
|
* @throws \Comodojo\Exception\XmlrpcException |
|
454
|
|
|
*/ |
|
455
|
9 |
|
private function encodeStruct(XMLWriter $xml, $value) { |
|
456
|
|
|
|
|
457
|
9 |
|
$xml->startElement("struct"); |
|
458
|
|
|
|
|
459
|
9 |
|
foreach ( $value as $k => $v ) { |
|
460
|
|
|
|
|
461
|
9 |
|
$xml->startElement("member"); |
|
462
|
|
|
|
|
463
|
9 |
|
$xml->writeElement("name", $k); |
|
464
|
|
|
|
|
465
|
9 |
|
$xml->startElement("value"); |
|
466
|
|
|
|
|
467
|
9 |
|
$this->encodeValue($xml, $v); |
|
468
|
|
|
|
|
469
|
9 |
|
$xml->endElement(); |
|
470
|
|
|
|
|
471
|
9 |
|
$xml->endElement(); |
|
472
|
|
|
|
|
473
|
3 |
|
} |
|
474
|
|
|
|
|
475
|
9 |
|
$xml->endElement(); |
|
476
|
|
|
|
|
477
|
9 |
|
} |
|
478
|
|
|
|
|
479
|
|
|
/** |
|
480
|
|
|
* Return true if $value is a struct, false otherwise |
|
481
|
|
|
* |
|
482
|
|
|
* @param mixed $value |
|
483
|
|
|
* |
|
484
|
|
|
* @return bool |
|
485
|
|
|
*/ |
|
486
|
12 |
|
private static function catchStruct($value) { |
|
487
|
|
|
|
|
488
|
12 |
|
$values = count($value); |
|
489
|
|
|
|
|
490
|
12 |
|
for ( $i = 0; $i < $values; $i++ ) if ( !array_key_exists($i, $value) ) return true; |
|
491
|
|
|
|
|
492
|
12 |
|
return false; |
|
493
|
|
|
|
|
494
|
|
|
} |
|
495
|
|
|
|
|
496
|
|
|
/** |
|
497
|
|
|
* Convert timestamp to Iso8601 |
|
498
|
|
|
* |
|
499
|
|
|
* @param int $timestamp |
|
500
|
|
|
* |
|
501
|
|
|
* @return string Iso8601 formatted date |
|
502
|
|
|
*/ |
|
503
|
|
|
private static function timestampToIso8601Time($timestamp) { |
|
504
|
|
|
|
|
505
|
|
|
return date("Ymd\TH:i:s", $timestamp); |
|
506
|
|
|
|
|
507
|
|
|
} |
|
508
|
|
|
|
|
509
|
|
|
/** |
|
510
|
|
|
* Recode named entities into numeric ones |
|
511
|
|
|
* |
|
512
|
|
|
* @param mixed $matches |
|
513
|
|
|
* |
|
514
|
|
|
* @return string Iso8601 formatted date |
|
515
|
|
|
*/ |
|
516
|
|
|
private static function numericEntities($matches) { |
|
|
|
|
|
|
517
|
|
|
|
|
518
|
|
|
static $table = array( |
|
519
|
|
|
'quot' => '"', 'amp' => '&', 'lt' => '<', 'gt' => '>', 'OElig' => 'Œ', 'oelig' => 'œ', |
|
520
|
|
|
'Scaron' => 'Š', 'scaron' => 'š', 'Yuml' => 'Ÿ', 'circ' => 'ˆ', 'tilde' => '˜', 'ensp' => ' ', |
|
521
|
|
|
'emsp' => ' ', 'thinsp' => ' ', 'zwnj' => '‌', 'zwj' => '‍', 'lrm' => '‎', 'rlm' => '‏', |
|
522
|
|
|
'ndash' => '–', 'mdash' => '—', 'lsquo' => '‘', 'rsquo' => '’', 'sbquo' => '‚', 'ldquo' => '“', |
|
523
|
|
|
'rdquo' => '”', 'bdquo' => '„', 'dagger' => '†', 'Dagger' => '‡', 'permil' => '‰', 'lsaquo' => '‹', |
|
524
|
|
|
'rsaquo' => '›', 'euro' => '€', 'fnof' => 'ƒ', 'Alpha' => 'Α', 'Beta' => 'Β', 'Gamma' => 'Γ', |
|
525
|
|
|
'Delta' => 'Δ', 'Epsilon' => 'Ε', 'Zeta' => 'Ζ', 'Eta' => 'Η', 'Theta' => 'Θ', 'Iota' => 'Ι', |
|
526
|
|
|
'Kappa' => 'Κ', 'Lambda' => 'Λ', 'Mu' => 'Μ', 'Nu' => 'Ν', 'Xi' => 'Ξ', 'Omicron' => 'Ο', |
|
527
|
|
|
'Pi' => 'Π', 'Rho' => 'Ρ', 'Sigma' => 'Σ', 'Tau' => 'Τ', 'Upsilon' => 'Υ', 'Phi' => 'Φ', |
|
528
|
|
|
'Chi' => 'Χ', 'Psi' => 'Ψ', 'Omega' => 'Ω', 'alpha' => 'α', 'beta' => 'β', 'gamma' => 'γ', |
|
529
|
|
|
'delta' => 'δ', 'epsilon' => 'ε', 'zeta' => 'ζ', 'eta' => 'η', 'theta' => 'θ', 'iota' => 'ι', |
|
530
|
|
|
'kappa' => 'κ', 'lambda' => 'λ', 'mu' => 'μ', 'nu' => 'ν', 'xi' => 'ξ', 'omicron' => 'ο', |
|
531
|
|
|
'pi' => 'π', 'rho' => 'ρ', 'sigmaf' => 'ς', 'sigma' => 'σ', 'tau' => 'τ', 'upsilon' => 'υ', |
|
532
|
|
|
'phi' => 'φ', 'chi' => 'χ', 'psi' => 'ψ', 'omega' => 'ω', 'thetasym' => 'ϑ', 'upsih' => 'ϒ', |
|
533
|
|
|
'piv' => 'ϖ', 'bull' => '•', 'hellip' => '…', 'prime' => '′', 'Prime' => '″', 'oline' => '‾', |
|
534
|
|
|
'frasl' => '⁄', 'weierp' => '℘', 'image' => 'ℑ', 'real' => 'ℜ', 'trade' => '™', 'alefsym' => 'ℵ', |
|
535
|
|
|
'larr' => '←', 'uarr' => '↑', 'rarr' => '→', 'darr' => '↓', 'harr' => '↔', 'crarr' => '↵', |
|
536
|
|
|
'lArr' => '⇐', 'uArr' => '⇑', 'rArr' => '⇒', 'dArr' => '⇓', 'hArr' => '⇔', 'forall' => '∀', |
|
537
|
|
|
'part' => '∂', 'exist' => '∃', 'empty' => '∅', 'nabla' => '∇', 'isin' => '∈', 'notin' => '∉', |
|
538
|
|
|
'ni' => '∋', 'prod' => '∏', 'sum' => '∑', 'minus' => '−', 'lowast' => '∗', 'radic' => '√', |
|
539
|
|
|
'prop' => '∝', 'infin' => '∞', 'ang' => '∠', 'and' => '∧', 'or' => '∨', 'cap' => '∩', |
|
540
|
|
|
'cup' => '∪', 'int' => '∫', 'there4' => '∴', 'sim' => '∼', 'cong' => '≅', 'asymp' => '≈', |
|
541
|
|
|
'ne' => '≠', 'equiv' => '≡', 'le' => '≤', 'ge' => '≥', 'sub' => '⊂', 'sup' => '⊃', |
|
542
|
|
|
'nsub' => '⊄', 'sube' => '⊆', 'supe' => '⊇', 'oplus' => '⊕', 'otimes' => '⊗', 'perp' => '⊥', |
|
543
|
|
|
'sdot' => '⋅', 'lceil' => '⌈', 'rceil' => '⌉', 'lfloor' => '⌊', 'rfloor' => '⌋', 'lang' => '〈', |
|
544
|
|
|
'rang' => '〉', 'loz' => '◊', 'spades' => '♠', 'clubs' => '♣', 'hearts' => '♥', 'diams' => '♦', |
|
545
|
|
|
'nbsp' => ' ', 'iexcl' => '¡', 'cent' => '¢', 'pound' => '£', 'curren' => '¤', 'yen' => '¥', |
|
546
|
|
|
'brvbar' => '¦', 'sect' => '§', 'uml' => '¨', 'copy' => '©', 'ordf' => 'ª', 'laquo' => '«', |
|
547
|
|
|
'not' => '¬', 'shy' => '­', 'reg' => '®', 'macr' => '¯', 'deg' => '°', 'plusmn' => '±', |
|
548
|
|
|
'sup2' => '²', 'sup3' => '³', 'acute' => '´', 'micro' => 'µ', 'para' => '¶', 'middot' => '·', |
|
549
|
|
|
'cedil' => '¸', 'sup1' => '¹', 'ordm' => 'º', 'raquo' => '»', 'frac14' => '¼', 'frac12' => '½', |
|
550
|
|
|
'frac34' => '¾', 'iquest' => '¿', 'Agrave' => 'À', 'Aacute' => 'Á', 'Acirc' => 'Â', 'Atilde' => 'Ã', |
|
551
|
|
|
'Auml' => 'Ä', 'Aring' => 'Å', 'AElig' => 'Æ', 'Ccedil' => 'Ç', 'Egrave' => 'È', 'Eacute' => 'É', |
|
552
|
|
|
'Ecirc' => 'Ê', 'Euml' => 'Ë', 'Igrave' => 'Ì', 'Iacute' => 'Í', 'Icirc' => 'Î', 'Iuml' => 'Ï', |
|
553
|
|
|
'ETH' => 'Ð', 'Ntilde' => 'Ñ', 'Ograve' => 'Ò', 'Oacute' => 'Ó', 'Ocirc' => 'Ô', 'Otilde' => 'Õ', |
|
554
|
|
|
'Ouml' => 'Ö', 'times' => '×', 'Oslash' => 'Ø', 'Ugrave' => 'Ù', 'Uacute' => 'Ú', 'Ucirc' => 'Û', |
|
555
|
|
|
'Uuml' => 'Ü', 'Yacute' => 'Ý', 'THORN' => 'Þ', 'szlig' => 'ß', 'agrave' => 'à', 'aacute' => 'á', |
|
556
|
|
|
'acirc' => 'â', 'atilde' => 'ã', 'auml' => 'ä', 'aring' => 'å', 'aelig' => 'æ', 'ccedil' => 'ç', |
|
557
|
|
|
'egrave' => 'è', 'eacute' => 'é', 'ecirc' => 'ê', 'euml' => 'ë', 'igrave' => 'ì', 'iacute' => 'í', |
|
558
|
|
|
'icirc' => 'î', 'iuml' => 'ï', 'eth' => 'ð', 'ntilde' => 'ñ', 'ograve' => 'ò', 'oacute' => 'ó', |
|
559
|
|
|
'ocirc' => 'ô', 'otilde' => 'õ', 'ouml' => 'ö', 'divide' => '÷', 'oslash' => 'ø', 'ugrave' => 'ù', |
|
560
|
|
|
'uacute' => 'ú', 'ucirc' => 'û', 'uuml' => 'ü', 'yacute' => 'ý', 'thorn' => 'þ', 'yuml' => 'ÿ' |
|
561
|
|
|
); |
|
562
|
|
|
|
|
563
|
|
|
// cleanup invalid entities |
|
564
|
|
|
return isset($table[$matches[1]]) ? $table[$matches[1]] : ''; |
|
565
|
|
|
|
|
566
|
|
|
} |
|
567
|
|
|
|
|
568
|
|
|
} |
|
569
|
|
|
|
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.