Skip to content

Commit

Permalink
Merge pull request #749 from Tofandel/fix/exception
Browse files Browse the repository at this point in the history
Fix creation context issue
  • Loading branch information
rubenvanassche committed May 3, 2024
2 parents 57b7686 + d32c8e2 commit ecea4cc
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ Laravel-data 4.0.0 was released 5 hours ago, time for an update!

- Make ValidationPath Stringable
- Fix PHPStan
- Improve performance when optional peoperty exists (#612)
- Improve performance when optional property exists (#612)

## 3.10.0 - 2023-12-01

Expand Down
10 changes: 7 additions & 3 deletions src/DataPipes/CastPropertiesDataPipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ protected function cast(
$property->type->kind->isDataObject()
|| $property->type->kind->isDataCollectable()
) {
$context = $creationContext->next($property->type->dataClass, $property->name);

try {
return $property->type->kind->isDataObject()
$context = $creationContext->next($property->type->dataClass, $property->name);

$data = $property->type->kind->isDataObject()
? $context->from($value)
: $context->collect($value, $property->type->iterableClass);

$creationContext->previous();

return $data;
} catch (CannotCreateData) {
return $value;
}
Expand Down
52 changes: 52 additions & 0 deletions tests/CreationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\ValidationException;

use Spatie\LaravelData\DataPipeline;
use Spatie\LaravelData\DataPipes\DataPipe;
use Spatie\LaravelData\Support\Creation\CreationContext;
use Spatie\LaravelData\Support\DataClass;
use function Pest\Laravel\postJson;

use Spatie\LaravelData\Attributes\Computed;
Expand Down Expand Up @@ -1068,6 +1072,53 @@ public function __invoke(SimpleData $data)
->toEqual(['a', 'collection']);
})->skip(fn () => config('data.features.cast_and_transform_iterables') === false);

it('keeps the creation context path up to date', function () {
global $testCreationContexts;
$testCreationContexts = [];
class TestDataPipe implements DataPipe
{
public function handle(mixed $payload, DataClass $class, array $properties, CreationContext $creationContext): array
{
global $testCreationContexts;
$testCreationContexts[] = clone $creationContext;

return $properties;
}
}

class SimpleDataWithTestPipe extends SimpleData
{
public static function pipeline(): DataPipeline
{
return parent::pipeline()
->through(TestDataPipe::class);
}
}

$dataClass = new class () extends Data {
#[DataCollectionOf(SimpleDataWithTestPipe::class)]
public Collection $collection;

public static function pipeline(): DataPipeline
{
return parent::pipeline()
->through(TestDataPipe::class);
}
};

$dataClass::from([
'collection' => [['string' => 'no'], 'models', ['string' => 'here']],
]);

expect($testCreationContexts)->toHaveCount(3);
expect($testCreationContexts[0])->toBeInstanceOf(CreationContext::class);

expect($testCreationContexts[0]->currentPath)->toBe([0 => 'collection', 1 => 0]);
expect($testCreationContexts[1]->currentPath)->toBe([0 => 'collection', 1 => 2]);
expect($testCreationContexts[2]->currentPath)->toHaveCount(0);

});

it('is possible to create an union type data object', function () {
$dataClass = new class () extends Data {
public string|SimpleData $property;
Expand Down Expand Up @@ -1102,3 +1153,4 @@ public function __invoke(SimpleData $data)
[10, SimpleData::from('Hello World')]
);
})->todo();

26 changes: 26 additions & 0 deletions tests/PartialsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@
]);
});

it('can conditionally include nested collection', function () {
$dataClass = new class () extends Data {
#[DataCollectionOf(MultiLazyData::class)]
public Collection $nested;
};

$data = $dataClass::collect([
[
'nested' => [DummyDto::rick()],
], [
'nested' => [DummyDto::bon()],
]
], DataCollection::class);

expect($data->toArray())->toMatchArray([
['nested' => [[]]],
['nested' => [[]]]
]);

expect($data->include('nested.{artist,year}')->toArray())
->toMatchArray([
['nested' => [['artist' => DummyDto::rick()->artist, 'year' => DummyDto::rick()->year]]],
['nested' => [['artist' => DummyDto::bon()->artist, 'year' => DummyDto::bon()->year]]]
]);
});

it('can conditionally include using class defaults', function () {
PartialClassConditionalData::setDefinitions(includeDefinitions: [
'string' => fn (PartialClassConditionalData $data) => $data->enabled,
Expand Down

0 comments on commit ecea4cc

Please sign in to comment.