Skip to content

Commit

Permalink
Small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvanassche committed Jan 9, 2024
1 parent 66b845f commit 425d7c0
Show file tree
Hide file tree
Showing 16 changed files with 135 additions and 40 deletions.
10 changes: 0 additions & 10 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,6 @@ parameters:
count: 1
path: src/Resolvers/DataFromArrayResolver.php

-
message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#"
count: 1
path: src/Support/DataType.php

-
message: "#^Parameter \\#1 \\$reflection of method Spatie\\\\LaravelData\\\\Support\\\\DataType\\:\\:resolveDataCollectableType\\(\\) expects ReflectionNamedType, ReflectionType given\\.$#"
count: 1
path: src/Support/DataType.php

-
message: "#^Call to an undefined method DateTimeInterface\\:\\:setTimezone\\(\\)\\.$#"
count: 1
Expand Down
10 changes: 7 additions & 3 deletions src/Concerns/BaseData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

namespace Spatie\LaravelData\Concerns;

use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Contracts\Pagination\CursorPaginator as CursorPaginatorContract;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\LazyCollection;
use Spatie\LaravelData\CursorPaginatedDataCollection;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\DataPipeline;
Expand Down Expand Up @@ -56,7 +60,7 @@ public static function withoutMagicalCreationFrom(mixed ...$payloads): static
);
}

