Chris@17
|
1 <?php
|
Chris@17
|
2 /**
|
Chris@17
|
3 * Functions for helping process standards.
|
Chris@17
|
4 *
|
Chris@17
|
5 * @author Greg Sherwood <gsherwood@squiz.net>
|
Chris@17
|
6 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
|
Chris@17
|
7 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
|
Chris@17
|
8 */
|
Chris@17
|
9
|
Chris@17
|
10 namespace PHP_CodeSniffer\Util;
|
Chris@17
|
11
|
Chris@17
|
12 use PHP_CodeSniffer\Config;
|
Chris@17
|
13
|
Chris@17
|
14 class Standards
|
Chris@17
|
15 {
|
Chris@17
|
16
|
Chris@17
|
17
|
Chris@17
|
18 /**
|
Chris@17
|
19 * Get a list paths where standards are installed.
|
Chris@17
|
20 *
|
Chris@17
|
21 * @return array
|
Chris@17
|
22 */
|
Chris@17
|
23 public static function getInstalledStandardPaths()
|
Chris@17
|
24 {
|
Chris@17
|
25 $ds = DIRECTORY_SEPARATOR;
|
Chris@17
|
26
|
Chris@17
|
27 $installedPaths = [dirname(dirname(__DIR__)).$ds.'src'.$ds.'Standards'];
|
Chris@17
|
28 $configPaths = Config::getConfigData('installed_paths');
|
Chris@17
|
29 if ($configPaths !== null) {
|
Chris@17
|
30 $installedPaths = array_merge($installedPaths, explode(',', $configPaths));
|
Chris@17
|
31 }
|
Chris@17
|
32
|
Chris@17
|
33 $resolvedInstalledPaths = [];
|
Chris@17
|
34 foreach ($installedPaths as $installedPath) {
|
Chris@17
|
35 if (substr($installedPath, 0, 1) === '.') {
|
Chris@17
|
36 $installedPath = Common::realPath(__DIR__.$ds.'..'.$ds.'..'.$ds.$installedPath);
|
Chris@17
|
37 }
|
Chris@17
|
38
|
Chris@17
|
39 $resolvedInstalledPaths[] = $installedPath;
|
Chris@17
|
40 }
|
Chris@17
|
41
|
Chris@17
|
42 return $resolvedInstalledPaths;
|
Chris@17
|
43
|
Chris@17
|
44 }//end getInstalledStandardPaths()
|
Chris@17
|
45
|
Chris@17
|
46
|
Chris@17
|
47 /**
|
Chris@17
|
48 * Get the details of all coding standards installed.
|
Chris@17
|
49 *
|
Chris@17
|
50 * Coding standards are directories located in the
|
Chris@17
|
51 * CodeSniffer/Standards directory. Valid coding standards
|
Chris@17
|
52 * include a Sniffs subdirectory.
|
Chris@17
|
53 *
|
Chris@17
|
54 * The details returned for each standard are:
|
Chris@17
|
55 * - path: the path to the coding standard's main directory
|
Chris@17
|
56 * - name: the name of the coding standard, as sourced from the ruleset.xml file
|
Chris@17
|
57 * - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file
|
Chris@17
|
58 *
|
Chris@17
|
59 * If you only need the paths to the installed standards,
|
Chris@17
|
60 * use getInstalledStandardPaths() instead as it performs less work to
|
Chris@17
|
61 * retrieve coding standard names.
|
Chris@17
|
62 *
|
Chris@17
|
63 * @param boolean $includeGeneric If true, the special "Generic"
|
Chris@17
|
64 * coding standard will be included
|
Chris@17
|
65 * if installed.
|
Chris@17
|
66 * @param string $standardsDir A specific directory to look for standards
|
Chris@17
|
67 * in. If not specified, PHP_CodeSniffer will
|
Chris@17
|
68 * look in its default locations.
|
Chris@17
|
69 *
|
Chris@17
|
70 * @return array
|
Chris@17
|
71 * @see getInstalledStandardPaths()
|
Chris@17
|
72 */
|
Chris@17
|
73 public static function getInstalledStandardDetails(
|
Chris@17
|
74 $includeGeneric=false,
|
Chris@17
|
75 $standardsDir=''
|
Chris@17
|
76 ) {
|
Chris@17
|
77 $rulesets = [];
|
Chris@17
|
78
|
Chris@17
|
79 if ($standardsDir === '') {
|
Chris@17
|
80 $installedPaths = self::getInstalledStandardPaths();
|
Chris@17
|
81 } else {
|
Chris@17
|
82 $installedPaths = [$standardsDir];
|
Chris@17
|
83 }
|
Chris@17
|
84
|
Chris@17
|
85 foreach ($installedPaths as $standardsDir) {
|
Chris@17
|
86 // Check if the installed dir is actually a standard itself.
|
Chris@17
|
87 $csFile = $standardsDir.'/ruleset.xml';
|
Chris@17
|
88 if (is_file($csFile) === true) {
|
Chris@17
|
89 $rulesets[] = $csFile;
|
Chris@17
|
90 continue;
|
Chris@17
|
91 }
|
Chris@17
|
92
|
Chris@17
|
93 if (is_dir($standardsDir) === false) {
|
Chris@17
|
94 continue;
|
Chris@17
|
95 }
|
Chris@17
|
96
|
Chris@17
|
97 $di = new \DirectoryIterator($standardsDir);
|
Chris@17
|
98 foreach ($di as $file) {
|
Chris@17
|
99 if ($file->isDir() === true && $file->isDot() === false) {
|
Chris@17
|
100 $filename = $file->getFilename();
|
Chris@17
|
101
|
Chris@17
|
102 // Ignore the special "Generic" standard.
|
Chris@17
|
103 if ($includeGeneric === false && $filename === 'Generic') {
|
Chris@17
|
104 continue;
|
Chris@17
|
105 }
|
Chris@17
|
106
|
Chris@17
|
107 // Valid coding standard dirs include a ruleset.
|
Chris@17
|
108 $csFile = $file->getPathname().'/ruleset.xml';
|
Chris@17
|
109 if (is_file($csFile) === true) {
|
Chris@17
|
110 $rulesets[] = $csFile;
|
Chris@17
|
111 }
|
Chris@17
|
112 }
|
Chris@17
|
113 }
|
Chris@17
|
114 }//end foreach
|
Chris@17
|
115
|
Chris@17
|
116 $installedStandards = [];
|
Chris@17
|
117
|
Chris@17
|
118 foreach ($rulesets as $rulesetPath) {
|
Chris@18
|
119 $ruleset = @simplexml_load_string(file_get_contents($rulesetPath));
|
Chris@17
|
120 if ($ruleset === false) {
|
Chris@17
|
121 continue;
|
Chris@17
|
122 }
|
Chris@17
|
123
|
Chris@17
|
124 $standardName = (string) $ruleset['name'];
|
Chris@17
|
125 $dirname = basename(dirname($rulesetPath));
|
Chris@17
|
126
|
Chris@17
|
127 if (isset($ruleset['namespace']) === true) {
|
Chris@17
|
128 $namespace = (string) $ruleset['namespace'];
|
Chris@17
|
129 } else {
|
Chris@17
|
130 $namespace = $dirname;
|
Chris@17
|
131 }
|
Chris@17
|
132
|
Chris@17
|
133 $installedStandards[$dirname] = [
|
Chris@17
|
134 'path' => dirname($rulesetPath),
|
Chris@17
|
135 'name' => $standardName,
|
Chris@17
|
136 'namespace' => $namespace,
|
Chris@17
|
137 ];
|
Chris@17
|
138 }//end foreach
|
Chris@17
|
139
|
Chris@17
|
140 return $installedStandards;
|
Chris@17
|
141
|
Chris@17
|
142 }//end getInstalledStandardDetails()
|
Chris@17
|
143
|
Chris@17
|
144
|
Chris@17
|
145 /**
|
Chris@17
|
146 * Get a list of all coding standards installed.
|
Chris@17
|
147 *
|
Chris@17
|
148 * Coding standards are directories located in the
|
Chris@17
|
149 * CodeSniffer/Standards directory. Valid coding standards
|
Chris@17
|
150 * include a Sniffs subdirectory.
|
Chris@17
|
151 *
|
Chris@17
|
152 * @param boolean $includeGeneric If true, the special "Generic"
|
Chris@17
|
153 * coding standard will be included
|
Chris@17
|
154 * if installed.
|
Chris@17
|
155 * @param string $standardsDir A specific directory to look for standards
|
Chris@17
|
156 * in. If not specified, PHP_CodeSniffer will
|
Chris@17
|
157 * look in its default locations.
|
Chris@17
|
158 *
|
Chris@17
|
159 * @return array
|
Chris@17
|
160 * @see isInstalledStandard()
|
Chris@17
|
161 */
|
Chris@17
|
162 public static function getInstalledStandards(
|
Chris@17
|
163 $includeGeneric=false,
|
Chris@17
|
164 $standardsDir=''
|
Chris@17
|
165 ) {
|
Chris@17
|
166 $installedStandards = [];
|
Chris@17
|
167
|
Chris@17
|
168 if ($standardsDir === '') {
|
Chris@17
|
169 $installedPaths = self::getInstalledStandardPaths();
|
Chris@17
|
170 } else {
|
Chris@17
|
171 $installedPaths = [$standardsDir];
|
Chris@17
|
172 }
|
Chris@17
|
173
|
Chris@17
|
174 foreach ($installedPaths as $standardsDir) {
|
Chris@17
|
175 // Check if the installed dir is actually a standard itself.
|
Chris@17
|
176 $csFile = $standardsDir.'/ruleset.xml';
|
Chris@17
|
177 if (is_file($csFile) === true) {
|
Chris@17
|
178 $installedStandards[] = basename($standardsDir);
|
Chris@17
|
179 continue;
|
Chris@17
|
180 }
|
Chris@17
|
181
|
Chris@17
|
182 if (is_dir($standardsDir) === false) {
|
Chris@17
|
183 // Doesn't exist.
|
Chris@17
|
184 continue;
|
Chris@17
|
185 }
|
Chris@17
|
186
|
Chris@17
|
187 $di = new \DirectoryIterator($standardsDir);
|
Chris@17
|
188 foreach ($di as $file) {
|
Chris@17
|
189 if ($file->isDir() === true && $file->isDot() === false) {
|
Chris@17
|
190 $filename = $file->getFilename();
|
Chris@17
|
191
|
Chris@17
|
192 // Ignore the special "Generic" standard.
|
Chris@17
|
193 if ($includeGeneric === false && $filename === 'Generic') {
|
Chris@17
|
194 continue;
|
Chris@17
|
195 }
|
Chris@17
|
196
|
Chris@17
|
197 // Valid coding standard dirs include a ruleset.
|
Chris@17
|
198 $csFile = $file->getPathname().'/ruleset.xml';
|
Chris@17
|
199 if (is_file($csFile) === true) {
|
Chris@17
|
200 $installedStandards[] = $filename;
|
Chris@17
|
201 }
|
Chris@17
|
202 }
|
Chris@17
|
203 }
|
Chris@17
|
204 }//end foreach
|
Chris@17
|
205
|
Chris@17
|
206 return $installedStandards;
|
Chris@17
|
207
|
Chris@17
|
208 }//end getInstalledStandards()
|
Chris@17
|
209
|
Chris@17
|
210
|
Chris@17
|
211 /**
|
Chris@17
|
212 * Determine if a standard is installed.
|
Chris@17
|
213 *
|
Chris@17
|
214 * Coding standards are directories located in the
|
Chris@17
|
215 * CodeSniffer/Standards directory. Valid coding standards
|
Chris@17
|
216 * include a ruleset.xml file.
|
Chris@17
|
217 *
|
Chris@17
|
218 * @param string $standard The name of the coding standard.
|
Chris@17
|
219 *
|
Chris@17
|
220 * @return boolean
|
Chris@17
|
221 * @see getInstalledStandards()
|
Chris@17
|
222 */
|
Chris@17
|
223 public static function isInstalledStandard($standard)
|
Chris@17
|
224 {
|
Chris@17
|
225 $path = self::getInstalledStandardPath($standard);
|
Chris@17
|
226 if ($path !== null && strpos($path, 'ruleset.xml') !== false) {
|
Chris@17
|
227 return true;
|
Chris@17
|
228 } else {
|
Chris@17
|
229 // This could be a custom standard, installed outside our
|
Chris@17
|
230 // standards directory.
|
Chris@17
|
231 $standard = Common::realPath($standard);
|
Chris@17
|
232
|
Chris@17
|
233 // Might be an actual ruleset file itUtil.
|
Chris@17
|
234 // If it has an XML extension, let's at least try it.
|
Chris@17
|
235 if (is_file($standard) === true
|
Chris@17
|
236 && (substr(strtolower($standard), -4) === '.xml'
|
Chris@17
|
237 || substr(strtolower($standard), -9) === '.xml.dist')
|
Chris@17
|
238 ) {
|
Chris@17
|
239 return true;
|
Chris@17
|
240 }
|
Chris@17
|
241
|
Chris@17
|
242 // If it is a directory with a ruleset.xml file in it,
|
Chris@17
|
243 // it is a standard.
|
Chris@17
|
244 $ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml';
|
Chris@17
|
245 if (is_file($ruleset) === true) {
|
Chris@17
|
246 return true;
|
Chris@17
|
247 }
|
Chris@17
|
248 }//end if
|
Chris@17
|
249
|
Chris@17
|
250 return false;
|
Chris@17
|
251
|
Chris@17
|
252 }//end isInstalledStandard()
|
Chris@17
|
253
|
Chris@17
|
254
|
Chris@17
|
255 /**
|
Chris@17
|
256 * Return the path of an installed coding standard.
|
Chris@17
|
257 *
|
Chris@17
|
258 * Coding standards are directories located in the
|
Chris@17
|
259 * CodeSniffer/Standards directory. Valid coding standards
|
Chris@17
|
260 * include a ruleset.xml file.
|
Chris@17
|
261 *
|
Chris@17
|
262 * @param string $standard The name of the coding standard.
|
Chris@17
|
263 *
|
Chris@17
|
264 * @return string|null
|
Chris@17
|
265 */
|
Chris@17
|
266 public static function getInstalledStandardPath($standard)
|
Chris@17
|
267 {
|
Chris@17
|
268 if (strpos($standard, '.') !== false) {
|
Chris@17
|
269 return null;
|
Chris@17
|
270 }
|
Chris@17
|
271
|
Chris@17
|
272 $installedPaths = self::getInstalledStandardPaths();
|
Chris@17
|
273 foreach ($installedPaths as $installedPath) {
|
Chris@17
|
274 $standardPath = $installedPath.DIRECTORY_SEPARATOR.$standard;
|
Chris@17
|
275 if (file_exists($standardPath) === false) {
|
Chris@17
|
276 if (basename($installedPath) !== $standard) {
|
Chris@17
|
277 continue;
|
Chris@17
|
278 }
|
Chris@17
|
279
|
Chris@17
|
280 $standardPath = $installedPath;
|
Chris@17
|
281 }
|
Chris@17
|
282
|
Chris@17
|
283 $path = Common::realpath($standardPath.DIRECTORY_SEPARATOR.'ruleset.xml');
|
Chris@17
|
284
|
Chris@17
|
285 if (is_file($path) === true) {
|
Chris@17
|
286 return $path;
|
Chris@17
|
287 } else if (Common::isPharFile($standardPath) === true) {
|
Chris@17
|
288 $path = Common::realpath($standardPath);
|
Chris@17
|
289 if ($path !== false) {
|
Chris@17
|
290 return $path;
|
Chris@17
|
291 }
|
Chris@17
|
292 }
|
Chris@17
|
293 }//end foreach
|
Chris@17
|
294
|
Chris@17
|
295 return null;
|
Chris@17
|
296
|
Chris@17
|
297 }//end getInstalledStandardPath()
|
Chris@17
|
298
|
Chris@17
|
299
|
Chris@17
|
300 /**
|
Chris@17
|
301 * Prints out a list of installed coding standards.
|
Chris@17
|
302 *
|
Chris@17
|
303 * @return void
|
Chris@17
|
304 */
|
Chris@17
|
305 public static function printInstalledStandards()
|
Chris@17
|
306 {
|
Chris@17
|
307 $installedStandards = self::getInstalledStandards();
|
Chris@17
|
308 $numStandards = count($installedStandards);
|
Chris@17
|
309
|
Chris@17
|
310 if ($numStandards === 0) {
|
Chris@17
|
311 echo 'No coding standards are installed.'.PHP_EOL;
|
Chris@17
|
312 } else {
|
Chris@17
|
313 $lastStandard = array_pop($installedStandards);
|
Chris@17
|
314 if ($numStandards === 1) {
|
Chris@17
|
315 echo "The only coding standard installed is $lastStandard".PHP_EOL;
|
Chris@17
|
316 } else {
|
Chris@17
|
317 $standardList = implode(', ', $installedStandards);
|
Chris@17
|
318 $standardList .= ' and '.$lastStandard;
|
Chris@17
|
319 echo 'The installed coding standards are '.$standardList.PHP_EOL;
|
Chris@17
|
320 }
|
Chris@17
|
321 }
|
Chris@17
|
322
|
Chris@17
|
323 }//end printInstalledStandards()
|
Chris@17
|
324
|
Chris@17
|
325
|
Chris@17
|
326 }//end class
|