[TASK] Add CGL check for CSV fixtures
[Packages/TYPO3.CMS.git] / Build / Scripts / checkIntegrityCsvFixtures.php
1 #!/usr/bin/env php
2 <?php
3 declare(strict_types = 1);
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 require __DIR__ . '/../../vendor/autoload.php';
18
19 if (PHP_SAPI !== 'cli') {
20 die('Script must be called from command line.' . chr(10));
21 }
22
23 /**
24 * Core integrity test script:
25 *
26 * Find all CSV files in fixtures and make sure they have the correct column
27 * count across all lines in them
28 */
29 class checkIntegrityCsvFixtures
30 {
31 /**
32 * Executes the CGL check.
33 * The return value is used directly in the ext() call outside this class.
34 *
35 * @return int
36 */
37 public function execute(): int
38 {
39 $filesToProcess = $this->findCsvFixtures();
40 $scanResult = [];
41 $failureCount = 0;
42 $output = new \Symfony\Component\Console\Output\ConsoleOutput();
43
44 $resultAcrossAllFiles = 0;
45 /** @var \SplFileInfo $csvFixture */
46 foreach ($filesToProcess as $csvFixture) {
47 $fullFilePath = $csvFixture->getRealPath();
48 $singleFileScanResult = $this->validateCsvFile($fullFilePath);
49 if ($singleFileScanResult === false) {
50 $resultAcrossAllFiles = 1;
51 $failureCount++;
52 $scanResult[$this->getRelativePath($fullFilePath)] = $singleFileScanResult;
53 }
54 }
55 if (!empty($scanResult)) {
56 foreach ($scanResult as $key => $_item) {
57 $output->writeln('The file "' . $this->formatOutputString($key) . '" is not in valid CSV format');
58 }
59 }
60 return $resultAcrossAllFiles;
61 }
62
63 /**
64 * Finds all CSV fixtures in TYPO3s core
65 *
66 * @return \Symfony\Component\Finder\Finder
67 */
68 private function findCsvFixtures(): \Symfony\Component\Finder\Finder
69 {
70 $finder = new Symfony\Component\Finder\Finder();
71 $csvFixtures = $finder
72 ->files()
73 ->in(__DIR__ . '/../../typo3/sysext/*/Tests/Functional/**')
74 ->name('*.csv');
75 return $csvFixtures;
76 }
77
78 /**
79 * Checks if a CSV uses the same amount of columns across all
80 * lines in that file
81 *
82 * @param string $csvFixture
83 * @return bool
84 */
85 private function validateCsvFile(string $csvFixture): bool
86 {
87 // Load file content into array split by line
88 $lines = file($csvFixture);
89 $columnCount = 0;
90 foreach ($lines as $index => $line) {
91 // count columns in file
92 $columns = str_getcsv($line);
93 if ($columnCount === 0) {
94 $columnCount = count($columns);
95 } else {
96 if (count($columns) !== $columnCount) {
97 return false;
98 }
99 }
100 }
101 return true;
102 }
103
104 private function getRelativePath(string $fullPath): string
105 {
106 $pathSegment = str_replace('Build/Scripts', '', __DIR__);
107 return str_replace($pathSegment, '', $fullPath);
108 }
109
110 /**
111 * Makes the output on CLI a bit more readable
112 *
113 * @param string $filename
114 * @return string
115 */
116 private function formatOutputString(string $filename): string
117 {
118 $pattern = '/typo3\/sysext\/(?<extName>[a-z].+?)\/Tests\/Functional\/(?<file>.*)/';
119 preg_match_all($pattern, $filename, $matches, PREG_SET_ORDER, 0);
120 return 'EXT:' . $matches[0]['extName'] . ' > ' . $matches[0]['file'];
121 }
122 }
123
124 $cglFixer = new checkIntegrityCsvFixtures();
125 exit($cglFixer->execute());