GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#73)
by
unknown
02:10
created

ArrayMatcher::shouldSkippValueMatchingFor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Coduo\PHPMatcher\Matcher;
4
5
use Coduo\PHPMatcher\Parser;
6
use Coduo\ToString\StringConverter;
7
use Symfony\Component\PropertyAccess\PropertyAccess;
8
use Symfony\Component\PropertyAccess\PropertyAccessor;
9
10
final class ArrayMatcher extends Matcher
11
{
12
    const UNBOUNDED_PATTERN = '@...@';
13
14
    /**
15
     * @var PropertyMatcher
16
     */
17
    private $propertyMatcher;
18
19
    /**
20
     * @var PropertyAccessor
21
     */
22
    private $accessor;
23
24
    /**
25
     * @var Parser
26
     */
27
    private $parser;
28
29
    /**
30
     * @param ValueMatcher $propertyMatcher
31
     */
32
    public function __construct(ValueMatcher $propertyMatcher, Parser $parser)
33
    {
34
        $this->propertyMatcher = $propertyMatcher;
0 ignored issues
show
Documentation Bug introduced by
It seems like $propertyMatcher of type object<Coduo\PHPMatcher\Matcher\ValueMatcher> is incompatible with the declared type object<Coduo\PHPMatcher\Matcher\PropertyMatcher> of property $propertyMatcher.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
35
        $this->parser = $parser;
36
    }
37
38
    /**
39
     * {@inheritDoc}
40
     */
41
    public function match($value, $pattern)
42
    {
43
        if (parent::match($value, $pattern)) {
44
            return true;
45
        }
46
47
        if (!is_array($value)) {
48
            $this->error = sprintf("%s \"%s\" is not a valid array.", gettype($value), new StringConverter($value));
49
            return false;
50
        }
51
52
        if ($this->isArrayPattern($pattern)) {
53
            return $this->allExpandersMatch($value, $pattern);
54
        }
55
56
        if (false === $this->iterateMatch($value, $pattern)) {
57
            return false;
58
        }
59
60
        return true;
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    public function canMatch($pattern)
67
    {
68
        return is_array($pattern) || $this->isArrayPattern($pattern);
69
    }
70
71
    private function isArrayPattern($pattern)
72
    {
73
        if (!is_string($pattern)) {
74
            return false;
75
        }
76
77
        return $this->parser->hasValidSyntax($pattern) && $this->parser->parse($pattern)->is('array');
78
    }
79
80
    /**
81
     * @param  array $values
82
     * @param  array $patterns
83
     * @param string $parentPath
84
     * @return bool
85
     */
86
    private function iterateMatch(array $values, array $patterns, $parentPath = "")
87
    {
88
        $pattern = null;
89
        foreach ($values as $key => $value) {
90
            $path = $this->formatAccessPath($key);
91
92
            if ($this->shouldSkippValueMatchingFor($pattern)) {
93
                continue;
94
            }
95
96
            if ($this->valueExist($path, $patterns)) {
97
                $pattern = $this->getValueByPath($patterns, $path);
98
            } else {
99
                $this->setMissingElementInError('pattern', $this->formatFullPath($parentPath, $path));
100
                return false;
101
            }
102
103
            if ($this->shouldSkippValueMatchingFor($pattern)) {
104
                continue;
105
            }
106
107
            if ($this->valueMatchPattern($value, $pattern)) {
108
                continue;
109
            }
110
111
            if (!is_array($value) || !$this->canMatch($pattern)) {
112
                return false;
113
            }
114
115
            if ($this->isArrayPattern($pattern)) {
116
                if (!$this->allExpandersMatch($value, $pattern)) {
117
                    return false;
118
                }
119
120
                continue;
121
            }
122
123
            if (false === $this->iterateMatch($value, $pattern, $this->formatFullPath($parentPath, $path))) {
124
                return false;
125
            }
126
        }
127
128
        if (!$this->isPatternValid($patterns, $values, $parentPath)) {
129
            return false;
130
        }
131
132
        return true;
133
    }
134
135
    /**
136
     * Check if pattern elements exist in value array
137
     *
138
     * @param array $pattern
139
     * @param array $values
140
     * @param $parentPath
141
     * @return bool
142
     */
143
    private function isPatternValid(array $pattern, array $values, $parentPath)
144
    {
145
        if (is_array($pattern)) {
146
            $notExistingKeys = array_diff_key($pattern, $values);
147
148
            if (count($notExistingKeys) > 0) {
149
                $keyNames = array_keys($notExistingKeys);
150
                $path = $this->formatFullPath($parentPath,  $this->formatAccessPath($keyNames[0]));
151
                $this->setMissingElementInError('value', $path);
152
                return false;
153
            }
154
        }
155
156
        return true;
157
    }
158
159
    /**
160
     * @param $value
161
     * @param $pattern
162
     * @return bool
163
     */
164
    private function valueMatchPattern($value, $pattern)
165
    {
166
        $match = $this->propertyMatcher->canMatch($pattern) &&
167
            true === $this->propertyMatcher->match($value, $pattern);
168
169
        if (!$match) {
170
            $this->error = $this->propertyMatcher->getError();
171
        }
172
173
        return $match;
174
    }
175
176
    /**
177
     * @param $path
178
     * @param $haystack
179
     * @return bool
180
     */
181
    private function valueExist($path, array $haystack)
182
    {
183
        return null !== $this->getPropertyAccessor()->getValue($haystack, $path);
184
    }
185
186
    /**
187
     * @param $array
188
     * @param $path
189
     * @return mixed
190
     */
191
    private function getValueByPath($array, $path)
192
    {
193
        return $this->getPropertyAccessor()->getValue($array, $path);
194
    }
195
196
    /**
197
     * @return \Symfony\Component\PropertyAccess\PropertyAccessorInterface
198
     */
199
    private function getPropertyAccessor()
200
    {
201
        if (isset($this->accessor)) {
202
            return $this->accessor;
203
        }
204
205
        $accessorBuilder = PropertyAccess::createPropertyAccessorBuilder();
206
        $this->accessor = $accessorBuilder->getPropertyAccessor();
207
208
        return $this->accessor;
209
    }
210
211
    /**
212
     * @param $place
213
     * @param $path
214
     */
215
    private function setMissingElementInError($place, $path)
216
    {
217
        $this->error = sprintf('There is no element under path %s in %s.', $path, $place);
218
    }
219
220
    /**
221
     * @param $key
222
     * @return string
223
     */
224
    private function formatAccessPath($key)
225
    {
226
        return sprintf("[%s]", $key);
227
    }
228
229
    /**
230
     * @param $parentPath
231
     * @param $path
232
     * @return string
233
     */
234
    private function formatFullPath($parentPath, $path)
235
    {
236
        return sprintf("%s%s", $parentPath, $path);
237
    }
238
239
    /**
240
     * @param $lastPattern
241
     * @return bool
242
     */
243
    private function shouldSkippValueMatchingFor($lastPattern)
244
    {
245
        return $lastPattern === self::UNBOUNDED_PATTERN;
246
    }
247
248
    /**
249
     * @param $value
250
     * @param $pattern
251
     * @return bool
252
     * @throws \Coduo\PHPMatcher\Exception\UnknownExpanderException
253
     */
254
    private function allExpandersMatch($value, $pattern)
255
    {
256
        $typePattern = $this->parser->parse($pattern);
257
        if (!$typePattern->matchExpanders($value)) {
258
            $this->error = $typePattern->getError();
259
            return false;
260
        }
261
262
        return true;
263
    }
264
}
265