1 | <?php |
||||
2 | |||||
3 | namespace garethp\ews; |
||||
4 | |||||
5 | use garethp\ews\API\Type; |
||||
6 | use garethp\ews\API\XmlObject; |
||||
7 | |||||
8 | trait BuildableTrait |
||||
9 | { |
||||
10 | /** |
||||
11 | * @var string |
||||
12 | */ |
||||
13 | public $_ = ''; |
||||
14 | |||||
15 | public $_value = null; |
||||
16 | |||||
17 | 32 | public function getNonNullItems($includeHiddenValue = false) |
|||
18 | { |
||||
19 | 32 | $items = get_object_vars($this); |
|||
20 | |||||
21 | 32 | foreach ($items as $key => $item) { |
|||
22 | 32 | if (substr($key, 0, 1) == "_" || $item === null) { |
|||
23 | 32 | unset($items[$key]); |
|||
24 | } |
||||
25 | } |
||||
26 | |||||
27 | 32 | if ($includeHiddenValue && $this->_value !== null) { |
|||
28 | 1 | $items['_value'] = $this->_value; |
|||
29 | } |
||||
30 | |||||
31 | 32 | return $items; |
|||
32 | } |
||||
33 | |||||
34 | /** |
||||
35 | * @param $array |
||||
36 | * @param bool $strict When set to true, we'll use reflection to build the objects |
||||
37 | * |
||||
38 | * @return static|XmlObject |
||||
39 | */ |
||||
40 | 33 | public static function buildFromArray($array, bool $strict = false) |
|||
41 | { |
||||
42 | 33 | if (static::class === Type::class) { |
|||
0 ignored issues
–
show
introduced
by
![]() |
|||||
43 | 33 | return XmlObject::buildFromArray($array, $strict); |
|||
44 | } |
||||
45 | |||||
46 | 33 | if ($array instanceof XmlObject && $strict) { |
|||
47 | 2 | $array = (array)$array; |
|||
48 | } |
||||
49 | |||||
50 | 33 | if (!is_array($array)) { |
|||
51 | 18 | return $array; |
|||
52 | } |
||||
53 | |||||
54 | 33 | if (!self::arrayIsAssoc($array)) { |
|||
55 | 19 | return self::buildArrayFromArray($array, $strict); |
|||
0 ignored issues
–
show
The call to
garethp\ews\BuildableTrait::buildArrayFromArray() has too many arguments starting with $strict .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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. Please note the @ignore annotation hint above. ![]() |
|||||
56 | } else { |
||||
57 | 33 | return self::buildObjectFromArray($array, $strict); |
|||
58 | } |
||||
59 | } |
||||
60 | |||||
61 | 33 | protected static function buildObjectFromArray($array, bool $strict = false) |
|||
62 | { |
||||
63 | 33 | $object = new static(); |
|||
64 | 33 | $reflect = new \ReflectionClass(static::class); |
|||
65 | |||||
66 | 33 | foreach ($array as $key => $value) { |
|||
67 | // If we're in strict mode, let's take the reflection class, check for a setter and try to use that to build |
||||
68 | // the array, resulting in type-correct responses the whole way down. |
||||
69 | 33 | if ($strict === true && $reflect->hasMethod("set" . ucfirst($key))) { |
|||
70 | 2 | $parameters = $reflect->getMethod("set" . ucfirst($key))->getParameters(); |
|||
71 | |||||
72 | 2 | if (count($parameters) === 1 |
|||
73 | 2 | && $parameters[0]->hasType() |
|||
74 | 2 | && $parameters[0]->getClass() !== null) { |
|||
75 | 2 | $classToBuild = $parameters[0]->getClass()->getName(); |
|||
76 | |||||
77 | 2 | $newValue = call_user_func("$classToBuild::buildFromArray", $value, true); |
|||
78 | 2 | $object->$key = $newValue; |
|||
79 | 2 | continue; |
|||
80 | } |
||||
81 | } |
||||
82 | |||||
83 | 33 | if (is_array($value)) { |
|||
84 | 32 | $value = self::buildFromArray($value); |
|||
85 | } |
||||
86 | |||||
87 | //I think _value is a more expressive way to set string value, but Soap needs _ |
||||
88 | 33 | if ($key === "_value") { |
|||
89 | 7 | $key = "_"; |
|||
90 | } |
||||
91 | |||||
92 | 33 | $object->$key = $value; |
|||
93 | } |
||||
94 | |||||
95 | 33 | return $object; |
|||
96 | } |
||||
97 | |||||
98 | 19 | public static function buildArrayFromArray($array) |
|||
99 | { |
||||
100 | 19 | foreach ($array as $key => $value) { |
|||
101 | 19 | $array[$key] = self::buildFromArray($value); |
|||
102 | } |
||||
103 | |||||
104 | 19 | return $array; |
|||
105 | } |
||||
106 | |||||
107 | 6 | public function toXmlObject() |
|||
108 | { |
||||
109 | 6 | $objectToReturn = new XmlObject(); |
|||
110 | 6 | $objectToReturn->_ = (string)$this; |
|||
111 | |||||
112 | 6 | $properties = $this->getNonNullItems(true); |
|||
113 | |||||
114 | 6 | foreach ($properties as $name => $property) { |
|||
115 | //I think _value is a more expressive way to set string value, but Soap needs _ |
||||
116 | 6 | if ($name == "_value") { |
|||
117 | $name = "_"; |
||||
118 | } |
||||
119 | |||||
120 | 6 | $name = ucfirst($name); |
|||
121 | 6 | $objectToReturn->$name = $this->propertyToXml($name, $property); |
|||
122 | } |
||||
123 | |||||
124 | 6 | return $objectToReturn; |
|||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * @param $name |
||||
129 | * @param $property |
||||
130 | * @return array|Type|null |
||||
131 | */ |
||||
132 | 6 | protected function propertyToXml($name, $property) |
|||
0 ignored issues
–
show
The parameter
$name is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
133 | { |
||||
134 | 6 | if ($property instanceof \DateTime) { |
|||
135 | $property = $property->format("c"); |
||||
136 | } |
||||
137 | |||||
138 | 6 | if ($property instanceof Type) { |
|||
139 | 6 | return $property->toXmlObject(); |
|||
0 ignored issues
–
show
|
|||||
140 | } |
||||
141 | |||||
142 | 6 | if (is_array($property) && $this->arrayIsAssoc($property)) { |
|||
143 | return $this->buildFromArray($property); |
||||
0 ignored issues
–
show
|
|||||
144 | } |
||||
145 | |||||
146 | 6 | if (is_array($property)) { |
|||
147 | 5 | return array_map(function ($property) { |
|||
148 | 5 | if ($property instanceof Type) { |
|||
149 | 5 | return $property->toXmlObject(); |
|||
150 | } |
||||
151 | |||||
152 | 1 | return $property; |
|||
153 | 5 | }, $property); |
|||
154 | } |
||||
155 | |||||
156 | 6 | return $property; |
|||
157 | } |
||||
158 | |||||
159 | 39 | public static function arrayIsAssoc($array) |
|||
160 | { |
||||
161 | 39 | return (bool)count(array_filter(array_keys($array), 'is_string')); |
|||
162 | } |
||||
163 | |||||
164 | /** |
||||
165 | * Clones any object properties on a type object when it is cloned. Allows |
||||
166 | * for a deep clone required when using object to represent data types when |
||||
167 | * making a SOAP call. |
||||
168 | */ |
||||
169 | 1 | public function __clone() |
|||
170 | { |
||||
171 | // Iterate over all properties on the current object. |
||||
172 | 1 | foreach (get_object_vars($this) as $property => $value) { |
|||
173 | 1 | $this->$property = \garethp\ews\Utilities\cloneValue($value); |
|||
174 | } |
||||
175 | } |
||||
176 | |||||
177 | 23 | public function __toString() |
|||
178 | { |
||||
179 | 23 | if (!is_string($this->_)) { |
|||
0 ignored issues
–
show
|
|||||
180 | 6 | return ''; |
|||
181 | } |
||||
182 | |||||
183 | 19 | return $this->_; |
|||
184 | } |
||||
185 | } |
||||
186 |