[TASK] Make ArrayDimensionMatcherTest notice free
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / ExtensionScanner / Php / Matcher / ArrayDimensionMatcher.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Install\ExtensionScanner\Php\Matcher;
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
18 use PhpParser\Node;
19 use PhpParser\Node\Expr\ArrayDimFetch;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Find usages of dropped configuration values and hook registrations.
24 * Matches on "last" key only.
25 * Definition of $GLOBALS['foo']['bar'] and usage as $foo['bar'] matches.
26 */
27 class ArrayDimensionMatcher extends AbstractCoreMatcher
28 {
29 /**
30 * Initialize "flat" matcher array from matcher definitions.
31 *
32 * @param array $matcherDefinitions Incoming main configuration
33 */
34 public function __construct(array $matcherDefinitions)
35 {
36 $this->matcherDefinitions = $matcherDefinitions;
37 $this->validateMatcherDefinitions();
38 $this->initializeLastArrayKeyNameArray();
39 }
40
41 /**
42 * Called by PhpParser.
43 *
44 * @param Node $node
45 */
46 public function enterNode(Node $node)
47 {
48 if (!$this->isFileIgnored($node)
49 && !$this->isLineIgnored($node)
50 && $node instanceof ArrayDimFetch
51 && isset($node->dim->value)
52 && in_array($node->dim->value, array_keys($this->flatMatcherDefinitions), true)
53 ) {
54 $match = [
55 'restFiles' => [],
56 'line' => $node->getAttribute('startLine'),
57 'message' => 'Access to array key "' . $node->dim->value . '"',
58 'indicator' => 'weak',
59 ];
60
61 foreach ($this->flatMatcherDefinitions[$node->dim->value]['candidates'] as $candidate) {
62 $match['restFiles'] = array_unique(array_merge($match['restFiles'], $candidate['restFiles']));
63 }
64 $this->matches[] = $match;
65 }
66 }
67
68 /**
69 * Prepare 'lastKey' => [$details] array in flatMatcherDefinitions
70 */
71 protected function initializeLastArrayKeyNameArray()
72 {
73 $methodNameArray = [];
74 foreach ($this->matcherDefinitions as $fullArrayString => $details) {
75 // Goal: find last part "foobar" of an array path "$foo['bar']['foobar']"
76 // Reverse string $foo['bar']['foobar']
77 $lastKey = strrev($fullArrayString);
78 // Cut off "['"
79 $lastKey = substr($lastKey, 2);
80 $lastKey = GeneralUtility::trimExplode('\'[', $lastKey);
81 // Last key name
82 $lastKey = $lastKey[0];
83 // And reverse key name again
84 $lastKey = strrev($lastKey);
85
86 if (!array_key_exists($lastKey, $methodNameArray)) {
87 $methodNameArray[$lastKey]['candidates'] = [];
88 }
89 $methodNameArray[$lastKey]['candidates'][] = $details;
90 }
91 $this->flatMatcherDefinitions = $methodNameArray;
92 }
93 }