Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/OffloadingSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,21 @@ public function process_token( $stackPtr ) {
return;
}

// Only match HTML markup not arbitrary strings, as those could be covered by EnqueuedResourceOffloadingSniff already.

if (
false === strpos( $content, '<img' ) &&
false === strpos( $content, '<video' ) &&
false === strpos( $content, '<audio' ) &&
false === strpos( $content, '<source' ) &&
false === strpos( $content, '<link' ) &&
false === strpos( $content, '<script' )
) {
return;
// Skip check if the string is within wp_enqueue_script/etc function calls,
// as EnqueuedResourceOffloadingSniff already handles those and we want to avoid double reporting.
if ( isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) {
foreach ( $this->tokens[ $stackPtr ]['nested_parenthesis'] as $opener => $closer ) {
$prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $opener - 1 ), null, true );
if ( false !== $prev && \T_STRING === $this->tokens[ $prev ]['code'] ) {
$function_name = $this->tokens[ $prev ]['content'];
if ( in_array( $function_name, array( 'wp_enqueue_script', 'wp_enqueue_style', 'wp_register_script', 'wp_register_style' ), true ) ) {
return ( $end_ptr + 1 );
}
}
}
}

// First check: Always check against known offloading services pattern for all strings.
$pattern = $this->get_offloading_services_pattern();

$matches = array();
Expand All @@ -92,6 +94,20 @@ public function process_token( $stackPtr ) {
return ( $end_ptr + 1 );
}

// Second check: For HTML markup strings only, also check file extension-based patterns.
// This is limited to HTML context to avoid false positives on arbitrary URLs.

if (
false === strpos( $content, '<img' ) &&
false === strpos( $content, '<video' ) &&
false === strpos( $content, '<audio' ) &&
false === strpos( $content, '<source' ) &&
false === strpos( $content, '<link' ) &&
false === strpos( $content, '<script' )
) {
return ( $end_ptr + 1 );
}

// Known offloading extensions.
$look_known_offloading_ext = array(
'css',
Expand Down
22 changes: 22 additions & 0 deletions phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/OffloadingUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,25 @@
<script src="https://cdn.jsdelivr.net/awesome-script/foo/bar.js" />

<img src="https://s.w.org/some-image.png" />

<?php

// CDN URL in array assignment (issue #1156 pattern).
$assets[] = array(
'url' => 'https://cdn.jsdelivr.net/npm/intl-tel-input@21.2.4/build/js/intlTelInput.min.js',
);

// CDN URL in array assignment for CSS.
$assets[] = array(
'type' => 'css',
'url' => 'https://cdn.jsdelivr.net/npm/intl-tel-input@21.2.4/build/css/intlTelInput.css',
);

// CDN URL in variable assignment.
$script_url = 'https://unpkg.com/some-library@1.0.0/dist/lib.js';

// Non-CDN URL should NOT be flagged.
$api_url = 'https://api.example.com/data';

// Non-CDN safe URL should NOT be flagged.
$safe_url = 'https://mysite.com/wp-content/themes/my-theme/style.css';
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ final class OffloadingUnitTest extends AbstractSniffUnitTest {
*/
public function getErrorList() {
return array(
1 => 1,
3 => 1,
5 => 1,
1 => 1,
3 => 1,
5 => 1,
11 => 1,
17 => 1,
21 => 1,
);
}

Expand Down
Loading