Skip to content

Commit

Permalink
Version 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
the-pulli committed Dec 18, 2023
1 parent 08d8e10 commit 5626bd0
Show file tree
Hide file tree
Showing 16 changed files with 344 additions and 55 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to `collection-macros` will be documented in this file

## 0.2.0 - 2023-12-18

- Add Laravel ServiceProvider
- Rewrite of mapToCollection / recursiveToArray as Collection functions
- Introducing mapToCollectionFrom / recursiveToArrayFrom as static Collection functions

## 0.1.0 - 2023-09-12

- Initial release
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,29 @@ composer require pulli/collection-macros

## Macros

- mapToCollectionFrom
- mapToCollection
- recursiveToArrayFrom
- recursiveToArray

### `mapToCollection`
### `mapToCollectionFrom`

Maps all arrays/objects recursively to a collection object of collections, which allow nested function calling.

```php
$collection = Collection::mapToCollection([['test' => 1],2,3]);
$collection = Collection::mapToCollectionFrom([['test' => 1],2,3]);

$collection->get(0)->get('test'); // returns 1

// Item has a toArray() public method, then it can be wrapped into a collection like this:
$collection = Collection::mapToCollection([Item(),Item()], true);
```

### `recursiveToArray`
### `recursiveToArrayFrom`

Like `mapToCollection` it maps all arrays/objects recursively to an array.
Like `mapToCollectionFrom` it maps all arrays/objects recursively to an array.

```php
// Item has a toArray() public method, then it can be wrapped into the collection like this:
$array = Collection::recursiveToArray(['item1' => Item(), 'item2' => Item()]);
$array = Collection::recursiveToArrayFrom(['item1' => Item(), 'item2' => Item()]);
```
16 changes: 12 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
"php": ">=8.2",
"illuminate/collections": "^10.0"
},
"require-dev": {
"orchestra/testbench": "^8.17",
"pestphp/pest": "^2.16"
},
"license": "MIT",
"autoload": {
"files": [
Expand All @@ -38,12 +42,16 @@
"pestphp/pest-plugin": true
}
},
"extra": {
"laravel": {
"providers": [
"Pulli\\CollectionMacros\\CollectionMacroServiceProvider"
]
}
},
"scripts": {
"test": "vendor/bin/pest"
},
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"pestphp/pest": "^2.16"
}
"prefer-stable": true
}
26 changes: 26 additions & 0 deletions src/CollectionMacroServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Pulli\CollectionMacros;

use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;

