Skip to content
Closed
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
30 changes: 30 additions & 0 deletions src/Illuminate/Collections/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,43 @@

use ArgumentCountError;
use ArrayAccess;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use JsonSerializable;
use Traversable;
use UnitEnum;
use WeakMap;

class Arr
{
use Macroable;

/**
* Get the underlying array of items from the given argument.
*
* @param mixed $items
* @return array
*/
public static function from($items)
{
if (is_array($items)) {
return $items;
}

return match (true) {
$items instanceof WeakMap => throw new InvalidArgumentException('Arrays cannot be extracted from instances of WeakMap.'),
$items instanceof Enumerable => $items->all(),
$items instanceof Arrayable => $items->toArray(),
$items instanceof Traversable => iterator_to_array($items),
$items instanceof Jsonable => json_decode($items->toJson(), true),
$items instanceof JsonSerializable => (array) $items->jsonSerialize(),
$items instanceof UnitEnum => [$items],
default => (array) $items,
};
}

/**
* Determine whether the given value is array accessible.
*
Expand Down
19 changes: 1 addition & 18 deletions src/Illuminate/Collections/Traits/EnumeratesValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\HigherOrderCollectionProxy;
use InvalidArgumentException;
use JsonSerializable;
use Symfony\Component\VarDumper\VarDumper;
use Traversable;
use UnexpectedValueException;
use UnitEnum;
use WeakMap;

/**
* @template TKey of array-key
Expand Down Expand Up @@ -1022,20 +1018,7 @@ public function __get($key)
*/
protected function getArrayableItems($items)
{
if (is_array($items)) {
return $items;
}

return match (true) {
$items instanceof WeakMap => throw new InvalidArgumentException('Collections can not be created using instances of WeakMap.'),
$items instanceof Enumerable => $items->all(),
$items instanceof Arrayable => $items->toArray(),
$items instanceof Traversable => iterator_to_array($items),
$items instanceof Jsonable => json_decode($items->toJson(), true),
$items instanceof JsonSerializable => (array) $items->jsonSerialize(),
$items instanceof UnitEnum => [$items],
default => (array) $items,
};
return Arr::from($items);
}

/**
Expand Down
62 changes: 62 additions & 0 deletions tests/Support/Common.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Illuminate\Tests\Support;

use ArrayIterator;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use IteratorAggregate;
use JsonSerializable;
use Traversable;

class TestArrayableObject implements Arrayable
{
public function toArray()
{
return ['foo' => 'bar'];
}
}

class TestJsonableObject implements Jsonable
{
public function toJson($options = 0)
{
return '{"foo":"bar"}';
}
}

class TestJsonSerializeObject implements JsonSerializable
{
public function jsonSerialize(): array
{
return ['foo' => 'bar'];
}
}

class TestJsonSerializeWithScalarValueObject implements JsonSerializable
{
public function jsonSerialize(): string
{
return 'foo';
}
}

class TestTraversableAndJsonSerializableObject implements IteratorAggregate, JsonSerializable
{
public $items;

public function __construct($items)
{
$this->items = $items;
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->items);
}

public function jsonSerialize(): array
{
return json_decode(json_encode($this->items), true);
}
}
14 changes: 14 additions & 0 deletions tests/Support/SupportArrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,22 @@
use PHPUnit\Framework\TestCase;
use stdClass;

include_once 'Common.php';

class SupportArrTest extends TestCase
{
public function testFrom()
{
$this->assertSame(['foo' => 'bar'], Arr::from(new TestArrayableObject));
$this->assertSame(['foo' => 'bar'], Arr::from(new TestJsonableObject));
$this->assertSame(['foo' => 'bar'], Arr::from(new TestJsonSerializeObject));
$this->assertSame(['foo'], Arr::from(new TestJsonSerializeWithScalarValueObject));

$subject = [new stdClass, new stdClass];
$items = new TestTraversableAndJsonSerializableObject($subject);
$this->assertSame($subject, Arr::from($items));
}

public function testAccessible()
{
$this->assertTrue(Arr::accessible([]));
Expand Down
56 changes: 1 addition & 55 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,24 @@
use CachingIterator;
use Exception;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
use Illuminate\Support\ItemNotFoundException;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\MultipleItemsFoundException;
use Illuminate\Support\Str;
use InvalidArgumentException;
use IteratorAggregate;
use JsonSerializable;
use Mockery as m;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use stdClass;
use Symfony\Component\VarDumper\VarDumper;
use Traversable;
use UnexpectedValueException;
use WeakMap;

include_once 'Common.php';
include_once 'Enums.php';

class SupportCollectionTest extends TestCase
Expand Down Expand Up @@ -5816,30 +5814,6 @@ public function offsetUnset($offset): void
}
}

class TestArrayableObject implements Arrayable
{
public function toArray()
{
return ['foo' => 'bar'];
}
}

class TestJsonableObject implements Jsonable
{
public function toJson($options = 0)
{
return '{"foo":"bar"}';
}
}

class TestJsonSerializeObject implements JsonSerializable
{
public function jsonSerialize(): array
{
return ['foo' => 'bar'];
}
}

class TestJsonSerializeToStringObject implements JsonSerializable
{
public function jsonSerialize(): string
Expand All @@ -5848,34 +5822,6 @@ public function jsonSerialize(): string
}
}

class TestJsonSerializeWithScalarValueObject implements JsonSerializable
{
public function jsonSerialize(): string
{
return 'foo';
}
}

class TestTraversableAndJsonSerializableObject implements IteratorAggregate, JsonSerializable
{
public $items;

public function __construct($items)
{
$this->items = $items;
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->items);
}

public function jsonSerialize(): array
{
return json_decode(json_encode($this->items), true);
}
}

class TestCollectionMapIntoObject
{
public $value;
Expand Down