From e077fda7f5b4a447889d0b868366bb5b967b90aa Mon Sep 17 00:00:00 2001 From: Ahmed Bally Date: Wed, 13 Sep 2023 21:05:24 +0300 Subject: [PATCH] Support Route Scope Binding (#38) --- src/Traits/OptimusEncodedRouteKey.php | 25 +++++++++++++++++++ ...07_173419_add_parent_id_to_users_table.php | 23 +++++++++++++++++ .../UserWithCustomOptimusConnection.php | 12 +++++++++ .../UserWithDefaultOptimusConnection.php | 12 +++++++++ tests/Traits/OptimusEncodedRouteKeyTest.php | 19 +++++++++++--- 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 tests/Stubs/Migrations/2023_09_07_173419_add_parent_id_to_users_table.php diff --git a/src/Traits/OptimusEncodedRouteKey.php b/src/Traits/OptimusEncodedRouteKey.php index 748ead3..ee93801 100644 --- a/src/Traits/OptimusEncodedRouteKey.php +++ b/src/Traits/OptimusEncodedRouteKey.php @@ -40,6 +40,31 @@ public function resolveRouteBinding($value, $field = null) return $this->where($field, $value)->first(); } + /** + * Retrieve the model for a bound value. + * + * @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\Relation $query + * @param mixed $value + * @param string|null $field + * @return \Illuminate\Database\Eloquent\Relations\Relation + */ + public function resolveRouteBindingQuery($query, $value, $field = null) + { + if ($field === null) { + $field = $query->getRouteKeyName(); + } + + if (is_string($value) && ctype_digit($value)) { + $value = (int) $value; + } + + if (is_int($value) && $field === $this->getRouteKeyName()) { + $value = $this->getOptimus()->decode($value); + } + + return $query->where($field, $value); + } + /** * Get the Optimus instance. * diff --git a/tests/Stubs/Migrations/2023_09_07_173419_add_parent_id_to_users_table.php b/tests/Stubs/Migrations/2023_09_07_173419_add_parent_id_to_users_table.php new file mode 100644 index 0000000..cf3cf78 --- /dev/null +++ b/tests/Stubs/Migrations/2023_09_07_173419_add_parent_id_to_users_table.php @@ -0,0 +1,23 @@ +foreignId('parent_id') + ->nullable(); + }); + } + + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['parent_id']); + }); + } +} diff --git a/tests/Stubs/Models/UserWithCustomOptimusConnection.php b/tests/Stubs/Models/UserWithCustomOptimusConnection.php index 6d45cbf..4671516 100644 --- a/tests/Stubs/Models/UserWithCustomOptimusConnection.php +++ b/tests/Stubs/Models/UserWithCustomOptimusConnection.php @@ -4,6 +4,8 @@ use Cog\Laravel\Optimus\Traits\OptimusEncodedRouteKey; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; final class UserWithCustomOptimusConnection extends Model { @@ -14,4 +16,14 @@ final class UserWithCustomOptimusConnection extends Model protected $table = 'users'; protected $guarded = []; + + public function nestedUsers(): HasMany + { + return $this->hasMany(UserWithCustomOptimusConnection::class, 'parent_id'); + } + + public function parentUser(): BelongsTo + { + return$this->belongsTo(UserWithCustomOptimusConnection::class, 'parent_id'); + } } diff --git a/tests/Stubs/Models/UserWithDefaultOptimusConnection.php b/tests/Stubs/Models/UserWithDefaultOptimusConnection.php index 080c487..7db30cc 100644 --- a/tests/Stubs/Models/UserWithDefaultOptimusConnection.php +++ b/tests/Stubs/Models/UserWithDefaultOptimusConnection.php @@ -4,6 +4,8 @@ use Cog\Laravel\Optimus\Traits\OptimusEncodedRouteKey; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; final class UserWithDefaultOptimusConnection extends Model { @@ -12,4 +14,14 @@ final class UserWithDefaultOptimusConnection extends Model protected $table = 'users'; protected $guarded = []; + + public function nestedUsers(): HasMany + { + return $this->hasMany(UserWithDefaultOptimusConnection::class, 'parent_id'); + } + + public function parentUser(): BelongsTo + { + return$this->belongsTo(UserWithDefaultOptimusConnection::class, 'parent_id'); + } } diff --git a/tests/Traits/OptimusEncodedRouteKeyTest.php b/tests/Traits/OptimusEncodedRouteKeyTest.php index ce566b7..45daa4f 100644 --- a/tests/Traits/OptimusEncodedRouteKeyTest.php +++ b/tests/Traits/OptimusEncodedRouteKeyTest.php @@ -28,6 +28,7 @@ protected function setUp(): void parent::setUp(); $this->loadLaravelMigrations(config('database.default')); + $this->loadMigrationsFrom(__DIR__.'/../Stubs/Migrations'); $this->configurePrimeNumbers(); } @@ -51,6 +52,18 @@ public function testOptimusConnectionCanBeConfigured(): void $this->assertNotEquals($incorrectEncodedId, $routeKey); } + public function testResolveChildRouteWithEncodedKey(): void + { + $user = $this->createUserWithDefaultOptimusConnection(); + $nestedUser = $this->createUserWithDefaultOptimusConnection([ + 'email' => 'test1@user.com', + ]); + $nestedUser->parentUser()->associate($user)->save(); + $resolvedNestedUser = $user->resolveChildRouteBinding('nested_user', $nestedUser->getRouteKey(), 'id'); + + $this->assertEquals($nestedUser->id, $resolvedNestedUser->id); + } + public function testResolveModelWithEncodedKey(): void { $user = $this->createUserWithDefaultOptimusConnection(); @@ -172,13 +185,13 @@ public function testExistingIntegerValuesBelow256AreResolved() * * @return \Cog\Tests\Laravel\Optimus\Stubs\Models\UserWithDefaultOptimusConnection */ - protected function createUserWithDefaultOptimusConnection(): UserWithDefaultOptimusConnection + protected function createUserWithDefaultOptimusConnection(array $data = []): UserWithDefaultOptimusConnection { - return UserWithDefaultOptimusConnection::create([ + return UserWithDefaultOptimusConnection::create(array_merge([ 'name' => 'Default Test User', 'email' => 'test@user.com', 'password' => 'p4ssw0rd', - ]); + ], $data)); } /**