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
39 changes: 31 additions & 8 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
[default]
extend-ignore-re = [
"avail_post_stati",
"ba",
"MAGPIE_INITALIZED",
"setted_site_transient",
"setted_transient",
"stati",
"wheres",
# Ignore TLD names file - contains legitimate domain extensions that look like typos
]

[files]
# Ignore spell checking in TLD names file as it contains legitimate domain extensions
extend-exclude = [
"includes/Lib/Readme/*.php"
"includes/Traits/TLD_Names.php"
]

[default.extend-words]
# Brand names and legitimate TLDs
chanel = "chanel"
marshalls = "marshalls"
immobilien = "immobilien"
lolipop = "lolipop"
onl = "onl"
passagens = "passagens"

# WordPress core function names (intentional naming)
stati = "stati" # WordPress function: get_post_stati
wheres = "wheres" # WordPress variable: $wheres

# WordPress core action/hook names (must match exactly)
setted = "setted" # WordPress hooks: setted_site_transient, setted_transient

# WordPress core constants (legacy naming)
INITALIZED = "INITALIZED" # WordPress constant: MAGPIE_INITALIZED

# Third-party library names
ba = "ba" # jQuery plugin: jquery.ba-serializeobject

# Creative Commons license abbreviations
ND = "ND" # CC BY-ND (No Derivatives)

