From 63c6421c461465e78d31e446a19e2d0cefc41d58 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Fri, 11 Jun 2021 10:55:12 -0400 Subject: [PATCH 1/4] Add `Conditionable` support for callback conditions --- .../Support/Traits/Conditionable.php | 9 +- tests/Support/SupportConditionableTest.php | 93 ++++++++++++++++++- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Support/Traits/Conditionable.php b/src/Illuminate/Support/Traits/Conditionable.php index f70fe8412ee6..5e5d082e5c34 100644 --- a/src/Illuminate/Support/Traits/Conditionable.php +++ b/src/Illuminate/Support/Traits/Conditionable.php @@ -2,12 +2,13 @@ namespace Illuminate\Support\Traits; +use Closure; use Illuminate\Support\HigherOrderWhenProxy; trait Conditionable { /** - * Apply the callback if the given "value" is truthy. + * Apply the callback if the given "value" is (or resolves to) truthy. * * @param mixed $value * @param callable|null $callback @@ -17,6 +18,8 @@ trait Conditionable */ public function when($value, callable $callback = null, callable $default = null) { + $value = $value instanceof Closure ? $value($this) : $value; + if (! $callback) { return new HigherOrderWhenProxy($this, $value); } @@ -31,7 +34,7 @@ public function when($value, callable $callback = null, callable $default = null } /** - * Apply the callback if the given "value" is falsy. + * Apply the callback if the given "value" is (or resolves to) falsy. * * @param mixed $value * @param callable|null $callback @@ -41,6 +44,8 @@ public function when($value, callable $callback = null, callable $default = null */ public function unless($value, callable $callback = null, callable $default = null) { + $value = $value instanceof Closure ? $value($this) : $value; + if (! $callback) { return new HigherOrderWhenProxy($this, ! $value); } diff --git a/tests/Support/SupportConditionableTest.php b/tests/Support/SupportConditionableTest.php index 7a28dc7bd543..3e0166820f8d 100644 --- a/tests/Support/SupportConditionableTest.php +++ b/tests/Support/SupportConditionableTest.php @@ -9,68 +9,148 @@ class SupportConditionableTest extends TestCase { public function testWhenConditionCallback() { + // With static condition $logger = (new ConditionableLogger()) ->when(2, function ($logger, $condition) { $logger->log('when', $condition); - }, function () { + }, function ($logger, $condition) { $logger->log('default', $condition); }); $this->assertSame(['when', 2], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger())->log('init') + ->when(function ($logger) { + return $logger->has('init'); + }, function ($logger, $condition) { + $logger->log('when', $condition); + }, function ($logger, $condition) { + $logger->log('default', $condition); + }); + + $this->assertSame(['init', 'when', true], $logger->values); } public function testWhenDefaultCallback() { + // With static condition $logger = (new ConditionableLogger()) - ->when(null, function () { + ->when(null, function ($logger, $condition) { $logger->log('when', $condition); }, function ($logger, $condition) { $logger->log('default', $condition); }); $this->assertSame(['default', null], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger()) + ->when(function ($logger) { + return $logger->has('missing'); + }, function ($logger, $condition) { + $logger->log('when', $condition); + }, function ($logger, $condition) { + $logger->log('default', $condition); + }); + + $this->assertSame(['default', false], $logger->values); } public function testUnlessConditionCallback() { + // With static condition $logger = (new ConditionableLogger()) ->unless(null, function ($logger, $condition) { $logger->log('unless', $condition); - }, function () { + }, function ($logger, $condition) { $logger->log('default', $condition); }); $this->assertSame(['unless', null], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger()) + ->unless(function ($logger) { + return $logger->has('missing'); + }, function ($logger, $condition) { + $logger->log('unless', $condition); + }, function ($logger, $condition) { + $logger->log('default', $condition); + }); + + $this->assertSame(['unless', false], $logger->values); } public function testUnlessDefaultCallback() { + // With static condition $logger = (new ConditionableLogger()) - ->unless(2, function () { + ->unless(2, function ($logger, $condition) { $logger->log('unless', $condition); }, function ($logger, $condition) { $logger->log('default', $condition); }); $this->assertSame(['default', 2], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger())->log('init') + ->unless(function ($logger) { + return $logger->has('init'); + }, function ($logger, $condition) { + $logger->log('unless', $condition); + }, function ($logger, $condition) { + $logger->log('default', $condition); + }); + + $this->assertSame(['init', 'default', true], $logger->values); } public function testWhenProxy() { + // With static condition $logger = (new ConditionableLogger()) ->when(true)->log('one') ->when(false)->log('two'); $this->assertSame(['one'], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger())->log('init') + ->when(function ($logger) { + return $logger->has('init'); + }) + ->log('one') + ->when(function ($logger) { + return $logger->has('missing'); + }) + ->log('two'); + + $this->assertSame(['init', 'one'], $logger->values); } public function testUnlessProxy() { + // With static condition $logger = (new ConditionableLogger()) ->unless(true)->log('one') ->unless(false)->log('two'); $this->assertSame(['two'], $logger->values); + + // With callback condition + $logger = (new ConditionableLogger())->log('init') + ->unless(function ($logger) { + return $logger->has('init'); + }) + ->log('one') + ->unless(function ($logger) { + return $logger->has('missing'); + }) + ->log('two'); + + $this->assertSame(['init', 'two'], $logger->values); } } @@ -86,4 +166,9 @@ public function log(...$values) return $this; } + + public function has($value) + { + return in_array($value, $this->values); + } } From f7cc1f9014bd969cecfc28a24b35f906986bca88 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Fri, 11 Jun 2021 11:04:29 -0400 Subject: [PATCH 2/4] Update DocBlocks in `Enumerable` to match `Conditionable` --- src/Illuminate/Collections/Enumerable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Collections/Enumerable.php b/src/Illuminate/Collections/Enumerable.php index ef99c3143a92..a3e570ffe8db 100644 --- a/src/Illuminate/Collections/Enumerable.php +++ b/src/Illuminate/Collections/Enumerable.php @@ -268,7 +268,7 @@ public function except($keys); public function filter(callable $callback = null); /** - * Apply the callback if the value is truthy. + * Apply the callback if the given "value" is (or resolves to) truthy. * * @param bool $value * @param callable|null $callback @@ -296,7 +296,7 @@ public function whenEmpty(callable $callback, callable $default = null); public function whenNotEmpty(callable $callback, callable $default = null); /** - * Apply the callback if the value is falsy. + * Apply the callback if the given "value" is (or resolves to) truthy. * * @param bool $value * @param callable $callback From 8eb3545c3ce8d0cf6b438844c9661b279f2a0691 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Fri, 11 Jun 2021 11:05:10 -0400 Subject: [PATCH 3/4] Update uses --- src/Illuminate/Collections/Collection.php | 2 +- src/Illuminate/Collections/LazyCollection.php | 2 +- src/Illuminate/Collections/Traits/EnumeratesValues.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index 74e5f9d5053e..d9e07cdecb23 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -1069,7 +1069,7 @@ public function sole($key = null, $operator = null, $value = null) ? $this->operatorForWhere(...func_get_args()) : $key; - $items = $this->when($filter)->filter($filter); + $items = $this->unless($filter == null)->filter($filter); if ($items->isEmpty()) { throw new ItemNotFoundException; diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index 5b2f19f8add7..54acc3f90ed1 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -1028,7 +1028,7 @@ public function sole($key = null, $operator = null, $value = null) : $key; return $this - ->when($filter) + ->unless($filter == null) ->filter($filter) ->take(2) ->collect() diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index 21b0dc6c29e7..df29d62132b3 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -138,7 +138,7 @@ public static function times($number, callable $callback = null) } return static::range(1, $number) - ->when($callback) + ->unless($callback == null) ->map($callback); } From 5a86d89efd0935fdef4e1c6c1cb472861a8a1fb0 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Fri, 11 Jun 2021 11:05:35 -0400 Subject: [PATCH 4/4] Add to collection higher order proxy --- .../Collections/Traits/EnumeratesValues.php | 8 +++++-- tests/Support/SupportCollectionTest.php | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index df29d62132b3..3d29ce74cecf 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -31,16 +31,18 @@ * @property-read HigherOrderCollectionProxy $min * @property-read HigherOrderCollectionProxy $partition * @property-read HigherOrderCollectionProxy $reject + * @property-read HigherOrderCollectionProxy $skipUntil + * @property-read HigherOrderCollectionProxy $skipWhile * @property-read HigherOrderCollectionProxy $some * @property-read HigherOrderCollectionProxy $sortBy * @property-read HigherOrderCollectionProxy $sortByDesc - * @property-read HigherOrderCollectionProxy $skipUntil - * @property-read HigherOrderCollectionProxy $skipWhile * @property-read HigherOrderCollectionProxy $sum * @property-read HigherOrderCollectionProxy $takeUntil * @property-read HigherOrderCollectionProxy $takeWhile * @property-read HigherOrderCollectionProxy $unique + * @property-read HigherOrderCollectionProxy $unless * @property-read HigherOrderCollectionProxy $until + * @property-read HigherOrderCollectionProxy $when */ trait EnumeratesValues { @@ -76,7 +78,9 @@ trait EnumeratesValues 'takeUntil', 'takeWhile', 'unique', + 'unless', 'until', + 'when', ]; /** diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 0f0a8af49b6d..0c4d65bbacd6 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -4391,6 +4391,30 @@ public function testHigherOrderWhenAndUnless($collection) $this->assertSame(['michael', 'tom', 'chris', 'adam'], $data->toArray()); } + /** + * @dataProvider collectionClassProvider + */ + public function testHigherOrderWhenAndUnlessWithProxy($collection) + { + $data = new $collection(['michael', 'tom']); + + $data = $data->when->contains('michael')->concat(['chris']); + + $this->assertSame(['michael', 'tom', 'chris'], $data->toArray()); + + $data = $data->when->contains('missing')->concat(['adam']); + + $this->assertSame(['michael', 'tom', 'chris'], $data->toArray()); + + $data = $data->unless->contains('missing')->concat(['adam']); + + $this->assertSame(['michael', 'tom', 'chris', 'adam'], $data->toArray()); + + $data = $data->unless->contains('adam')->concat(['bogdan']); + + $this->assertSame(['michael', 'tom', 'chris', 'adam'], $data->toArray()); + } + /** * @dataProvider collectionClassProvider */