Skip to content
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

Closed
wants to merge 7 commits into from
Closed

Add sniff and tests for No CDN URL #108

wants to merge 7 commits into from

Conversation

ernilambar
Copy link
Member

@ernilambar ernilambar commented Jan 18, 2017

Based on #64 PR.

  • Warning message updated.
  • Maintain coding standard for the files

Fixes #20

@grappler
Copy link
Member

Thank you for the PR. I had a look why we did not merge #64 yet.

  • We are working on a Abstract sniff in WPCS that will allow us to define a function e.g. wp_enqueue_script and then check the second parameter. Once we have this this sniff would only be a few lines of code then.
  • When we use the new sniff it would be easier to whitelist the google fonts URLs then blacklist all of the CDNs.
  • I don't think we need to check for the CDN URLS for styles and scripts as there will be an error if styles and scripts are hardcoded from WordPress.WP.EnqueuedResources

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' );
Copy link
Member

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 ) );

@grappler
Copy link
Member

@ernilambar We have merged WPCS into our fork. You can now rebase your PR and extend WordPress_AbstractFunctionParameterSniff instead.

You can have a look how I have done it here. #26

@ernilambar
Copy link
Member Author

Looks like I did some mess while merging. I will create new PR for this.

@grappler
Copy link
Member

@ernilambar We can still fix this...

Copy link
Member

@grappler grappler left a 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 ) {
Copy link
Member

@grappler grappler Jan 31, 2017

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 ] ) )

Copy link
Member Author

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?

Copy link
Member

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 ----- */
Copy link
Member

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.

Copy link
Member Author

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?

Copy link
Member

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?

Copy link
Member Author

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',
Copy link
Member

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 grappler mentioned this pull request Feb 10, 2017
@ernilambar
Copy link
Member Author

@grappler Anything I need to do from my side here?

@grappler
Copy link
Member

I would like to get @jrfnl to review it too before we merge it.

@jrfnl jrfnl self-requested a review February 15, 2017 15:55
@jrfnl
Copy link
Contributor

jrfnl commented Feb 15, 2017

Put it on my list to review. Bear with me. I'm trying to catch up.

@jrfnl
Copy link
Contributor

jrfnl commented Mar 5, 2017

I don't think we need to check for the CDN URLS for styles and scripts as there will be an error if styles and scripts are hardcoded from WordPress.WP.EnqueuedResources

@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.
In that respect I'd suggest you may want to reconsider sniffing for the CDNs in text strings in general, rather than only limited to the functions now being checked. All the same, you are the better judge of what would work in the theme review process, so it's up to you.

Copy link
Contributor

@jrfnl jrfnl left a 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
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

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(
Copy link
Contributor

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.

Copy link
Member

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(
Copy link
Contributor

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 ?

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Contributor

@jrfnl jrfnl Mar 5, 2017

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'] );

Copy link
Contributor

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 ) );
Copy link
Contributor

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(
Copy link
Contributor

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(
Copy link
Contributor

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.
Copy link
Contributor

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.

Copy link
Member

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.

@grappler
Copy link
Member

grappler commented Mar 7, 2017

I found two more CDN's npmcdn.com from http://imagesloaded.desandro.com/ and unpkg.com

@jrfnl
Copy link
Contributor

jrfnl commented May 31, 2018

@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 ?
If not, would you be ok if I updated the PR ?

Updates needed:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants