comparison vendor/squizlabs/php_codesniffer/scripts/ValidatePEAR/ValidatePEARPackageXML.php @ 18:af1871eacc83

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:33:08 +0100
parents
children
comparison
equal deleted inserted replaced
17:129ea1e6d783 18:af1871eacc83
1 <?php
2 /**
3 * Validate the PHP_CodeSniffer PEAR package.xml file.
4 *
5 * PHP version 5
6 *
7 * @category PHP
8 * @package PHP_CodeSniffer
9 * @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
10 * @copyright 2019 Juliette Reinders Folmer. All rights reserved.
11 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 */
13
14 /**
15 * Validate the PHP_CodeSniffer PEAR package.xml file.
16 */
17 class ValidatePEARPackageXML
18 {
19
20 /**
21 * The root directory of the project.
22 *
23 * @var string
24 */
25 protected $projectRoot = '';
26
27 /**
28 * The contents of the package.xml file.
29 *
30 * @var \SimpleXMLElement
31 */
32 protected $packageXML;
33
34 /**
35 * List of all files in the repo.
36 *
37 * @var array
38 */
39 protected $allFiles = [];
40
41 /**
42 * Valid file roles.
43 *
44 * @var array
45 *
46 * @link https://pear.php.net/manual/en/developers.packagedef.intro.php#developers.packagedef.roles
47 */
48 private $validRoles = [
49 'data' => true,
50 'doc' => true,
51 'ext' => true,
52 'extsrc' => true,
53 'php' => true,
54 'script' => true,
55 'src' => true,
56 'test' => true,
57 ];
58
59 /**
60 * Files encountered in the package.xml <contents> tag.
61 *
62 * @var array
63 */
64 private $listedContents = [];
65
66
67 /**
68 * Constructor.
69 */
70 public function __construct()
71 {
72 $this->projectRoot = dirname(dirname(__DIR__)).'/';
73 $this->packageXML = simplexml_load_file($this->projectRoot.'package.xml');
74
75 $allFiles = (new FileList($this->projectRoot, $this->projectRoot))->getList();
76 $this->allFiles = array_flip($allFiles);
77
78 }//end __construct()
79
80
81 /**
82 * Validate the file listings in the package.xml file.
83 *
84 * @return void
85 */
86 public function validate()
87 {
88 $exitCode = 0;
89 if ($this->checkContents() !== true) {
90 $exitCode = 1;
91 }
92
93 if ($this->checkPHPRelease() !== true) {
94 $exitCode = 1;
95 }
96
97 exit($exitCode);
98
99 }//end validate()
100
101
102 /**
103 * Validate the file listings in the <contents> tag.
104 *
105 * @return bool
106 */
107 protected function checkContents()
108 {
109 echo PHP_EOL.'Checking Contents tag'.PHP_EOL;
110 echo '====================='.PHP_EOL;
111
112 $valid = true;
113
114 /*
115 * - Check that every file that is mentioned in the `<content>` tag exists in the repo.
116 * - Check that the "role" value is valid.
117 * - Check that the "baseinstalldir" value is valid.
118 */
119
120 $valid = $this->walkDirTag($this->packageXML->contents);
121 if ($valid === true) {
122 echo "Existing listings in the Contents tag are valid.".PHP_EOL;
123 }
124
125 /*
126 * Verify that all files in the `src` and the `tests` directories are listed in the `<contents>` tag.
127 */
128
129 $srcFiles = (new FileList(
130 $this->projectRoot.'src/',
131 $this->projectRoot,
132 '`\.(css|fixed|inc|js|php|xml)$`Di'
133 ))->getList();
134 $testsFiles = (new FileList(
135 $this->projectRoot.'tests/',
136 $this->projectRoot,
137 '`\.(css|inc|js|php|xml)$`Di'
138 ))->getList();
139 $files = array_merge($srcFiles, $testsFiles);
140
141 foreach ($files as $file) {
142 if (isset($this->listedContents[$file]) === true) {
143 continue;
144 }
145
146 echo "- File '{$file}' is missing from Contents tag.".PHP_EOL;
147 $valid = false;
148 }
149
150 if ($valid === true) {
151 echo "No missing files in the Contents tag.".PHP_EOL;
152 }
153
154 return $valid;
155
156 }//end checkContents()
157
158
159 /**
160 * Validate all child tags within a <dir> tag.
161 *
162 * @param \SimpleXMLElement $tag The current XML tag to examine.
163 * @param string $currentDirectory The complete relative path to the
164 * directory being examined.
165 *
166 * @return bool
167 */
168 protected function walkDirTag($tag, $currentDirectory='')
169 {
170 $valid = true;
171 $name = (string) $tag['name'];
172 if ($name !== '/' && empty($name) === false) {
173 $currentDirectory .= $name.'/';
174 }
175
176 $children = $tag->children();
177 foreach ($children as $key => $value) {
178 if ($key === 'dir') {
179 if ($this->walkDirTag($value, $currentDirectory) === false) {
180 $valid = false;
181 }
182 }
183
184 if ($key === 'file') {
185 if ($this->checkFileTag($value, $currentDirectory) === false) {
186 $valid = false;
187 }
188 }
189 }
190
191 return $valid;
192
193 }//end walkDirTag()
194
195
196 /**
197 * Validate the information within a <file> tag.
198 *
199 * @param \SimpleXMLElement $tag The current XML tag to examine.
200 * @param string $currentDirectory The complete relative path to the
201 * directory being examined.
202 *
203 * @return bool
204 */
205 protected function checkFileTag($tag, $currentDirectory='')
206 {
207 $valid = true;
208 $attributes = $tag->attributes();
209 $baseinstalldir = (string) $attributes['baseinstalldir'];
210 $name = $currentDirectory.(string) $attributes['name'];
211 $role = (string) $attributes['role'];
212
213 $this->listedContents[$name] = true;
214
215 if (empty($name) === true) {
216 echo "- Name attribute missing.".PHP_EOL;
217 $valid = false;
218 } else {
219 if (isset($this->allFiles[$name]) === false) {
220 echo "- File '{$name}' does not exist.".PHP_EOL;
221 $valid = false;
222 }
223
224 if (empty($role) === true) {
225 echo "- Role attribute missing for file '{$name}'.".PHP_EOL;
226 $valid = false;
227 } else {
228 if (isset($this->validRoles[$role]) === false) {
229 echo "- Role for file '{$name}' is invalid.".PHP_EOL;
230 $valid = false;
231 } else {
232 // Limited validation of the "role" tags.
233 if (strpos($name, 'Test.') !== false && $role !== 'test') {
234 echo "- Test files should have the role 'test'. Found: '$role' for file '{$name}'.".PHP_EOL;
235 $valid = false;
236 } else if ((strpos($name, 'Standard.xml') !== false || strpos($name, 'Sniff.php') !== false)
237 && $role !== 'php'
238 ) {
239 echo "- Sniff files, including sniff documentation files should have the role 'php'. Found: '$role' for file '{$name}'.".PHP_EOL;
240 $valid = false;
241 }
242 }
243
244 if (empty($baseinstalldir) === true) {
245 if ($role !== 'script' && strpos($name, 'tests/') !== 0) {
246 echo "- Baseinstalldir attribute missing for file '{$name}'.".PHP_EOL;
247 $valid = false;
248 }
249 } else {
250 if ($role === 'script' || strpos($name, 'tests/') === 0) {
251 echo "- Baseinstalldir for file '{$name}' should be empty.".PHP_EOL;
252 $valid = false;
253 }
254
255 if ($role !== 'script' && $baseinstalldir !== 'PHP/CodeSniffer') {
256 echo "- Baseinstalldir for file '{$name}' is invalid.".PHP_EOL;
257 $valid = false;
258 }
259 }
260 }//end if
261 }//end if
262
263 return $valid;
264
265 }//end checkFileTag()
266
267
268 /**
269 * Validate the file listings in the <phprelease> tags.
270 *
271 * @return bool True if the info in the "phprelease" tags is valid. False otherwise.
272 */
273 protected function checkPHPRelease()
274 {
275 echo PHP_EOL.'Checking PHPRelease tags'.PHP_EOL;
276 echo '========================'.PHP_EOL;
277
278 $valid = true;
279 $listedFiles = [];
280 $releaseTags = 1;
281
282 /*
283 * - Check that every file that is mentioned in the `<phprelease>` tags exists in the repo.
284 * - Check that the "as" value is valid.
285 */
286
287 foreach ($this->packageXML->phprelease as $release) {
288 foreach ($release->filelist->install as $install) {
289 $attributes = $install->attributes();
290 $name = (string) $attributes['name'];
291 $as = (string) $attributes['as'];
292
293 $listedFiles[$releaseTags][$name] = $as;
294
295 if (empty($as) === true || empty($name) === true) {
296 continue;
297 }
298
299 if (isset($this->allFiles[$name]) === false) {
300 echo "- File '{$name}' does not exist.".PHP_EOL;
301 $valid = false;
302 }
303
304 // Rest of the checks only apply to the test files.
305 if (strpos($name, 'tests/') !== 0) {
306 continue;
307 }
308
309 // Check validity of the tags for files in the tests root directory.
310 if (preg_match('`^tests/([^/]+\.php)$`', $name, $matches) === 1
311 && ($as === $name || $as === $matches[1])
312 ) {
313 continue;
314 }
315
316 // Check validity of the tags for files in the tests root subdirectories.
317 if (preg_match('`^tests/.+\.(php|inc|js|css|xml)$`', $name) === 1
318 && $as === str_replace('tests/', 'CodeSniffer/', $name)
319 ) {
320 continue;
321 }
322
323 echo "- Invalid 'as' attribute '{$as}' for test file '{$name}'.".PHP_EOL;
324 $valid = false;
325 }//end foreach
326
327 ++$releaseTags;
328 }//end foreach
329
330 if ($valid === true) {
331 echo "Existing PHPRelease tags are valid.".PHP_EOL;
332 }
333
334 /*
335 * Verify that all files in the `tests` directory are listed in both `<phprelease>` tags.
336 */
337
338 $testFiles = (new FileList($this->projectRoot.'tests/', $this->projectRoot, '`\.(inc|php|js|css|xml)$`Di'))->getList();
339
340 foreach ($testFiles as $file) {
341 foreach ($listedFiles as $key => $listed) {
342 if (isset($listed[$file]) === true) {
343 continue;
344 }
345
346 echo "- File '{$file}' is missing from PHPRelease tag [{$key}] .".PHP_EOL;
347 $valid = false;
348 }
349 }
350
351 if ($valid === true) {
352 echo "No missing PHPRelease tags.".PHP_EOL;
353 }
354
355 return $valid;
356
357 }//end checkPHPRelease()
358
359
360 }//end class