Completed
Pull Request — master (#1198)
by Martin Poirier
13:10
created

GroupsExclusionStrategy::buildPathFromContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 2
b 0
f 1
nc 1
nop 1
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer\Exclusion;
6
7
use JMS\Serializer\Context;
8
use JMS\Serializer\Metadata\ClassMetadata;
9
use JMS\Serializer\Metadata\PropertyMetadata;
10
11
final class GroupsExclusionStrategy implements ExclusionStrategyInterface
12
{
13
    public const DEFAULT_GROUP = 'Default';
14
15
    private $groups;
16
17
    /**
18
     * @var array<string,array<string,boolean>>
19 33
     */
20
    private $parsedGroups = [];
21 33
22 4
    /**
23
     * @var array<string,boolean>>
24
     */
25 33
    private $rootGroups = [];
26 33
27 2
    /**
28 33
     * @var bool
29
     */
30
    private $nestedGroups = false;
31
32 33
    public function __construct(array $groups)
33 2
    {
34
        $this->groups = $groups;
35 31
        $this->prepare($groups, '');
36 31
        $this->parsedGroups['.'] = $this->parsedGroups[''];
37
        unset($this->parsedGroups['']);
38
        $this->rootGroups = $this->parsedGroups['.'];
39 33
    }
40
41
    private function prepare(array $groups, $path)
42
    {
43
        $currentGroups = [];
44 15
        foreach ($groups as $key => $value) {
45
            if (is_string($key) && is_array($value)) {
46 15
                $this->nestedGroups = true;
47
                $this->prepare($value, $path . '.' . $key);
48
                continue;
49
            }
50
51
            $currentGroups[$value] = true;
52 33
        }
53
54 33
        if (empty($currentGroups)) {
55 2
            $currentGroups[self::DEFAULT_GROUP] = true;
56
        }
57 2
58 2
        $this->parsedGroups[$path] = $currentGroups;
59
    }
60
61 2
    /**
62
     * {@inheritDoc}
63
     */
64 31
    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext): bool
65 9
    {
66
        return false;
67
    }
68 29
69 29
    /**
70 29
     * {@inheritDoc}
71
     */
72
    public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext): bool
73 18
    {
74
        if (!$this->nestedGroups) {
75
            if(!$property->groups) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $property->groups of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
76
                return !isset($this->rootGroups[self::DEFAULT_GROUP]);
77 2
            }
78
79 2
            foreach ($property->groups as $group) {
80 2
                if (isset($this->rootGroups[$group])) {
81 2
                    return false;
82
                }
83
            }
84
            return true;
85 2
        } else {
86
            $groups = $property->groups ?: [self::DEFAULT_GROUP];
87
            $path = $this->buildPathFromContext($navigatorContext);
88 2
            if(!isset($this->parsedGroups[$path])) {
89
                // If we reach that path it's because we were allowed so we fallback on default group
90 2
                $this->parsedGroups[$path] = [self::DEFAULT_GROUP => true];
91
            }
92 2
        }
93 2
94 2
        $againstGroups = $this->parsedGroups[$path];
95 2
96
        foreach ($groups as $group) {
97
            if (isset($againstGroups[$group])) {
98 2
                return false;
99
            }
100
        }
101
102 2
        return true;
103
    }
104
105 2
    private function buildPathFromContext(Context $navigatorContext): string
106
    {
107
        return '.' . implode('.', $navigatorContext->getCurrentPath());
108
    }
109
110
    /**
111
     * @deprecated 
112
     */
113
    public function getGroupsFor(Context $navigatorContext): array
114
    {
115
        if (!$this->nestedGroups) {
116
            return array_keys($this->rootGroups);
117
        }
118
119
        $paths = $navigatorContext->getCurrentPath();
120
        $groups = $this->groups;
121
        foreach ($paths as $index => $path) {
122
            if (!array_key_exists($path, $groups)) {
123
                if ($index > 0) {
124
                    $groups = [self::DEFAULT_GROUP];
125
                }
126
                break;
127
            }
128
            $groups = $groups[$path];
129
            if (!array_filter($groups, 'is_string')) {
130
                $groups += [self::DEFAULT_GROUP];
131
            }
132
        }
133
        return $groups;
134
    }
135
}
136