Issues (3627)

ApiBundle/Serializer/Driver/ApiMetadataDriver.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2015 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\ApiBundle\Serializer\Driver;
13
14
use JMS\Serializer\Metadata\ClassMetadata;
15
use JMS\Serializer\Metadata\PropertyMetadata;
16
use Metadata\ClassMetadata as BaseClassMetadata;
17
use Metadata\Driver\DriverInterface;
18
use ReflectionClass;
19
use ReflectionException;
20
21
class ApiMetadataDriver implements DriverInterface
22
{
23
    /**
24
     * @var ClassMetadata
25
     */
26
    private $metadata;
27
28
    /**
29
     * @var PropertyMetadata[]
30
     */
31
    private $properties = [];
32
33
    /**
34
     * @var string
35
     */
36
    private $groupPrefix = '';
37
38
    /**
39
     * @var null
40
     */
41
    private $defaultVersion = '1.0';
42
43
    /**
44
     * @var null
45
     */
46
    private $currentPropertyName;
47
48
    /**
49
     * @return \Metadata\ClassMetadata
50
     *
51
     * @throws ReflectionException
52
     */
53
    public function loadMetadataForClass(ReflectionClass $class): ?BaseClassMetadata
54
    {
55
        if ($class->hasMethod('loadApiMetadata')) {
56
            $this->metadata = new ClassMetadata($class->getName());
57
58
            $class->getMethod('loadApiMetadata')->invoke(null, $this);
59
60
            $metadata = $this->metadata;
61
62
            $this->resetDefaults();
63
64
            return $metadata;
65
        }
66
67
        return null;
68
    }
69
70
    private function resetDefaults()
71
    {
72
        $this->metadata       = null;
73
        $this->properties     = [];
74
        $this->defaultVersion = '1.0';
0 ignored issues
show
Documentation Bug introduced by
It seems like '1.0' of type string is incompatible with the declared type null of property $defaultVersion.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
75
        $this->groupPrefix    = '';
76
    }
77
78
    /**
79
     * Set the root (base key).
80
     *
81
     * @param $root
82
     *
83
     * @return $this
84
     */
85
    public function setRoot($root)
86
    {
87
        $this->metadata->xmlRootName = $root;
88
89
        return $this;
90
    }
91
92
    /**
93
     * Set prefix for the List and Details groups.
94
     *
95
     * @param $name
96
     *
97
     * @return $this
98
     */
99
    public function setGroupPrefix($name)
100
    {
101
        $this->groupPrefix = $name;
102
103
        return $this;
104
    }
105
106
    /**
107
     * Set the default version for the properties if different than 1.0.
108
     *
109
     * @param $version
110
     *
111
     * @return $this
112
     */
113
    public function setDefaultVersion($version)
114
    {
115
        $this->defaultVersion = $version;
116
117
        return $this;
118
    }
119
120
    /**
121
     * Create a new property.
122
     *
123
     * @param $name
124
     *
125
     * @return $this
126
     */
127
    public function createProperty($name)
128
    {
129
        if (!isset($this->properties[$name])) {
130
            $this->properties[$name] = new PropertyMetadata($this->metadata->name, $name);
131
        }
132
133
        $this->currentPropertyName = $name;
134
135
        return $this;
136
    }
137
138
    /**
139
     * Add property and set default version and Details group.
140
     *
141
     * @param      $name
142
     * @param null $serializedName
143
     * @param bool $useGetter
144
     *
145
     * @return $this
146
     */
147
    public function addProperty($name, $serializedName = null, $useGetter = false)
148
    {
149
        if (empty($name)) {
150
            return $this;
151
        }
152
153
        $this->createProperty($name);
154
155
        if ($useGetter && !$this->properties[$name]->getter) {
156
            $this->properties[$name]->getter = 'get'.ucfirst($name);
157
        }
158
159
        $this->properties[$name]->serializedName = $serializedName ?? $name;
160
161
        if (null !== $this->defaultVersion) {
162
            // Set the default version
163
            $this->setSinceVersion($this->defaultVersion);
164
        }
165
166
        if (null !== $this->groupPrefix) {
167
            // Auto add to the Details group
168
            $this->addGroup($this->groupPrefix.'Details');
169
        }
170
171
        return $this;
172
    }
173
174
    /**
175
     * Create properties.
176
     *
177
     * @param bool|false $addToListGroup
178
     * @param bool|false $useGetter
179
     *
180
     * @return $this
181
     */
182
    public function addProperties(array $properties, $addToListGroup = false, $useGetter = false)
183
    {
184
        foreach ($properties as $prop) {
185
            if (!empty($prop)) {
186
                $serializedName = null;
187
                if (is_array($prop)) {
188
                    list($prop, $serializedName) = $prop;
189
                }
190
                $this->addProperty($prop, $serializedName, $useGetter);
191
192
                if ($addToListGroup) {
193
                    $this->inListGroup();
194
                }
195
            }
196
        }
197
198
        return $this;
199
    }
200
201
    /**
202
     * Create properties and add to the List group.
203
     *
204
     * @return $this
205
     */
206
    public function addListProperties(array $properties)
207
    {
208
        $this->addProperties($properties, true);
209
210
        return $this;
211
    }
212
213
    /**
214
     * @param      $version
215
     * @param null $property
216
     *
217
     * @return $this
218
     */
219
    public function setSinceVersion($version, $property = null)
220
    {
221
        if (null === $property) {
222
            $property = $this->getCurrentPropertyName();
223
        }
224
225
        $this->properties[$property]->sinceVersion = $version;
226
227
        return $this;
228
    }
229
230
    /**
231
     * @param      $version
232
     * @param null $property
233
     *
234
     * @return $this
235
     */
236
    public function setUntilVersion($version, $property = null)
237
    {
238
        if (null === $property) {
239
            $property = $this->getCurrentPropertyName();
240
        }
241
242
        $this->properties[$property]->untilVersion = $version;
243
244
        return $this;
245
    }
246
247
    /**
248
     * @param      $name
249
     * @param null $property
250
     *
251
     * @return $this
252
     */
253
    public function setSerializedName($name, $property = null)
254
    {
255
        if (null === $property) {
256
            $property = $this->getCurrentPropertyName();
257
        }
258
259
        $this->properties[$property]->serializedName = $name;
260
261
        return $this;
262
    }
263
264
    /**
265
     * Set the groups a property belongs to.
266
     *
267
     * @param $groups
268
     * @param $property
269
     *
270
     * @return $this
271
     */
272
    public function setGroups($groups, $property = null)
273
    {
274
        if (!is_array($groups)) {
275
            $groups = [$groups];
276
        }
277
278
        if (null === $property) {
279
            $property = $this->getCurrentPropertyName();
280
        }
281
282
        $this->properties[$property]->groups = $groups;
283
284
        return $this;
285
    }
286
287
    /**
288
     * Add a group the property belongs to.
289
     *
290
     * @param      $group
291
     * @param null $property True to apply to all current properties
292
     *
293
     * @return $this
294
     */
295
    public function addGroup($group, $property = null)
296
    {
297
        if (true === $property) {
298
            foreach ($this->properties as $prop => $metadata) {
299
                $this->addGroup($group, $prop);
300
            }
301
        } else {
302
            if (null === $property) {
303
                $property = $this->getCurrentPropertyName();
304
            }
305
306
            $this->properties[$property]->groups[] = $group;
307
        }
308
309
        return $this;
310
    }
311
312
    /**
313
     * Add property to the List group.
314
     *
315
     * @return $this
316
     */
317
    public function inListGroup()
318
    {
319
        $this->properties[$this->currentPropertyName]->groups[] =
320
            $this->groupPrefix.'List';
321
322
        return $this;
323
    }
324
325
    /**
326
     * Set max depth for the property if an association.
327
     *
328
     * @param      $depth
329
     * @param null $property
330
     *
331
     * @return $this
332
     */
333
    public function setMaxDepth($depth, $property = null)
334
    {
335
        if (null === $property) {
336
            $property = $this->getCurrentPropertyName();
337
        }
338
339
        $this->properties[$property]->maxDepth = (int) $depth;
340
341
        return $this;
342
    }
343
344
    /**
345
     * Push the properties into ClassMetadata.
346
     */
347
    public function build()
348
    {
349
        foreach ($this->properties as $prop) {
350
            $this->metadata->addPropertyMetadata($prop);
351
        }
352
353
        $this->currentPropertyName = null;
354
        $this->properties          = [];
355
    }
356
357
    /**
358
     * @return string
359
     *
360
     * @throws \Exception
361
     */
362
    protected function getCurrentPropertyName()
363
    {
364
        if (empty($this->currentPropertyName)) {
365
            throw new \Exception('Current property is not set');
366
        }
367
368
        return $this->currentPropertyName;
369
    }
370
}
371