public static function collect(mixed $items, ?string $into = null): array|DataCollection|PaginatedDataCollection|CursorPaginatedDataCollection|Enumerable|AbstractPaginator|Paginator|AbstractCursorPaginator|CursorPaginator
public static function collect(mixed $items, ?string $into = null): array|DataCollection|PaginatedDataCollection|CursorPaginatedDataCollection|Enumerable|AbstractPaginator|PaginatorContract|AbstractCursorPaginator|CursorPaginatorContract|LazyCollection|Collection
{
return app(DataCollectableFromSomethingResolver::class)->execute(
static::class,
Expand Down
19 changes: 14 additions & 5 deletions src/Contracts/BaseData.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@

namespace Spatie\LaravelData\Contracts;

use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Contracts\Pagination\CursorPaginator as CursorPaginatorContract;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\LazyCollection;
use Spatie\LaravelData\CursorPaginatedDataCollection;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\DataPipeline;
use Spatie\LaravelData\PaginatedDataCollection;

/**
* @template TValue
* @template TKey of array-key
*/
interface BaseData
{
Expand All @@ -23,16 +29,19 @@ public static function from(mixed ...$payloads): static;

public static function withoutMagicalCreationFrom(mixed ...$payloads): static;

public static function collect(mixed $items, ?string $into = null): array|DataCollection|PaginatedDataCollection|CursorPaginatedDataCollection|Enumerable|AbstractPaginator|Paginator|AbstractCursorPaginator|CursorPaginator;
/**
* @param Collection<TKey, TValue>|EloquentCollection<TKey, TValue>|LazyCollection<TKey, TValue>|Enumerable|array<TKey, TValue>|AbstractPaginator|PaginatorContract|AbstractCursorPaginator|CursorPaginatorContract|DataCollection<TKey, TValue> $items
*
* @return ($into is 'array' ? array<TKey, static> : ($into is class-string<EloquentCollection> ? Collection<TKey, static> : ($into is class-string<Collection> ? Collection<TKey, static> : ($into is class-string<LazyCollection> ? LazyCollection<TKey, static> : ($into is class-string<DataCollection> ? DataCollection<TKey, static> : ($into is class-string<PaginatedDataCollection> ? PaginatedDataCollection<TKey, static> : ($into is class-string<CursorPaginatedDataCollection> ? CursorPaginatedDataCollection<TKey, static> : ($items is EloquentCollection ? Collection<TKey, static> : ($items is Collection ? Collection<TKey, static> : ($items is LazyCollection ? LazyCollection<TKey, static> : ($items is Enumerable ? Enumerable<TKey, static> : ($items is array ? array<TKey, static> : ($items is AbstractPaginator ? AbstractPaginator : ($items is PaginatorContract ? PaginatorContract : ($items is AbstractCursorPaginator ? AbstractCursorPaginator : ($items is CursorPaginatorContract ? CursorPaginatorContract : ($items is DataCollection ? DataCollection<TKey, static> : ($items is CursorPaginator ? CursorPaginatedDataCollection<TKey, static> : ($items is Paginator ? PaginatedDataCollection<TKey, static> : DataCollection<TKey, static>))))))))))))))))))) */
public static function collect(mixed $items, ?string $into = null): array|DataCollection|PaginatedDataCollection|CursorPaginatedDataCollection|Enumerable|AbstractPaginator|PaginatorContract|AbstractCursorPaginator|CursorPaginatorContract|LazyCollection|Collection;

public static function withoutMagicalCreationCollect(mixed $items, ?string $into = null): array|DataCollection|PaginatedDataCollection|CursorPaginatedDataCollection|Enumerable|AbstractPaginator|Paginator|AbstractCursorPaginator|CursorPaginator;
public static function withoutMagicalCreationCollect(mixed $items, ?string $into = null);

public static function normalizers(): array;

public static function prepareForPipeline(\Illuminate\Support\Collection $properties): \Illuminate\Support\Collection;

public static function pipeline(): DataPipeline;
public static function empty(array $extra = []): array;

public function getMorphClass(): string;
}
8 changes: 8 additions & 0 deletions src/Resolvers/DataFromSomethingResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use Spatie\LaravelData\Support\DataConfig;
use Spatie\LaravelData\Support\DataMethod;

/**
* @template TData of BaseData
*/
class DataFromSomethingResolver
{
public function __construct(
Expand All @@ -33,6 +36,11 @@ public function ignoreMagicalMethods(string ...$methods): self
return $this;
}

/**
* @param class-string<TData> $class
*
* @return TData
*/
public function execute(string $class, mixed ...$payloads): BaseData
{
if ($data = $this->createFromCustomCreationMethod($class, $payloads)) {
Expand Down
1 change: 0 additions & 1 deletion src/Resolvers/RequestQueryStringPartialsResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public function execute(
$dataClass = $this->dataConfig->getDataClass(match (true) {
$data instanceof BaseData => $data::class,
$data instanceof BaseDataCollectable => $data->getDataClass(),
default => throw new TypeError('Invalid type of data')
});

$partials = new PartialsCollection();
Expand Down
5 changes: 3 additions & 2 deletions src/Support/DataClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Spatie\LaravelData\Contracts\TransformableData;
use Spatie\LaravelData\Contracts\ValidateableData;
use Spatie\LaravelData\Contracts\WrappableData;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Enums\DataTypeKind;
use Spatie\LaravelData\Mappers\ProvidedNameMapper;
use Spatie\LaravelData\Resolvers\NameMappersResolver;
Expand Down Expand Up @@ -58,7 +59,7 @@ public function __construct(

public static function create(ReflectionClass $class): self
{
/** @var class-string<BaseData> $name */
/** @var class-string<Data> $name */
$name = $class->name;

$attributes = static::resolveAttributes($class);
Expand Down Expand Up @@ -192,7 +193,7 @@ protected static function resolveDefaultValues(
/**
* @param Collection<string, DataProperty> $properties
*
* @return LazyDataStructureProperty<array<string, null|true>>
* @return LazyDataStructureProperty<array<string, null|bool>>
*/
protected static function resolveTransformationFields(
Collection $properties,
Expand Down
3 changes: 3 additions & 0 deletions src/Support/DataConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public function getDataClass(string $class): DataClass
return $this->dataClasses[$class] ??= DataClass::create(new ReflectionClass($class));
}

/**
* @param class-string<BaseData> $class
*/
public function getResolvedDataPipeline(string $class): ResolvedDataPipeline
{
return $this->resolvedDataPipelines[$class] ??= $class::pipeline()->resolve();
Expand Down
2 changes: 1 addition & 1 deletion src/Support/DataContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private function __construct()
public static function get(): DataContainer
{
if (! isset(static::$instance)) {
static::$instance = new static();
static::$instance = new self();
}

return static::$instance;
Expand Down
2 changes: 1 addition & 1 deletion src/Support/Partials/PartialsCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use SplObjectStorage;

/**
* @extends SplObjectStorage<Partial>
* @extends SplObjectStorage<Partial, null>
*/
class PartialsCollection extends SplObjectStorage
{
Expand Down
2 changes: 1 addition & 1 deletion src/Support/Partials/ResolvedPartial.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function getFields(): ?array
/** @return string[] */
public function toLaravel(): array
{
/** @var array<string> $partials */
/** @var array<string> $segments */
$segments = [];

for ($i = $this->pointer; $i < $this->segmentCount; $i++) {
Expand Down
2 changes: 1 addition & 1 deletion src/Support/Partials/ResolvedPartialsCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Stringable;

/**
* @extends SplObjectStorage<ResolvedPartial>
* @extends SplObjectStorage<ResolvedPartial, null>
*/
class ResolvedPartialsCollection extends SplObjectStorage implements Stringable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ protected function resolveTypeForProperty(
DataTypeKind::DataCollection, DataTypeKind::Array, DataTypeKind::Enumerable => $this->defaultCollectionType($dataProperty->type->dataClass),
DataTypeKind::Paginator, DataTypeKind::DataPaginatedCollection => $this->paginatedCollectionType($dataProperty->type->dataClass),
DataTypeKind::CursorPaginator, DataTypeKind::DataCursorPaginatedCollection => $this->cursorPaginatedCollectionType($dataProperty->type->dataClass),
null => throw new RuntimeException('Cannot end up here since the type is dataCollectable')
default => throw new RuntimeException('Cannot end up here since the type is dataCollectable')
};

if ($dataProperty->type->isNullable()) {
Expand Down
18 changes: 18 additions & 0 deletions tests/Fakes/SimpleDto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Spatie\LaravelData\Tests\Fakes;

use Spatie\LaravelData\Dto;

class SimpleDto extends Dto
{
public function __construct(
public string $string
) {
}

public static function fromString(string $string): self
{
return new self($string);
}
}
18 changes: 18 additions & 0 deletions tests/Fakes/SimpleResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Spatie\LaravelData\Tests\Fakes;

use Spatie\LaravelData\Resource;

class SimpleResource extends Resource
{
public function __construct(
public string $string
) {
}

public static function fromString(string $string): self
{
return new self($string);
}
}
56 changes: 42 additions & 14 deletions types/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,54 @@

/** @noinspection PhpExpressionResultUnusedInspection */

use function PHPStan\Testing\assertType;

use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\LazyCollection;
use Spatie\LaravelData\CursorPaginatedDataCollection;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\PaginatedDataCollection;
use Spatie\LaravelData\Tests\Fakes\Models\FakeModel;
use Spatie\LaravelData\Tests\Fakes\SimpleData;
use function PHPStan\Testing\assertType;

// Regular collections
$collection = SimpleData::collection(['A', 'B']);
assertType('Spatie\LaravelData\DataCollection<(int|string), Spatie\LaravelData\Tests\Fakes\SimpleData>', $collection);
$collection = SimpleData::collection(collect(['A', 'B']));
assertType('Spatie\LaravelData\DataCollection<(int|string), Spatie\LaravelData\Tests\Fakes\SimpleData>', $collection);
$collection = SimpleData::collect(['A', 'B']);
assertType('array<'.SimpleData::class.'>', $collection);

$collection = SimpleData::collect(collect(['A', 'B']));
assertType(Collection::class.'<(int|string), '.SimpleData::class.'>', $collection);

$collection = SimpleData::collect(new EloquentCollection([new FakeModel(), new FakeModel()]));
assertType(Collection::class.'<(int|string), '.SimpleData::class.'>', $collection);

$collection = SimpleData::collect(new LazyCollection(['A', 'B']));
assertType(LazyCollection::class.'<(int|string), '.SimpleData::class.'>', $collection);

// Paginators

$collection = SimpleData::collect(FakeModel::query()->paginate());
assertType(AbstractPaginator::class.'|'.Enumerable::class.'<(int|string), '.SimpleData::class.'>', $collection);

$collection = SimpleData::collect(FakeModel::query()->cursorPaginate());
assertType(PaginatorContract::class.'|'.AbstractCursorPaginator::class.'|'.Enumerable::class.'<(int|string), '.SimpleData::class.'>', $collection);

// PaginatedDataCollection
$paginator = \Illuminate\Database\Eloquent\Model::query()->paginate();
# into

$collection = SimpleData::collection($paginator);
$collection = SimpleData::collect(collect(['A', 'B']), 'array');
assertType('array<'.SimpleData::class.'>', $collection);

assertType('Spatie\LaravelData\PaginatedDataCollection<(int|string), Spatie\LaravelData\Tests\Fakes\SimpleData>', $collection);
$collection = SimpleData::collect(['A', 'B'], Collection::class);
assertType(Collection::class.'<(int|string), '.SimpleData::class.'>', $collection);

// CursorPaginatedDataCollection
$paginator = \Illuminate\Database\Eloquent\Model::query()->cursorPaginate();
$collection = SimpleData::collect(['A', 'B'], DataCollection::class);
assertType(DataCollection::class.'<(int|string), '.SimpleData::class.'>', $collection);

$collection = SimpleData::collection($paginator);
$collection = SimpleData::collect(FakeModel::query()->paginate(), PaginatedDataCollection::class);
assertType(PaginatedDataCollection::class.'<(int|string), '.SimpleData::class.'>', $collection);

assertType('Spatie\LaravelData\CursorPaginatedDataCollection<(int|string), Spatie\LaravelData\Tests\Fakes\SimpleData>', $collection);
$collection = SimpleData::collect(FakeModel::query()->paginate(), CursorPaginatedDataCollection::class);
assertType(CursorPaginatedDataCollection::class.'<(int|string), '.SimpleData::class.'>', $collection);
17 changes: 17 additions & 0 deletions types/Data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/** @noinspection PhpExpressionResultUnusedInspection */

use Spatie\LaravelData\Tests\Fakes\SimpleData;
use Spatie\LaravelData\Tests\Fakes\SimpleDto;
use Spatie\LaravelData\Tests\Fakes\SimpleResource;
use function PHPStan\Testing\assertType;

$data = SimpleData::from('Hello World');
assertType(SimpleData::class, $data);

$data = SimpleDto::from('Hello World');
assertType(SimpleDto::class, $data);

$data = SimpleResource::from('Hello World');
assertType(SimpleResource::class, $data);

0 comments on commit 425d7c0

Please sign in to comment.