MaxDepthExclusionStrategy   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 88.57%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 3
dl 0
loc 81
ccs 31
cts 35
cp 0.8857
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A skipClass() 0 4 1
A skipType() 0 4 1
D skip() 0 44 9
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