-
Notifications
You must be signed in to change notification settings - Fork 37
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
Add sniff and tests for No CDN URL #108
Add sniff and tests for No CDN URL #108
Conversation
Thank you for the PR. I had a look why we did not merge #64 yet.
In the normal case it would make sense to give Kevin props in the commit but if the sniff is completely rewritten then it is not needed. |
|
||
foreach ( $cdn_list as $cdn_url ) { | ||
if ( false !== strpos( $match[0], $cdn_url ) ) { | ||
$phpcsFile->addError( 'Found the URL to a CDN: (' . $cdn_url . ') The CSS or JavaScript resources cannot be loaded from a CDN but must be bundled.', $stackPtr, 'CDNFound' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning message can contain variables making it a bit cleaner
$phpcsFile->addError( 'Found the URL to a CDN: (%s). The CSS or JavaScript resources cannot be loaded from a CDN but must be bundled.', $stackPtr, 'CDNFound', array( $cdn_url ) );
@ernilambar We have merged WPCS into our fork. You can now rebase your PR and extend You can have a look how I have done it here. #26 |
Looks like I did some mess while merging. I will create new PR for this. |
@ernilambar We can still fix this... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great otherwise. Thanks!
|
||
$matched_parameter = $this->strip_quotes( $parameters[ $position ]['raw'] ); | ||
|
||
foreach ( $this->cdn_urls as $cdn ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be make a bit more performant with if ( isset( $this->cdn_urls[ $matched_parameter ] ) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key is like bootstrapcdn.com
and $matched_parameter
contains full URL like http://maxcdn.bootstrapcdn.com/bootstrap/file.ext
. So, I used strpos() check here. Should we parse the $matched_parameter
to get domain name only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I did not think of that. Parsing the URL will be resource intensive than the foreach. We could check that it is an URL before hand.
if ( false === strpos( $matched_parameter, '.com' ) ) {
return;
}
We could also stop the foreach once we have a match by adding break;
wp_enqueue_script( 'bootstrap', 'https://code.jquery.com/jquery-whatever/file.js' ); // Bad | ||
wp_enqueue_script( 'bootstrap', 'https://oss.maxcdn.com/libs/respond.js' ); // Bad | ||
|
||
/* ----- links in php comments will not be picked up ----- */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a few google fonts examples here as they they are the exception. If I remember correctly the google font URLs are not always the same. Try to find any many different examples as possible. I am not sure if one of them has googlecode.com
in it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we allow Google Fonts URL other than https://fonts.googleapis.com
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems not. I am not sure what I had in mind. Could you add it to the test data so that we can make sure in the future it is not marked as an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Google fonts CDN is added in the test.
'maxcdn.com' => 'maxcdn.com', | ||
'jquery.com' => 'jquery.com', | ||
'cdnjs.com' => 'cdnjs.com', | ||
'googlecode.com' => 'googlecode.com', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are few more URLs that we can add
cdnjs.cloudflare.com
ajax.googleapis.com
cdn.jsdelivr.net
use.fontawesome.com
opensource.keycdn.com
@grappler Anything I need to do from my side here? |
I would like to get @jrfnl to review it too before we merge it. |
Put it on my list to review. Bear with me. I'm trying to catch up. |
@grappler In general, it is a good idea to have sniffs be completely independent of each other. Now an error which will be identified by one sniff in a way "hides" a following error. From a theme review process perspective, I can imagine this might be frustrating as the theme author would first get a set of feedback and then once the first set is fixed, they'd get a second set of completely new errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ernilambar Thanks for your patience. I've added some remarks and questions inline.
Generally: looking good.
One real question I still have which is more a policy one: should the sniff whitelist or blacklist ? or a combination of both ?
Depending on the answer, I might have some more feedback.
/** | ||
* Array of functions with positions. | ||
* | ||
* The number represents the position in the function call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammer: The number represents the position of the target parameter in the function call
* Array of functions with positions. | ||
* | ||
* The number represents the position in the function call | ||
* passed variables, here the capability is to be listed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capability
?
); | ||
|
||
/** | ||
* Array of CDN URLs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an array of whitelisted or blacklisted CDNs ? Please expand the short description a little to make this clearer.
You may also want to consider changing the property name to $cdn_url_blacklist
or just $cdn_blacklist
.
* | ||
* @var array | ||
*/ | ||
protected $cdn_urls = array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something is niggling in the back of my mind saying that some CDNs use a number of different URLs including regional ones - so a URL might be bootstrapcdn.de
when in Germany. Not sure whether this is actually true or that I'm confusing different things here, but this might need to be investigated and confirmed to be false (and so documented) to be sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I understand it there is normally just one URL but the CDN then chooses which server to load the content from when the receive the request.
* | ||
* @var array | ||
*/ | ||
protected $target_functions = array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are CDNs allowed for loading theme images ? If not, these functions do not cover that, so how is this handled ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good point. I have not seen many themes use external sites to load their images. Normally the reason being that sites do not like hotlinking.
If we wanted to check for this then we would need to check the <img src="">
tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is good to check image also. I have seen usage of images from placehold.it
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no opinion on whether CDNs should be allowed and of is so where, but if you would decide to check text strings like the <img..>
tag, I would suggest also checking the <script...>
and <style..>
tags to prevent the "issues hiding behind other issues".
} | ||
|
||
$matched_parameter = $this->strip_quotes( $parameters[ $position ]['raw'] ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to check whether the parameter is empty here and if so, return early as further checking would be unnecessary.
|
||
foreach ( $this->cdn_urls as $cdn ) { | ||
if ( false !== strpos( $matched_parameter, $cdn ) ) { | ||
$this->phpcsFile->addError( 'Loading resources from %s is prohibited.', $stackPtr, $matched_parameter . ' Found', array( $matched_parameter ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the string_to_errorcode()
method to make sure that the dynamic error code is safe to use.
* | ||
* @var array | ||
*/ | ||
protected $cdn_urls = array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any logic to the order in which the CDNs are listed here ?
For updating, alphabetical order would be simplest, for efficiency of the sniff, the order of most encountered CDNs would be best (but might need some research to determine).
* | ||
* @var array | ||
*/ | ||
protected $cdn_urls = array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the array key isn't used at all, it could be removed.
@@ -0,0 +1,30 @@ | |||
<?php | |||
// Now lets check inside php. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call on having some examples with both http
as well as https
. What about other protocols ? Is ftp
ever used ? Any other protocols you may have encountered ?
I realize that for the sniff it won't make any difference, but might be good to show that those cases (if they exist) are covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not seen any other protocols being used.
I found two more CDN's npmcdn.com from http://imagesloaded.desandro.com/ and unpkg.com |
@ernilambar Hi Nilambar, how are you ? Are you still interested in finishing off this sniff ? If so, would you be willing to work with me over the next few weeks to get it done ? Updates needed:
|
Based on #64 PR.
Fixes #20