diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index eb796ba..23d9484 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,14 +9,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - php: [8.0, 7.4] + php: [8.0] laravel: [7.*, 8.*] dependency-version: [prefer-stable] include: - testbench: 6.* laravel: 8.* - - testbench: 5.* - laravel: 7.* name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bc0f05..792613d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to `laravel-collection-macros` will be documented in this file +## 7.7.0 - 2021-10-24 + +- add `if` macro + ## 7.6.0 - 2021-10-15 - Fix docblock indentation by @dwightwatson in https://github.com/spatie/laravel-collection-macros/pull/211 diff --git a/README.md b/README.md index 46471f0..c9fbbcf 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ The package will automatically register itself. - [`glob`](#glob) - [`groupByModel`](#groupbymodel) - [`head`](#head) +- [`if`](#if) - [`ifAny`](#ifany) - [`ifEmpty`](#ifempty) - [`insertAfter`](#insertafter) @@ -388,6 +389,47 @@ $collection = collect([]); $collection->head(); // return null ``` +### `if` + +The `if` macro can help branch collection chains. This is the signature of this macro: + +```php +if(mixed $if, mixed $then = null, mixed $else = null): mixed +``` + +`$if`, `$then` and `$else` can be any type. If a closure is passed to any of these parameters, then that closure will be executed and the macro will use its results. + +When `$if` returns a truthy value, then `$then` will be returned, otherwise `$else` will be returned. + +Here are some examples: + +```php +collect()->if(true, then: true, else: false) // returns true +collect()->if(false, then: true, else: false) // returns false +``` + +When a closure is passed to `$if`, `$then` or `$else`, the entire collection will be passed as an argument to that closure. + +```php +// the `then` closure will be executed +// the first element of the returned collection now contains "THIS IS THE VALUE" +$collection = collect(['this is a value']) + ->if( + fn(Collection $collection) => $collection->contains('this is a value'), + then: fn(Collection $collection) => $collection->map(fn(string $item) => strtoupper($item)), + else: fn(Collection $collection) => $collection->map(fn(string $item) => Str::kebab($item)) + ); + +// the `else` closure will be executed +// the first element of the returned collection now contains "this-is-another-value" +$collection = collect(['this is another value']) + ->if( + fn(Collection $collection) => $collection->contains('this is a value'), + then: fn(Collection $collection) => $collection->map(fn(string $item) => strtoupper($item)), + else: fn(Collection $collection) => $collection->map(fn(string $item) => Str::kebab($item)) + ); +``` + ### `ifAny` Executes the passed callable if the collection isn't empty. The entire collection will be returned. diff --git a/composer.json b/composer.json index a372248..5dc9d98 100644 --- a/composer.json +++ b/composer.json @@ -22,14 +22,14 @@ } ], "require": { - "php": "^7.4|^8.0", - "illuminate/support": "^7.0|^8.0" + "php": "^8.0", + "illuminate/support": "^8.67" }, "require-dev": { "amphp/parallel": "^0.2.5", "amphp/parallel-functions": "^0.1.3", "mockery/mockery": "^1.4.2", - "orchestra/testbench": "^5.5|^6.5", + "orchestra/testbench": "^6.5", "phpunit/phpunit": "^9.4.4", "symfony/stopwatch": "^5.2" }, diff --git a/src/CollectionMacroServiceProvider.php b/src/CollectionMacroServiceProvider.php index da18c46..05680b0 100644 --- a/src/CollectionMacroServiceProvider.php +++ b/src/CollectionMacroServiceProvider.php @@ -35,6 +35,7 @@ private function macros(): array 'glob' => \Spatie\CollectionMacros\Macros\Glob::class, 'groupByModel' => \Spatie\CollectionMacros\Macros\GroupByModel::class, 'head' => \Spatie\CollectionMacros\Macros\Head::class, + 'if' => \Spatie\CollectionMacros\Macros\IfMacro::class, 'ifAny' => \Spatie\CollectionMacros\Macros\IfAny::class, 'ifEmpty' => \Spatie\CollectionMacros\Macros\IfEmpty::class, 'insertAfter' => \Spatie\CollectionMacros\Macros\InsertAfter::class, diff --git a/src/Macros/IfMacro.php b/src/Macros/IfMacro.php new file mode 100644 index 0000000..d8f6d61 --- /dev/null +++ b/src/Macros/IfMacro.php @@ -0,0 +1,19 @@ +assertTrue(collect()->if(true, then: true, else: false)); + $this->assertFalse(collect()->if(false, then: true, else: false)); + } + + /** + * @test + * + * @dataProvider sentences + */ + public function it_will_pass_the_collection_to_the_branches(string $sentence, string $modifiedSentence) + { + $collection = collect([$sentence]) + ->if( + fn (Collection $collection) => $collection->contains('this is the value'), + then: fn (Collection $collection) => $collection->map(fn (string $item) => strtoupper($item)), + else: fn (Collection $collection) => $collection->map(fn (string $item) => Str::kebab($item)) + ); + + $this->assertEquals($modifiedSentence, $collection[0]); + } + + public function sentences(): array + { + return [ + ['this is the value', 'THIS IS THE VALUE'], + ['this is another value', 'this-is-another-value'], + ]; + } + + /** @test */ + public function the_branches_are_optional() + { + $result = collect(['this is a value']) + ->if( + false, + then: fn (Collection $collection) => 'something', + ); + + $this->assertNull($result); + } +}