diff --git a/includes/Traits/License_Utils.php b/includes/Traits/License_Utils.php index 062bbadf4..80ebe44af 100644 --- a/includes/Traits/License_Utils.php +++ b/includes/Traits/License_Utils.php @@ -56,6 +56,10 @@ protected function get_normalized_license( $license ) { $license = preg_replace( '/GPL\s*[-|\.]*\s*[v]?([0-9])(\.[0])?/i', 'GPL$1', $license, 1 ); $license = preg_replace( '/Apache.*?([0-9])(\.[0])?/i', 'Apache$1', $license ); $license = preg_replace( '/(The\s+)?Unlicense/i', 'Unlicense', $license ); + // Normalize WTFPL variations - must come before version removal to catch full text. + $license = preg_replace( '/Do\s+What\s+The\s+F[^\s]*\s+You\s+Want\s+To\s+Public\s+License/i', 'WTFPL', $license ); + // Remove version numbers from WTFPL (e.g., "WTFPL v2" -> "WTFPL"). + $license = preg_replace( '/WTFPL\s*[v]?([0-9])/i', 'WTFPL', $license ); $license = str_replace( '.', '', $license ); return $license; @@ -84,7 +88,13 @@ protected function is_license_valid_identifier( $license ) { * @return bool true if the license is GPL compatible, otherwise false. */ protected function is_license_gpl_compatible( $license ) { - $match = preg_match( '/GPL|GNU|MIT|FreeBSD|New BSD|BSD-3-Clause|BSD 3 Clause|OpenLDAP|Expat|Apache2|MPL20|ISC|CC0|Unlicense/im', $license ); + // Check for WTFPL in full text form before normalization. + $wtfpl_match = preg_match( '/Do\s+What\s+The\s+F[^\s]*\s+You\s+Want\s+To\s+Public\s+License/i', $license ); + if ( $wtfpl_match ) { + return true; + } + + $match = preg_match( '/GPL|GNU|MIT|FreeBSD|New BSD|BSD-3-Clause|BSD 3 Clause|OpenLDAP|Expat|Apache2|MPL20|ISC|CC0|Unlicense|WTFPL/im', $license ); return ( false === $match || 0 === $match ) ? false : true; } diff --git a/tests/phpunit/testdata/plugins/test-plugin-wtfpl-license/load.php b/tests/phpunit/testdata/plugins/test-plugin-wtfpl-license/load.php new file mode 100644 index 000000000..c8bab9522 --- /dev/null +++ b/tests/phpunit/testdata/plugins/test-plugin-wtfpl-license/load.php @@ -0,0 +1,12 @@ +assertCount( 1, wp_list_filter( $errors['load.php'][0][0], array( 'code' => 'plugin_header_invalid_license' ) ) ); } + public function test_run_with_valid_wtfpl_license() { + $check = new Plugin_Header_Fields_Check(); + $check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-wtfpl-license/load.php' ); + $check_result = new Check_Result( $check_context ); + + $check->run( $check_result ); + + $errors = $check_result->get_errors(); + + // Should not have invalid license error for WTFPL. + if ( isset( $errors['load.php'] ) && isset( $errors['load.php'][0][0] ) ) { + $invalid_license_errors = wp_list_filter( $errors['load.php'][0][0], array( 'code' => 'plugin_header_invalid_license' ) ); + $this->assertEmpty( $invalid_license_errors, 'WTFPL license should be recognized as GPL-compatible' ); + } else { + // If no errors at all, that's also fine - the license is valid. + $this->assertTrue( true ); + } + } + public function test_run_with_invalid_header_fields() { $check = new Plugin_Header_Fields_Check(); $check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-late-escaping-errors/load.php' ); diff --git a/tests/phpunit/tests/Traits/License_Utils_Tests.php b/tests/phpunit/tests/Traits/License_Utils_Tests.php index 65cb71e8c..a6dbf830e 100644 --- a/tests/phpunit/tests/Traits/License_Utils_Tests.php +++ b/tests/phpunit/tests/Traits/License_Utils_Tests.php @@ -78,6 +78,11 @@ public function data_licenses_for_normalization() { array( 'The Unlicense', 'Unlicense' ), array( 'Unlicense', 'Unlicense' ), + + array( 'WTFPL', 'WTFPL' ), + array( 'WTFPL v2', 'WTFPL' ), + array( 'Do What The F*ck You Want To Public License', 'WTFPL' ), + array( 'Do What The Fuck You Want To Public License', 'WTFPL' ), ); } @@ -120,6 +125,10 @@ public function data_license_gpl_compatibility() { array( 'CC0 1.0 Universal', true ), array( 'The Unlicense', true ), array( 'Unlicense', true ), + array( 'WTFPL', true ), + array( 'WTFPL v2', true ), + array( 'Do What The F*ck You Want To Public License', true ), + array( 'Do What The Fuck You Want To Public License', true ), array( 'EPL', false ), array( 'EUPL', false ),