Skip to content

Commit

Permalink
Add support for new iterables
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Mar 20, 2024
1 parent 09b38e5 commit 40b231e
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 54 deletions.
18 changes: 12 additions & 6 deletions src/Resolvers/DataCollectableFromSomethingResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ public function execute(
DataTypeKind::DataArray, DataTypeKind::Array => $this->normalizeToArray($normalizedItems),
DataTypeKind::DataEnumerable, DataTypeKind::Enumerable => new $intoType->name($this->normalizeToArray($normalizedItems)),
DataTypeKind::DataCollection => new $intoType->name($dataClass, $this->normalizeToArray($normalizedItems)),
DataTypeKind::DataPaginatedCollection => new $intoType->name($dataClass, $this->normalizeToPaginator($normalizedItems, $collectableMetaData)),
DataTypeKind::DataCursorPaginatedCollection => new $intoType->name($dataClass, $this->normalizeToCursorPaginator($normalizedItems, $collectableMetaData)),
DataTypeKind::DataPaginator, DataTypeKind::Paginator => $this->normalizeToPaginator($normalizedItems, $collectableMetaData),
DataTypeKind::DataCursorPaginator, DataTypeKind::CursorPaginator => $this->normalizeToCursorPaginator($normalizedItems, $collectableMetaData),
DataTypeKind::DataPaginatedCollection => new $intoType->name($dataClass, $this->normalizeToPaginator($normalizedItems, $collectableMetaData, null)),
DataTypeKind::DataCursorPaginatedCollection => new $intoType->name($dataClass, $this->normalizeToCursorPaginator($normalizedItems, $collectableMetaData, null)),
DataTypeKind::DataPaginator, DataTypeKind::Paginator => $this->normalizeToPaginator($normalizedItems, $collectableMetaData, $intoType),
DataTypeKind::DataCursorPaginator, DataTypeKind::CursorPaginator => $this->normalizeToCursorPaginator($normalizedItems, $collectableMetaData, $intoType),
default => throw CannotCreateDataCollectable::create(get_debug_type($items), $intoType->name)
};
}
Expand Down Expand Up @@ -173,14 +173,17 @@ protected function normalizeToArray(
protected function normalizeToPaginator(
array|Paginator|AbstractPaginator|CursorPaginator|AbstractCursorPaginator $items,
CollectableMetaData $collectableMetaData,
?NamedType $intoType,
): Paginator|AbstractPaginator {
if ($items instanceof Paginator || $items instanceof AbstractPaginator) {
return $items;
}

$normalizedItems = $this->normalizeToArray($items);

return new LengthAwarePaginator(
$type = $intoType->name ?? LengthAwarePaginator::class;

return new ($type)(
$normalizedItems,
$collectableMetaData->paginator_total ?? count($items),
$collectableMetaData->paginator_per_page ?? 15,
Expand All @@ -190,14 +193,17 @@ protected function normalizeToPaginator(
protected function normalizeToCursorPaginator(
array|Paginator|AbstractPaginator|CursorPaginator|AbstractCursorPaginator $items,
CollectableMetaData $collectableMetaData,
?NamedType $intoType,
): CursorPaginator|AbstractCursorPaginator {
if ($items instanceof CursorPaginator || $items instanceof AbstractCursorPaginator) {
return $items;
}

$normalizedItems = $this->normalizeToArray($items);

return new \Illuminate\Pagination\CursorPaginator(
$type = $intoType->name ?? \Illuminate\Pagination\CursorPaginator::class;

return new ($type)(
$normalizedItems,
$collectableMetaData->paginator_per_page ?? 15,
$collectableMetaData->paginator_cursor
Expand Down
94 changes: 94 additions & 0 deletions src/Support/Iterables/Concerns/IterableData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Spatie\LaravelData\Support\Iterables\Concerns;

use Spatie\LaravelData\Support\DataContainer;
use Spatie\LaravelData\Support\Transformation\TransformationContextFactory;

trait IterableData
{
public function data(
string $dataClass,
array|string|null $include = null,
array|string|null $exclude = null,
array|string|null $only = null,
array|string|null $except = null,
array|string|null $includePermanently = null,
array|string|null $excludePermanently = null,
array|string|null $onlyPermanently = null,
array|string|null $exceptPermanently = null,
null|bool $wrap = null,
bool|null $transformValues = null,
bool|null $mapPropertyNames = null,
TransformationContextFactory $factory = null
): self {
$factory = $factory ?? TransformationContextFactory::create();

if ($include) {
$factory->include($include);
}

if ($exclude) {
$factory->exclude($exclude);
}

if ($only) {
$factory->only($only);
}

if ($except) {
$factory->except($except);
}

if ($includePermanently) {
$factory->includePermanently($includePermanently);
}

if ($excludePermanently) {
$factory->excludePermanently($excludePermanently);
}

if ($onlyPermanently) {
$factory->onlyPermanently($onlyPermanently);
}

if ($exceptPermanently) {
$factory->exceptPermanently($exceptPermanently);
}

if ($wrap === true) {
$factory->withWrapping();
}

if ($wrap === false) {
$factory->withoutWrapping();
}

if ($transformValues !== null) {
$factory->withValueTransformation($transformValues);
}

if ($mapPropertyNames !== null) {
$factory->withPropertyNameMapping($mapPropertyNames);
}

$transformationContext = null;

foreach ($this->items as $key => $value) {
$this->items[$key] = $value instanceof $dataClass
? $value
: $dataClass::from($value);

$transformationContext ??= $factory->create($this->items[$key]);


}

return $this;
}

public function toArray(): array
{
return DataContainer::get()
}

Check failure on line 93 in src/Support/Iterables/Concerns/IterableData.php

View workflow job for this annotation

GitHub Actions / phpstan

Syntax error, unexpected '}', expecting ';' on line 93

Check failure on line 93 in src/Support/Iterables/Concerns/IterableData.php

View workflow job for this annotation

GitHub Actions / phpstan

Syntax error, unexpected '}', expecting ';' on line 93
}
11 changes: 11 additions & 0 deletions src/Support/Iterables/LengthAwareDataPaginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Spatie\LaravelData\Support\Iterables;

use Illuminate\Pagination\LengthAwarePaginator;
use Spatie\LaravelData\Support\Iterables\Concerns\IterableData;

class LengthAwareDataPaginator extends LengthAwarePaginator
{
use IterableData;

Check failure on line 10 in src/Support/Iterables/LengthAwareDataPaginator.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Spatie\LaravelData\Support\Iterables\LengthAwareDataPaginator uses unknown trait Spatie\LaravelData\Support\Iterables\Concerns\IterableData.

Check failure on line 10 in src/Support/Iterables/LengthAwareDataPaginator.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Spatie\LaravelData\Support\Iterables\LengthAwareDataPaginator uses unknown trait Spatie\LaravelData\Support\Iterables\Concerns\IterableData.
}
137 changes: 89 additions & 48 deletions src/Support/Partials/ForwardsToPartialsDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,94 +16,135 @@ trait ForwardsToPartialsDefinition
*/
abstract protected function getPartialsContainer(): object;

public function include(string ...$includes): static
public function include(string|array ...$includes): static
{
$partialsCollection = $this->getPartialsContainer()->includePartials ??= new PartialsCollection();

foreach ($includes as $include) {
$partialsCollection->attach(Partial::create($include));
}
$this->expandPartials(
$this->getPartialsContainer()->includePartials ??= new PartialsCollection(),
$includes,
permanent: false,
);

return $this;
}

public function includePermanently(string ...$includes): static
public function includePermanently(string|array ...$includes): static
{
$partialsCollection = $this->getPartialsContainer()->includePartials ??= new PartialsCollection();

foreach ($includes as $include) {
$partialsCollection->attach(Partial::create($include, permanent: true));
}
$this->expandPartials(
$this->getPartialsContainer()->includePartials ??= new PartialsCollection(),
$includes,
permanent: true,
);

return $this;
}

public function exclude(string ...$excludes): static
public function exclude(string|array ...$excludes): static
{
$partialsCollection = $this->getPartialsContainer()->excludePartials ??= new PartialsCollection();

foreach ($excludes as $exclude) {
$partialsCollection->attach(Partial::create($exclude));
}
$this->expandPartials(
$this->getPartialsContainer()->excludePartials ??= new PartialsCollection(),
$excludes,
permanent: false,
);

return $this;
}

public function excludePermanently(string ...$excludes): static
public function excludePermanently(string|array ...$excludes): static
{
$partialsCollection = $this->getPartialsContainer()->excludePartials ??= new PartialsCollection();

foreach ($excludes as $exclude) {
$partialsCollection->attach(Partial::create($exclude, permanent: true));
}
$this->expandPartials(
$this->getPartialsContainer()->excludePartials ??= new PartialsCollection(),
$excludes,
permanent: true,
);

return $this;
}

public function only(string ...$only): static
public function only(string|array ...$only): static
{
$partialsCollection = $this->getPartialsContainer()->onlyPartials ??= new PartialsCollection();

foreach ($only as $onlyDefinition) {
$partialsCollection->attach(Partial::create($onlyDefinition));
}
$this->expandPartials(
$this->getPartialsContainer()->onlyPartials ??= new PartialsCollection(),
$only,
permanent: false,
);

return $this;
}

public function onlyPermanently(string ...$only): static
public function onlyPermanently(string|array ...$only): static
{
$partialsCollection = $this->getPartialsContainer()->onlyPartials ??= new PartialsCollection();

foreach ($only as $onlyDefinition) {
$partialsCollection->attach(Partial::create($onlyDefinition, permanent: true));
}
$this->expandPartials(
$this->getPartialsContainer()->onlyPartials ??= new PartialsCollection(),
$only,
permanent: true,
);

return $this;
}

public function except(string ...$except): static
public function except(string|array ...$except): static
{
$partialsCollection = $this->getPartialsContainer()->exceptPartials ??= new PartialsCollection();

foreach ($except as $exceptDefinition) {
$partialsCollection->attach(Partial::create($exceptDefinition));
}
$this->expandPartials(
$this->getPartialsContainer()->exceptPartials ??= new PartialsCollection(),
$except,
permanent: false,
);

return $this;
}

public function exceptPermanently(string ...$except): static
public function exceptPermanently(string|array ...$except): static
{
$partialsCollection = $this->getPartialsContainer()->exceptPartials ??= new PartialsCollection();

foreach ($except as $exceptDefinition) {
$partialsCollection->attach(Partial::create($exceptDefinition, permanent: true));
}
$this->expandPartials(
$this->getPartialsContainer()->exceptPartials ??= new PartialsCollection(),
$except,
permanent: true,
);

return $this;
}

/**
* @param array<int, string|array<int, string>|array<string,Closure|bool>> $partials
*/
protected function expandPartials(
PartialsCollection $partialsCollection,
array $partials,
bool $permanent,
): void {
foreach ($partials as $partial) {
if (is_string($partial)) {
$partialsCollection->attach(Partial::create($partial, permanent: $permanent));

continue;
}

if (! is_array($partial)) {
continue;
}

foreach ($partial as $key => $subPartial) {
if (is_string($key) && is_callable($subPartial)) {
$partialsCollection->attach(Partial::createConditional($key, condition: $subPartial, permanent: $permanent));

continue;
}

if (is_string($key) && $subPartial === true) {
$partialsCollection->attach(Partial::create($key, permanent: $permanent));

continue;
}

if (is_string($subPartial)) {
$partialsCollection->attach(Partial::create($subPartial, permanent: $permanent));

continue;
}
}
}
}

public function includeWhen(string $include, bool|Closure $condition, bool $permanent = false): static
{
$partialsCollection = $this->getPartialsContainer()->includePartials ??= new PartialsCollection();
Expand Down
35 changes: 35 additions & 0 deletions tests/Support/Iterables/LengthtAwareDataPaginatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use Illuminate\Support\Facades\Route;

use function Pest\Laravel\get;
use function Pest\Laravel\withExceptionHandling;

use Spatie\LaravelData\Data;
use Spatie\LaravelData\Support\Iterables\LengthAwareDataPaginator;
use Spatie\LaravelData\Tests\Fakes\SimpleData;

it('can paginate data', function () {
withExceptionHandling();

Route::get('/', function () {
return (new LengthAwareDataPaginator(['Hello', 'World', 'Welcome'], 3, 1))->data(SimpleData::class);
//
//
// return SimpleData::collect(["Hello", "World", "Weclome"], LengthAwareDataPaginator::class)->data(
// include: 'single',
// exclude: ['multiple', 'items'],
// only: [
// 'callable' => fn(Data $data) => $data->property === 'something',
// ],
// includePermanently: 'permanently',
// wrap: null, // default
// // wrap: false // disabled
// // wrap: 'key' // defined
// transformValues: true, //
// mapPropertyNames: true,
// );
});

get('/')->dump();
});

0 comments on commit 40b231e

Please sign in to comment.