c7aa3dbebb5f07ac867f04a793f0a1a934b3630d
[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 && in_array($node->dim->value, array_keys($this->flatMatcherDefinitions), true)
52 ) {
53 $match = [
54 'restFiles' => [],
55 'line' => $node->getAttribute('startLine'),
56 'message' => 'Access to array key "' . $node->dim->value . '"',
57 'indicator' => 'weak',
58 ];
59
60 foreach ($this->flatMatcherDefinitions[$node->dim->value]['candidates'] as $candidate) {
61 $match['restFiles'] = array_unique(array_merge($match['restFiles'], $candidate['restFiles']));
62 }
63 $this->matches[] = $match;
64 }
65 }
66
67 /**
68 * Prepare 'lastKey' => [$details] array in flatMatcherDefinitions
69 */
70 protected function initializeLastArrayKeyNameArray()
71 {
72 $methodNameArray = [];
73 foreach ($this->matcherDefinitions as $fullArrayString => $details) {
74 // Goal: find last part "foobar" of an array path "$foo['bar']['foobar']"
75 // Reverse string $foo['bar']['foobar']
76 $lastKey = strrev($fullArrayString);
77 // Cut off "['"
78 $lastKey = substr($lastKey, 2);
79 $lastKey = GeneralUtility::trimExplode('\'[', $lastKey);
80 // Last key name
81 $lastKey = $lastKey[0];
82 // And reverse key name again
83 $lastKey = strrev($lastKey);
84
85 if (!array_key_exists($lastKey, $methodNameArray)) {
86 $methodNameArray[$lastKey]['candidates'] = [];
87 }
88 $methodNameArray[$lastKey]['candidates'][] = $details;
89 }
90 $this->flatMatcherDefinitions = $methodNameArray;
91 }
92 }