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

3.0 | Drop support for PHP < 7.0 #192

Merged
merged 4 commits into from
Sep 6, 2024
Merged
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
6 changes: 1 addition & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

strategy:
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', 'nightly']
php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', 'nightly']

continue-on-error: ${{ matrix.php == 'nightly' }}

Expand Down Expand Up @@ -62,10 +62,6 @@ jobs:
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")

- name: "Lint PHP files against parse errors - PHP < 7.0"
if: ${{ matrix.php != 'nightly' && matrix.php < 7.0 }}
run: composer lint-lt70 -- --checkstyle | cs2pr

- name: "Lint PHP files against parse errors - PHP 7.0"
if: ${{ matrix.php == '7.0' }}
run: composer lint70
Expand Down
12 changes: 4 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,18 @@ jobs:

strategy:
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
phpunit: ['auto']
coverage: [true]
experimental: [false]

include:
# Test against a version on the low-end of the PHPUnit versions supported for each PHP version.
# Using the Composer `--prefer-lowest` option is, unfortunately, not viable, as
# it would result PHP 5.6 - 7.4 all using PHPUnit 5.7.21, which is not the intention.
# it would result PHP 7.0 - 7.4 all using PHPUnit 5.7.21, which is not the intention.
# It also would run into trouble with PHP 8.5.12 being used on PHP 8.0+, while the
# 8.5.12 release still contained a bug which makes it incompatible with PHP 8.1+,
# even though it officially allows for it..
- php: '5.6'
phpunit: '5.7.21'
coverage: true
experimental: false
- php: '7.0'
phpunit: '5.7.27'
coverage: true
Expand Down Expand Up @@ -211,9 +207,9 @@ jobs:
# This should be sufficient to record the coverage for the PHAR specific code.

# PHPUnit 5 is only supported for PHPUnit 5.7.21-latest.
- php: '5.6'
- php: '7.0'
phpunit: '5.7.21'
- php: '5.6'
- php: '7.0'
phpunit: '5'
- php: '7.1'
phpunit: '5.7.21'
Expand Down
23 changes: 7 additions & 16 deletions .phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
<exclude name="WordPressVIPMinimum"/>

<!-- Exclude select "modern PHP" sniffs, which conflict with the minimum supported PHP version of this package. -->
<exclude name="Modernize.FunctionCalls.Dirname.Nested"/><!-- PHP 7.0+. -->
<exclude name="PSR12.Properties.ConstantVisibility"/><!-- PHP 7.1+. -->
<exclude name="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue"/><!-- PHP 7.1+. -->

Expand All @@ -68,10 +67,6 @@
polyfilled functionality from not being flagged in this repo. -->
<rule ref="PHPCompatibility">
<severity>5</severity>

<!-- These PHP 7.0+ classes are polyfilled for this repo. -->
<exclude name="PHPCompatibility.Classes.NewClasses.errorFound"/>
<exclude name="PHPCompatibility.Classes.NewClasses.typeerrorFound"/>
</rule>

