diff --git a/config/next-ide-helper.php b/config/next-ide-helper.php index 646491e..18ba04c 100644 --- a/config/next-ide-helper.php +++ b/config/next-ide-helper.php @@ -57,7 +57,8 @@ 'larastan_friendly' => false, /** - * Do not use nullable for timestamps defined in the model. For example: created_at, updated_at. + * For convenience, model timestamps are by default considered as non-nullable even if they are nullable in the database. + * Setting this to true will force the timestamps to be documented as nullable. */ 'nullable_timestamps' => false, ], diff --git a/src/Domain/Models/Actions/ResolveModelAttributes.php b/src/Domain/Models/Actions/ResolveModelAttributes.php index be8d97b..470984b 100644 --- a/src/Domain/Models/Actions/ResolveModelAttributes.php +++ b/src/Domain/Models/Actions/ResolveModelAttributes.php @@ -20,7 +20,7 @@ public function execute(Model $model): void foreach ($columns as $column) { $attribute = new Attribute($column['name'], $column['type_name'], $column['comment']); $attribute->inDatabase = true; - if ($column['nullable'] && !$this->isLaravelTimestamp($model, $attribute)) { + if ($column['nullable'] && !$this->forceNullableColumnAsNonNullable($model, $attribute)) { $attribute->nullable = true; $attribute->nullableInDatabase = true; } @@ -42,6 +42,15 @@ private function resolveColumns(Model $model): array ->getColumns($model->instance()->getTable()); } + private function forceNullableColumnAsNonNullable(Model $model, Attribute $attribute): bool + { + if (!$this->isLaravelTimestamp($model, $attribute)) { + return false; + } + + return !$this->modelTimestampsAreNonNullable(); + } + private function isLaravelTimestamp(Model $model, Attribute $attribute): bool { if (!$model->instance()->usesTimestamps()) { @@ -49,9 +58,8 @@ private function isLaravelTimestamp(Model $model, Attribute $attribute): bool } if ( - !$this->isNullableLaravelTimestamp() - && ($attribute->name === $model->instance()->getCreatedAtColumn() - || $attribute->name === $model->instance()->getUpdatedAtColumn()) + $attribute->name === $model->instance()->getCreatedAtColumn() + || $attribute->name === $model->instance()->getUpdatedAtColumn() ) { return true; } @@ -59,7 +67,7 @@ private function isLaravelTimestamp(Model $model, Attribute $attribute): bool return false; } - private function isNullableLaravelTimestamp(): bool + private function modelTimestampsAreNonNullable(): bool { return (bool) config('next-ide-helper.models.nullable_timestamps', false); } diff --git a/tests/Unit/Domain/Models/Actions/ResolveModelAttributeTest.php b/tests/Unit/Domain/Models/Actions/ResolveModelAttributeTest.php index 029c954..4e7be41 100644 --- a/tests/Unit/Domain/Models/Actions/ResolveModelAttributeTest.php +++ b/tests/Unit/Domain/Models/Actions/ResolveModelAttributeTest.php @@ -43,4 +43,23 @@ public function timestampsAreCorrectlyResolved(): void $this->assertEquals('\\' . Date::now()::class, $createdAt->type); $this->assertFalse($createdAt->nullable); } + + /** + * @test + */ + public function timestampsNullabilityCanBeConfigured(): void + { + config(['next-ide-helper.models.nullable_timestamps' => true]); + + $model = new Model(User::class, $this->fixturePath('User.php')); + + $resolveAttributes = new ResolveModelAttributes(); + + $resolveAttributes->execute($model); + + $createdAt = $model->attributes->findByName('created_at'); + $this->assertNotNull($createdAt); + $this->assertEquals('\\' . Date::now()::class, $createdAt->type); + $this->assertTrue($createdAt->nullable); + } }