Skip to content

Commit

Permalink
Merge pull request #192 from Yoast/feature/3.x/drop-support-for-php-7.0
Browse files Browse the repository at this point in the history
3.0 | Drop support for PHP < 7.0
  • Loading branch information
hellofromtonya authored Sep 6, 2024
2 parents 61623d6 + 8de2ad1 commit 805f0ba
Show file tree
Hide file tree
Showing 18 changed files with 256 additions and 674 deletions.
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

0 comments on commit 805f0ba

Please sign in to comment.