‪TYPO3CMS  10.4
AbstractCoreMatcher.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PhpParser\Node;
21 use PhpParser\Node\Stmt\Class_;
22 use PhpParser\NodeVisitorAbstract;
25 
33 abstract class ‪AbstractCoreMatcher extends NodeVisitorAbstract implements ‪CodeScannerInterface
34 {
35  public const ‪NODE_RESOLVED_AS = 'nodeResolvedAs';
36 
42  protected ‪$matcherDefinitions = [];
43 
47  protected ‪$matches = [];
48 
55  protected ‪$flatMatcherDefinitions = [];
56 
60  protected ‪$currentCodeLine = 0;
61 
65  protected ‪$isCurrentLineIgnored = false;
66 
70  protected ‪$isFullFileIgnored = false;
71 
77  public function ‪getMatches(): array
78  {
79  return ‪$this->matches;
80  }
81 
94  protected function ‪validateMatcherDefinitions(array $requiredArrayKeys = [])
95  {
96  foreach ($this->matcherDefinitions as $key => $matcherDefinition) {
97  $this->‪validateMatcherDefinitionKeys($key, $matcherDefinition, $requiredArrayKeys);
98  }
99  }
100 
101  protected function ‪validateMatcherDefinitionKeys(string $key, array $matcherDefinition, array $requiredArrayKeys = []): void
102  {
103  // Each config must point to at least one .rst file
104  if (empty($matcherDefinition['restFiles'])) {
105  throw new \InvalidArgumentException(
106  'Each configuration must have at least one referenced "restFiles" entry. Offending key: ' . $key,
107  1500496068
108  );
109  }
110  foreach ($matcherDefinition['restFiles'] as $file) {
111  if (empty($file)) {
112  throw new \InvalidArgumentException(
113  'Empty restFiles definition',
114  1500735983
115  );
116  }
117  }
118  // Config broken if not all required array keys are specified in config
119  $sharedArrays = array_intersect(array_keys($matcherDefinition), $requiredArrayKeys);
120  if (count($sharedArrays) !== count($requiredArrayKeys)) {
121  $missingKeys = array_diff($requiredArrayKeys, array_keys($matcherDefinition));
122  throw new \InvalidArgumentException(
123  'Required matcher definitions missing: ' . implode(', ', $missingKeys) . ' offending key: ' . $key,
124  1500492001
125  );
126  }
127  }
128 
140  protected function ‪initializeFlatMatcherDefinitions()
141  {
142  $methodNameArray = [];
143  foreach ($this->matcherDefinitions as $classAndMethod => $details) {
144  $method = ‪GeneralUtility::trimExplode('::', $classAndMethod);
145  if (count($method) !== 2) {
146  $method = ‪GeneralUtility::trimExplode('->', $classAndMethod);
147  }
148  if (count($method) !== 2) {
149  throw new \RuntimeException(
150  'Keys in $this->matcherDefinitions must have a Class\Name->method or Class\Name::method structure',
151  1500557309
152  );
153  }
154  $method = $method[1];
155  if (!array_key_exists($method, $methodNameArray)) {
156  $methodNameArray[$method]['candidates'] = [];
157  }
158  $methodNameArray[$method]['candidates'][] = $details;
159  }
160  $this->flatMatcherDefinitions = $methodNameArray;
161  }
162 
170  protected function ‪isArgumentUnpackingUsed(array $arguments = []): bool
171  {
172  foreach ($arguments as $arg) {
173  if ($arg->unpack === true) {
174  return true;
175  }
176  }
177  return false;
178  }
179 
187  protected function ‪isLineIgnored(Node $node): bool
188  {
189  // Early return if this line is marked as ignored
190  $startLineOfNode = $node->getAttribute('startLine');
191  if ($startLineOfNode === $this->currentCodeLine) {
193  }
194 
195  $currentLineIsIgnored = false;
196  if ($startLineOfNode !== $this->currentCodeLine) {
197  $this->currentCodeLine = $startLineOfNode;
198  // First node of a new line may contain the annotation
199  $comments = $node->getAttribute('comments');
200  if (!empty($comments)) {
201  foreach ($comments as $comment) {
202  if (strpos($comment->getText(), '@extensionScannerIgnoreLine') !== false) {
203  $this->isCurrentLineIgnored = true;
204  $currentLineIsIgnored = true;
205  break;
206  }
207  }
208  }
209  }
210  return $currentLineIsIgnored;
211  }
212 
220  protected function ‪isFileIgnored(Node $node): bool
221  {
222  if ($this->isFullFileIgnored) {
223  return true;
224  }
225  $currentFileIsIgnored = false;
226  if ($node instanceof Class_) {
227  $comments = $node->getAttribute('comments');
228  if (!empty($comments)) {
229  foreach ($comments as $comment) {
230  if (strpos($comment->getText(), '@extensionScannerIgnoreFile') !== false) {
231  $this->isFullFileIgnored = true;
232  $currentFileIsIgnored = true;
233  break;
234  }
235  }
236  }
237  }
238  return $currentFileIsIgnored;
239  }
240 }
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\NODE_RESOLVED_AS
‪const NODE_RESOLVED_AS
Definition: AbstractCoreMatcher.php:35
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\isArgumentUnpackingUsed
‪bool isArgumentUnpackingUsed(array $arguments=[])
Definition: AbstractCoreMatcher.php:164
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\validateMatcherDefinitionKeys
‪validateMatcherDefinitionKeys(string $key, array $matcherDefinition, array $requiredArrayKeys=[])
Definition: AbstractCoreMatcher.php:95
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher
Definition: AbstractCoreMatcher.php:18
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\isLineIgnored
‪bool isLineIgnored(Node $node)
Definition: AbstractCoreMatcher.php:181
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher
Definition: AbstractCoreMatcher.php:34
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$currentCodeLine
‪int $currentCodeLine
Definition: AbstractCoreMatcher.php:56
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\getMatches
‪array getMatches()
Definition: AbstractCoreMatcher.php:71
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$isCurrentLineIgnored
‪bool $isCurrentLineIgnored
Definition: AbstractCoreMatcher.php:60
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$matches
‪array $matches
Definition: AbstractCoreMatcher.php:45
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\validateMatcherDefinitions
‪validateMatcherDefinitions(array $requiredArrayKeys=[])
Definition: AbstractCoreMatcher.php:88
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\isFileIgnored
‪bool isFileIgnored(Node $node)
Definition: AbstractCoreMatcher.php:214
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$matcherDefinitions
‪array $matcherDefinitions
Definition: AbstractCoreMatcher.php:41
‪TYPO3\CMS\Install\ExtensionScanner\CodeScannerInterface
Definition: CodeScannerInterface.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$isFullFileIgnored
‪bool $isFullFileIgnored
Definition: AbstractCoreMatcher.php:64
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\initializeFlatMatcherDefinitions
‪initializeFlatMatcherDefinitions()
Definition: AbstractCoreMatcher.php:134
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\AbstractCoreMatcher\$flatMatcherDefinitions
‪array $flatMatcherDefinitions
Definition: AbstractCoreMatcher.php:52