Issues (63)

src/BuildableTrait.php (7 issues)

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 40
    public function getNonNullItems($includeHiddenValue = false)
18
    {
19 40
        $items = get_object_vars($this);
20
21 40
        foreach ($items as $key => $item) {
22 40
            if (substr($key, 0, 1) == "_" || $item === null) {
23 40
                unset($items[$key]);
24
            }
25
        }
26
27 40
        if ($includeHiddenValue && $this->_value !== null) {
28 1
            $items['_value'] = $this->_value;
29
        }
30
31 40
        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 41
    public static function buildFromArray($array, bool $strict = false)
41
    {
42 41
        if (static::class === Type::class) {
0 ignored issues
show
The condition static::class === garethp\ews\API\Type::class is always false.
Loading history...
43 40
            return XmlObject::buildFromArray($array, $strict);
44
        }
45
46 41
        if ($array instanceof XmlObject && $strict) {
47 2
            $array = (array)$array;
48
        }
49
50 41
        if (!is_array($array)) {
51 23
            return $array;
52
        }
53
54 41
        if (!self::arrayIsAssoc($array)) {
55 26
            return self::buildArrayFromArray($array, $strict);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::buildArrayFromArray($array, $strict) returns the type array which is incompatible with the documented return type garethp\ews\API\XmlObjec...ethp\ews\BuildableTrait.
Loading history...
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 ignore-call  annotation

55
            return self::/** @scrutinizer ignore-call */ buildArrayFromArray($array, $strict);

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.

Loading history...
56
        } else {
57 41
            return self::buildObjectFromArray($array, $strict);
58
        }
59
    }
60
61 41
    protected static function buildObjectFromArray($array, bool $strict = false)
62
    {
63 41
        $object = new static();
64 41
        $reflect = new \ReflectionClass(static::class);
65
66 41
        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 41
            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->{ucfirst($key)} = $newValue;
79 2
                    continue;
80
                }
81
            }
82
83 41
            if (is_array($value)) {
84 39
                $value = self::buildFromArray($value);
85
            }
86
87
            //I think _value is a more expressive way to set string value, but Soap needs _
88 41
            if ($key === "_value") {
89 10
                $key = "_";
90
            }
91
92 41
            if ($value instanceof Type) {
93 1
                $value = $value->toXmlObject();
94
            }
95
96 41
            $object->{ucfirst($key)} = $value;
97
        }
98
99 41
        return $object;
100
    }
101
102 26
    public static function buildArrayFromArray($array)
103
    {
104 26
        foreach ($array as $key => $value) {
105 26
            $array[$key] = self::buildFromArray($value);
106
        }
107
108 26
        return $array;
109
    }
110
111 9
    public function toXmlObject()
112
    {
113 9
        $objectToReturn = new XmlObject();
114 9
        $objectToReturn->_ = (string)$this;
115
116 9
        $properties = $this->getNonNullItems(true);
117
118 9
        foreach ($properties as $name => $property) {
119
            //I think _value is a more expressive way to set string value, but Soap needs _
120 9
            if ($name == "_value") {
121
                $name = "_";
122
            }
123
124 9
            $name = ucfirst($name);
125 9
            $objectToReturn->$name = $this->propertyToXml($name, $property);
126
        }
127
128 9
        return $objectToReturn;
129
    }
130
131
    /**
132
     * @param $name
133
     * @param $property
134
     * @return array|Type|null
135
     */
136 9
    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 ignore-unused  annotation

136
    protected function propertyToXml(/** @scrutinizer ignore-unused */ $name, $property)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
137
    {
138 9
        if ($property instanceof \DateTime) {
139
            $property = $property->format("c");
140
        }
141
142 9
        if ($property instanceof Type) {
143 7
            return $property->toXmlObject();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $property->toXmlObject() returns the type garethp\ews\API\XmlObject which is incompatible with the documented return type array|garethp\ews\API\Type|null.
Loading history...
144
        }
145
146 9
        if (is_array($property) && $this->arrayIsAssoc($property)) {
147
            return $this->buildFromArray($property);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->buildFromArray($property) returns the type garethp\ews\API\XmlObject which is incompatible with the documented return type array|garethp\ews\API\Type|null.
Loading history...
148
        }
149
150 9
        if (is_array($property)) {
151 6
            return array_map(function ($property) {
152 6
                if ($property instanceof Type) {
153 6
                    return $property->toXmlObject();
154
                }
155
156
                return $property;
157 6
            }, $property);
158
        }
159
160 9
        return $property;
161
    }
162
163 47
    public static function arrayIsAssoc($array)
164
    {
165 47
        return (bool)count(array_filter(array_keys($array), 'is_string'));
166
    }
167
168
    /**
169
     * Clones any object properties on a type object when it is cloned. Allows
170
     * for a deep clone required when using object to represent data types when
171
     * making a SOAP call.
172
     */
173 1
    public function __clone()
174
    {
175
        // Iterate over all properties on the current object.
176 1
        foreach (get_object_vars($this) as $property => $value) {
177 1
            $this->$property = \garethp\ews\Utilities\cloneValue($value);
178
        }
179
    }
180
181 29
    public function __toString()
182
    {
183 29
        if (!is_string($this->_)) {
0 ignored issues
show
The condition is_string($this->_) is always true.
Loading history...
184 6
            return '';
185
        }
186
187 25
        return $this->_;
188
    }
189
}
190