Skip to content

Commit

Permalink
[11.x] Improves Collection support for enums using firstWhere() a…
Browse files Browse the repository at this point in the history
…nd `value()` (#53777)

* [11.x] Improves `Collection` support for enums using `firstWhere()` and `value()`

Fixes #53676

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

---------

Signed-off-by: Mior Muhammad Zaki <[email protected]>
Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
crynobone and StyleCIBot authored Dec 6, 2024
1 parent 8b889c7 commit b8bb5e9
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 26 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
},
"autoload": {
"files": [
"src/Illuminate/Collections/functions.php",
"src/Illuminate/Collections/helpers.php",
"src/Illuminate/Events/functions.php",
"src/Illuminate/Filesystem/functions.php",
Expand Down
11 changes: 9 additions & 2 deletions src/Illuminate/Collections/Traits/EnumeratesValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
use UnitEnum;
use WeakMap;

use function Illuminate\Support\enum_value;

/**
* @template TKey of array-key
*
Expand Down Expand Up @@ -1092,10 +1094,15 @@ protected function operatorForWhere($key, $operator = null, $value = null)
}

return function ($item) use ($key, $operator, $value) {
$retrieved = data_get($item, $key);
$retrieved = enum_value(data_get($item, $key));
$value = enum_value($value);

$strings = array_filter([$retrieved, $value], function ($value) {
return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
return match (true) {
is_string($value) => true,
$value instanceof \Stringable => true,
default => false,
};
});

if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Collections/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"Illuminate\\Support\\": ""
},
"files": [
"functions.php",
"helpers.php"
]
},
Expand Down
27 changes: 27 additions & 0 deletions src/Illuminate/Collections/functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Illuminate\Support;

if (! function_exists('Illuminate\Support\enum_value')) {
/**
* Return a scalar value for the given value that might be an enum.
*
* @internal
*
* @template TValue
* @template TDefault
*
* @param TValue $value
* @param TDefault|callable(TValue): TDefault $default
* @return ($value is empty ? TDefault : mixed)
*/
function enum_value($value, $default = null)
{
return transform($value, fn ($value) => match (true) {
$value instanceof \BackedEnum => $value->value,
$value instanceof \UnitEnum => $value->name,

default => $value,
}, $default ?? $value);
}
}
24 changes: 0 additions & 24 deletions src/Illuminate/Support/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,6 @@ function defer(?callable $callback = null, ?string $name = null, bool $always =
}
}

if (! function_exists('Illuminate\Support\enum_value')) {
/**
* Return a scalar value for the given value that might be an enum.
*
* @internal
*
* @template TValue
* @template TDefault
*
* @param TValue $value
* @param TDefault|callable(TValue): TDefault $default
* @return ($value is empty ? TDefault : mixed)
*/
function enum_value($value, $default = null)
{
return transform($value, fn ($value) => match (true) {
$value instanceof \BackedEnum => $value->value,
$value instanceof \UnitEnum => $value->name,

default => $value,
}, $default ?? $value);
}
}

if (! function_exists('Illuminate\Support\php_binary')) {
/**
* Determine the PHP Binary.
Expand Down
30 changes: 30 additions & 0 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,20 @@ public function testFirstWhere($collection)
$this->assertNull($data->firstWhere(fn ($value) => ($value['nonexistent'] ?? null) === 'key'));
}

#[DataProvider('collectionClassProvider')]
public function testFirstWhereUsingEnum($collection)
{
$data = new $collection([
['id' => 1, 'name' => StaffEnum::Taylor],
['id' => 2, 'name' => StaffEnum::Joe],
['id' => 3, 'name' => StaffEnum::James],
]);

$this->assertSame(1, $data->firstWhere('name', 'Taylor')['id']);
$this->assertSame(2, $data->firstWhere('name', StaffEnum::Joe)['id']);
$this->assertSame(3, $data->firstWhere('name', StaffEnum::James)['id']);
}

#[DataProvider('collectionClassProvider')]
public function testLastReturnsLastItemInCollection($collection)
{
Expand Down Expand Up @@ -1130,6 +1144,15 @@ public function testValue($collection)
$this->assertEquals('bar', $c->where('id', 2)->value('pivot.value'));
}

#[DataProvider('collectionClassProvider')]
public function testValueUsingEnum($collection)
{
$c = new $collection([['id' => 1, 'name' => StaffEnum::Taylor], ['id' => 2, 'name' => StaffEnum::Joe]]);

$this->assertSame(StaffEnum::Taylor, $c->value('name'));
$this->assertEquals(StaffEnum::Joe, $c->where('id', 2)->value('name'));
}

#[DataProvider('collectionClassProvider')]
public function testBetween($collection)
{
Expand Down Expand Up @@ -5737,3 +5760,10 @@ class TestCollectionSubclass extends Collection
{
//
}

enum StaffEnum
{
case Taylor;
case Joe;
case James;
}

0 comments on commit b8bb5e9

Please sign in to comment.