This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace BestIt\Sniffs\Formatting; |
||
6 | |||
7 | use BestIt\CodeSniffer\Helper\PropertyHelper; |
||
8 | use BestIt\CodeSniffer\Helper\TokenHelper; |
||
9 | use BestIt\CodeSniffer\Helper\UseStatementHelper; |
||
10 | use BestIt\Sniffs\AbstractSniff; |
||
11 | use BestIt\Sniffs\ClassRegistrationTrait; |
||
12 | use function array_combine; |
||
13 | use function array_filter; |
||
14 | use function array_keys; |
||
15 | use function array_map; |
||
16 | use function array_search; |
||
17 | use function uasort; |
||
18 | use const T_CONST; |
||
19 | use const T_FUNCTION; |
||
20 | use const T_USE; |
||
21 | use const T_VARIABLE; |
||
22 | |||
23 | /** |
||
24 | * Checks the sorting of the contents of a class (T_USE > T_CONST > T_VARIABLE > T_FUNCTION). |
||
25 | * |
||
26 | * @author blange <[email protected]> |
||
27 | * @package BestIt\Sniffs\Formatting |
||
28 | */ |
||
29 | class UCVFSortingSniff extends AbstractSniff |
||
30 | { |
||
31 | use ClassRegistrationTrait; |
||
32 | |||
33 | /** |
||
34 | * You MUST sort the contents of your classes, traits, interface, etc. in the following order: T_USE, T_CONST, T_VARIABLE, T_FUNCTION. |
||
35 | * |
||
36 | * @var string |
||
37 | */ |
||
38 | public const CODE_WRONG_POSITION = 'WrongPosition'; |
||
39 | |||
40 | /** |
||
41 | * The error message of a structure is at the wrong position. |
||
42 | * |
||
43 | * @var string |
||
44 | */ |
||
45 | private const MESSAGE_WRONG_POSITION = 'Your php structure is at a wrong position. ' . |
||
46 | 'The sorting order is: T_USE, T_CONST, T_VARIABLE, T_FUNCTION. We expect a %s (%s).'; |
||
47 | |||
48 | /** |
||
49 | * The tokens which are checked in the correct sorting order. |
||
50 | * |
||
51 | * @var array |
||
52 | */ |
||
53 | private array $sortedTokens = [ |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
54 | T_USE, |
||
55 | T_CONST, |
||
56 | T_VARIABLE, |
||
57 | T_FUNCTION |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * Loads the positons for the tokens of $this->>sortedTokens. |
||
62 | * |
||
63 | * @return int[] |
||
64 | */ |
||
65 | private function loadSubTokenPositions(): array |
||
66 | { |
||
67 | return TokenHelper::findNextAll( |
||
68 | $this->file, |
||
69 | $this->sortedTokens, |
||
70 | $this->stackPos, |
||
71 | $this->token['scope_closer'] |
||
72 | ); |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Loads all sub tokens. |
||
77 | * |
||
78 | * @return array |
||
79 | */ |
||
80 | private function loadSubTokens(): array |
||
81 | { |
||
82 | $subTokens = $this->loadTokensForPositions($this->loadSubTokenPositions()); |
||
83 | |||
84 | return $this->removeUnwantedTokens($subTokens); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Loads the tokens for the positions. |
||
89 | * |
||
90 | * @param array $subTokenPoss |
||
91 | * |
||
92 | * @return array |
||
93 | */ |
||
94 | private function loadTokensForPositions(array $subTokenPoss): array |
||
95 | { |
||
96 | $subTokens = array_map(function (int $position): array { |
||
97 | return $this->tokens[$position]; |
||
98 | }, $subTokenPoss); |
||
99 | |||
100 | return array_combine($subTokenPoss, $subTokens); |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Processes the token. |
||
105 | * |
||
106 | * @return void |
||
107 | */ |
||
108 | protected function processToken(): void |
||
109 | { |
||
110 | $subTokens = $this->loadSubTokens(); |
||
111 | $sortedTokens = $this->sortTokens($subTokens); |
||
112 | |||
113 | $this->validateSorting($subTokens, $sortedTokens); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * Removes inline vars and uses for anon-functions. |
||
118 | * |
||
119 | * @param array $subTokens |
||
120 | * |
||
121 | * @return array |
||
122 | */ |
||
123 | private function removeUnwantedTokens(array $subTokens): array |
||
124 | { |
||
125 | return array_filter($subTokens, function (array $subToken): bool { |
||
126 | switch ($subToken['code']) { |
||
127 | case T_VARIABLE: |
||
128 | $return = (new PropertyHelper($this->file))->isProperty($subToken['pointer']); |
||
129 | break; |
||
130 | |||
131 | case T_USE: |
||
132 | $return = UseStatementHelper::isTraitUse($this->file, $subToken['pointer']); |
||
133 | break; |
||
134 | |||
135 | default: |
||
136 | $return = true; |
||
137 | } |
||
138 | |||
139 | return $return; |
||
140 | }); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * This sniff needs the pointer marker so add it to the tokens. |
||
145 | * |
||
146 | * @return void |
||
147 | */ |
||
148 | protected function setUp(): void |
||
149 | { |
||
150 | parent::setUp(); |
||
151 | |||
152 | $this->addPointerToTokens(); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Sorts the tokens as required by $this->sortingTokens. |
||
157 | * |
||
158 | * @param array $subTokens |
||
159 | * |
||
160 | * @return array |
||
161 | */ |
||
162 | private function sortTokens(array $subTokens): array |
||
163 | { |
||
164 | uasort($subTokens, function (array $leftToken, array $rightToken): int { |
||
165 | // Don't change the structure by default. |
||
166 | $return = $leftToken['line'] <=> $rightToken['line']; |
||
167 | |||
168 | // Sort by type |
||
169 | if ($leftToken['code'] != $rightToken['code']) { |
||
170 | $leftIndex = array_search($leftToken['code'], $this->sortedTokens); |
||
171 | $rightIndex = array_search($rightToken['code'], $this->sortedTokens); |
||
172 | |||
173 | $return = $leftIndex <=> $rightIndex; |
||
174 | } |
||
175 | |||
176 | return $return; |
||
177 | }); |
||
178 | |||
179 | return $subTokens; |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Validates the sorting of the tokens and registers an error if wrong sorted. |
||
184 | * |
||
185 | * @param array $originalTokens |
||
186 | * @param array $sortedTokens |
||
187 | * |
||
188 | * @return void |
||
189 | */ |
||
190 | private function validateSorting(array $originalTokens, array $sortedTokens): void |
||
191 | { |
||
192 | $sortedPositions = array_keys($sortedTokens); |
||
193 | $sortedIndex = 0; |
||
194 | |||
195 | foreach ($originalTokens as $originalPosition => $originalToken) { |
||
196 | $sortedPosition = $sortedPositions[$sortedIndex++]; |
||
197 | $sortedToken = $sortedTokens[$sortedPosition]; |
||
198 | |||
199 | // We don't need an error if the "type block" is the same, so check the code additionally. |
||
200 | if (($sortedPosition !== $originalPosition) && ($originalToken['code'] !== $sortedToken['code'])) { |
||
201 | $this->file->addError( |
||
202 | self::MESSAGE_WRONG_POSITION, |
||
203 | $originalPosition, |
||
204 | static::CODE_WRONG_POSITION, |
||
205 | [ |
||
206 | $sortedToken['type'], |
||
207 | $sortedToken['content'] |
||
208 | ] |
||
209 | ); |
||
210 | } |
||
211 | } |
||
212 | } |
||
213 | } |
||
214 |