WordPress-Coding-Standards
WordPress-Coding-Standards copied to clipboard
Use a PHPCS bootstrap file to auto-detect text-domain and minimum supported wp version
The I18n sniff needs a text_domain property to be set in a custom ruleset to trigger the text-domain checks.
The DeprecatedFunctions, DeprecatedClasses and the upcoming DeprecatedParameters (#826) sniffs need a minimum_supported_version property.
When the sniffs are used on plugins and themes, this information is typically already available in the theme/plugin headers in style.css/ readme.txt or the main plugin file and - at least for the minimum_supported_version a pain to keep in sync.
Since PHPCS 2.5.0 there appears to be a - rarely used - option to bootstrap a file to be run between when the sniffs are loaded and when they are actually run. See:
- https://github.com/squizlabs/PHP_CodeSniffer/pull/783
- https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-bootstrap-file
I would like to suggest we explore the possibility of auto-detecting the above mentioned properties using a bootstrap file.
Some thoughts:
- Look only in the root of the directory being sniffed for any of the files mentioned & if the file is found, parse the top of the file similar to how WP core does. Looking further down or up can quickly become more complicated than is warranted.
- Custom
text_domainproperties if set should still be respected as this is an array and the property can be used to pass more than one text-domain.- So I suggest for the in-sniff logic to check for a custom property first and if none is found, use the auto-detected info. Alternatively, the auto-detected property could be merged into the custom property.
- Custom
minimum_supported_versionproperties should be overruled if something different is auto-detected, as that is the "official" minimum supported version so this should always be leading.
I suggest this to be added to the Extra ruleset as these sniffs are typically contained therein.
Opinions ?
/cc @grappler This principle may also be useful for the theme sniffs.
I have started playing around and it works. This is the bit of code needed to fetch the text domain.
One issue that I came across is if only PHP is defined in extensions then the style.css file will not be loaded in the list of files. The same problem would be if TXT files would not be included.
<?php
$my_files = $phpcs->getFilesToProcess($values['files'], $values['local']);
foreach ( $my_files as $file ) {
if ( false === strpos( $file, 'style.css' ) ) {
continue;
}
$contents = file_get_contents($file);
if (preg_match('/^[ \t\/*#@]*' . preg_quote('Text Domain', '/') . ':(.*)$/mi', $contents, $match)
&& $match[1]) {
PHP_CodeSniffer::setConfigData( 'text_domain', cleanHeaderComment($match[1]) );
}
}
function cleanHeaderComment($content)
{
return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $content));
}
@grappler Interesting. I would expect not to have access to the $phpcs object from within the bootstrap file. Where did you place/run this code snippet in the flow of things ?
Where did you place/run this code snippet in the flow of things ?
This code would be placed in bootstrap.php which is loaded via phpcs --bootstrap=bootstrap.php.
The file is included in PHP_CodeSniffer_CLI::process() in line 995.
@grappler Nice! I was actually thinking of not using the getFilesToProcess(), but of just glob()-ing the root directory of the project being sniffed. That would get round the --extensions=php issue.
Also: style.css would only work for themes and we'd need to cater for plugins too.
I was actually thinking of not using the
getFilesToProcess(), but of justglob()-ing the root directory of the project being sniffed.
The reason I wanted to use getFilesToProcess() is that I felt it was more stable. I am a bit worried that $values['files'][0] is not always going to be the root directory.
Also:
style.csswould only work for themes and we'd need to cater for plugins too.
This was just a proof of concept so we can always extend it to support plugins too.
One caution here that comes to mind is that some IDEs will take the file being edited and place it in /tmp at a random path name and then run it through phpcs. So this could throw a wrench into this being able to be used by many users. I think this issue came up before when attempting to autodetect the text domain.
Yeah, PhpStorm does that. But perhaps the values could be cached in some way, and the cached versions could be used in that case.
Just found this when trying to work through a custom exclude-pattern bootstrap for each of our projects that use a shared phpcs.xml config. On the latest version, at least, I think you're going to want the following:
\PHP_CodeSniffer\Config::setConfigData();