PluginProbe
Depicter — Popup & Slider Builder / 1.9.2
Depicter — Popup & Slider Builder v1.9.2
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
← All changes | vendor/netresearch/jsonmapper/src/JsonMapper.php +94 -20 1.5.2 → 1.9.2 View file →
@@ -74,9 +74,9 @@
74 74 */
75 75 public $bStrictNullTypes = true;
76 76
77 77 /**
78 - * Allow mapping of private and proteted properties.
78 + * Allow mapping of private and protected properties.
79 79 *
80 80 * @var boolean
81 81 */
82 82 public $bIgnoreVisibility = false;
@@ -130,10 +130,10 @@
130 130
131 131 /**
132 132 * Map data all data in $json into the given $object instance.
133 133 *
134 - * @param object|array $json JSON object structure from json_decode()
135 - * @param object $object Object to map $json data into
134 + * @param object|array $json JSON object structure from json_decode()
135 + * @param object|class-string $object Object to map $json data into
136 136 *
137 137 * @return mixed Mapped object is returned.
138 138 * @see mapArray()
139 139 */
@@ -144,15 +144,20 @@
144 144 'JsonMapper::map() requires first argument to be an object'
145 145 . ', ' . gettype($json) . ' given.'
146 146 );
147 147 }
148 - if (!is_object($object)) {
148 + if (!is_object($object) && (!is_string($object) || !class_exists($object))) {
149 149 throw new InvalidArgumentException(
150 - 'JsonMapper::map() requires second argument to be an object'
150 + 'JsonMapper::map() requires second argument to '
151 + . 'be an object or existing class name'
151 152 . ', ' . gettype($object) . ' given.'
152 153 );
153 154 }
154 155
156 + if (is_string($object)) {
157 + $object = $this->createInstance($object);
158 + }
159 +
155 160 $strClassName = get_class($object);
156 161 $rc = new ReflectionClass($object);
157 162 $strNs = $rc->getNamespaceName();
158 163 $providedProperties = array();
@@ -176,12 +181,17 @@
176 181 'JSON property "' . $key . '" does not exist'
177 182 . ' in object of type ' . $strClassName
178 183 );
179 184 } else if ($this->undefinedPropertyHandler !== null) {
180 - call_user_func(
185 + $undefinedPropertyKey = call_user_func(
181 186 $this->undefinedPropertyHandler,
182 187 $object, $key, $jvalue
183 188 );
189 +
190 + if (is_string($undefinedPropertyKey)) {
191 + list($hasProperty, $accessor, $type, $isNullable)
192 + = $this->inspectProperty($rc, $undefinedPropertyKey);
193 + }
184 194 } else {
185 195 $this->log(
186 196 'info',
187 197 'Property {property} does not exist in {class}',
@@ -187,9 +197,12 @@
187 197 'Property {property} does not exist in {class}',
188 198 array('property' => $key, 'class' => $strClassName)
189 199 );
190 200 }
191 - continue;
201 +
202 + if (!$hasProperty) {
203 + continue;
204 + }
192 205 }
193 206
194 207 if ($accessor === null) {
195 208 if ($this->bExceptionOnUndefinedProperty) {
@@ -228,9 +241,11 @@
228 241 continue;
229 242 } else if ($this->isObjectOfSameType($type, $jvalue)) {
230 243 $this->setProperty($object, $accessor, $jvalue);
231 244 continue;
232 - } else if ($this->isSimpleType($type)) {
245 + } else if ($this->isSimpleType($type)
246 + && !(is_array($jvalue) && $this->hasVariadicArrayType($accessor))
247 + ) {
233 248 if ($type === 'string' && is_object($jvalue)) {
234 249 throw new JsonMapper_Exception(
235 250 'JSON property "' . $key . '" in class "'
236 251 . $strClassName . '" is an object and'
@@ -247,8 +262,13 @@
247 262 throw new JsonMapper_Exception(
248 263 'Empty type at property "'
249 264 . $strClassName . '::$' . $key . '"'
250 265 );
266 + } else if (strpos($type, '|')) {
267 + throw new JsonMapper_Exception(
268 + 'Cannot decide which of the union types shall be used: '
269 + . $type
270 + );
251 271 }
252 272
253 273 $array = null;
254 274 $subtype = null;
@@ -262,10 +282,13 @@
262 282 $array = array();
263 283 } else {
264 284 $array = $this->createInstance($proptype, false, $jvalue);
265 285 }
286 + } else if (is_array($jvalue) && $this->hasVariadicArrayType($accessor)) {
287 + $array = array();
288 + $subtype = $type;
266 289 } else {
267 - if (is_a($type, 'ArrayObject', true)) {
290 + if (is_a($type, 'ArrayAccess', true)) {
268 291 $array = $this->createInstance($type, false, $jvalue);
269 292 }
270 293 }
271 294
@@ -479,16 +502,9 @@
479 502 if (count($rparams) > 0) {
480 503 $isNullable = $rparams[0]->allowsNull();
481 504 $ptype = $rparams[0]->getType();
482 505 if ($ptype !== null) {
483 - if ($ptype instanceof ReflectionNamedType) {
484 - $typeName = $ptype->getName();
485 - }
486 - if ($ptype instanceof ReflectionUnionType
487 - || !$ptype->isBuiltin()
488 - ) {
489 - $typeName = '\\' . $typeName;
490 - }
506 + $typeName = $this->stringifyReflectionType($ptype);
491 507 //allow overriding an "array" type hint
492 508 // with a more specific class in the docblock
493 509 if ($typeName !== 'array') {
494 510 return array(
@@ -539,10 +555,9 @@
539 555 // If there is no annotations (higher priority) inspect
540 556 // if there's a scalar type being defined
541 557 if (PHP_VERSION_ID >= 70400 && $rprop->hasType()) {
542 558 $rPropType = $rprop->getType();
543 - $propTypeName = $rPropType->getName();
544 -
559 + $propTypeName = $this->stringifyReflectionType($rPropType);
545 560 if ($this->isSimpleType($propTypeName)) {
546 561 return array(
547 562 true,
548 563 $rprop,
@@ -553,9 +568,9 @@
553 568
554 569 return array(
555 570 true,
556 571 $rprop,
557 - '\\'.$propTypeName,
572 + '\\' . ltrim($propTypeName, '\\'),
558 573 $rPropType->allowsNull()
559 574 );
560 575 }
561 576
@@ -627,8 +642,10 @@
627 642 $accessor->setAccessible(true);
628 643 }
629 644 if ($accessor instanceof ReflectionProperty) {
630 645 $accessor->setValue($object, $value);
646 + } else if (is_array($value) && $this->hasVariadicArrayType($accessor)) {
647 + $accessor->invoke($object, ...$value);
631 648 } else {
632 649 //setter method
633 650 $accessor->invoke($object, $value);
634 651 }
@@ -649,8 +666,14 @@
649 666 protected function createInstance(
650 667 $class, $useParameter = false, $jvalue = null
651 668 ) {
652 669 if ($useParameter) {
670 + if (PHP_VERSION_ID >= 80100
671 + && is_subclass_of($class, \BackedEnum::class)
672 + ) {
673 + return $class::from($jvalue);
674 + }
675 +
653 676 return new $class($jvalue);
654 677 } else {
655 678 $reflectClass = new ReflectionClass($class);
656 679 $constructor = $reflectClass->getConstructor();
@@ -761,8 +784,34 @@
761 784 return substr($strType, -2) === '[]';
762 785 }
763 786
764 787 /**
788 + * Returns true if accessor is a method and has only one parameter
789 + * which is variadic.
790 + *
791 + * @param ReflectionMethod|ReflectionProperty|null $accessor accessor
792 + * to set value
793 + *
794 + * @return bool
795 + */
796 + protected function hasVariadicArrayType($accessor)
797 + {
798 + if (!$accessor instanceof ReflectionMethod) {
799 + return false;
800 + }
801 +
802 + $parameters = $accessor->getParameters();
803 +
804 + if (count($parameters) !== 1) {
805 + return false;
806 + }
807 +
808 + $parameter = $parameters[0];
809 +
810 + return $parameter->isVariadic();
811 + }
812 +
813 + /**
765 814 * Checks if the given type is nullable
766 815 *
767 816 * @param string $type type name from the phpdoc param
768 817 *
@@ -787,8 +836,33 @@
787 836 }
788 837 return substr(
789 838 str_ireplace('|null|', '|', '|' . $type . '|'),
790 839 1, -1
840 + );
841 + }
842 +
843 + /**
844 + * Get a string representation of the reflection type.
845 + * Required because named, union and intersection types need to be handled.
846 + *
847 + * @param ReflectionType $type Native PHP type
848 + *
849 + * @return string "foo|bar"
850 + */
851 + protected function stringifyReflectionType(ReflectionType $type)
852 + {
853 + if ($type instanceof ReflectionNamedType) {
854 + return ($type->isBuiltin() ? '' : '\\') . $type->getName();
855 + }
856 +
857 + return implode(
858 + '|',
859 + array_map(
860 + function (ReflectionNamedType $type) {
861 + return ($type->isBuiltin() ? '' : '\\') . $type->getName();
862 + },
863 + $type->getTypes()
864 + )
791 865 );
792 866 }
793 867
794 868 /**