Passed
Pull Request — master (#32)
by Viacheslav
02:34
created

Schema::getObjectItemClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Swaggest\JsonSchema;
4
5
6
use PhpLang\ScopeExit;
7
use Swaggest\JsonDiff\JsonDiff;
8
use Swaggest\JsonSchema\Constraint\Content;
9
use Swaggest\JsonSchema\Constraint\Format;
10
use Swaggest\JsonSchema\Constraint\Properties;
11
use Swaggest\JsonSchema\Constraint\Type;
12
use Swaggest\JsonSchema\Constraint\UniqueItems;
13
use Swaggest\JsonSchema\Exception\ArrayException;
14
use Swaggest\JsonSchema\Exception\ConstException;
15
use Swaggest\JsonSchema\Exception\EnumException;
16
use Swaggest\JsonSchema\Exception\LogicException;
17
use Swaggest\JsonSchema\Exception\NumericException;
18
use Swaggest\JsonSchema\Exception\ObjectException;
19
use Swaggest\JsonSchema\Exception\StringException;
20
use Swaggest\JsonSchema\Exception\TypeException;
21
use Swaggest\JsonSchema\Meta\MetaHolder;
22
use Swaggest\JsonSchema\Path\PointerUtil;
23
use Swaggest\JsonSchema\Structure\ClassStructure;
24
use Swaggest\JsonSchema\Structure\Egg;
25
use Swaggest\JsonSchema\Structure\ObjectItem;
26
use Swaggest\JsonSchema\Structure\ObjectItemContract;
27
28
/**
29
 * Class Schema
30
 * @package Swaggest\JsonSchema
31
 */
32
class Schema extends JsonSchema implements MetaHolder, SchemaContract
33
{
34
    const ENUM_NAMES_PROPERTY = 'x-enum-names';
35
    const CONST_PROPERTY = 'const';
36
37
    const DEFAULT_MAPPING = 'default';
38
39
    const VERSION_AUTO = 'a';
40
    const VERSION_DRAFT_04 = 4;
41
    const VERSION_DRAFT_06 = 6;
42
    const VERSION_DRAFT_07 = 7;
43
44
    const PROP_REF = '$ref';
45
    const PROP_ID = '$id';
46
    const PROP_ID_D4 = 'id';
47
48
    // Object
49
    /** @var null|Properties|Schema[]|Schema */
50
    public $properties;
51
    /** @var Schema|bool */
52
    public $additionalProperties;
53
    /** @var Schema[] */
54
    public $patternProperties;
55
    /** @var string[][]|Schema[]|\stdClass */
56
    public $dependencies;
57
58
    // Array
59
    /** @var null|Schema|Schema[] */
60
    public $items;
61
    /** @var null|Schema|bool */
62
    public $additionalItems;
63
64
    /** @var Schema[] */
65
    public $allOf;
66
    /** @var Schema */
67
    public $not;
68
    /** @var Schema[] */
69
    public $anyOf;
70
    /** @var Schema[] */
71
    public $oneOf;
72
73
    /** @var Schema */
74
    public $if;
75
    /** @var Schema */
76
    public $then;
77
    /** @var Schema */
78
    public $else;
79
80
81
    public $objectItemClass;
82
    private $useObjectAsArray = false;
83
84
    private $__dataToProperty = array();
85
    private $__propertyToData = array();
86
87
    private $__booleanSchema;
88
89 2
    public function addPropertyMapping($dataName, $propertyName, $mapping = self::DEFAULT_MAPPING)
90
    {
91 2
        $this->__dataToProperty[$mapping][$dataName] = $propertyName;
92 2
        $this->__propertyToData[$mapping][$propertyName] = $dataName;
93 2
        return $this;
94
    }
95
96
    /**
97
     * @param mixed $data
98
     * @param Context|null $options
99
     * @return SchemaContract
100
     * @throws Exception
101
     * @throws InvalidValue
102
     * @throws \Exception
103
     */
104 3179
    public static function import($data, Context $options = null)
105
    {
106 3179
        if (null === $options) {
107 20
            $options = new Context();
108
        }
109
110 3179
        $options->applyDefaults = false;
111
112 3179
        if (isset($options->schemasCache) && is_object($data)) {
113
            if ($options->schemasCache->contains($data)) {
114
                return $options->schemasCache->offsetGet($data);
115
            } else {
116
                $schema = parent::import($data, $options);
117
                $options->schemasCache->attach($data, $schema);
118
                return $schema;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $schema also could return the type Swaggest\JsonSchema\Structure\ClassStructureTrait which is incompatible with the documented return type Swaggest\JsonSchema\SchemaContract.
Loading history...
119
            }
120
        }
121
122
        // string $data is expected to be $ref uri
123 3179
        if (is_string($data)) {
124 4
            $data = (object)array(self::PROP_REF => $data);
125
        }
126
127 3179
        $data = self::unboolSchema($data);
128 3179
        if ($data instanceof SchemaContract) {
129 72
            return $data;
130
        }
131
132 3107
        return parent::import($data, $options);
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::import($data, $options) also could return the type Swaggest\JsonSchema\Structure\ClassStructureTrait which is incompatible with the documented return type Swaggest\JsonSchema\SchemaContract.
Loading history...
133
    }
134
135
    /**
136
     * @param mixed $data
137
     * @param Context|null $options
138
     * @return array|mixed|null|object|\stdClass
139
     * @throws Exception
140
     * @throws InvalidValue
141
     * @throws \Exception
142
     */
143 3201
    public function in($data, Context $options = null)
144
    {
145 3201
        if (null !== $this->__booleanSchema) {
146 72
            if ($this->__booleanSchema) {
147 36
                return $data;
148 36
            } elseif (empty($options->skipValidation)) {
149 18
                $this->fail(new InvalidValue('Denied by false schema'), '#');
150
            }
151
        }
152
153 3147
        if ($options === null) {
154 50
            $options = new Context();
155
        }
156
157 3147
        $options->import = true;
158
159 3147
        if ($options->refResolver === null) {
160 2828
            $options->refResolver = new RefResolver($data);
161
        } else {
162 1701
            $options->refResolver->setRootData($data);
163
        }
164
165 3147
        if ($options->remoteRefProvider) {
166 3086
            $options->refResolver->setRemoteRefProvider($options->remoteRefProvider);
167
        }
168
169 3147
        $options->refResolver->preProcessReferences($data, $options);
170
171 3147
        return $this->process($data, $options, '#');
172
    }
173
174
175
    /**
176
     * @param mixed $data
177
     * @param Context|null $options
178
     * @return array|mixed|null|object|\stdClass
179
     * @throws InvalidValue
180
     * @throws \Exception
181
     */
182 2365
    public function out($data, Context $options = null)
183
    {
184 2365
        if ($options === null) {
185 956
            $options = new Context();
186
        }
187
188 2365
        $options->circularReferences = new \SplObjectStorage();
189 2365
        $options->import = false;
190 2365
        return $this->process($data, $options);
191
    }
192
193
    /**
194
     * @param mixed $data
195
     * @param Context $options
196
     * @param string $path
197
     * @throws InvalidValue
198
     * @throws \Exception
199
     */
200 3129
    private function processType($data, Context $options, $path = '#')
201
    {
202 3129
        if ($options->tolerateStrings && is_string($data)) {
203
            $valid = Type::readString($this->type, $data);
204
        } else {
205 3129
            $valid = Type::isValid($this->type, $data, $options->version);
206
        }
207 3129
        if (!$valid) {
208 675
            $this->fail(new TypeException(ucfirst(
209 675
                    implode(', ', is_array($this->type) ? $this->type : array($this->type))
210 675
                    . ' expected, ' . json_encode($data) . ' received')
211 675
            ), $path);
212
        }
213 3127
    }
214
215
    /**
216
     * @param mixed $data
217
     * @param string $path
218
     * @throws InvalidValue
219
     * @throws \Exception
220
     */
221 1467
    private function processEnum($data, $path = '#')
222
    {
223 1467
        $enumOk = false;
224 1467
        foreach ($this->enum as $item) {
225 1467
            if ($item === $data) {
226 1447
                $enumOk = true;
227 1447
                break;
228
            } else {
229 1403
                if (is_array($item) || is_object($item)) {
230 12
                    $diff = new JsonDiff($item, $data, JsonDiff::STOP_ON_DIFF);
231 12
                    if ($diff->getDiffCnt() === 0) {
232 3
                        $enumOk = true;
233 1403
                        break;
234
                    }
235
                }
236
            }
237
        }
238 1467
        if (!$enumOk) {
239 94
            $this->fail(new EnumException('Enum failed, enum: ' . json_encode($this->enum) . ', data: ' . json_encode($data)), $path);
240
        }
241 1450
    }
242
243
    /**
244
     * @param mixed $data
245
     * @param string $path
246
     * @throws InvalidValue
247
     * @throws \Swaggest\JsonDiff\Exception
248
     */
249 43
    private function processConst($data, $path)
250
    {
251 43
        if ($this->const !== $data) {
252 37
            if ((is_object($this->const) && is_object($data))
253 37
                || (is_array($this->const) && is_array($data))) {
254 15
                $diff = new JsonDiff($this->const, $data,
255 15
                    JsonDiff::STOP_ON_DIFF);
256 15
                if ($diff->getDiffCnt() != 0) {
257 15
                    $this->fail(new ConstException('Const failed'), $path);
258
                }
259
            } else {
260 22
                $this->fail(new ConstException('Const failed'), $path);
261
            }
262
        }
263 20
    }
264
265
    /**
266
     * @param mixed $data
267
     * @param Context $options
268
     * @param string $path
269
     * @throws InvalidValue
270
     * @throws \Exception
271
     * @throws \Swaggest\JsonDiff\Exception
272
     */
273 69
    private function processNot($data, Context $options, $path)
274
    {
275 69
        $exception = false;
276
        try {
277 69
            self::unboolSchema($this->not)->process($data, $options, $path . '->not');
278 16
        } catch (InvalidValue $exception) {
279
            // Expected exception
280
        }
281 69
        if ($exception === false) {
282 55
            $this->fail(new LogicException('Not ' . json_encode($this->not) . ' expected, ' . json_encode($data) . ' received'), $path);
283
        }
284 16
    }
285
286
    /**
287
     * @param string $data
288
     * @param string $path
289
     * @throws InvalidValue
290
     */
291 2230
    private function processString($data, $path)
292
    {
293 2230
        if ($this->minLength !== null) {
294 38
            if (mb_strlen($data, 'UTF-8') < $this->minLength) {
295 9
                $this->fail(new StringException('String is too short', StringException::TOO_SHORT), $path);
296
            }
297
        }
298 2224
        if ($this->maxLength !== null) {
299 43
            if (mb_strlen($data, 'UTF-8') > $this->maxLength) {
300 19
                $this->fail(new StringException('String is too long', StringException::TOO_LONG), $path);
301
            }
302
        }
303 2221
        if ($this->pattern !== null) {
304 18
            if (0 === preg_match(Helper::toPregPattern($this->pattern), $data)) {
305 4
                $this->fail(new StringException(json_encode($data) . ' does not match to '
306 4
                    . $this->pattern, StringException::PATTERN_MISMATCH), $path);
307
            }
308
        }
309 2221
        if ($this->format !== null) {
310 404
            $validationError = Format::validationError($this->format, $data);
311 404
            if ($validationError !== null) {
312 137
                if (!($this->format === "uri" && substr($path, -3) === ':id')) {
313 122
                    $this->fail(new StringException($validationError), $path);
314
                }
315
            }
316
        }
317 2221
    }
318
319
    /**
320
     * @param float|int $data
321
     * @param string $path
322
     * @throws InvalidValue
323
     */
324 1041
    private function processNumeric($data, $path)
325
    {
326 1041
        if ($this->multipleOf !== null) {
327 39
            $div = $data / $this->multipleOf;
328 39
            if ($div != (int)$div) {
329 15
                $this->fail(new NumericException($data . ' is not multiple of ' . $this->multipleOf, NumericException::MULTIPLE_OF), $path);
330
            }
331
        }
332
333 1041
        if ($this->exclusiveMaximum !== null && !is_bool($this->exclusiveMaximum)) {
334 32
            if ($data >= $this->exclusiveMaximum) {
335 18
                $this->fail(new NumericException(
336 18
                    'Value less or equal than ' . $this->exclusiveMaximum . ' expected, ' . $data . ' received',
337 18
                    NumericException::MAXIMUM), $path);
338
            }
339
        }
340
341 1041
        if ($this->exclusiveMinimum !== null && !is_bool($this->exclusiveMinimum)) {
342 24
            if ($data <= $this->exclusiveMinimum) {
343 12
                $this->fail(new NumericException(
344 12
                    'Value more or equal than ' . $this->exclusiveMinimum . ' expected, ' . $data . ' received',
345 12
                    NumericException::MINIMUM), $path);
346
            }
347
        }
348
349 1041
        if ($this->maximum !== null) {
350 43
            if ($this->exclusiveMaximum === true) {
351 3
                if ($data >= $this->maximum) {
352 2
                    $this->fail(new NumericException(
353 2
                        'Value less or equal than ' . $this->maximum . ' expected, ' . $data . ' received',
354 3
                        NumericException::MAXIMUM), $path);
355
                }
356
            } else {
357 40
                if ($data > $this->maximum) {
358 13
                    $this->fail(new NumericException(
359 13
                        'Value less than ' . $this->minimum . ' expected, ' . $data . ' received',
360 13
                        NumericException::MAXIMUM), $path);
361
                }
362
            }
363
        }
364
365 1041
        if ($this->minimum !== null) {
366 516
            if ($this->exclusiveMinimum === true) {
367 93
                if ($data <= $this->minimum) {
368 2
                    $this->fail(new NumericException(
369 2
                        'Value more or equal than ' . $this->minimum . ' expected, ' . $data . ' received',
370 93
                        NumericException::MINIMUM), $path);
371
                }
372
            } else {
373 441
                if ($data < $this->minimum) {
374 43
                    $this->fail(new NumericException(
375 43
                        'Value more than ' . $this->minimum . ' expected, ' . $data . ' received',
376 43
                        NumericException::MINIMUM), $path);
377
                }
378
            }
379
        }
380 1040
    }
381
382
    /**
383
     * @param mixed $data
384
     * @param Context $options
385
     * @param string $path
386
     * @return array|mixed|null|object|\stdClass
387
     * @throws InvalidValue
388
     * @throws \Exception
389
     * @throws \Swaggest\JsonDiff\Exception
390
     */
391 101
    private function processOneOf($data, Context $options, $path)
392
    {
393 101
        $successes = 0;
394 101
        $failures = '';
395 101
        $subErrors = [];
396 101
        $skipValidation = false;
397 101
        if ($options->skipValidation) {
398 41
            $skipValidation = true;
399 41
            $options->skipValidation = false;
400
        }
401
402 101
        $result = $data;
403 101
        foreach ($this->oneOf as $index => $item) {
404
            try {
405 101
                $result = self::unboolSchema($item)->process($data, $options, $path . '->oneOf[' . $index . ']');
406 79
                $successes++;
407 79
                if ($successes > 1 || $options->skipValidation) {
408 79
                    break;
409
                }
410 69
            } catch (InvalidValue $exception) {
411 69
                $subErrors[$index] = $exception;
412 101
                $failures .= ' ' . $index . ': ' . Helper::padLines(' ', $exception->getMessage()) . "\n";
413
                // Expected exception
414
            }
415
        }
416 101
        if ($skipValidation) {
0 ignored issues
show
introduced by
The condition $skipValidation is always true.
Loading history...
417 41
            $options->skipValidation = true;
418 41
            if ($successes === 0) {
419 8
                $result = self::unboolSchema($this->oneOf[0])->process($data, $options, $path . '->oneOf[0]');
420
            }
421
        }
422
423 101
        if (!$options->skipValidation) {
424 60
            if ($successes === 0) {
425 15
                $exception = new LogicException('No valid results for oneOf {' . "\n" . substr($failures, 0, -1) . "\n}");
426 15
                $exception->error = 'No valid results for oneOf';
427 15
                $exception->subErrors = $subErrors;
428 15
                $this->fail($exception, $path);
429 46
            } elseif ($successes > 1) {
430 17
                $exception = new LogicException('More than 1 valid result for oneOf: '
431 17
                    . $successes . '/' . count($this->oneOf) . ' valid results for oneOf {'
432 17
                    . "\n" . substr($failures, 0, -1) . "\n}");
433 17
                $exception->error = 'More than 1 valid result for oneOf';
434 17
                $exception->subErrors = $subErrors;
435 17
                $this->fail($exception, $path);
436
            }
437
        }
438 71
        return $result;
439
    }
440
441
    /**
442
     * @param mixed $data
443
     * @param Context $options
444
     * @param string $path
445
     * @return array|mixed|null|object|\stdClass
446
     * @throws InvalidValue
447
     * @throws \Exception
448
     * @throws \Swaggest\JsonDiff\Exception
449
     */
450 1705
    private function processAnyOf($data, Context $options, $path)
451
    {
452 1705
        $successes = 0;
453 1705
        $failures = '';
454 1705
        $subErrors = [];
455 1705
        $result = $data;
456 1705
        foreach ($this->anyOf as $index => $item) {
457
            try {
458 1705
                $result = self::unboolSchema($item)->process($data, $options, $path . '->anyOf[' . $index . ']');
459 1699
                $successes++;
460 1699
                if ($successes) {
461 1699
                    break;
462
                }
463 430
            } catch (InvalidValue $exception) {
464 430
                $subErrors[$index] = $exception;
465 430
                $failures .= ' ' . $index . ': ' . $exception->getMessage() . "\n";
466
                // Expected exception
467
            }
468
        }
469 1705
        if (!$successes && !$options->skipValidation) {
470 29
            $exception = new LogicException('No valid results for anyOf {' . "\n"
471 29
                . substr(Helper::padLines(' ', $failures, false), 0, -1)
472 29
                . "\n}");
473 29
            $exception->error = 'No valid results for anyOf';
474 29
            $exception->subErrors = $subErrors;
475 29
            $this->fail($exception, $path);
476
        }
477 1699
        return $result;
478
    }
479
480
    /**
481
     * @param mixed $data
482
     * @param Context $options
483
     * @param string $path
484
     * @return array|mixed|null|object|\stdClass
485
     * @throws InvalidValue
486
     * @throws \Exception
487
     * @throws \Swaggest\JsonDiff\Exception
488
     */
489 352
    private function processAllOf($data, Context $options, $path)
490
    {
491 352
        $result = $data;
492 352
        foreach ($this->allOf as $index => $item) {
493 352
            $result = self::unboolSchema($item)->process($data, $options, $path . '->allOf[' . $index . ']');
494
        }
495 314
        return $result;
496
    }
497
498
    /**
499
     * @param mixed $data
500
     * @param Context $options
501
     * @param string $path
502
     * @return array|mixed|null|object|\stdClass
503
     * @throws InvalidValue
504
     * @throws \Exception
505
     * @throws \Swaggest\JsonDiff\Exception
506
     */
507 26
    private function processIf($data, Context $options, $path)
508
    {
509 26
        $valid = true;
510
        try {
511 26
            self::unboolSchema($this->if)->process($data, $options, $path . '->if');
512 13
        } catch (InvalidValue $exception) {
513 13
            $valid = false;
514
        }
515 26
        if ($valid) {
516 18
            if ($this->then !== null) {
517 18
                return self::unboolSchema($this->then)->process($data, $options, $path . '->then');
518
            }
519
        } else {
520 13
            if ($this->else !== null) {
521 6
                return self::unboolSchema($this->else)->process($data, $options, $path . '->else');
522
            }
523
        }
524 10
        return null;
525
    }
526
527
    /**
528
     * @param \stdClass $data
529
     * @param Context $options
530
     * @param string $path
531
     * @throws InvalidValue
532
     */
533 161
    private function processObjectRequired($data, Context $options, $path)
534
    {
535 161
        if (isset($this->__dataToProperty[$options->mapping])) {
536 2
            if ($options->import) {
537 1
                foreach ($this->required as $item) {
538 1
                    if (isset($this->__propertyToData[$options->mapping][$item])) {
539 1
                        $item = $this->__propertyToData[$options->mapping][$item];
540
                    }
541 1
                    if (!property_exists($data, $item)) {
542 1
                        $this->fail(new ObjectException('Required property missing: ' . $item . ', data: ' . json_encode($data, JSON_UNESCAPED_SLASHES), ObjectException::REQUIRED), $path);
543
                    }
544
                }
545
            } else {
546 2
                foreach ($this->required as $item) {
547 2
                    if (isset($this->__dataToProperty[$options->mapping][$item])) {
548
                        $item = $this->__dataToProperty[$options->mapping][$item];
549
                    }
550 2
                    if (!property_exists($data, $item)) {
551 2
                        $this->fail(new ObjectException('Required property missing: ' . $item . ', data: ' . json_encode($data, JSON_UNESCAPED_SLASHES), ObjectException::REQUIRED), $path);
552
                    }
553
                }
554
            }
555
556
        } else {
557 160
            foreach ($this->required as $item) {
558 156
                if (!property_exists($data, $item)) {
559 156
                    $this->fail(new ObjectException('Required property missing: ' . $item . ', data: ' . json_encode($data, JSON_UNESCAPED_SLASHES), ObjectException::REQUIRED), $path);
560
                }
561
            }
562
        }
563 129
    }
564
565
    /**
566
     * @param \stdClass $data
567
     * @param Context $options
568
     * @param string $path
569
     * @param ObjectItemContract|null $result
570
     * @return array|null|ClassStructure|ObjectItemContract
571
     * @throws InvalidValue
572
     * @throws \Exception
573
     * @throws \Swaggest\JsonDiff\Exception
574
     */
575 3142
    private function processObject($data, Context $options, $path, $result = null)
576
    {
577 3142
        $import = $options->import;
578
579 3142
        if (!$options->skipValidation && $this->required !== null) {
580 161
            $this->processObjectRequired($data, $options, $path);
581
        }
582
583 3141
        if ($import) {
584 3129
            if (!$options->validateOnly) {
585
586 3129
                if ($this->useObjectAsArray) {
587 1
                    $result = array();
588 3128
                } elseif (!$result instanceof ObjectItemContract) {
589
                    //* todo check performance impact
590 3128
                    if (null === $this->objectItemClass) {
591 1152
                        $result = new ObjectItem();
592
                    } else {
593 3117
                        $className = $this->objectItemClass;
594 3117
                        if ($options->objectItemClassMapping !== null) {
595
                            if (isset($options->objectItemClassMapping[$className])) {
596
                                $className = $options->objectItemClassMapping[$className];
597
                            }
598
                        }
599 3117
                        $result = new $className;
600
                    }
601
                    //*/
602
603
604 3128
                    if ($result instanceof ClassStructure) {
605 3116
                        if ($result->__validateOnSet) {
0 ignored issues
show
Bug Best Practice introduced by
The property __validateOnSet does not exist on Swaggest\JsonSchema\Structure\ObjectItem. Since you implemented __get, consider adding a @property annotation.
Loading history...
606 3116
                            $result->__validateOnSet = false;
0 ignored issues
show
Bug Best Practice introduced by
The property __validateOnSet does not exist on Swaggest\JsonSchema\Structure\ObjectItem. Since you implemented __set, consider adding a @property annotation.
Loading history...
607
                            /** @noinspection PhpUnusedLocalVariableInspection */
608
                            /* todo check performance impact
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
609
                            $validateOnSetHandler = new ScopeExit(function () use ($result) {
610
                                $result->__validateOnSet = true;
611
                            });
612
                            //*/
613
                        }
614
                    }
615
616
                    //* todo check performance impact
617 3128
                    if ($result instanceof ObjectItemContract) {
618 3128
                        $result->setDocumentPath($path);
619
                    }
620
                    //*/
621
                }
622
            }
623
        }
624
625
        // @todo better check for schema id
626
627 3141
        if ($import
628 3141
            && isset($data->{Schema::PROP_ID_D4})
629 3141
            && ($options->version === Schema::VERSION_DRAFT_04 || $options->version === Schema::VERSION_AUTO)
630 3141
            && is_string($data->{Schema::PROP_ID_D4})) {
631 30
            $id = $data->{Schema::PROP_ID_D4};
632 30
            $refResolver = $options->refResolver;
633 30
            $parentScope = $refResolver->updateResolutionScope($id);
634
            /** @noinspection PhpUnusedLocalVariableInspection */
635
            $defer = new ScopeExit(function () use ($parentScope, $refResolver) {
0 ignored issues
show
Unused Code introduced by
The assignment to $defer is dead and can be removed.
Loading history...
636 30
                $refResolver->setResolutionScope($parentScope);
637 30
            });
638
        }
639
640 3141
        if ($import
641 3141
            && isset($data->{self::PROP_ID})
642 3141
            && ($options->version >= Schema::VERSION_DRAFT_06 || $options->version === Schema::VERSION_AUTO)
643 3141
            && is_string($data->{self::PROP_ID})) {
644 114
            $id = $data->{self::PROP_ID};
645 114
            $refResolver = $options->refResolver;
646 114
            $parentScope = $refResolver->updateResolutionScope($id);
647
            /** @noinspection PhpUnusedLocalVariableInspection */
648
            $defer = new ScopeExit(function () use ($parentScope, $refResolver) {
649 114
                $refResolver->setResolutionScope($parentScope);
650 114
            });
651
        }
652
653 3141
        if ($import) {
654
            try {
655
                while (
656 3129
                    isset($data->{self::PROP_REF})
657 3129
                    && is_string($data->{self::PROP_REF})
658 3129
                    && !isset($this->properties[self::PROP_REF])
659
                ) {
660 410
                    $refString = $data->{self::PROP_REF};
661
662
                    // todo check performance impact
663 410
                    if ($refString === 'http://json-schema.org/draft-04/schema#'
664 400
                        || $refString === 'http://json-schema.org/draft-06/schema#'
665 410
                        || $refString === 'http://json-schema.org/draft-07/schema#') {
666 26
                        return Schema::schema();
667
                    }
668
669
                    // TODO consider process # by reference here ?
670 384
                    $refResolver = $options->refResolver;
671 384
                    $preRefScope = $refResolver->getResolutionScope();
672
                    /** @noinspection PhpUnusedLocalVariableInspection */
673 384
                    $deferRefScope = new ScopeExit(function () use ($preRefScope, $refResolver) {
0 ignored issues
show
Unused Code introduced by
The assignment to $deferRefScope is dead and can be removed.
Loading history...
674 384
                        $refResolver->setResolutionScope($preRefScope);
675 384
                    });
676
677 384
                    $ref = $refResolver->resolveReference($refString);
678 384
                    $data = self::unboolSchemaData($ref->getData());
679 384
                    if (!$options->validateOnly) {
680 384
                        if ($ref->isImported()) {
681 173
                            $refResult = $ref->getImported();
682 173
                            return $refResult;
683
                        }
684 384
                        $ref->setImported($result);
685
                        try {
686 384
                            $refResult = $this->process($data, $options, $path . '->$ref:' . $refString, $result);
687 384
                            if ($refResult instanceof ObjectItemContract) {
688 384
                                $refResult->setFromRef($refString);
689
                            }
690 384
                            $ref->setImported($refResult);
691 1
                        } catch (InvalidValue $exception) {
692 1
                            $ref->unsetImported();
693 1
                            throw $exception;
694
                        }
695 384
                        return $refResult;
696
                    } else {
697
                        $this->process($data, $options, $path . '->$ref:' . $refString);
698
                    }
699
                }
700 1
            } catch (InvalidValue $exception) {
701 1
                $this->fail($exception, $path);
702
            }
703
        }
704
705
        /** @var Schema[]|null $properties */
706 3141
        $properties = null;
707
708 3141
        $nestedProperties = null;
709 3141
        if ($this->properties !== null) {
710 3127
            $properties = $this->properties->toArray(); // todo call directly
711 3127
            if ($this->properties instanceof Properties) {
712 3127
                $nestedProperties = $this->properties->nestedProperties;
0 ignored issues
show
Bug Best Practice introduced by
The property nestedProperties does not exist on Swaggest\JsonSchema\Schema. Since you implemented __get, consider adding a @property annotation.
Loading history...
713
            } else {
714 575
                $nestedProperties = array();
715
            }
716
        }
717
718 3141
        $array = array();
719 3141
        if (!empty($this->__dataToProperty[$options->mapping])) { // todo skip on $options->validateOnly
720 3109
            foreach ((array)$data as $key => $value) {
721 3105
                if ($import) {
722 3104
                    if (isset($this->__dataToProperty[$options->mapping][$key])) {
723 3104
                        $key = $this->__dataToProperty[$options->mapping][$key];
724
                    }
725
                } else {
726 20
                    if (isset($this->__propertyToData[$options->mapping][$key])) {
727 1
                        $key = $this->__propertyToData[$options->mapping][$key];
728
                    }
729
                }
730 3109
                $array[$key] = $value;
731
            }
732
        } else {
733 1229
            $array = (array)$data;
734
        }
735
736 3141
        if (!$options->skipValidation) {
737 3120
            if ($this->minProperties !== null && count($array) < $this->minProperties) {
738 4
                $this->fail(new ObjectException("Not enough properties", ObjectException::TOO_FEW), $path);
739
            }
740 3120
            if ($this->maxProperties !== null && count($array) > $this->maxProperties) {
741 3
                $this->fail(new ObjectException("Too many properties", ObjectException::TOO_MANY), $path);
742
            }
743 3120
            if ($this->propertyNames !== null) {
744 17
                $propertyNames = self::unboolSchema($this->propertyNames);
745 17
                foreach ($array as $key => $tmp) {
746 10
                    $propertyNames->process($key, $options, $path . '->propertyNames:' . $key);
747
                }
748
            }
749
        }
750
751 3141
        $defaultApplied = array();
752 3141
        if ($import
753 3141
            && !$options->validateOnly
754 3141
            && $options->applyDefaults
755 3141
            && $properties !== null
756
        ) {
757 34
            foreach ($properties as $key => $property) {
758
                // todo check when property is \stdClass `{}` here (RefTest)
759 32
                if ($property instanceof SchemaContract && null !== $default = $property->getDefault()) {
760 6
                    if (isset($this->__dataToProperty[$options->mapping][$key])) {
761
                        $key = $this->__dataToProperty[$options->mapping][$key];
762
                    }
763 6
                    if (!array_key_exists($key, $array)) {
764 6
                        $defaultApplied[$key] = true;
765 32
                        $array[$key] = $default;
766
                    }
767
                }
768
            }
769
        }
770
771 3141
        foreach ($array as $key => $value) {
772 3131
            if ($key === '' && PHP_VERSION_ID < 71000) {
773 1
                $this->fail(new InvalidValue('Empty property name'), $path);
774
            }
775
776 3130
            $found = false;
777
778 3130
            if (!$options->skipValidation && !empty($this->dependencies)) {
779 73
                $deps = $this->dependencies;
780 73
                if (isset($deps->$key)) {
781 63
                    $dependencies = $deps->$key;
782 63
                    $dependencies = self::unboolSchema($dependencies);
783 63
                    if ($dependencies instanceof SchemaContract) {
784 29
                        $dependencies->process($data, $options, $path . '->dependencies:' . $key);
785
                    } else {
786 34
                        foreach ($dependencies as $item) {
787 31
                            if (!property_exists($data, $item)) {
788 18
                                $this->fail(new ObjectException('Dependency property missing: ' . $item,
789 31
                                    ObjectException::DEPENDENCY_MISSING), $path);
790
                            }
791
                        }
792
                    }
793
                }
794
            }
795
796 3130
            $propertyFound = false;
797 3130
            if (isset($properties[$key])) {
798
                /** @var Schema[] $properties */
799 3120
                $prop = self::unboolSchema($properties[$key]);
800 3120
                $propertyFound = true;
801 3120
                $found = true;
802 3120
                if ($prop instanceof SchemaContract) {
803 3063
                    $value = $prop->process(
804 3063
                        $value,
805 3063
                        isset($defaultApplied[$key]) ? $options->withDefault() : $options,
806 3063
                        $path . '->properties:' . $key
807
                    );
808
                }
809
            }
810
811
            /** @var Egg[] $nestedEggs */
812 3125
            $nestedEggs = null;
813 3125
            if (isset($nestedProperties[$key])) {
814 6
                $found = true;
815 6
                $nestedEggs = $nestedProperties[$key];
816
                // todo iterate all nested props?
817 6
                $value = self::unboolSchema($nestedEggs[0]->propertySchema)->process($value, $options, $path . '->nestedProperties:' . $key);
818
            }
819
820 3125
            if ($this->patternProperties !== null) {
821 166
                foreach ($this->patternProperties as $pattern => $propertySchema) {
822 166
                    if (preg_match(Helper::toPregPattern($pattern), $key)) {
823 120
                        $found = true;
824 120
                        $value = self::unboolSchema($propertySchema)->process($value, $options,
825 120
                            $path . '->patternProperties[' . strtr($pattern, array('~' => '~1', ':' => '~2')) . ']:' . $key);
826 93
                        if (!$options->validateOnly && $import) {
827 144
                            $result->addPatternPropertyName($pattern, $key);
0 ignored issues
show
Bug introduced by
The method addPatternPropertyName() does not exist on Swaggest\JsonSchema\Structure\ObjectItemContract. It seems like you code against a sub-type of said class. However, the method does not exist in Swaggest\JsonSchema\Stru...\ClassStructureContract. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

827
                            $result->/** @scrutinizer ignore-call */ 
828
                                     addPatternPropertyName($pattern, $key);
Loading history...
828
                        }
829
                        //break; // todo manage multiple import data properly (pattern accessor)
830
                    }
831
                }
832
            }
833 3125
            if (!$found && $this->additionalProperties !== null) {
834 989
                if (!$options->skipValidation && $this->additionalProperties === false) {
835 12
                    $this->fail(new ObjectException('Additional properties not allowed'), $path . ':' . $key);
836
                }
837
838 989
                if ($this->additionalProperties instanceof SchemaContract) {
839 989
                    $value = $this->additionalProperties->process($value, $options, $path . '->additionalProperties:' . $key);
840
                }
841
842 982
                if ($import && !$this->useObjectAsArray && !$options->validateOnly) {
843 981
                    $result->addAdditionalPropertyName($key);
844
                }
845
            }
846
847 3121
            if (!$options->validateOnly && $nestedEggs && $import) {
848 5
                foreach ($nestedEggs as $nestedEgg) {
849 5
                    $result->setNestedProperty($key, $value, $nestedEgg);
850
                }
851 5
                if ($propertyFound) {
852 5
                    $result->$key = $value;
853
                }
854
            } else {
855 3120
                if ($this->useObjectAsArray && $import) {
856 1
                    $result[$key] = $value;
857
                } else {
858 3120
                    if ($found || !$import) {
859 3119
                        $result->$key = $value;
860 1136
                    } elseif (!isset($result->$key)) {
861 3121
                        $result->$key = $value;
862
                    }
863
                }
864
            }
865
        }
866
867 3129
        return $result;
868
    }
869
870
    /**
871
     * @param array $data
872
     * @param Context $options
873
     * @param string $path
874
     * @param array $result
875
     * @return mixed
876
     * @throws InvalidValue
877
     * @throws \Exception
878
     * @throws \Swaggest\JsonDiff\Exception
879
     */
880 1210
    private function processArray($data, Context $options, $path, $result)
881
    {
882 1210
        $count = count($data);
883 1210
        if (!$options->skipValidation) {
884 1010
            if ($this->minItems !== null && $count < $this->minItems) {
885 9
                $this->fail(new ArrayException("Not enough items in array"), $path);
886
            }
887
888 1004
            if ($this->maxItems !== null && $count > $this->maxItems) {
889 6
                $this->fail(new ArrayException("Too many items in array"), $path);
890
            }
891
        }
892
893 1198
        $pathItems = 'items';
894 1198
        $this->items = self::unboolSchema($this->items);
895 1198
        if ($this->items instanceof SchemaContract) {
0 ignored issues
show
introduced by
$this->items is never a sub-type of Swaggest\JsonSchema\SchemaContract.
Loading history...
896 845
            $items = array();
897 845
            $additionalItems = $this->items;
898 690
        } elseif ($this->items === null) { // items defaults to empty schema so everything is valid
899 690
            $items = array();
900 690
            $additionalItems = true;
901
        } else { // listed items
902 104
            $items = $this->items;
903 104
            $additionalItems = $this->additionalItems;
904 104
            $pathItems = 'additionalItems';
905
        }
906
907
        /**
908
         * @var Schema|Schema[] $items
909
         * @var null|bool|Schema $additionalItems
910
         */
911 1198
        $itemsLen = is_array($items) ? count($items) : 0;
912 1198
        $index = 0;
913 1198
        foreach ($result as $key => $value) {
914 1073
            if ($index < $itemsLen) {
915 94
                $itemSchema = self::unboolSchema($items[$index]);
916 94
                $result[$key] = $itemSchema->process($value, $options, $path . '->items:' . $index);
917
            } else {
918 1073
                if ($additionalItems instanceof SchemaContract) {
919 819
                    $result[$key] = $additionalItems->process($value, $options, $path . '->' . $pathItems
920 819
                        . '[' . $index . ']:' . $index);
921 574
                } elseif (!$options->skipValidation && $additionalItems === false) {
922 6
                    $this->fail(new ArrayException('Unexpected array item'), $path);
923
                }
924
            }
925 1053
            ++$index;
926
        }
927
928 1174
        if (!$options->skipValidation && $this->uniqueItems) {
929 508
            if (!UniqueItems::isValid($data)) {
930 19
                $this->fail(new ArrayException('Array is not unique'), $path);
931
            }
932
        }
933
934 1155
        if (!$options->skipValidation && $this->contains !== null) {
935
            /** @var Schema|bool $contains */
936 36
            $contains = $this->contains;
937 36
            if ($contains === false) {
938 4
                $this->fail(new ArrayException('Contains is false'), $path);
939
            }
940 32
            if ($count === 0) {
941 7
                $this->fail(new ArrayException('Empty array fails contains constraint'), $path);
942
            }
943 25
            if ($contains === true) {
944 2
                $contains = self::unboolSchema($contains);
945
            }
946 25
            $containsOk = false;
947 25
            foreach ($data as $key => $item) {
948
                try {
949 25
                    $contains->process($item, $options, $path . '->' . $key);
950 17
                    $containsOk = true;
951 17
                    break;
952 21
                } catch (InvalidValue $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
953
                }
954
            }
955 25
            if (!$containsOk) {
956 8
                $this->fail(new ArrayException('Array fails contains constraint'), $path);
957
            }
958
        }
959 1136
        return $result;
960
    }
961
962
    /**
963
     * @param mixed|string $data
964
     * @param Context $options
965
     * @param string $path
966
     * @return bool|mixed|string
967
     * @throws InvalidValue
968
     */
969 14
    private function processContent($data, Context $options, $path)
970
    {
971
        try {
972 14
            if ($options->unpackContentMediaType) {
973 7
                return Content::process($options, $this->contentEncoding, $this->contentMediaType, $data, $options->import);
974
            } else {
975 7
                Content::process($options, $this->contentEncoding, $this->contentMediaType, $data, true);
976
            }
977 4
        } catch (InvalidValue $exception) {
978 4
            $this->fail($exception, $path);
979
        }
980 7
        return $data;
981
    }
982
983
    /**
984
     * @param mixed $data
985
     * @param Context $options
986
     * @param string $path
987
     * @param mixed|null $result
988
     * @return array|mixed|null|object|\stdClass
989
     * @throws InvalidValue
990
     * @throws \Exception
991
     * @throws \Swaggest\JsonDiff\Exception
992
     */
993 3188
    public function process($data, Context $options, $path = '#', $result = null)
994
    {
995 3188
        $import = $options->import;
996
997 3188
        if ($ref = $this->getFromRef()) {
998 357
            $path .= '->$ref[' . strtr($ref, array('~' => '~1', ':' => '~2')) . ']';
999
        }
1000
1001 3188
        if (!$import && $data instanceof ObjectItemContract) {
1002 781
            $result = new \stdClass();
1003
1004 781
            if ($ref = $data->getFromRef()) {
1005 1
                $result->{self::PROP_REF} = $ref;
1006 1
                return $result;
1007
            }
1008
1009 781
            if ($options->circularReferences->contains($data)) {
1010
                /** @noinspection PhpIllegalArrayKeyTypeInspection */
1011 1
                $path = $options->circularReferences[$data];
1012 1
                $result->{self::PROP_REF} = PointerUtil::getDataPointer($path, true);
1013 1
                return $result;
1014
            }
1015 781
            $options->circularReferences->attach($data, $path);
1016
1017 781
            $data = $data->jsonSerialize();
1018
        }
1019 3188
        if (!$import && is_array($data) && $this->useObjectAsArray) {
1020 1
            $data = (object)$data;
1021
        }
1022
1023 3188
        if (null !== $options->dataPreProcessor) {
1024
            $data = $options->dataPreProcessor->process($data, $this, $import);
1025
        }
1026
1027 3188
        if ($result === null) {
1028 3188
            $result = $data;
1029
        }
1030
1031 3188
        if ($options->skipValidation) {
1032 1416
            goto skipValidation;
1033
        }
1034
1035 3150
        if ($this->type !== null) {
1036 3129
            $this->processType($data, $options, $path);
1037
        }
1038
1039 3149
        if ($this->enum !== null) {
1040 1467
            $this->processEnum($data, $path);
1041
        }
1042
1043 3149
        if (array_key_exists(self::CONST_PROPERTY, $this->__arrayOfData)) {
1044 43
            $this->processConst($data, $path);
1045
        }
1046
1047 3149
        if ($this->not !== null) {
1048 69
            $this->processNot($data, $options, $path);
1049
        }
1050
1051 3149
        if (is_string($data)) {
1052 2230
            $this->processString($data, $path);
1053
        }
1054
1055 3149
        if (is_int($data) || is_float($data)) {
1056 1041
            $this->processNumeric($data, $path);
1057
        }
1058
1059 3149
        if ($this->if !== null) {
1060 26
            $result = $this->processIf($data, $options, $path);
1061
        }
1062
1063
        skipValidation:
1064
1065 3187
        if ($this->oneOf !== null) {
1066 101
            $result = $this->processOneOf($data, $options, $path);
1067
        }
1068
1069 3187
        if ($this->anyOf !== null) {
1070 1705
            $result = $this->processAnyOf($data, $options, $path);
1071
        }
1072
1073 3187
        if ($this->allOf !== null) {
1074 352
            $result = $this->processAllOf($data, $options, $path);
1075
        }
1076
1077 3187
        if ($data instanceof \stdClass) {
1078 3142
            $result = $this->processObject($data, $options, $path, $result);
1079
        }
1080
1081 3184
        if (is_array($data)) {
1082 1210
            $result = $this->processArray($data, $options, $path, $result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type object and stdClass and Swaggest\JsonSchema\Structure\ObjectItemContract and Swaggest\JsonSchema\Structure\ClassStructure; however, parameter $result of Swaggest\JsonSchema\Schema::processArray() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1082
            $result = $this->processArray($data, $options, $path, /** @scrutinizer ignore-type */ $result);
Loading history...
1083
        }
1084
1085 3184
        if ($this->contentEncoding !== null || $this->contentMediaType !== null) {
1086 14
            $result = $this->processContent($data, $options, $path);
1087
        }
1088
1089 3184
        return $result;
1090
    }
1091
1092
    /**
1093
     * @param boolean $useObjectAsArray
1094
     * @return Schema
1095
     */
1096 1
    public function setUseObjectAsArray($useObjectAsArray)
1097
    {
1098 1
        $this->useObjectAsArray = $useObjectAsArray;
1099 1
        return $this;
1100
    }
1101
1102
    /**
1103
     * @param InvalidValue $exception
1104
     * @param string $path
1105
     * @throws InvalidValue
1106
     */
1107 1217
    private function fail(InvalidValue $exception, $path)
1108
    {
1109 1217
        if ($path !== '#') {
1110 755
            $exception->addPath($path);
1111
        }
1112 1217
        throw $exception;
1113
    }
1114
1115 13
    public static function integer()
1116
    {
1117 13
        $schema = new static();
1118 13
        $schema->type = Type::INTEGER;
1119 13
        return $schema;
1120
    }
1121
1122 4
    public static function number()
1123
    {
1124 4
        $schema = new static();
1125 4
        $schema->type = Type::NUMBER;
1126 4
        return $schema;
1127
    }
1128
1129 8
    public static function string()
1130
    {
1131 8
        $schema = new static();
1132 8
        $schema->type = Type::STRING;
1133 8
        return $schema;
1134
    }
1135
1136 4
    public static function boolean()
1137
    {
1138 4
        $schema = new static();
1139 4
        $schema->type = Type::BOOLEAN;
1140 4
        return $schema;
1141
    }
1142
1143 6
    public static function object()
1144
    {
1145 6
        $schema = new static();
1146 6
        $schema->type = Type::OBJECT;
1147 6
        return $schema;
1148
    }
1149
1150 1
    public static function arr()
1151
    {
1152 1
        $schema = new static();
1153 1
        $schema->type = Type::ARR;
1154 1
        return $schema;
1155
    }
1156
1157
    public static function null()
1158
    {
1159
        $schema = new static();
1160
        $schema->type = Type::NULL;
1161
        return $schema;
1162
    }
1163
1164
1165
    /**
1166
     * @param Properties $properties
1167
     * @return Schema
1168
     */
1169 3
    public function setProperties($properties)
1170
    {
1171 3
        $this->properties = $properties;
1172 3
        return $this;
1173
    }
1174
1175
    /**
1176
     * @param string $name
1177
     * @param Schema $schema
1178
     * @return $this
1179
     */
1180 3
    public function setProperty($name, $schema)
1181
    {
1182 3
        if (null === $this->properties) {
1183 3
            $this->properties = new Properties();
1184
        }
1185 3
        $this->properties->__set($name, $schema);
1186 3
        return $this;
1187
    }
1188
1189
    /** @var mixed[] */
1190
    private $metaItems = array();
1191
1192 1
    public function addMeta($meta, $name = null)
1193
    {
1194 1
        if ($name === null) {
1195 1
            $name = get_class($meta);
1196
        }
1197 1
        $this->metaItems[$name] = $meta;
1198 1
        return $this;
1199
    }
1200
1201 1
    public function getMeta($name)
1202
    {
1203 1
        if (isset($this->metaItems[$name])) {
1204 1
            return $this->metaItems[$name];
1205
        }
1206
        return null;
1207
    }
1208
1209
    /**
1210
     * @param Context $options
1211
     * @return ObjectItemContract
1212
     */
1213 5
    public function makeObjectItem(Context $options = null)
1214
    {
1215 5
        if (null === $this->objectItemClass) {
1216
            return new ObjectItem();
1217
        } else {
1218 5
            $className = $this->objectItemClass;
1219 5
            if ($options !== null) {
1220
                if (isset($options->objectItemClassMapping[$className])) {
1221
                    $className = $options->objectItemClassMapping[$className];
1222
                }
1223
            }
1224 5
            return new $className;
1225
        }
1226
    }
1227
1228
    /**
1229
     * @param mixed $schema
1230
     * @return mixed|Schema
1231
     */
1232 3200
    private static function unboolSchema($schema)
1233
    {
1234 3200
        static $trueSchema;
1235 3200
        static $falseSchema;
1236
1237 3200
        if (null === $trueSchema) {
1238 1
            $trueSchema = new Schema();
1239 1
            $trueSchema->__booleanSchema = true;
1240 1
            $falseSchema = new Schema();
1241 1
            $falseSchema->not = $trueSchema;
1242 1
            $falseSchema->__booleanSchema = false;
1243
        }
1244
1245 3200
        if ($schema === true) {
1246 108
            return $trueSchema;
1247 3172
        } elseif ($schema === false) {
1248 94
            return $falseSchema;
1249
        } else {
1250 3140
            return $schema;
1251
        }
1252
    }
1253
1254
    /**
1255
     * @param mixed $data
1256
     * @return \stdClass
1257
     */
1258 384
    private static function unboolSchemaData($data)
1259
    {
1260 384
        static $trueSchema;
1261 384
        static $falseSchema;
1262
1263 384
        if (null === $trueSchema) {
1264 1
            $trueSchema = new \stdClass();
1265 1
            $falseSchema = new \stdClass();
1266 1
            $falseSchema->not = $trueSchema;
1267
        }
1268
1269 384
        if ($data === true) {
1270 6
            return $trueSchema;
1271 380
        } elseif ($data === false) {
1272 5
            return $falseSchema;
1273
        } else {
1274 375
            return $data;
1275
        }
1276
    }
1277
1278 32
    public function getDefault()
1279
    {
1280 32
        return $this->default;
1281
    }
1282
1283 86
    public function getProperties()
1284
    {
1285 86
        return $this->properties;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->properties also could return the type Swaggest\JsonSchema\Schema which is incompatible with the return type mandated by Swaggest\JsonSchema\Sche...ntract::getProperties() of null|Swaggest\JsonSchema...a\Constraint\Properties.
Loading history...
1286
    }
1287
1288
    public function getObjectItemClass()
1289
    {
1290
        return $this->objectItemClass;
1291
    }
1292
}
1293