Skip to content

Commit

Permalink
Add IDE helper model hook
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed Dec 16, 2023
1 parent c5f9558 commit 18b5d55
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 0 deletions.
10 changes: 10 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
}
},
Expand All @@ -33,6 +36,13 @@
"config": {
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"Staudenmeir\\BelongsToThrough\\IdeHelperServiceProvider"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
57 changes: 57 additions & 0 deletions src/IdeHelper/BelongsToThroughRelationsHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Staudenmeir\BelongsToThrough\IdeHelper;

use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use ReflectionClass;
use ReflectionMethod;
use Throwable;
use Znck\Eloquent\Relations\BelongsToThrough as BelongsToThroughRelation;
use Znck\Eloquent\Traits\BelongsToThrough as BelongsToThroughTrait;

class BelongsToThroughRelationsHook implements ModelHookInterface
{
public function run(ModelsCommand $command, Model $model): void
{
$traits = class_uses_recursive($model);

if (!in_array(BelongsToThroughTrait::class, $traits)) {
return;
}

$methods = (new ReflectionClass($model))->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
);
}
}
32 changes: 32 additions & 0 deletions src/IdeHelperServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Staudenmeir\BelongsToThrough;

use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Staudenmeir\BelongsToThrough\IdeHelper\BelongsToThroughRelationsHook;

class IdeHelperServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
/** @var \Illuminate\Contracts\Config\Repository $config */
$config = $this->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,
];
}
}
46 changes: 46 additions & 0 deletions tests/IdeHelper/BelongsToThroughRelationsHookTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Tests\IdeHelper;

use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Illuminate\Database\Capsule\Manager as DB;
use Mockery;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use Orchestra\Testbench\TestCase;
use Staudenmeir\BelongsToThrough\IdeHelper\BelongsToThroughRelationsHook;
use Tests\IdeHelper\Models\Comment;

class BelongsToThroughRelationsHookTest extends TestCase
{
use MockeryPHPUnitIntegration;

protected function setUp(): void
{
parent::setUp();

$db = new DB();
$db->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());
}
}
16 changes: 16 additions & 0 deletions tests/IdeHelper/Models/Comment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Tests\IdeHelper\Models;

use Illuminate\Database\Eloquent\Model;
use Znck\Eloquent\Traits\BelongsToThrough;

class Comment extends Model
{
use BelongsToThrough;

public function country()
{
return $this->belongsToThrough(Country::class, [User::class, Post::class]);
}
}
10 changes: 10 additions & 0 deletions tests/IdeHelper/Models/Country.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Tests\IdeHelper\Models;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
//
}
10 changes: 10 additions & 0 deletions tests/IdeHelper/Models/Post.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Tests\IdeHelper\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
//
}
10 changes: 10 additions & 0 deletions tests/IdeHelper/Models/User.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Tests\IdeHelper\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
//
}
33 changes: 33 additions & 0 deletions tests/IdeHelperServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Tests;

use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider as BarryvdhIdeHelperServiceProvider;
use Orchestra\Testbench\TestCase;
use Staudenmeir\BelongsToThrough\IdeHelper\BelongsToThroughRelationsHook;
use Staudenmeir\BelongsToThrough\IdeHelperServiceProvider;

class IdeHelperServiceProviderTest extends TestCase
{
public function testAutoRegistrationOfModelHook(): void
{
$this->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,
];
}
}

0 comments on commit 18b5d55

Please sign in to comment.