Skip to content

Commit

Permalink
refactor!: upgrade to spatie/data-transfer-object ^3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
alexzarbn committed Jun 14, 2021
1 parent 24bc093 commit 33cc77c
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 134 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

strategy:
matrix:
php-version: [ '7.4', '8.0' ]
php-version: [ '8.0' ]

name: Tests on PHP ${{ matrix.php-version }}

Expand Down Expand Up @@ -42,4 +42,4 @@ jobs:
run: composer install --prefer-dist --no-progress --no-suggest

- name: Run test suite
run: vendor/bin/phpunit --verbose
run: vendor/bin/phpunit --verbose
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
}
],
"require": {
"php": ">=7.4",
"php": ">=8.0",
"ext-json": "*",
"illuminate/contracts": "^8.0",
"spatie/data-transfer-object": "^2.5|^3.0"
"spatie/data-transfer-object": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^8.0",
Expand Down
19 changes: 13 additions & 6 deletions src/CastableDataTransferObjectCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@
namespace Tailflow\DataTransferObjects;

use Illuminate\Contracts\Database\Eloquent\Castable;
use Spatie\DataTransferObject\DataTransferObjectCollection;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection;
use Tailflow\DataTransferObjects\Casts\DataTransferObject as DataTransferObjectCast;

abstract class CastableDataTransferObjectCollection extends DataTransferObjectCollection implements Castable
abstract class CastableDataTransferObjectCollection implements Castable, Arrayable
{
protected static string $itemClass;
protected Collection $collection;

public function __construct(array $collection = [])
{
$itemClass = static::$itemClass;

$this->collection = array_map(function($item) use ($itemClass) {
$this->collection = collect($collection)->map(function($item) use ($itemClass) {
return is_array($item) ? new $itemClass($item) : $item;
}, $collection);
});
}

public static function castUsing(array $arguments): DataTransferObjectCast
Expand All @@ -37,6 +39,11 @@ public static function fromJson($json)

$itemClass = static::$itemClass;

return new static($itemClass::arrayOf($collection));
return collect($itemClass::arrayOf($collection));
}
}

public function toArray(): array
{
return $this->collection->toArray();
}
}
8 changes: 7 additions & 1 deletion src/Casts/DataTransferObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use InvalidArgumentException;

class DataTransferObject implements CastsAttributes
Expand All @@ -28,6 +29,7 @@ public function __construct(string $class)
* @param string $key
* @param mixed $value
* @param array $attributes
* @return void
*/
public function get($model, string $key, $value, $attributes)
{
Expand Down Expand Up @@ -57,10 +59,14 @@ public function set($model, $key, $value, $attributes)
$value = new $this->class($value);
}

if ($value instanceof Collection) {
$value = new $this->class($value->toArray());
}

if (!$value instanceof $this->class) {
throw new InvalidArgumentException("Value must be of type [$this->class], array, or null");
}

return $value->toJson();
}
}
}
180 changes: 102 additions & 78 deletions tests/CastableDataTransferObjectCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace Tailflow\DataTransferObjects\Tests;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;
use Spatie\DataTransferObject\DataTransferObjectError;
use Tailflow\DataTransferObjects\Tests\Fixtures\App\DataTransferObjects\Address;
use Tailflow\DataTransferObjects\Tests\Fixtures\App\DataTransferObjects\Addresses;
use Tailflow\DataTransferObjects\Tests\Fixtures\App\Models\User;
Expand All @@ -16,88 +16,106 @@ class CastableDataTransferObjectCollectionTest extends TestCase
/** @test */
public function it_casts_arrays_to_json(): void
{
User::factory()->create([
'delivery_addresses' => [
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '4-2-8 Shiba-koen'
],
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '5-2-0 Ueno-koen'
User::factory()->create(
[
'delivery_addresses' => [
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '4-2-8 Shiba-koen'
],
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '5-2-0 Ueno-koen'
],
],
],
]);

self::assertTrue(DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].street") = "4-2-8 Shiba-koen"')
->exists());

self::assertTrue(DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].street") = "5-2-0 Ueno-koen"')
->exists());
]
);

self::assertTrue(
DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].street") = "4-2-8 Shiba-koen"')
->exists()
);

self::assertTrue(
DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].street") = "5-2-0 Ueno-koen"')
->exists()
);
}

/** @test */
public function it_casts_data_transfer_objects_to_json(): void
{
User::factory()->create([
'delivery_addresses' => new Addresses(
[
new Address([
User::factory()->create(
[
'delivery_addresses' => new Addresses(
[
new Address(
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '4-2-8 Shiba-koen'
]
),
new Address(
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '5-2-0 Ueno-koen'
]
),
]
),
]
);

self::assertTrue(
DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].street") = "4-2-8 Shiba-koen"')
->exists()
);

self::assertTrue(
DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].street") = "5-2-0 Ueno-koen"')
->exists()
);
}

/** @test */
public function it_casts_json_to_a_data_transfer_object(): void
{
$user = User::factory()->create(
[
'delivery_addresses' => [
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '4-2-8 Shiba-koen'
]),
new Address([
],
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '5-2-0 Ueno-koen'
]),
]
),
]);

self::assertTrue(DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[0].street") = "4-2-8 Shiba-koen"')
->exists());

self::assertTrue(DB::table('users')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].country") = "jp"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].city") = "Tokyo"')
->whereRaw('JSON_EXTRACT(delivery_addresses, "$[1].street") = "5-2-0 Ueno-koen"')
->exists());
}

/** @test */
public function it_casts_json_to_a_data_transfer_object(): void
{
$user = User::factory()->create([
'delivery_addresses' => [
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '4-2-8 Shiba-koen'
],
[
'country' => 'jp',
'city' => 'Tokyo',
'street' => '5-2-0 Ueno-koen'
],
],
],
]);
]
);

$user = $user->fresh();

self::assertInstanceOf(Addresses::class, $user->delivery_addresses);
self::assertInstanceOf(Collection::class, $user->delivery_addresses);

self::assertEquals('jp', $user->delivery_addresses[0]->country);
self::assertEquals('Tokyo', $user->delivery_addresses[0]->city);
Expand All @@ -111,23 +129,29 @@ public function it_casts_json_to_a_data_transfer_object(): void
/** @test */
public function it_throws_exceptions_for_incorrect_data_structures(): void
{
$this->expectException(DataTransferObjectError::class);

User::factory()->create([
'delivery_addresses' => [
['bad' => 'thing'],
],
]);
$this->expectExceptionMessage(
'Cannot assign null to property Tailflow\DataTransferObjects\Tests\Fixtures\App\DataTransferObjects\Address::$country of type string'
);

User::factory()->create(
[
'delivery_addresses' => [
['bad' => 'thing'],
],
]
);
}

/** @test */
public function it_rejects_invalid_types(): void
{
$this->expectException(InvalidArgumentException::class);

User::factory()->create([
'delivery_addresses' => 'string',
]);
User::factory()->create(
[
'delivery_addresses' => 'string',
]
);
}

/** @test */
Expand All @@ -139,4 +163,4 @@ public function it_handles_nullable_columns(): void

self::assertNull($user->refresh()->address);
}
}
}
Loading

0 comments on commit 33cc77c

Please sign in to comment.