-
Notifications
You must be signed in to change notification settings - Fork 572
Expand file tree
/
Copy pathParameterAllowedConstants.php
More file actions
103 lines (84 loc) · 2.2 KB
/
ParameterAllowedConstants.php
File metadata and controls
103 lines (84 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php declare(strict_types = 1);
namespace PHPStan\Reflection;
use function count;
use function in_array;
/**
* Describes which constants a function/method parameter accepts.
*
* Parameters are either 'single' (exactly one constant, e.g. `array_unique($flags)`)
* or 'bitmask' (constants combinable with `|`, e.g. `json_encode($flags)`).
* Bitmask parameters may have exclusive groups — subsets of constants
* that are mutually exclusive even within a bitmask.
*
* Populated from resources/constantToFunctionParameterMap.php and
* available via ExtendedParameterReflection::getAllowedConstants().
*
* @api
*/
final class ParameterAllowedConstants
{
/**
* @param 'single'|'bitmask' $type
* @param list<string> $constants
* @param list<list<string>> $exclusiveGroups
*/
public function __construct(
private string $type,
private array $constants,
private array $exclusiveGroups,
)
{
}
public function isBitmask(): bool
{
return $this->type === 'bitmask';
}
/**
* @return list<list<string>>
*/
public function getExclusiveGroups(): array
{
return $this->exclusiveGroups;
}
private function resolveConstantName(ConstantReflection $constant): string
{
if ($constant instanceof ClassConstantReflection) {
return $constant->getDeclaringClass()->getName() . '::' . $constant->getName();
}
return $constant->getName();
}
/**
* @param list<ConstantReflection> $constants
*/
public function check(array $constants): AllowedConstantsResult
{
$bitmaskNotAllowed = !$this->isBitmask() && count($constants) > 1;
$disallowed = [];
$names = [];
foreach ($constants as $constant) {
$name = $this->resolveConstantName($constant);
$names[] = $name;
if (in_array($name, $this->constants, true)) {
continue;
}
$disallowed[] = $constant;
}
$violated = [];
if ($this->isBitmask()) {
foreach ($this->exclusiveGroups as $group) {
$matched = [];
foreach ($names as $name) {
if (!in_array($name, $group, true)) {
continue;
}
$matched[] = $name;
}
if (count($matched) < 2) {
continue;
}
$violated[] = $matched;
}
}
return new AllowedConstantsResult($disallowed, $violated, $bitmaskNotAllowed);
}
}