Skip to content

Commit

Permalink
It is time to stop supporting PHP <=7.3 (#117)
Browse files Browse the repository at this point in the history
* Workflow improvements
* Introduce some safeguards
* Improve types
  • Loading branch information
sanmai committed Apr 15, 2023
1 parent 9260c4d commit dd7c3c8
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 54 deletions.
44 changes: 10 additions & 34 deletions .github/workflows/main.yml
Expand Up @@ -17,17 +17,13 @@ jobs:
strategy:
matrix:
php-version:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
- '8.3'
coverage: ['pcov']
dependencies: ['']
include:
- { php-version: '7.1', coverage: 'xdebug', dependencies: '' }

steps:
- name: Checkout code
Expand Down Expand Up @@ -67,41 +63,12 @@ jobs:
run: |
php vendor/bin/php-coveralls -v
coding-standards:
name: Coding Standards
runs-on: ubuntu-latest

env:
PHP_VERSION: '8.1'
PHP_CS_FIXER_VERSION: v3.16.0

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
tools: php-cs-fixer:${{ env.PHP_CS_FIXER_VERSION }}

- name: Restore PHP-CS-Fixer cache
uses: actions/cache@v3
with:
path: .php_cs.cache
key: "php-cs-fixer"
restore-keys: "php-cs-fixer"

- name: Run PHP-CS-Fixer, version ${{ env.PHP_CS_FIXER_VERSION }}
run: |
php-cs-fixer fix --diff --dry-run --verbose
analyze:
name: Static Analysis and Validation
runs-on: ubuntu-latest

env:
PHP_VERSION: '8.1'
PHP_VERSION: '8.2'
COMPOSER_ROOT_VERSION: v5.99

steps:
Expand All @@ -125,6 +92,15 @@ jobs:
composer-${{ env.PHP_VERSION }}-
composer-
- name: Restore PHP-CS-Fixer cache
uses: actions/cache@v3
with:
path: .php_cs.cache
key: php-cs-fixer-${{ env.PHP_VERSION }}-${{ hashFiles('composer.*') }}
restore-keys: |
php-cs-fixer-${{ env.PHP_VERSION }}-
php-cs-fixer-
- name: Install dependencies
run: |
composer update --prefer-dist --no-interaction --no-progress
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
@@ -1,4 +1,5 @@
/composer.lock
/vendor
/build
/.phpunit.result.cache
*.cache
.?*
2 changes: 1 addition & 1 deletion .phan/config.php
Expand Up @@ -3,7 +3,7 @@
use Phan\Issue;

return [
'target_php_version' => '7.1',
'target_php_version' => '7.4',
'backward_compatibility_checks' => false,
'exclude_analysis_directory_list' => [
'vendor/',
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -14,7 +14,7 @@ This rigorously tested library just works. Pipeline neither defines nor throws a

composer require sanmai/pipeline

The latest version requires PHP 7.1 or above, including PHP 8.0 and later.
The latest version requires PHP 7.4 or above, including PHP 8.0 and later.

There are earlier versions that work under PHP 5.6 and above, but they are not as feature complete.

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -10,7 +10,7 @@
}
],
"require": {
"php": "^7.1 || ^8.0"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.8",
Expand Down
27 changes: 11 additions & 16 deletions src/Standard.php
Expand Up @@ -59,14 +59,12 @@ class Standard implements IteratorAggregate, Countable
*
* @var ?iterable
*/
private $pipeline;
private ?iterable $pipeline;

/**
* Contructor with an optional source of data.
*
* @param ?iterable $input
*/
public function __construct(iterable $input = null)
public function __construct(?iterable $input = null)
{
// IteratorAggregate is a nuance best we avoid dealing with.
// For example, CallbackFilterIterator needs a plain Iterator.
Expand All @@ -79,10 +77,8 @@ public function __construct(iterable $input = null)

/**
* Appends the contents of an interable to the end of the pipeline.
*
* @param ?iterable $values
*/
public function append(iterable $values = null): self
public function append(?iterable $values = null): self
{
// Do we need to do anything here?
if ($this->willReplace($values)) {
Expand All @@ -108,10 +104,8 @@ public function push(...$vector): self

/**
* Prepends the pipeline with the contents of an iterable.
*
* @param ?iterable $values
*/
public function prepend(iterable $values = null): self
public function prepend(?iterable $values = null): self
{
// Do we need to do anything here?
if ($this->willReplace($values)) {
Expand Down Expand Up @@ -140,7 +134,7 @@ public function unshift(...$vector): self
*
* Utility method for appending/prepending methods.
*/
private function willReplace(iterable $values = null): bool
private function willReplace(?iterable $values = null): bool
{
// Nothing needs to be done here.
/** @phan-suppress-next-line PhanTypeComparisonFromArray */
Expand Down Expand Up @@ -263,7 +257,7 @@ public function chunk(int $length, bool $preserve_keys = false): self
}

/**
* @psalm-param positive-int $length
* @psalm-param positive-int $length
*/
private static function toChunks(Generator $input, int $length, bool $preserve_keys): iterable
{
Expand Down Expand Up @@ -295,14 +289,15 @@ public function map(?callable $func = null): self
}

// Let's check what we got for a start.
$this->pipeline = $func();
$value = $func();

// Generator is a generator, moving along
if ($this->pipeline instanceof Generator) {
if ($value instanceof Generator) {
// It is possible to detect if callback is a generator like so:
// (new \ReflectionFunction($func))->isGenerator();
// Yet this will restrict users from replacing the pipeline and has unknown performance impact.
// But, again, we could add a direct internal method to replace the pipeline, e.g. as done by unpack()
$this->pipeline = $value;

return $this;
}
Expand All @@ -311,7 +306,7 @@ public function map(?callable $func = null): self
// We do not cast to an array here because casting a null to an array results in
// an empty array; that's surprising and not how it works for other values.
$this->pipeline = [
$this->pipeline,
$value,
];

return $this;
Expand Down Expand Up @@ -343,7 +338,7 @@ private static function apply(iterable $previous, callable $func): iterable
*
* @return $this
*/
public function cast(callable $func = null): self
public function cast(?callable $func = null): self
{
if (null === $func) {
return $this;
Expand Down
124 changes: 124 additions & 0 deletions tests/StaticAnalysisTest.php
Expand Up @@ -19,10 +19,12 @@

namespace Tests\Pipeline;

use ArrayIterator;
use PHPUnit\Framework\TestCase;
use Pipeline\Standard;
use ReflectionClass;
use ReflectionMethod;
use Traversable;

/**
* @coversNothing
Expand Down Expand Up @@ -63,4 +65,126 @@ public function testAllMethodsArePublicOrPrivate(ReflectionMethod $method): void
$this->assertFalse($method->isProtected());
$this->assertTrue($method->isPublic() || $method->isPrivate());
}

/**
* Test the interface is compatible with PHP 7.1 variety.
*/
public function testInterfaceCompatibilityPHP71(): void
{
$example = new class() extends Standard {
private $input;

public function __construct(iterable $input = null)
{
$this->input = $input;
}

public function append(iterable $values = null): self
{
return $this;
}

public function push(...$vector): self
{
return $this;
}

public function prepend(iterable $values = null): self
{
return $this;
}

public function unshift(...$vector): self
{
return $this;
}

public function flatten(): self
{
return $this;
}

public function unpack(?callable $func = null): self
{
return $this;
}

public function chunk(int $length, bool $preserve_keys = false): self
{
return $this;
}

public function map(?callable $func = null): self
{
return $this;
}

public function cast(callable $func = null): self
{
return $this;
}

public function filter(?callable $func = null): self
{
return $this;
}

public function reduce(?callable $func = null, $initial = null)
{
return null;
}

public function fold($initial, ?callable $func = null)
{
return null;
}

public function getIterator(): Traversable
{
return new ArrayIterator([]);
}

public function toArray(bool $preserve_keys = false): array
{
return [];
}

public function count(): int
{
return 0;
}

public function slice(int $offset, ?int $length = null)
{
return $this;
}

public function zip(iterable ...$inputs)
{
return $this;
}

public function reservoir(int $size, ?callable $weightFunc = null): array
{
return [];
}

public function min()
{
return 0;
}

public function max()
{
return 0;
}

public function flip()
{
return $this;
}
};

$this->assertSame(0, $example->count());
}
}

0 comments on commit dd7c3c8

Please sign in to comment.