class CollectionMacroServiceProvider extends ServiceProvider
{
public function register(): void
{
Collection::make(self::macros())
->reject(fn ($class, $macro) => Collection::hasMacro($macro))
->each(fn ($class, $macro) => Collection::macro($macro, app($class)()));
}

public static function macros(): array
{
return [
'mapToCollection' => \Pulli\CollectionMacros\Macros\MapToCollection::class,
'mapToCollectionFrom' => \Pulli\CollectionMacros\Macros\MapToCollectionFrom::class,
'recursiveToArray' => \Pulli\CollectionMacros\Macros\RecursiveToArray::class,
'recursiveToArrayFrom' => \Pulli\CollectionMacros\Macros\RecursiveToArrayFrom::class,
];
}
}
19 changes: 7 additions & 12 deletions src/Macros/MapToCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,15 @@ class MapToCollection
{
public function __invoke(): Closure
{
return function (array $ary, bool $deep = false): Collection {
$closure = function (&$ary) use ($deep) {
if (is_array($ary)) {
$ary = Collection::mapToCollection($ary, $deep);
}
return function (array $ary = [], bool $deep = false): Collection {
$ary = Collection::mapToCollectionFrom($ary, $deep);
$data = Collection::mapToCollectionFrom($this->all(), $deep);

if ($deep && is_object($ary) && method_exists($ary, 'toArray')) {
$ary = Collection::mapToCollection($ary->toArray(), $deep);
}
};
if ($ary->isNotEmpty()) {
return $data->merge([$ary]);
}

array_walk($ary, $closure);

return new Collection($ary);
return $data;
};
}
}
28 changes: 28 additions & 0 deletions src/Macros/MapToCollectionFrom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Pulli\CollectionMacros\Macros;

use Closure;
use Illuminate\Support\Collection;

class MapToCollectionFrom
{
public function __invoke(): Closure
{
return function (array $ary, bool $deep = false): Collection {
$closure = function (&$ary) use ($deep) {
if (is_array($ary)) {
$ary = Collection::mapToCollectionFrom($ary, $deep);
}

if ($deep && is_object($ary) && method_exists($ary, 'toArray')) {
$ary = Collection::mapToCollectionFrom($ary->toArray(), $deep);
}
};

array_walk($ary, $closure);

return new Collection($ary);
};
}
}
19 changes: 5 additions & 14 deletions src/Macros/RecursiveToArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,11 @@ class RecursiveToArray
{
public function __invoke(): Closure
{
return function (array $ary): array {
$closure = function (&$ary) {
if (is_array($ary)) {
$ary = Collection::recursiveToArray($ary);
}

if (is_object($ary) && method_exists($ary, 'toArray')) {
$ary = Collection::recursiveToArray($ary->toArray());
}
};

array_walk($ary, $closure);

return $ary;
return function (array $ary = []): array {
return array_merge(
Collection::recursiveToArrayFrom($this->all()),
Collection::recursiveToArrayFrom($ary)
);
};
}
}
28 changes: 28 additions & 0 deletions src/Macros/RecursiveToArrayFrom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Pulli\CollectionMacros\Macros;

use Closure;
use Illuminate\Support\Collection;

class RecursiveToArrayFrom
{
public function __invoke(): Closure
{
return function (array $ary): array {
$closure = function (&$ary) {
if (is_array($ary)) {
$ary = Collection::recursiveToArrayFrom($ary);
}

if (is_object($ary) && method_exists($ary, 'toArray')) {
$ary = Collection::recursiveToArrayFrom($ary->toArray());
}
};

array_walk($ary, $closure);

return $ary;
};
}
}
9 changes: 2 additions & 7 deletions src/register.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@

use Illuminate\Support\Collection;

$macros = [
'mapToCollection' => \Pulli\CollectionMacros\Macros\MapToCollection::class,
'recursiveToArray' => \Pulli\CollectionMacros\Macros\RecursiveToArray::class,
];

if (!function_exists('app')) {
Collection::make($macros)
if (!class_exists('\Illuminate\Foundation\Application')) {
Collection::make(\Pulli\CollectionMacros\CollectionMacroServiceProvider::macros())
->reject(fn ($class, $macro) => Collection::hasMacro($macro))
->each(fn ($class, $macro) => Collection::macro($macro, (new $class())()));
}
19 changes: 19 additions & 0 deletions tests/IntegrationTestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Pulli\CollectionMacros\Test;

use Orchestra\Testbench\TestCase as Orchestra;
use Pulli\CollectionMacros\CollectionMacroServiceProvider;

abstract class IntegrationTestCase extends Orchestra
{
protected function getPackageProviders($app): array
{
return [CollectionMacroServiceProvider::class];
}

public function avoidTestMarkedAsRisky(): void
{
$this->assertTrue(true);
}
}
97 changes: 97 additions & 0 deletions tests/Macros/MapToCollectionFromTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

use Illuminate\Support\Collection;
use Pulli\CollectionMacros\Test\Data\ChildObject;
use Pulli\CollectionMacros\Test\Data\OtherObject;
use Pulli\CollectionMacros\Test\Data\ParentObject;
use Pulli\CollectionMacros\Test\Data\TestObject;

describe('mapToCollectionFrom macro', function () {
it('wraps all arrays into collection objects', function () {
$data = Collection::mapToCollectionFrom([
['test' => ['test' => '1.1']],
['test' => ['test' => '1.2']],
['test' => ['test' => ['test' => '1.3.1']]],
]);

expect($data[0])->toBeInstanceOf(Collection::class)
->and($data[1])->toBeInstanceOf(Collection::class)
->and($data[0]['test'])->toBeInstanceOf(Collection::class)
->and($data[1]['test'])->toBeInstanceOf(Collection::class)
->and($data->get(0)->get('test')->get('test'))->toBe('1.1')
->and($data->get(1)->get('test')->get('test'))->toBe('1.2')
->and($data->get(2)->get('test')->get('test')->get('test'))->toBe('1.3.1');
});

it('wraps data objects into collection objects', function () {
$data = Collection::mapToCollectionFrom([
new TestObject('John Doe', 'Programmer'),
new TestObject('Jane Doe', 'Designer'),
], true);

expect($data[0])->toBeInstanceOf(Collection::class)
->and($data[1])->toBeInstanceOf(Collection::class)
->and($data->get(0))->toEqual(new Collection([
'name' => 'John Doe',
'job' => 'Programmer',
]))
->and($data->get(1))->toEqual(new Collection([
'name' => 'Jane Doe',
'job' => 'Designer',
]));
});

it('wraps nested data objects into collection objects', function () {
$data = Collection::mapToCollectionFrom([
['first' => new TestObject('John Doe', 'Programmer')],
['second' => new TestObject('Jane Doe', 'Designer')],
], true);

expect($data[0])->toBeInstanceOf(Collection::class)
->and($data[1])->toBeInstanceOf(Collection::class)
->and($data->get(0)->get('first'))->toEqual(new Collection([
'name' => 'John Doe',
'job' => 'Programmer',
]))
->and($data->get(1)->get('second'))->toEqual(new Collection([
'name' => 'Jane Doe',
'job' => 'Designer',
]));
});

it('wraps nested arrays and objects into collection objects', function () {
$data = Collection::mapToCollectionFrom([
new ParentObject(
name: 'parent1',
children: new Collection([new ChildObject(name: 'child1')]),
other: new Collection([new OtherObject(value: 'other1')]),
),
new ParentObject(
name: 'parent2',
children: new Collection([new ChildObject(name: 'child2')]),
other: new Collection([new OtherObject(value: 'other2')]),
),
], true);

expect($data)->toEqual(new Collection([
new Collection([
'name' => 'parent1',
'children' => new Collection([
new Collection(['name' => 'child1']),
]),
'other' => new Collection([
new Collection(['value' => 'other1']),
]),
]),
new Collection([
'name' => 'parent2',
'children' => new Collection([
new Collection(['name' => 'child2']),
]),
'other' => new Collection([
new Collection(['value' => 'other2']),
]),
]),
]));
});
});
Loading

0 comments on commit 5626bd0

Please sign in to comment.