Passed
Push — master ( c22b6a...5f79f5 )
by Julito
11:21
created

JsonDeserializableTrait   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 34
c 0
b 0
f 0
dl 0
loc 108
rs 10
wmc 14

4 Methods

Rating   Name   Duplication   Size   Complexity  
A initializeExtraProperties() 0 2 1
A fromJson() 0 11 3
A fromObject() 0 6 1
B recursivelyCopyObjectProperties() 0 33 9
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\PluginBundle\Zoom\API;
6
7
use Exception;
8
9
/**
10
 * Trait JsonDeserializableTrait.
11
 * Utility functions to help convert server-generated JSON to API class instances.
12
 */
13
trait JsonDeserializableTrait
14
{
15
    /**
16
     * Builds a class instance from the Json description of the object.
17
     *
18
     * @param string $json
19
     *
20
     * @throws Exception on JSON-decode error or unexpected object property
21
     *
22
     * @return static
23
     */
24
    public static function fromJson($json)
25
    {
26
        if (empty($json)) {
27
            throw new Exception('Cannot JSON-decode empty string');
28
        }
29
        $object = json_decode($json);
30
        if (null === $object) {
31
            throw new Exception('Could not decode JSON: '.$json);
32
        }
33
34
        return static::fromObject($object);
35
    }
36
37
    /**
38
     * Builds a class instance from an already json-decoded object.
39
     *
40
     * @param object $object
41
     *
42
     * @throws Exception on unexpected object property
43
     *
44
     * @return static
45
     */
46
    public static function fromObject($object)
47
    {
48
        $instance = new static();
49
        static::recursivelyCopyObjectProperties($object, $instance);
50
51
        return $instance;
52
    }
53
54
    /**
55
     * Returns the class name of the items to be found in the named array property.
56
     *
57
     * To override in classes that have a property of type array
58
     *
59
     * @param string $propertyName array property name
60
     *
61
     * @throws Exception if not implemented for this propertyName
62
     *
63
     * @return string class name of the items to be found in the named array property
64
     */
65
    abstract public function itemClass($propertyName);
66
67
    /**
68
     * Initializes properties that can be calculated from json-decoded properties.
69
     *
70
     * Called at the end of method recursivelyCopyObjectProperties()
71
     * and indirectly at the end of static method fromJson().
72
     *
73
     * By default it does nothing.
74
     */
75
    public function initializeExtraProperties()
76
    {
77
        // default does nothing
78
    }
79
80
    /**
81
     * Copies values from another object properties to an instance, recursively.
82
     *
83
     * @param object $source      source object
84
     * @param object $destination specific class instance, with already initialized properties
85
     *
86
     * @throws Exception when the source object has an unexpected property
87
     */
88
    protected static function recursivelyCopyObjectProperties($source, &$destination)
89
    {
90
        foreach (get_object_vars($source) as $name => $value) {
91
            if (property_exists($destination, $name)) {
92
                if (is_object($value)) {
93
                    if (is_object($destination->$name)) {
94
                        static::recursivelyCopyObjectProperties($value, $destination->$name);
95
                    } else {
96
                        throw new Exception("Source property $name is an object, which is not expected");
97
                    }
98
                } elseif (is_array($value)) {
99
                    if (is_array($destination->$name)) {
100
                        $itemClass = $destination->itemClass($name);
101
                        foreach ($value as $sourceItem) {
102
                            if ('string' === $itemClass) {
103
                                $destination->$name[] = $sourceItem;
104
                            } else {
105
                                $item = new $itemClass();
106
                                static::recursivelyCopyObjectProperties($sourceItem, $item);
107
                                $destination->$name[] = $item;
108
                            }
109
                        }
110
                    } else {
111
                        throw new Exception("Source property $name is an array, which is not expected");
112
                    }
113
                } else {
114
                    $destination->$name = $value;
115
                }
116
            } else {
117
                error_log("Source object has property $name, which was not expected: ".json_encode($source));
118
            }
119
        }
120
        $destination->initializeExtraProperties();
121
    }
122
}
123