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

New iterables #715

Closed
wants to merge 1 commit into from
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
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();
});
Loading