MaxDepthExclusionStrategy::skip()   D
last analyzed

Complexity

Conditions 9
Paths 27

Size

Total Lines 44
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 9.0036

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 27
cts 28
cp 0.9643
rs 4.909
c 0
b 0
f 0
cc 9
eloc 24
nc 27
nop 1
crap 9.0036
1
<?php
2
3
/*
4
 * This file is part of the Ivory Serializer package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\Serializer\Exclusion;
13
14
use Ivory\Serializer\Context\ContextInterface;
15
use Ivory\Serializer\Mapping\ClassMetadataInterface;
16
use Ivory\Serializer\Mapping\PropertyMetadataInterface;
17
use Ivory\Serializer\Mapping\TypeMetadataInterface;
18
19
/**
20
 * @author GeLo <[email protected]>
21
 */
22
class MaxDepthExclusionStrategy extends ExclusionStrategy
23
{
24
    /**
25
     * @var int
26
     */
27
    private $circularReferenceLimit;
28
29
    /**
30
     * @param int $circularReferenceLimit
31
     */
32
    public function __construct($circularReferenceLimit = 1)
33
    {
34
        $this->circularReferenceLimit = $circularReferenceLimit;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 32
    public function skipClass(ClassMetadataInterface $class, ContextInterface $context)
41
    {
42 32
        return $this->skip($context);
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 32
    public function skipType(TypeMetadataInterface $type, ContextInterface $context)
49
    {
50 32
        return $this->skip($context);
51
    }
52
53
    /**
54
     * @param ContextInterface $context
55
     *
56
     * @return bool
57
     */
58 32
    private function skip(ContextInterface $context)
59
    {
60 32
        $dataStack = $context->getDataStack();
61 32
        $metadataStack = $context->getMetadataStack();
62 32
        $references = [];
63 32
        $depth = 0;
64
65 32
        for ($index = count($metadataStack) - 1; $index >= 0; --$index) {
66 32
            $metadata = $metadataStack[$index];
67 32
            $data = $dataStack[$index];
68
69 32
            if ($metadata instanceof ClassMetadataInterface) {
70 32
                $hash = spl_object_hash($data);
71
72 32
                if (!isset($references[$hash])) {
73 32
                    $references[$hash] = 0;
74 16
                }
75
76 32
                if (++$references[$hash] > $this->circularReferenceLimit) {
77 16
                    return true;
78
                }
79 16
            }
80
81 32
            if ($metadata instanceof TypeMetadataInterface) {
82 32
                ++$depth;
83 16
            }
84
85 32
            if (!$metadata instanceof PropertyMetadataInterface) {
86 32
                continue;
87
            }
88
89 32
            ++$depth;
90
91 32
            if (!$metadata->hasMaxDepth()) {
92
                continue;
93
            }
94
95 32
            if ($depth > $metadata->getMaxDepth()) {
96 20
                return true;
97
            }
98 16
        }
99
100 32
        return false;
101
    }
102
}
103