Passed
Push — master ( 3ceccd...81fd1b )
by Vitor de
02:38
created

Base::isDataWrapper()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 8
nc 3
nop 1
crap 3
1
<?php
2
3
namespace GFG\DTOContext\DataWrapper;
4
5
abstract class Base implements \ArrayAccess, DataWrapperInterface
6
{
7
    /**
8
     * Base constructor - you may use an array to initialize the dataWrapper
9
     *
10
     * @param array $data
11
     */
12 11
    public function __construct(array $data = array())
13
    {
14 11
        if (!empty($data)) {
15 7
            $ref = new \ReflectionObject($this);
16 7
            foreach ($ref->getProperties() as $property) {
17
                try {
18 7
                    $value = $this->getValue($data, $property->getName());
19 7
                    if ($this->isDataWrapper($property)) {
20 1
                        $value = $this->toDataWrapper($value, $property);
21 1
                    }
22 7
                    $property->setAccessible(true);
23 7
                    $property->setValue($this, $value);
24 7
                } catch (\Exception $e) {
25
                    // does nothing when we don't have a certain property in
26
                    // the $data array
27
                }
28 7
            }
29 7
        }
30 11
    }
31
32
    /**
33
     * Getter and Setters
34
     *
35
     * @param string $name
36
     * @param array $args
37
     */
38 5
    public function __call($name, array $args)
39
    {
40 5
        $getSet = substr($name, 0, 3);
41 5
        if (in_array($getSet, array('get', 'set'))) {
42 4
            $property = lcfirst(substr($name, 3));
43 4
            $ref = new \ReflectionObject($this);
44
45 4
            if ($ref->hasProperty($property)) {
46 3
                $property = $ref->getProperty($property);
47 3
                $property->setAccessible(true);
48
49 3
                if ($getSet === 'get') {
50 3
                    return $property->getValue($this);
51
                } else {
52 2
                    $property->setValue($this, $args[0]);
53 2
                    return $this;
54
                }
55
            }
56
57 1
            throw new \InvalidArgumentException(
58 1
                sprintf('Property %s does not exists', $property)
59 1
            );
60
        }
61
62 1
        throw new \InvalidArgumentException('Method does not exists');
63
    }
64
65
    /**
66
     * Export dataWrapper values as an array
67
     *
68
     * @return array
69
     */
70 6
    public function toArray()
71
    {
72 6
        $ref = new \ReflectionObject($this);
73 6
        $export = array();
74
75 6
        foreach ($ref->getProperties() as $property) {
76 6
            $property->setAccessible(true);
77 6
            $name = strtolower(
78 6
                preg_replace('@([A-Z])@', '_\1', $property->getName())
79 6
            );
80 6
            $export[$name] = $property->getValue($this);
81
82 6
            if ($export[$name] instanceof DataWrapperInterface) {
83 2
                $export[$name] = $export[$name]->toArray();
84 6
            } elseif ($export[$name] instanceof \DateTime) {
85 1
                $export[$name] = $export[$name]->format('Y-m-d');
86 1
            }
87 6
        }
88
89 6
        return $export;
90
    }
91
92
    /**
93
     * ToArray with unset null fields
94
     *
95
     * @return array
96
     */
97 1
    public function toCleanArray()
98
    {
99 1
        $export = $this->toArray();
100
101 1
        $cleanExport = array();
102 1
        foreach ($export as $key => $value) {
103 1
            if ($value) {
104 1
                $cleanExport[$key] = $value;
105 1
            }
106 1
        }
107
108 1
        return $cleanExport;
109
    }
110
111
    /**
112
     * Extract dataWrapper $property value from $data
113
     *
114
     * @param array $data
115
     * @param string $property
116
     * @return
117
     */
118 7
    private function getValue(array $data, $property)
119
    {
120 7
        if (isset($data[$property])) {
121 5
            return $data[$property];
122
        }
123
124 6
        $property = strtolower(preg_replace('@([A-Z])@', '_\1', $property));
125 6
        if (isset($data[$property])) {
126 3
            return $data[$property];
127
        }
128
129 4
        throw new \OutOfBoundsException('');
130
    }
131
132
    /**
133
     * Convert from undescore to camel case
134
     *
135
     * @param string $name
136
     * @return void
137
     */
138 8
    private function toCamelCase($name)
139
    {
140 8
        return lcfirst(
141 8
            str_replace(' ', '', ucwords(str_replace('_', ' ', $name)))
142 8
        );
143
    }
144
145
    /**
146
     * Convert from undescore to studly caps
147
     *
148
     * @param string $name
149
     * @return void
150
     */
151 8
    private function toStudlyCaps($name)
152
    {
153 8
        return ucfirst($this->toCamelCase($name));
154
    }
155
156
    /**
157
     * @param string $offset
158
     * @return mixed
159
     */
160 1
    public function offsetGet($offset)
161
    {
162 1
        $property = $this->toStudlyCaps($offset);
163 1
        return call_user_func(array($this, 'get' . $property));
164
    }
165
166
    /**
167
     * @param string $offset
168
     * @param mixed $value
169
     * @return mixed
170
     */
171 1
    public function offsetSet($offset, $value)
172
    {
173 1
        $property = $this->toStudlyCaps($offset);
174 1
        return call_user_func(array($this, 'set' . $property), $value);
175
    }
176
177
    /**
178
     * @param string
179
     * @return mixed
180
     */
181 1
    public function offsetExists($offset)
182
    {
183 1
        $property = $this->toCamelCase($offset);
184 1
        return (new \ReflectionObject($this))->hasProperty($property);
185
    }
186
187
    /**
188
     * @param string offset
189
     * @return void
190
     */
191 1
    public function offsetUnset($offset)
192
    {
193 1
        $this->offsetSet($offset, null);
194 1
    }
195
196
    /**
197
     * @param \ReflectionProperty $property
198
     * @return bool
199
     */
200 7
    public function isDataWrapper(\ReflectionProperty $property)
201
    {
202 7
        $class = $this->findType($property);
203
204 7
        if (!$class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
205 4
            return false;
206
        }
207 5
        if (!class_exists($class)) {
208 4
            return false;
209
        }
210
211 1
        $ref = new \ReflectionClass($class);
212 1
        return $ref->implementsInterface(DataWrapperInterface::class);
213
    }
214
215
    /**
216
     * @param mixed $value
217
     * @param \ReflectionProperty $property
218
     * @return BaseCollection
219
     */
220 1
    public function toDataWrapper($value, \ReflectionProperty $property)
221
    {
222 1
        $type = $this->findType($property);
223 1
        return new $type($value);
224
    }
225
226
    /**
227
     * @param \ReflectionProperty $property
228
     * @return string
229
     */
230 7
    private function findType(\ReflectionProperty $property)
231
    {
232 7
        $class      = $property->getDeclaringClass();
233 7
        $doc        = $class->getDocComment();
234 7
        $getter     = 'get' . $this->toStudlyCaps($property->getName());
235 7
        $regex      = "#@method (.+?) #";
236
237 7
        foreach (explode(PHP_EOL, $doc) as $commentLine) {
238 7
            if (false !== strpos($commentLine, $getter)) {
239 6
                preg_match($regex, $commentLine, $matches);
240 6
                if (isset($matches[1])) {
241 5
                    return $matches[1];
242
                }
243 1
            }
244 7
        }
245 4
    }
246
}
247