<!-- Enforce PSR1 compatible namespaces. -->
Expand Down Expand Up @@ -179,22 +174,18 @@
<exclude-pattern>/tests/Polyfills/Fixtures/*\.php$</exclude-pattern>
</rule>

<!-- These fixtures for the assertEqualObject() tests will only be loaded on PHP 7+/8+ respectively. -->
<rule ref="PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations">
<exclude-pattern>/tests/Polyfills/Fixtures/ChildValueObject\.php$</exclude-pattern>
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObject\.php$</exclude-pattern>
<!-- These fixtures for the assertEqualObject() tests will only be loaded on PHP 7.1+/8+ respectively. -->
<rule ref="PHPCompatibility.FunctionDeclarations.NewNullableTypes.typeDeclarationFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectParamNotRequired\.php$</exclude-pattern>
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectUnion\.php$</exclude-pattern>
</rule>
<rule ref="PHPCompatibility.FunctionDeclarations.NewNullableTypes.returnTypeFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectNullableReturnType\.php$</exclude-pattern>
</rule>
<rule ref="PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.UnionTypeFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectUnion\.php$</exclude-pattern>
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType\.php$</exclude-pattern>
</rule>
<rule ref="PHPCompatibility.FunctionDeclarations.NewNullableTypes.typeDeclarationFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectParamNotRequired\.php$</exclude-pattern>
</rule>
<rule ref="PHPCompatibility.Operators.NewOperators.t_spaceshipFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObject\.php$</exclude-pattern>
<rule ref="PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.UnionTypeFound">
<exclude-pattern>/tests/Polyfills/Fixtures/ValueObjectUnionReturnType\.php$</exclude-pattern>
</rule>

</ruleset>
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit
Requirements
------------

* PHP 5.6 or higher.
* PHP 7.0 or higher.
* [PHPUnit] 5.7 - 10.x (automatically required via Composer).

[PHPUnit]: https://packagist.org/packages/phpunit/phpunit
Expand Down Expand Up @@ -391,17 +391,10 @@ This assertion expects an object to contain a comparator method in the object it

The `assertObjectEquals()` assertion was introduced in PHPUnit 9.4.0.

> :information_source: Due to [limitations in how this assertion is implemented in PHPUnit] itself, it is currently not possible to create a single comparator method which will be compatible with both PHP < 7.0 and PHP 7.0 or higher.
>
> In effect two declarations of the same object would be needed to be compatible with PHP < 7.0 and PHP 7.0 and higher and still allow for testing the object using the `assertObjectEquals()` assertion.
>
> Due to this limitation, it is recommended to only use this assertion if the minimum supported PHP version of a project is PHP 7.0 or higher; or if the project does not run its tests on PHPUnit >= 9.4.0.
>
> The implementation of this assertion in the Polyfills is PHP cross-version compatible.

[limitations in how this assertion is implemented in PHPUnit]: https://github.com/sebastianbergmann/phpunit/issues/4707
> :information_source: In PHPUnit Polyfills 1.x and 2.x, the polyfill for this assertion had [some limitations][assertobjectequals-limitations]. These limitations are no longer present in PHPUnit Polyfills 3.x and the assertion now matches the PHPUnit native implementation.

[`Assert::assertObjectEquals()`]: https://docs.phpunit.de/en/main/assertions.html#assertobjectequals
[assertobjectequals-limitations]: https://github.com/Yoast/PHPUnit-Polyfills/?tab=readme-ov-file#phpunit--940-yoastphpunitpolyfillspolyfillsassertobjectequals

#### PHPUnit < 10.0.0: `Yoast\PHPUnitPolyfills\Polyfills\AssertIgnoringLineEndings`

Expand Down
14 changes: 5 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy"
},
"require": {
"php": ">=5.6",
"php": ">=7.0",
"phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0"
},
"require-dev": {
Expand Down Expand Up @@ -59,22 +59,19 @@
},
"scripts": {
"lint7": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php"
],
"lint70": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
],
"lint-lt70": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/TestCases/TestCasePHPUnitGte8.php --exclude src/TestListeners/TestListenerDefaultImplementationPHPUnitGte7.php --exclude tests/Polyfills/Fixtures/ChildValueObject.php --exclude tests/Polyfills/Fixtures/ValueObject.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionNoReturnType.php"
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude src/Exceptions/Error.php --exclude src/Exceptions/TypeError.php --exclude tests/Polyfills/Fixtures/ValueObjectParamNotRequired.php --exclude tests/Polyfills/Fixtures/ValueObjectNullableReturnType.php --exclude tests/Polyfills/Fixtures/ValueObjectUnion.php --exclude tests/Polyfills/Fixtures/ValueObjectUnionReturnType.php"
],
"lint-gte80": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git"
],
"lint-gte84": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git --exclude tests/Polyfills/Fixtures/ValueObjectNoReturnType.php"
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git"
],
"check-cs": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 5.6-"
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 7.0-"
],
"fix-cs": [
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf"
Expand All @@ -95,7 +92,6 @@
"scripts-descriptions": {
"lint7": "Check the PHP files for parse errors. (PHP 7.1 - 7.4)",
"lint70": "Check the PHP files for parse errors. (PHP 7.0)",
"lint-lt70": "Check the PHP files for parse errors. (PHP < 7.0)",
"lint-gte80": "Check the PHP files for parse errors. (PHP 8.0 - 8.3)",
"lint-gte84": "Check the PHP files for parse errors. (PHP 8.4+)",
"check-cs": "Check the PHP files for code style violations and best practices.",
Expand Down
16 changes: 0 additions & 16 deletions phpunitpolyfills-autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,6 @@ final class Autoload {
* @return bool
*/
public static function load( $className ) {
/*
* Polyfill two PHP 7.0 classes.
* The autoloader will only be called for these if these classes don't already
* exist in PHP natively.
*/
if ( $className === 'Error' || $className === 'TypeError' ) {
$file = \realpath( __DIR__ . '/src/Exceptions/' . $className . '.php' );

if ( \is_string( $file ) && \file_exists( $file ) === true ) {
require_once $file;
return true;
}

return false;
}

// Only load classes belonging to this library.
if ( \stripos( $className, 'Yoast\PHPUnitPolyfills' ) !== 0 ) {
return false;
Expand Down
8 changes: 0 additions & 8 deletions src/Exceptions/Error.php

This file was deleted.

8 changes: 0 additions & 8 deletions src/Exceptions/TypeError.php

This file was deleted.

124 changes: 61 additions & 63 deletions src/Polyfills/AssertObjectEquals.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Yoast\PHPUnitPolyfills\Polyfills;

use ReflectionClass;
use ReflectionException;
use ReflectionNamedType;
use ReflectionObject;
use ReflectionType;
Expand All @@ -16,7 +14,7 @@
* Introduced in PHPUnit 9.4.0.
*
* The polyfill implementation closely matches the PHPUnit native implementation with the exception
* of the return type check and the names of the thrown exceptions.
* of the thrown exceptions.
*
* @link https://github.com/sebastianbergmann/phpunit/issues/4467
* @link https://github.com/sebastianbergmann/phpunit/issues/4707
Expand All @@ -37,8 +35,7 @@ trait AssertObjectEquals {
* - The method must accept exactly one argument and this argument must be required.
* - This parameter must have a classname-based declared type.
* - The $expected object must be compatible with this declared type.
* - The method must have a declared bool return type. (JRF: not verified in this implementation)
* - `$actual->$method($expected)` returns boolean true.
* - The method must have a declared bool return type.
*
* @param object $expected Expected value.
* @param object $actual The value to test.
Expand Down Expand Up @@ -103,14 +100,49 @@ final public static function assertObjectEquals( $expected, $actual, $method = '
$reflMethod = $reflObject->getMethod( $method );

/*
* As the next step, PHPUnit natively would validate the return type,
* but as return type declarations is a PHP 7.0+ feature, the polyfill
* skips this check in favour of checking the type of the actual
* returned value.
*
* Also see the upstream discussion about this:
* {@link https://github.com/sebastianbergmann/phpunit/issues/4707}
* Comparator method return type requirements validation.
*/
$returnTypeError = \sprintf(
'Comparison method %s::%s() does not declare bool return type.',
\get_class( $actual ),
$method
);

if ( $reflMethod->hasReturnType() === false ) {
throw new InvalidComparisonMethodException( $returnTypeError );
}

$returnType = $reflMethod->getReturnType();

if ( \class_exists( 'ReflectionNamedType' ) ) {
// PHP >= 7.1: guard against union/intersection return types.
if ( ( $returnType instanceof ReflectionNamedType ) === false ) {
throw new InvalidComparisonMethodException( $returnTypeError );
}
}
elseif ( ( $returnType instanceof ReflectionType ) === false ) {
/*
* PHP 7.0.
* Checking for `ReflectionType` will not throw an error on union types,
* but then again union types are not supported on PHP 7.0.
*/
throw new InvalidComparisonMethodException( $returnTypeError );
}

if ( $returnType->allowsNull() === true ) {
throw new InvalidComparisonMethodException( $returnTypeError );
}

if ( \method_exists( $returnType, 'getName' ) ) {
// PHP 7.1+.
if ( $returnType->getName() !== 'bool' ) {
throw new InvalidComparisonMethodException( $returnTypeError );
}
}
elseif ( (string) $returnType !== 'bool' ) {
// PHP 7.0.
throw new InvalidComparisonMethodException( $returnTypeError );
}

/*
* Comparator method parameter requirements validation.
Expand Down Expand Up @@ -142,55 +174,31 @@ final public static function assertObjectEquals( $expected, $actual, $method = '

$reflParameter = $reflMethod->getParameters()[0];

if ( \method_exists( $reflParameter, 'hasType' ) ) {
// PHP >= 7.0.
$hasType = $reflParameter->hasType();
if ( $hasType === false ) {
$hasType = $reflParameter->hasType();
if ( $hasType === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}

$type = $reflParameter->getType();
if ( \class_exists( 'ReflectionNamedType' ) ) {
// PHP >= 7.1.
if ( ( $type instanceof ReflectionNamedType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}

$type = $reflParameter->getType();
if ( \class_exists( 'ReflectionNamedType' ) ) {
// PHP >= 7.1.
if ( ( $type instanceof ReflectionNamedType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}

$typeName = $type->getName();
}
else {
/*
* PHP 7.0.
* Checking for `ReflectionType` will not throw an error on union types,
* but then again union types are not supported on PHP 7.0.
*/
if ( ( $type instanceof ReflectionType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}

$typeName = (string) $type;
}
$typeName = $type->getName();
}
else {
// PHP < 7.0.
try {
/*
* Using `ReflectionParameter::getClass()` will trigger an autoload of the class,
* but that's okay as for a valid class type that would be triggered on the
* function call to the $method (at the end of this assertion) anyway.
*/
$hasType = $reflParameter->getClass();
} catch ( ReflectionException $e ) {
// Class with a type declaration for a non-existent class.
throw new InvalidComparisonMethodException( $notAcceptableTypeError );
}

if ( ( $hasType instanceof ReflectionClass ) === false ) {
// Array or callable type.
/*
* PHP 7.0.
* Checking for `ReflectionType` will not throw an error on union types,
* but then again union types are not supported on PHP 7.0.
*/
if ( ( $type instanceof ReflectionType ) === false ) {
throw new InvalidComparisonMethodException( $noDeclaredTypeError );
}

$typeName = $hasType->name;
$typeName = (string) $type;
}

/*
Expand All @@ -209,16 +217,6 @@ final public static function assertObjectEquals( $expected, $actual, $method = '
*/
$result = $actual->{$method}( $expected );

if ( \is_bool( $result ) === false ) {
throw new InvalidComparisonMethodException(
\sprintf(
'Comparison method %s::%s() does not return a boolean value.',
\get_class( $actual ),
$method
)
);
}

$msg = \sprintf(
'Failed asserting that two objects are equal. The objects are not equal according to %s::%s()',
\get_class( $actual ),
Expand Down
Loading
Loading