Completed
Pull Request — master (#888)
by Robert
03:06
created

PropertyMetadata   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 94.5%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
lcom 2
cbo 2
dl 0
loc 218
ccs 103
cts 109
cp 0.945
rs 10
c 2
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A __get() 0 10 2
A getReflection() 0 9 2
A setAccessor() 0 7 1
A getValue() 0 13 3
A setValue() 0 9 2
A setType() 0 8 2
B serialize() 0 30 1
B unserialize() 0 47 5
A prepareLazyReflection() 0 5 1
1
<?php
2
3
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer\Metadata;
20
21
use JMS\Serializer\TypeParser;
22
use Metadata\PropertyMetadata as BasePropertyMetadata;
23
24
class PropertyMetadata extends BasePropertyMetadata
25
{
26
    const ACCESS_TYPE_PROPERTY = 'property';
27
    const ACCESS_TYPE_PUBLIC_METHOD = 'public_method';
28
29
    const ACCESS_TYPE_NAMING_EXACT = 'exact';
30
    const ACCESS_TYPE_NAMING_CAMEL_CASE = 'camel_case';
31
32
    public $sinceVersion;
33
    public $untilVersion;
34
    public $groups;
35
    public $serializedName;
36
    public $type;
37
    public $xmlCollection = false;
38
    public $xmlCollectionInline = false;
39
    public $xmlCollectionSkipWhenEmpty = true;
40
    public $xmlEntryName;
41
    public $xmlEntryNamespace;
42
    public $xmlKeyAttribute;
43
    public $xmlAttribute = false;
44
    public $xmlValue = false;
45
    public $xmlNamespace;
46
    public $xmlKeyValuePairs = false;
47
    public $xmlElementCData = true;
48
    public $getter;
49
    public $setter;
50
    public $inline = false;
51
    public $skipWhenEmpty = false;
52
    public $readOnly = false;
53
    public $xmlAttributeMap = false;
54
    public $maxDepth = null;
55
    public $excludeIf = null;
56
57
    /** @deprecated Use getReflection() */
58
    public $reflection;
59
    public $accessType;
60
    public $accessTypeNaming;
61
62
    private $closureAccessor;
63
64
    /**
65
     * @var \ReflectionProperty|null
66
     */
67
    private $lazyReflection;
68
69
    private static $typeParser;
70
71
    /**
72
     * @param string $class
73
     * @param string $name
74
     * @noinspection PhpMissingParentConstructorInspection
75
     */
76 328
    public function __construct($class, $name)
77
    {
78 328
        $this->class = $class;
79 328
        $this->name = $name;
80 328
        $this->prepareLazyReflection();
81
82 328
        $this->closureAccessor = \Closure::bind(function ($o, $name) {
83 191
            return $o->$name;
84 328
        }, null, $class);
85 328
    }
86
87 65
    public function __get($name)
88
    {
89
        // Default PHP notice when no property:
90 65
        if ($name !== 'reflection') {
91
            trigger_error("Undefined property: $name", \E_NOTICE);
92
            return null;
93
        }
94
95 65
        return $this->getReflection();
96
    }
97
98 76
    public function getReflection()
99
    {
100 76
        if (!$this->lazyReflection) {
101 76
            $this->lazyReflection = new \ReflectionProperty($this->class, $this->name);
102 76
            $this->lazyReflection->setAccessible(true);
103
        }
104
105 76
        return $this->lazyReflection;
106
    }
107
108
    /**
109
     * @see PropertyMetadata::ACCESS_TYPE_PROPERTY
110
     * @param string $type
111
     *
112
     * @param string|null $getter
113
     * @param string|null $setter
114
     * @param string $naming
115
     */
116 296
    public function setAccessor($type, $getter = null, $setter = null, $naming = self::ACCESS_TYPE_NAMING_EXACT)
117
    {
118 296
        $this->accessType = $type;
119 296
        $this->accessTypeNaming = $naming;
120 296
        $this->getter = $getter;
121 296
        $this->setter = $setter;
122 296
    }
123
124 202
    public function getValue($obj)
125
    {
126 202
        if (null === $this->getter) {
127 191
            if (null !== $this->closureAccessor) {
128 191
                $accessor = $this->closureAccessor;
129 191
                return $accessor($obj, $this->name);
130
            }
131
132
            return parent::getValue($obj);
133
        }
134
135 38
        return $obj->{$this->getter}();
136
    }
137
138 62
    public function setValue($obj, $value)
139
    {
140 62
        if (null === $this->setter) {
141 57
            parent::setValue($obj, $value);
142 57
            return;
143
        }
144
145 7
        $obj->{$this->setter}($value);
146 7
    }
147
148 257
    public function setType($type)
149
    {
150 257
        if (null === self::$typeParser) {
151 1
            self::$typeParser = new TypeParser();
152
        }
153
154 257
        $this->type = self::$typeParser->parse($type);
155 257
    }
156
157 1
    public function serialize()
158
    {
159 1
        return serialize(array(
160 1
            $this->sinceVersion,
161 1
            $this->untilVersion,
162 1
            $this->groups,
163 1
            $this->serializedName,
164 1
            $this->type,
165 1
            $this->xmlCollection,
166 1
            $this->xmlCollectionInline,
167 1
            $this->xmlEntryName,
168 1
            $this->xmlKeyAttribute,
169 1
            $this->xmlAttribute,
170 1
            $this->xmlValue,
171 1
            $this->xmlNamespace,
172 1
            $this->xmlKeyValuePairs,
173 1
            $this->xmlElementCData,
174 1
            $this->getter,
175 1
            $this->setter,
176 1
            $this->inline,
177 1
            $this->readOnly,
178 1
            $this->xmlAttributeMap,
179 1
            $this->maxDepth,
180 1
            parent::serialize(),
181 1
            'xmlEntryNamespace' => $this->xmlEntryNamespace,
182 1
            'xmlCollectionSkipWhenEmpty' => $this->xmlCollectionSkipWhenEmpty,
183 1
            'excludeIf' => $this->excludeIf,
184 1
            'skipWhenEmpty' => $this->skipWhenEmpty,
185
        ));
186
    }
187
188 1
    public function unserialize($str)
189
    {
190 1
        $unserialized = unserialize($str);
191
        list(
192 1
            $this->sinceVersion,
193 1
            $this->untilVersion,
194 1
            $this->groups,
195 1
            $this->serializedName,
196 1
            $this->type,
197 1
            $this->xmlCollection,
198 1
            $this->xmlCollectionInline,
199 1
            $this->xmlEntryName,
200 1
            $this->xmlKeyAttribute,
201 1
            $this->xmlAttribute,
202 1
            $this->xmlValue,
203 1
            $this->xmlNamespace,
204 1
            $this->xmlKeyValuePairs,
205 1
            $this->xmlElementCData,
206 1
            $this->getter,
207 1
            $this->setter,
208 1
            $this->inline,
209 1
            $this->readOnly,
210 1
            $this->xmlAttributeMap,
211 1
            $this->maxDepth,
212
            $parentStr
213 1
            ) = $unserialized;
214
215 1
        if (isset($unserialized['xmlEntryNamespace'])) {
216
            $this->xmlEntryNamespace = $unserialized['xmlEntryNamespace'];
217
        }
218 1
        if (isset($unserialized['xmlCollectionSkipWhenEmpty'])) {
219 1
            $this->xmlCollectionSkipWhenEmpty = $unserialized['xmlCollectionSkipWhenEmpty'];
220
        }
221 1
        if (isset($unserialized['excludeIf'])) {
222
            $this->excludeIf = $unserialized['excludeIf'];
223
        }
224 1
        if (isset($unserialized['skipWhenEmpty'])) {
225 1
            $this->skipWhenEmpty = $unserialized['skipWhenEmpty'];
226
        }
227
228 1
        list($this->class, $this->name) = unserialize($parentStr);
229 1
        $this->prepareLazyReflection();
230
231 1
        $this->closureAccessor = \Closure::bind(function ($o, $name) {
232
            return $o->$name;
233 1
        }, null, $this->class);
234 1
    }
235
236 328
    protected function prepareLazyReflection()
237
    {
238
        // Use __get() instead of $this->reflection.
239 328
        unset($this->reflection);
240 328
    }
241
}
242