# Parser checks for invalid licenses (intentionally includes common misspellings)
Proprietery = "Proprietery" # Intentional check in Parser.php for common license typo
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"composer/installers": true,
"cweagans/composer-patches": false,
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
"phpstan/extension-installer": true,
"php-http/discovery": true
},
"platform": {
"php": "7.4"
Expand Down
88 changes: 88 additions & 0 deletions includes/Checker/Checks/Plugin_Repo/Plugin_Readme_Check.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
use WordPress\Plugin_Check\Checker\Checks\Abstract_File_Check;
use WordPress\Plugin_Check\Lib\Readme\Parser as PCPParser;
use WordPress\Plugin_Check\Traits\Amend_Check_Result;
use WordPress\Plugin_Check\Traits\External_Utils;
use WordPress\Plugin_Check\Traits\Find_Readme;
use WordPress\Plugin_Check\Traits\Language_Utils;
use WordPress\Plugin_Check\Traits\License_Utils;
use WordPress\Plugin_Check\Traits\Stable_Check;
use WordPress\Plugin_Check\Traits\TLD_Names;
use WordPress\Plugin_Check\Traits\URL_Utils;
use WordPress\Plugin_Check\Traits\Version_Utils;
use WordPressdotorg\Plugin_Directory\Readme\Parser as DotorgParser;
Expand All @@ -32,6 +34,8 @@ class Plugin_Readme_Check extends Abstract_File_Check {

use Amend_Check_Result;
use Find_Readme;
use TLD_Names;
use External_Utils;
use Stable_Check;
use License_Utils;
use URL_Utils;
Expand Down Expand Up @@ -118,6 +122,9 @@ protected function check_files( Check_Result $result, array $files ) {
// Check the readme file for contributors.
$this->check_for_contributors( $result, $readme_file );

// Check for third parties privacy notes.
$this->check_for_privacy_notes( $result, $readme_file, $parser, $files );

// Check the readme file for requires headers.
$this->check_requires_headers( $result, $readme_file, $parser );

Expand Down Expand Up @@ -849,6 +856,87 @@ function ( $value ) {
}

/**
* Checks the readme file for external privacy notes.
*
* @since 1.4.0
*
* @param Check_Result $result The Check Result to amend.
* @param string $readme_file Readme file.
* @param DotorgParser|PCPParser $parser The Parser object.
* @param array $files Array of plugin files.
*/
private function check_for_privacy_notes( Check_Result $result, string $readme_file, $parser, array $files ) {
$existing_tld_names = $this->get_tld_names();

// Load domains mentioned in readme.
$this->domains_mentioned_readme = $this->load_domains_mentioned_in_readme( $readme_file, $existing_tld_names );

// Filter files to check (PHP, JS, CSS).
$files_ext = self::filter_files_by_extensions( $files, array( 'php', 'css', 'js' ) );

// Collect all external domains found in the plugin files.
$found_domains = array();
foreach ( $files_ext as $file ) {
$domains_in_file = $this->find_external_domains_in_file( $file );
if ( ! empty( $domains_in_file ) ) {
foreach ( $domains_in_file as $domain ) {
$found_domains[ $domain ] = $file;
}
}
}

// Skip if no external domains found.
if ( empty( $found_domains ) ) {
return;
}

// Check each found domain.
foreach ( $found_domains as $domain => $file ) {
// Extract base domain using TLD list.
$base_domain = $this->extract_domain_from_host( $domain, $existing_tld_names );

// Check if domain is mentioned in readme.
if ( ! $this->is_domain_mentioned_in_readme( $base_domain ) ) {
$this->add_result_error_for_file(
$result,
sprintf(
/* translators: 1: domain, 2: file where found */
__( '<strong>Undocumented use of a 3rd party or external service.</strong><br>We permit plugins to require the use of 3rd party (external) services, provided they are properly documented in a clear manner. Please update your readme with documentation for the external service "%1$s" found in file %2$s. In order to do so, you must update your readme to: clearly explain that your plugin is relying on a 3rd party as a service and under what circumstances, provide a link to the service, and provide a link to the service\'s terms of use and/or privacy policies.', 'plugin-check' ),
esc_html( $domain ),
esc_html( basename( $file ) )
),
'undocumented_third_party_service',
$readme_file,
0,
0,
'https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/#8-plugins-may-not-send-executable-code-via-third-party-systems',
7
);
continue;
}

// Domain is mentioned, check if it's documented with privacy/terms.
if ( ! $this->is_domain_documented_readme( $base_domain ) ) {
$this->add_result_warning_for_file(
$result,
sprintf(
/* translators: %s: domain */
__( '<strong>Third-party service may not be properly documented.</strong><br>The external service "%s" is mentioned in your readme, but we could not find clear links to privacy policy or terms of service. Please ensure you provide links to the service\'s terms of use and/or privacy policies.', 'plugin-check' ),
esc_html( $domain )
),
'incomplete_third_party_service_documentation',
$readme_file,
0,
0,
'https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/#8-plugins-may-not-send-executable-code-via-third-party-systems',
6
);
}
}
}

/**
* Returns current major WordPress version.
* Checks the readme file for requires headers.
*
* @since 1.5.0
Expand Down
6 changes: 3 additions & 3 deletions includes/Lib/Readme/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Parser {
public $faq = array();

/**
* Warning flags which indicate specific parsing failures have occured.
* Warning flags which indicate specific parsing failures have occurred.
*
* @var array
*/
Expand Down Expand Up @@ -830,7 +830,7 @@ protected function sanitize_requires_version( $version ) {
if (
// x.y or x.y.z
! preg_match( '!^\d+\.\d(\.\d+)?$!', $version ) ||
// Allow plugins to mark themselves as requireing Stable+0.1 (trunk/master) but not higher
// Allow plugins to mark themselves as requiring Stable+0.1 (trunk/master) but not higher
defined( 'WP_CORE_STABLE_BRANCH' ) && ( (float) $version > (float) WP_CORE_STABLE_BRANCH + 0.1 )
) {
$this->warnings['requires_header_ignored'] = true;
Expand Down Expand Up @@ -945,7 +945,7 @@ public function validate_license( $license ) {
$probably_compatible = array(
'GPL',
'General Public License',
// 'GNU 2', 'GNU Public', 'GNU Version 2' explicitely not included, as it's not a specific license.
// 'GNU 2', 'GNU Public', 'GNU Version 2' explicitly not included, as it's not a specific license.
'MIT',
'ISC',
'Expat',
Expand Down
Loading
Loading