diff --git a/packages/core/src/Base/Traits/HasModelExtending.php b/packages/core/src/Base/Traits/HasModelExtending.php index 7cafe6c00d..a8e0f2a689 100644 --- a/packages/core/src/Base/Traits/HasModelExtending.php +++ b/packages/core/src/Base/Traits/HasModelExtending.php @@ -3,25 +3,71 @@ namespace Lunar\Base\Traits; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Arr; +use Illuminate\Support\Str; +use Lunar\Base\BaseModel; use Lunar\Facades\ModelManifest; trait HasModelExtending { public function newModelQuery(): Builder { - $realClass = static::modelClass(); + $concreteClass = static::modelClass(); + $parentClass = get_parent_class($concreteClass); // If they are both the same class i.e. they haven't changed // then just call the parent method. - if ($this instanceof $realClass) { + if ($parentClass == BaseModel::class || $this instanceof $concreteClass) { return parent::newModelQuery(); } return $this->newEloquentBuilder( $this->newBaseQueryBuilder() - )->setModel(new $realClass($this->toArray())); + )->setModel( + static::withoutEvents( + fn () => $this->replicateInto($concreteClass) + ) + ); + } + + public function replicateInto($newClass) + { + $defaults = array_values(array_filter([ + $this->getKeyName(), + $this->getCreatedAtColumn(), + $this->getUpdatedAtColumn(), + ...$this->uniqueIds(), + 'laravel_through_key', + ])); + + $attributes = Arr::except( + $this->getAttributes(), $defaults + ); + + return tap(new $newClass, function ($instance) use ($attributes): Model { + $instance->setRawAttributes($attributes); + + $instance->setRelations($this->relations); + + return $instance; + }); + } + + public function getForeignKey(): string + { + $parentClass = get_parent_class($this); + + return $parentClass == BaseModel::class ? parent::getForeignKey() : Str::snake(class_basename($parentClass)).'_'.$this->getKeyName(); + + } + + public function getTable() + { + $parentClass = get_parent_class($this); + + return $parentClass == BaseModel::class ? parent::getTable() : (new $parentClass)->table; } public static function __callStatic($method, $parameters) @@ -50,10 +96,11 @@ public static function modelClass(): string /** * Returns the model alias registered in the model relation morph map. */ - public static function morphName():string{ + public static function morphName(): string + { return (new (static::modelClass()))->getMorphClass(); } - + public function getMorphClass(): string { $morphMap = Relation::morphMap(); diff --git a/tests/core/Stubs/Models/CustomOrder.php b/tests/core/Stubs/Models/CustomOrder.php new file mode 100644 index 0000000000..7cf7db04ce --- /dev/null +++ b/tests/core/Stubs/Models/CustomOrder.php @@ -0,0 +1,5 @@ +create([ 'default' => true, ]); @@ -223,8 +229,8 @@ function can_update_draft_order() ->and($order->shippingAddress)->toBeInstanceOf(OrderAddress::class) ->and($order->billingAddress)->toBeInstanceOf(OrderAddress::class); - $this->assertDatabaseHas((new Order)->getTable(), $datacheck); - $this->assertDatabaseHas((new OrderLine)->getTable(), [ + assertDatabaseHas((new Order)->getTable(), $datacheck); + assertDatabaseHas((new OrderLine)->getTable(), [ 'identifier' => $shippingOption->getIdentifier(), ]); diff --git a/tests/core/Unit/Base/Traits/HasModelExtendingTest.php b/tests/core/Unit/Base/Traits/HasModelExtendingTest.php index da758ad99d..24f55d3e09 100644 --- a/tests/core/Unit/Base/Traits/HasModelExtendingTest.php +++ b/tests/core/Unit/Base/Traits/HasModelExtendingTest.php @@ -38,6 +38,13 @@ function () { expect($sizeOption->sizes)->toHaveCount(1); }); +test('extended model returns correct table name', function () { + expect((new \Lunar\Tests\Core\Stubs\Models\CustomOrder)->getTable()) + ->toBe( + (new \Lunar\Models\Order)->getTable() + ); +}); + test('can forward static method calls to extended model', function () { /** @see \Lunar\Tests\Core\Stubs\Models\ProductOption::getSizesStatic() */ $newStaticMethod = ProductOption::getSizesStatic();