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

[9.x] Add Conditionable support for callback conditions #37667

Merged
merged 4 commits into from
Jun 17, 2021
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
2 changes: 1 addition & 1 deletion src/Illuminate/Collections/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/Illuminate/Collections/Enumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Collections/LazyCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
10 changes: 7 additions & 3 deletions src/Illuminate/Collections/Traits/EnumeratesValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -76,7 +78,9 @@ trait EnumeratesValues
'takeUntil',
'takeWhile',
'unique',
'unless',
'until',
'when',
];

/**
Expand Down Expand Up @@ -138,7 +142,7 @@ public static function times($number, callable $callback = null)
}

return static::range(1, $number)
->when($callback)
->unless($callback == null)
->map($callback);
}

Expand Down
9 changes: 7 additions & 2 deletions src/Illuminate/Support/Traits/Conditionable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
Expand All @@ -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
Expand All @@ -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);
}
Expand Down
24 changes: 24 additions & 0 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
93 changes: 89 additions & 4 deletions tests/Support/SupportConditionableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -86,4 +166,9 @@ public function log(...$values)

return $this;
}

public function has($value)
{
return in_array($value, $this->values);
}
}