1
|
|
|
<?php |
2
|
|
|
namespace Braintree\Xml; |
3
|
|
|
|
4
|
|
|
use DateTime; |
5
|
|
|
use DateTimeZone; |
6
|
|
|
use XMLWriter; |
7
|
|
|
use Braintree\Util; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* PHP version 5 |
11
|
|
|
* |
12
|
|
|
* @copyright 2015 Braintree, a division of PayPal, Inc. |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Generates XML output from arrays using PHP's |
17
|
|
|
* built-in XMLWriter |
18
|
|
|
* |
19
|
|
|
* @copyright 2015 Braintree, a division of PayPal, Inc. |
20
|
|
|
*/ |
21
|
|
|
class Generator |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* arrays passed to this method should have a single root element |
25
|
|
|
* with an array as its value |
26
|
|
|
* @param array $aData the array of data |
27
|
|
|
* @return string XML string |
28
|
|
|
*/ |
29
|
|
|
public static function arrayToXml($aData) |
30
|
|
|
{ |
31
|
|
|
$aData = Util::camelCaseToDelimiterArray($aData, '-'); |
32
|
|
|
// set up the XMLWriter |
33
|
|
|
$writer = new XMLWriter(); |
34
|
|
|
$writer->openMemory(); |
35
|
|
|
|
36
|
|
|
$writer->setIndent(true); |
37
|
|
|
$writer->setIndentString(' '); |
38
|
|
|
$writer->startDocument('1.0', 'UTF-8'); |
39
|
|
|
|
40
|
|
|
// get the root element name |
41
|
|
|
$aKeys = array_keys($aData); |
42
|
|
|
$rootElementName = $aKeys[0]; |
43
|
|
|
// open the root element |
44
|
|
|
$writer->startElement($rootElementName); |
45
|
|
|
// create the body |
46
|
|
|
self::_createElementsFromArray($writer, $aData[$rootElementName], $rootElementName); |
|
|
|
|
47
|
|
|
|
48
|
|
|
// close the root element and document |
49
|
|
|
$writer->endElement(); |
50
|
|
|
$writer->endDocument(); |
51
|
|
|
|
52
|
|
|
// send the output as string |
53
|
|
|
return $writer->outputMemory(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Construct XML elements with attributes from an associative array. |
58
|
|
|
* |
59
|
|
|
* @access protected |
60
|
|
|
* @static |
61
|
|
|
* @param object $writer XMLWriter object |
62
|
|
|
* @param array $aData contains attributes and values |
63
|
|
|
* @return void |
64
|
|
|
*/ |
65
|
|
|
private static function _createElementsFromArray(&$writer, $aData) |
66
|
|
|
{ |
67
|
|
|
if (!is_array($aData)) { |
68
|
|
|
if (is_bool($aData)) { |
69
|
|
|
$writer->text($aData ? 'true' : 'false'); |
70
|
|
|
} else { |
71
|
|
|
$writer->text($aData); |
72
|
|
|
} |
73
|
|
|
return; |
74
|
|
|
} |
75
|
|
|
foreach ($aData AS $elementName => $element) { |
76
|
|
|
// handle child elements |
77
|
|
|
$writer->startElement($elementName); |
78
|
|
|
if (is_array($element)) { |
79
|
|
|
if (array_key_exists(0, $element) || empty($element)) { |
80
|
|
|
$writer->writeAttribute('type', 'array'); |
81
|
|
|
foreach ($element AS $ignored => $itemInArray) { |
82
|
|
|
$writer->startElement('item'); |
83
|
|
|
self::_createElementsFromArray($writer, $itemInArray); |
84
|
|
|
$writer->endElement(); |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
else { |
88
|
|
|
self::_createElementsFromArray($writer, $element); |
89
|
|
|
} |
90
|
|
|
} else { |
91
|
|
|
// generate attributes as needed |
92
|
|
|
$attribute = self::_generateXmlAttribute($element); |
93
|
|
|
if (is_array($attribute)) { |
94
|
|
|
$writer->writeAttribute($attribute[0], $attribute[1]); |
95
|
|
|
$element = $attribute[2]; |
96
|
|
|
} |
97
|
|
|
$writer->text($element); |
98
|
|
|
} |
99
|
|
|
$writer->endElement(); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* convert passed data into an array of attributeType, attributeName, and value |
105
|
|
|
* dates sent as DateTime objects will be converted to strings |
106
|
|
|
* @access protected |
107
|
|
|
* @param mixed $value |
108
|
|
|
* @return array attributes and element value |
109
|
|
|
*/ |
110
|
|
|
private static function _generateXmlAttribute($value) |
111
|
|
|
{ |
112
|
|
|
if ($value instanceof DateTime) { |
113
|
|
|
return ['type', 'datetime', self::_dateTimeToXmlTimestamp($value)]; |
114
|
|
|
} |
115
|
|
|
if (is_int($value)) { |
116
|
|
|
return ['type', 'integer', $value]; |
117
|
|
|
} |
118
|
|
|
if (is_bool($value)) { |
119
|
|
|
return ['type', 'boolean', ($value ? 'true' : 'false')]; |
120
|
|
|
} |
121
|
|
|
if ($value === NULL) { |
122
|
|
|
return ['nil', 'true', $value]; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
/** |
126
|
|
|
* converts datetime back to xml schema format |
127
|
|
|
* @access protected |
128
|
|
|
* @param object $dateTime |
129
|
|
|
* @return string XML schema formatted timestamp |
130
|
|
|
*/ |
131
|
|
|
private static function _dateTimeToXmlTimestamp($dateTime) |
132
|
|
|
{ |
133
|
|
|
$dateTimeForUTC = clone $dateTime; |
134
|
|
|
|
135
|
|
|
$dateTimeForUTC->setTimeZone(new DateTimeZone('UTC')); |
136
|
|
|
return ($dateTimeForUTC->format('Y-m-d\TH:i:s') . 'Z'); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
private static function _castDateTime($string) |
|
|
|
|
140
|
|
|
{ |
141
|
|
|
try { |
142
|
|
|
if (empty($string)) { |
143
|
|
|
return false; |
144
|
|
|
} |
145
|
|
|
$dateTime = new DateTime($string); |
146
|
|
|
return self::_dateTimeToXmlTimestamp($dateTime); |
147
|
|
|
} catch (Exception $e) { |
|
|
|
|
148
|
|
|
// not a datetime |
149
|
|
|
return false; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
class_alias('Braintree\Xml\Generator', 'Braintree_Xml_Generator'); |
154
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.