Completed
Push — master ( 0959b6...35dc50 )
by Eric
04:50
created

MaxDepthExclusionStrategy::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
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 24
    public function skipClass(ClassMetadataInterface $class, ContextInterface $context)
41
    {
42 24
        return $this->skip($context);
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 24
    public function skipType(TypeMetadataInterface $type, ContextInterface $context)
49
    {
50 24
        return $this->skip($context);
51
    }
52
53
    /**
54
     * @param ContextInterface $context
55
     *
56
     * @return bool
57
     */
58 24
    private function skip(ContextInterface $context)
59
    {
60 24
        $dataStack = $context->getDataStack();
61 24
        $metadataStack = $context->getMetadataStack();
62 24
        $references = [];
63 24
        $depth = 0;
64
65 24
        for ($index = count($metadataStack) - 1; $index >= 0; --$index) {
66 24
            $metadata = $metadataStack[$index];
67 24
            $data = $dataStack[$index];
68
69 24
            if ($metadata instanceof ClassMetadataInterface) {
70 24
                $hash = spl_object_hash($data);
71
72 24
                if (!isset($references[$hash])) {
73 24
                    $references[$hash] = 0;
74 16
                }
75
76 24
                if (++$references[$hash] > $this->circularReferenceLimit) {
77 12
                    return true;
78
                }
79 16
            }
80
81 24
            if ($metadata instanceof TypeMetadataInterface) {
82 24
                ++$depth;
83 16
            }
84
85 24
            if (!$metadata instanceof PropertyMetadataInterface) {
86 24
                continue;
87
            }
88
89 24
            ++$depth;
90
91 24
            if (!$metadata->hasMaxDepth()) {
92
                continue;
93
            }
94
95 24
            if ($depth > $metadata->getMaxDepth()) {
96 15
                return true;
97
            }
98 16
        }
99
100 24
        return false;
101
    }
102
}
103