Completed
Push — hotfix/schema-expose-realId ( cf9ec6 )
by
unknown
11:01
created

Schema::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Graviton Schema Document
4
 */
5
6
namespace Graviton\SchemaBundle\Document;
7
8
/**
9
 * Graviton\SchemaBundle\Document\Schema
10
 *
11
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
12
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
13
 * @link     http://swisscom.ch
14
 */
15
class Schema
16
{
17
    /**
18
     * @var string
19
     */
20
    protected $title;
21
22
    /**
23
     * @var string
24
     */
25
    protected $description;
26
27
    /**
28
     * @var string
29
     */
30
    protected $type;
31
32
    /**
33
     * @var string
34
     */
35
    protected $format;
36
37
    /**
38
     * @var Schema
39
     */
40
    protected $items;
41
42
    /**
43
     * @var \Doctrine\Common\Collections\ArrayCollection
44
     */
45
    protected $properties;
46
47
    /**
48
     * @var Array
49
     */
50
    protected $propertiesArray = array();
51
52
    /**
53
     * @var Schema
54
     */
55
    protected $additionalProperties;
56
57
    /**
58
     * @var string[]
59
     */
60
    protected $required = array();
61
62
    /**
63
     * @var boolean
64
     */
65
    protected $translatable;
66
67
    /**
68
     * @var array
69
     */
70
    protected $refCollection = array();
71
72
    /**
73
     * possible event names this collection implements (queue events)
74
     *
75
     * @var array
76
     */
77
    protected $eventNames = array();
78
79
    /**
80
     * @var bool
81
     */
82
    protected $readOnly = false;
83
84
    /**
85
     * these are the BSON primitive types.
86
     * http://json-schema.org/latest/json-schema-core.html#anchor8
87
     * every type set *not* in this set will be carried over to 'format'
88
     *
89
     * @var string[]
90
     */
91
    protected $primitiveTypes = array(
92
        'array',
93
        'boolean',
94
        'integer',
95
        'number',
96
        'null',
97
        'object',
98
        'string'
99
    );
100
101
    /**
102
     * known non-primitive types we map to primitives here.
103
     * the type itself is set to the format.
104
     *
105
     * @var string[]
106
     */
107
    protected $specialTypeMapping = array(
108
        'extref' => 'string',
109
        'translatable' => 'object'
110
    );
111
112
    /**
113
    * Build properties
114
    */
115
    public function __construct()
116
    {
117
        $this->properties = new \Doctrine\Common\Collections\ArrayCollection();
118
    }
119
120
    /**
121
     * set title
122
     *
123
     * @param string $title title
124
     *
125
     * @return void
126
     */
127
    public function setTitle($title)
128
    {
129
        $this->title = $title;
130
    }
131
132
    /**
133
     * get title
134
     *
135
     * @return string
136
     */
137
    public function getTitle()
138
    {
139
        return $this->title;
140
    }
141
142
    /**
143
     * set description
144
     *
145
     * @param string $description description
146
     *
147
     * @return void
148
     */
149
    public function setDescription($description)
150
    {
151
        $this->description = $description;
152
    }
153
154
    /**
155
     * get description
156
     *
157
     * @return string
158
     */
159
    public function getDescription()
160
    {
161
        return $this->description;
162
    }
163
164
    /**
165
     * set type
166
     *
167
     * @param string $type type
168
     *
169
     * @return void
170
     */
171
    public function setType($type)
172
    {
173
        if ($type === 'int') {
174
            $type = 'integer';
175
        }
176
        if ($type === 'hash') {
177
            $type = 'object';
178
        }
179
180
        // handle non-primitive types
181
        if (!in_array($type, $this->primitiveTypes)) {
182
            $setType = 'string';
183
            if (isset($this->specialTypeMapping[$type])) {
184
                $setType = $this->specialTypeMapping[$type];
185
            }
186
            $this->type = $setType;
187
            $this->setFormat($type);
188
        } else {
189
            $this->type = $type;
190
        }
191
    }
192
193
    /**
194
     * get type
195
     *
196
     * @return string type
197
     */
198
    public function getType()
199
    {
200
        return $this->type;
201
    }
202
203
    /**
204
     * get format
205
     *
206
     * @return string format
207
     */
208
    public function getFormat()
209
    {
210
        return $this->format;
211
    }
212
213
    /**
214
     * sets format
215
     *
216
     * @param string $format format
217
     *
218
     * @return void
219
     */
220
    public function setFormat($format)
221
    {
222
        $this->format = $format;
223
    }
224
225
    /**
226
     * set items
227
     *
228
     * @param Schema $items items schema
229
     *
230
     * @return void
231
     */
232
    public function setItems($items)
233
    {
234
        $this->items = $items;
235
    }
236
237
    /**
238
     * get items
239
     *
240
     * @return Schema
241
     */
242
    public function getItems()
243
    {
244
        return $this->items;
245
    }
246
247
    /**
248
     * add a property
249
     *
250
     * @param string $name     property name
251
     * @param Schema $property property
252
     *
253
     * @return void
254
     */
255
    public function addProperty($name, $property)
256
    {
257 View Code Duplication
        if (!$this->properties->contains($property)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
            $this->propertiesArray[$name] = $property;
259
            $this->properties->add($property);
260
        }
261
    }
262
263
    /**
264
     * removes a property
265
     *
266
     * @param string $name property name
267
     *
268
     * @return void
269
     */
270
    public function removeProperty($name)
271
    {
272
        if ($name && array_key_exists($name, $this->propertiesArray)) {
273 View Code Duplication
            if (!$this->properties->contains($this->propertiesArray[$name])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
274
                $this->properties->remove($this->propertiesArray[$name]);
275
            }
276
            unset($this->propertiesArray[$name]);
277
        }
278
    }
279
280
    /**
281
     * returns a property
282
     *
283
     * @param string $name property name
284
     *
285
     * @return void|Schema property
286
     */
287
    public function getProperty($name)
288
    {
289
        if (array_key_exists($name, $this->propertiesArray)) {
290
            return $this->propertiesArray[$name];
291
        }
292
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Graviton\SchemaBundle\Document\Schema::getProperty of type null|Graviton\SchemaBundle\Document\Schema.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
293
    }
294
295
    /**
296
     * get properties
297
     *
298
     * @return Schema[]|null
299
     */
300
    public function getProperties()
301
    {
302
        $properties = $this->properties;
303
        if (empty($properties)) {
304
            $properties = null;
305
        }
306
307
        return $properties;
308
    }
309
310
    /**
311
     * set additionalProperties on schema
312
     *
313
     * @param Schema $schema schema to use for additionalProperties type
314
     *
315
     * @return void
316
     */
317
    public function setAdditionalProperties(Schema $schema)
318
    {
319
        $this->additionalProperties = $schema;
320
    }
321
322
    /**
323
     * get addtionalProperties for schema
324
     *
325
     * @return Schema
326
     */
327
    public function getAdditionalProperties()
328
    {
329
        return $this->additionalProperties;
330
    }
331
332
    /**
333
     * set required variables
334
     *
335
     * @param string[] $required arary of required fields
336
     *
337
     * @return void
338
     */
339
    public function setRequired($required)
340
    {
341
        $this->required = $required;
342
    }
343
344
    /**
345
     * get required fields
346
     *
347
     * @return string[]|null
348
     */
349
    public function getRequired()
350
    {
351
        $required = $this->required;
352
        if (empty($required)) {
353
            $required = null;
354
        }
355
356
        return $required;
357
    }
358
359
    /**
360
     * set translatable flag
361
     *
362
     * This flag is a local extension to json schema.
363
     *
364
     * @param boolean $translatable translatable flag
365
     *
366
     * @return void
367
     */
368
    public function setTranslatable($translatable)
369
    {
370
        if ($translatable === true) {
371
            $this->setType('translatable');
372
        } else {
373
            $this->setType('string');
374
        }
375
    }
376
377
    /**
378
     * get translatable flag
379
     *
380
     * @return boolean
381
     */
382
    public function isTranslatable()
383
    {
384
        $ret = false;
385
        if ($this->getFormat() == 'translatable') {
386
            $ret = true;
387
        }
388
389
        return $ret;
390
    }
391
392
    /**
393
     * set a array of urls that can extref refer to
394
     *
395
     * @param array $refCollection urls
396
     *
397
     * @return void
398
     */
399
    public function setRefCollection(array $refCollection)
400
    {
401
        $this->refCollection = $refCollection;
402
    }
403
404
    /**
405
     * get a collection of urls that can extref refer to
406
     *
407
     * @return array
408
     */
409
    public function getRefCollection()
410
    {
411
        $collection = $this->refCollection;
412
        if (empty($collection)) {
413
            $collection = null;
414
        }
415
416
        return $collection;
417
    }
418
419
    /**
420
     * set an array of possible event names
421
     *
422
     * @param array $eventNames event names
423
     *
424
     * @return void
425
     */
426
    public function setEventNames(array $eventNames)
427
    {
428
        $this->eventNames = array_values($eventNames);
429
    }
430
431
    /**
432
     * get a collection of possible event names
433
     *
434
     * @return array
435
     */
436
    public function getEventNames()
437
    {
438
        $collection = $this->eventNames;
439
        if (empty($collection)) {
440
            $collection = null;
441
        }
442
443
        return $collection;
444
    }
445
446
    /**
447
     * Set the readOnly flag
448
     *
449
     * @param bool $readOnly ReadOnly flag
450
     *
451
     * @return void
452
     */
453
    public function setReadOnly($readOnly)
454
    {
455
        $this->readOnly = (bool) $readOnly;
456
    }
457
458
    /**
459
     * Get the readOnly flag.
460
     * Returns null if the flag is set to false so the serializer will ignore it.
461
     *
462
     * @return bool|null true if readOnly isset to true or null if not
463
     */
464
    public function getReadOnly()
465
    {
466
        return $this->readOnly ? true : null;
467
    }
468
}
469