-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PHPCS 3.x: Autoloading not working with arbitrary namespace prefix #1469
Comments
FYI: I've put a work-in-progress branch online if you need it: https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/tree/WIP/issue-718-862-phpcs-3.x-compatibility |
I could change the autoloader to detect that the class name looks like a sniff, but the namespace you've used for this abstract sniff wouldn't match the require format of So what the autoloader would need to do is keep chopping off parts of the namespace and looking to see if any file matches somewhere in the Here are some options:
Right now, the prefixing of the namespace works because PHPCS goes and loads all the sniffs in a standard and then uses a util function to look at that special namespace format and figure out the sniff details from it. So if one sniff extends another, PHPCS already knows about them because it loaded all the sniffs files up manually. But it doesn't go through and load files outside the The naming convention in the doc is for sniff files, and so that is what is enforced. There is no naming convention for helpers, so PHPCS can't autoload them. That means adding a convention for helpers is possible (option 2) but I'm not really sold on it. Option 4 sounds ok, but I'm not sure how that would work with multiple custom standards referencing each other. You'd probably need to hard-code the autoloader option into the ruleset of the standard to make it work, which might be fine. Got an opinion about those options, or other options? |
I might have misunderstood this but I don't see the problem about it. Most of the frameworks and packages I see for PHP in github are using the autoload of composer. We live in that age (thank god) that Jordi made the autoloading pretty simple. Codesniffer has made a huge step moving into that age and using this autoloading.
So IMHO this is a WP issue and libraries/framework should not try to be backward compatible for something that the age has moved on. |
This is not my position and I am committed to getting this working. I'd hate for PHPCS to only be usable with projects that use composer, or to force custom coding standards to be installed via composer for them to work. |
I believe that in order to achieve this you will need to create your own custom autoloading mechanism combined with the one of composer just in order to be independent from that autoload mechanism (that I think most of the PHP community uses). I don't see the reason, but anyway... |
That's something I've was working on the entire 2 years 3.0 was in development. You can check out the history of the autoloader if you'd like to see how it came together: https://github.com/squizlabs/PHP_CodeSniffer/blob/master/autoload.php This is just an extension of that already released system. |
Hi @gsherwood Thanks for getting back to me.
I'm trying to create a version which is compatible with PHPCS 2.x and 3.x - though have found since that 2.x can't handle prefixed namespaces either, but that's another matter -. I am trying to balance the needs of both. After everything I've tried so far, option 3 sounds like it would be most flexible.
I believe you are talking about option 3 here ? |
Sorry, yes I was. I think I can have an autoload file (defined in a ruleset.xml file) loaded up before the rest of the ruleset is processed. I'm fairly sure I wont be able to define any sort of order because I need to process a ruleset in order to figure out what other rulesets it requires, so loading order would be dependant on how the ruleset is constructed. I don't know if that's a problem, but I don't think it would be a problem in your specific case, so it might be a good first step. I'll take a look into it and report back. |
Sounds great! I really appreciate your help with this! |
I built the autoload include point, but I'm wondering if it's actually easier to just have the ruleset tell PHPCS what the NS prefix is instead of having to write your own autoloader for just a couple of files. When PHPCS adds the search path based on the standard it includes, it could tell the autoloader what portion of the NS to strip. So for the WP standard, you'd include something like I could also do both. |
… the autoloader to load non-sniff helper files (ref #1469)
I've pushed up a change to allow a namespace to be set for a custom coding standard. You put this into the ruleset.xml for any standard that has custom sniffs and has a prefixed namespace. In your case, you'd put this into the main WordPress ruleset.xml file: <?xml version="1.0"?>
<ruleset name="WordPress" namespace="WordPressCS\WordPress">
<description>WordPress Coding Standards</description>
...
</ruleset> When I do this, the helper files are loading correctly, but I still get errors about |
Note that I haven't changed the upgrade guide yet. I won't do that until we get this issue sorted and confirm the best way to do things. |
Hi @gsherwood Oh wow, both actually sound great! I'm on the road (well, in the air) today, but will have a play with it as soon as I can and get back to you.
That's strange, I thought I'd fixed those (and pushed the fix) already. |
I went ahead and added the autoload feature to rulesets even though I don't think it is currently needed in this case. It's not much code, so doesn't really matter if it doesn't get used right now. |
@gsherwood Thank you very much for that. Much appreciated. Will try to have a play with it next week once I'm back from the conference I'm currently at. And will - of course - report back ;-) |
…arts Notes: * I've added the `PHPCSAliases.php` file in the project root so it won't confuse the PHPCS autoloader and so it can easily be used by other standards if we'd choose to add any in the future. * The file is automatically loaded by PHPCS using the new `<autoload>` option. This option, when encountered in the ruleset, is ignored by previous PHPCS versions, so can be used safely and will automatically make sure the file is only loaded for PHPCS 3.x. * The file is loaded after the PHPCS native autoloader has started, but before any sniffs are loaded making for a clean way to add the aliases and prevent fatal 'class not found' errors. * The PHPCS 3.x custom autoload option does still contain a bug which would cause `class already defined` fatals. See squizlabs/PHP_CodeSniffer/pull/1563. A (temporary) work-around for this is in place, using a constant to make sure the aliases are only set once. The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer/issues/1469
Closing as this was released a couple of versions back. Autoload problems can now be handled in new issues. |
…arts Notes: * I've added the `PHPCSAliases.php` file in the project root so it won't confuse the PHPCS autoloader and so it can easily be used by other standards if we'd choose to add any in the future. * The file is automatically loaded by PHPCS using the new `<autoload>` option. This option, when encountered in the ruleset, is ignored by previous PHPCS versions, so can be used safely and will automatically make sure the file is only loaded for PHPCS 3.x. * The file is loaded after the PHPCS native autoloader has started, but before any sniffs are loaded making for a clean way to add the aliases and prevent fatal 'class not found' errors. * Each class alias statement has to be wrapped in a `class_exists` condition to prevent fatal `class already declared` errors when this ruleset is used in combination with another external ruleset which uses the same methodology to create PHPCS cross-version compatibility. * The PHPCS 3.x custom autoload option does still contain a bug which would cause `class already defined` fatals. See squizlabs/PHP_CodeSniffer/pull/1563. A (temporary) work-around for this is in place, using a constant to make sure the aliases are only set once. This bug has been fixed in PHPCS 3.0.2. The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer/issues/1469
…arts Notes: * The file is automatically loaded by PHPCS using the new `<autoload>` option. This option, when encountered in the ruleset, is ignored by previous PHPCS versions, so can be used safely and will automatically make sure the file is only loaded for PHPCS 3.x. * The file is loaded after the PHPCS native autoloader has started, but before any sniffs are loaded making for a clean way to add the aliases and prevent fatal 'class not found' errors. * Each class alias statement has to be wrapped in a `class_exists` condition to prevent fatal `class already declared` errors when this ruleset is used in combination with another external ruleset which uses the same methodology to create PHPCS cross-version compatibility. The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer#1469
…arts Notes: * The file is automatically loaded by PHPCS using the new `<autoload>` option. This option, when encountered in the ruleset, is ignored by previous PHPCS versions, so can be used safely and will automatically make sure the file is only loaded for PHPCS 3.x. * The file is loaded after the PHPCS native autoloader has started, but before any sniffs are loaded making for a clean way to add the aliases and prevent fatal 'class not found' errors. * Each class alias statement has to be wrapped in a `class_exists` condition to prevent fatal `class already declared` errors when this ruleset is used in combination with another external ruleset which uses the same/similar methodology to create PHPCS cross-version compatibility. The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer#1469
…arts Notes: * The file is automatically loaded by PHPCS using the new `<autoload>` option. This option, when encountered in the ruleset, is ignored by previous PHPCS versions, so can be used safely and will automatically make sure the file is only loaded for PHPCS 3.x. * The file is loaded after the PHPCS native autoloader has started, but before any sniffs are loaded making for a clean way to add the aliases and prevent fatal 'class not found' errors. * Each class alias statement has to be wrapped in a `class_exists` condition to prevent fatal `class already declared` errors when this ruleset is used in combination with other external ruleset(s) which use the same/similar methodology to create PHPCS cross-version compatibility. The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer#1469
The `<autoload>` ruleset directive was added in PHPCS 3.0.1 in response to issue squizlabs/PHP_CodeSniffer#1469
PHPCS has specific naming and directory layout requirements for external standards which the `Security` standard did not comply with. While things sort of worked with the symlink hack, the net effect was: - The PHPCS autoloader did not work. - None of the PHPCS ruleset configuration options worked as PHPCS could not match sniffs to files. - Some sniffs would never load. This PR fixes this by: 1. Setting the base namespace to `PHPCS_SecurityAudit\Security` and annotating this in the `ruleset.xml` file in the correct manner. 2. Fixing all namespaces and uses thereof throughout the codebase. 3. Fixing the `Drupal8/Utils.php` file which was missing the namespace and was still referring to an out-of-date class name to extend. 4. Fixing the namespace names and file names of the CVE sniffs. - The namespace of a sniff has to reflect its path in the standard. - The file name has to reflect the name of the sniff. 5. Fixing the names of the CVE sniffs in the example rulesets 6. Removing the symlink file and all references to it. Instead `require` the [DealerDirect Composer PHPCS plugin](https://github.com/Dealerdirect/phpcodesniffer-composer-installer) which will sort out the `installed_paths` for PHPCS . 7. Setting the minimum PHPCS version to `3.0.2` as prior to that external standards weren't fully supported in the 3.x branch. 8. Removing the `autoload` section in `composer.json`. This is no longer needed and in certain situations can cause conflicts/fatal errors. References: * https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial * https://github.com/squizlabs/PHP_CodeSniffer/wiki/Version-3.0-Upgrade-Guide * squizlabs/PHP_CodeSniffer#2481 (comment) * squizlabs/PHP_CodeSniffer#2606 * squizlabs/PHP_CodeSniffer#1469 * https://github.com/Dealerdirect/phpcodesniffer-composer-installer Fixes 47
PHPCS has specific naming and directory layout requirements for external standards which the `Security` standard did not comply with. While things sort of worked with the symlink hack, the net effect was: - The PHPCS autoloader did not work. - None of the PHPCS ruleset configuration options worked as PHPCS could not match sniffs to files. - Some sniffs would never load. This PR fixes this by: 1. Setting the base namespace to `PHPCS_SecurityAudit\Security` and annotating this in the `ruleset.xml` file in the correct manner. 2. Fixing all namespaces and uses thereof throughout the codebase. 3. Fixing the `Drupal8/Utils.php` file which was missing the namespace and was still referring to an out-of-date class name to extend. 4. Fixing the namespace names and file names of the CVE sniffs. - The namespace of a sniff has to reflect its path in the standard. - The file name has to reflect the name of the sniff. 5. Fixing the names of the CVE sniffs in the example rulesets 6. Removing the symlink file and all references to it. Instead `require` the [DealerDirect Composer PHPCS plugin](https://github.com/Dealerdirect/phpcodesniffer-composer-installer) which will sort out the `installed_paths` for PHPCS . 7. Setting the minimum PHPCS version to `3.0.2` as prior to that external standards weren't fully supported in the 3.x branch. 8. Removing the `autoload` section in `composer.json`. This is no longer needed and in certain situations can cause conflicts/fatal errors. References: * https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial * https://github.com/squizlabs/PHP_CodeSniffer/wiki/Version-3.0-Upgrade-Guide * squizlabs/PHP_CodeSniffer#2481 (comment) * squizlabs/PHP_CodeSniffer#2606 * squizlabs/PHP_CodeSniffer#1469 * https://github.com/Dealerdirect/phpcodesniffer-composer-installer Fixes 47
In the upgrade guide, it says:
I'm currently trying to upgrade the WordPress Coding Standards library and am using the following namespace / class declaration for one of the sniffs:
The file
AbstractArrayAssignmentRestrictionsSniff
class is as expected located in/path/to/WPCS/WordPress/AbstractArrayAssignmentRestrictionsSniff.php
and the/path/to/WPCS
location is registered withinstalled_paths
.This results in a Fatal Error:
Some light debugging shows me that the autoloader is trying to find the file in the following locations:
This would imply that - unless you use Composer and force all users of the standard to use Composer - you cannot use prefixed namespaces.
Or is there a way to "hook in" an extra autoload file which I haven't found out about yet ? The
bootstrap
option cannot be used as it is run too late (after the autoloading of the sniffs).Basically - for the purpose of the autoloading -, I would expect the namespace prefix
WordPressCS
to be ignored, or, to be stripped off the sniff based namespace if the prefixed file cannot be loaded, in order to "try again".While I could use a non-prefixed namespace - after all WP currently does not use namespaces (yet) -, it would be kind of irresponsible to do so IMHO and considering how large the userbase is of the standard, changing the name of the standard would also cause a massive BC break.
Bright ideas or solutions very welcome ;-)
The text was updated successfully, but these errors were encountered: