diff --git a/composer.json b/composer.json index 4a1bc49..c462702 100644 --- a/composer.json +++ b/composer.json @@ -17,11 +17,14 @@ "illuminate/database": "^10.0" }, "require-dev": { + "barryvdh/laravel-ide-helper": "^2.13", + "orchestra/testbench": "^8.17", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^10.1" }, "autoload": { "psr-4": { + "Staudenmeir\\BelongsToThrough\\": "src/", "Znck\\Eloquent\\": "src/" } }, @@ -33,6 +36,13 @@ "config": { "sort-packages": true }, + "extra": { + "laravel": { + "providers": [ + "Staudenmeir\\BelongsToThrough\\IdeHelperServiceProvider" + ] + } + }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/IdeHelper/BelongsToThroughRelationsHook.php b/src/IdeHelper/BelongsToThroughRelationsHook.php new file mode 100644 index 0000000..99bf185 --- /dev/null +++ b/src/IdeHelper/BelongsToThroughRelationsHook.php @@ -0,0 +1,57 @@ +getMethods(ReflectionMethod::IS_PUBLIC); + + foreach ($methods as $method) { + if ($method->isStatic() || $method->getNumberOfParameters() > 0) { + continue; + } + + try { + $relationship = $method->invoke($model); + } catch (Throwable) { + continue; + } + + if ($relationship instanceof BelongsToThroughRelation) { + $this->addRelationship($command, $method, $relationship); + } + } + } + + protected function addRelationship(ModelsCommand $command, ReflectionMethod $method, Relation $relationship): void + { + $type = '\\' . $relationship->getRelated()::class; + + $command->setProperty( + $method->getName(), + $type, + true, + false, + '', + true + ); + } +} diff --git a/src/IdeHelperServiceProvider.php b/src/IdeHelperServiceProvider.php new file mode 100644 index 0000000..16e7643 --- /dev/null +++ b/src/IdeHelperServiceProvider.php @@ -0,0 +1,32 @@ +app->get('config'); + + $config->set( + 'ide-helper.model_hooks', + array_merge( + [BelongsToThroughRelationsHook::class], + $config->get('ide-helper.model_hooks', []) + ) + ); + } + + public function provides(): array + { + return [ + ModelsCommand::class, + ]; + } +} diff --git a/tests/IdeHelper/BelongsToThroughRelationsHookTest.php b/tests/IdeHelper/BelongsToThroughRelationsHookTest.php new file mode 100644 index 0000000..31e6bce --- /dev/null +++ b/tests/IdeHelper/BelongsToThroughRelationsHookTest.php @@ -0,0 +1,46 @@ +addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '', + ]); + $db->setAsGlobal(); + $db->bootEloquent(); + } + + public function testRun() + { + $command = Mockery::mock(ModelsCommand::class); + $command->shouldReceive('setProperty')->once()->with( + 'country', + '\Tests\IdeHelper\Models\Country', + true, + false, + '', + true + ); + + $hook = new BelongsToThroughRelationsHook(); + $hook->run($command, new Comment()); + } +} diff --git a/tests/IdeHelper/Models/Comment.php b/tests/IdeHelper/Models/Comment.php new file mode 100644 index 0000000..7189f30 --- /dev/null +++ b/tests/IdeHelper/Models/Comment.php @@ -0,0 +1,16 @@ +belongsToThrough(Country::class, [User::class, Post::class]); + } +} diff --git a/tests/IdeHelper/Models/Country.php b/tests/IdeHelper/Models/Country.php new file mode 100644 index 0000000..0eb7599 --- /dev/null +++ b/tests/IdeHelper/Models/Country.php @@ -0,0 +1,10 @@ +app->loadDeferredProvider(BarryvdhIdeHelperServiceProvider::class); + $this->app->loadDeferredProvider(IdeHelperServiceProvider::class); + + /** @var \Illuminate\Contracts\Config\Repository $config */ + $config = $this->app->get('config'); + + $this->assertContains( + BelongsToThroughRelationsHook::class, + $config->get('ide-helper.model_hooks'), + ); + } + + protected function getPackageProviders($app): array + { + return [ + BarryvdhIdeHelperServiceProvider::class, + IdeHelperServiceProvider::class, + ]; + } +}