Skip to content

Commit

Permalink
feat: support SoftDeletes methods on relations (#692)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdrieghe committed Oct 21, 2020
1 parent 957f34a commit 72733fe
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- `SoftDeletes` methods on relations are no longer marked as undefined ([#692](https://github.com/nunomaduro/larastan/pull/692))
- Generic model type is preserved when `with` method is used on a model instance.

## [0.6.6] - 2020-10-17
Expand Down
18 changes: 16 additions & 2 deletions src/Methods/RelationForwardsCallsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace NunoMaduro\Larastan\Methods;

use Illuminate\Database\Eloquent\Relations\Relation;
use NunoMaduro\Larastan\Reflection\EloquentBuilderMethodReflection;
use PHPStan\Analyser\OutOfClassScope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\ShouldNotHappenException;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\ObjectType;
Expand Down Expand Up @@ -42,7 +45,11 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):
new GenericObjectType($classReflection->getName(), [$relatedModel])
);

return $returnMethodReflection !== null;
if ($returnMethodReflection === null) {
return $relatedModel->hasMethod($methodName)->yes();
}

return true;
}

public function getMethod(
Expand All @@ -64,7 +71,14 @@ public function getMethod(
);

if ($returnMethodReflection === null) {
throw new ShouldNotHappenException(sprintf('%s does not have %s method. But it should.', $classReflection->getName(), $methodName));
$originalMethodReflection = $relatedModel->getMethod($methodName, new OutOfClassScope());

$returnMethodReflection = new EloquentBuilderMethodReflection(
$methodName, $classReflection, $originalMethodReflection,
ParametersAcceptorSelector::selectSingle($originalMethodReflection->getVariants())->getParameters(),
new GenericObjectType($classReflection->getName(), [$relatedModel]),
false
);
}

return $returnMethodReflection;
Expand Down
3 changes: 3 additions & 0 deletions tests/Application/app/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
* @property string $name
*/
class Group extends Model
{
use SoftDeletes;

public function accounts(): HasMany
{
return $this->hasMany(Account::class);
Expand Down
15 changes: 15 additions & 0 deletions tests/Features/Models/Relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,21 @@ public function testFirstWhereWithBelongsToRelation(User $user): ?Group
{
return $user->group()->firstWhere('name', 'bar');
}

public function testWithTrashedWithBelongsToRelation(User $user): BelongsTo
{
return $user->group()->withTrashed();
}

public function testOnlyTrashedWithBelongsToRelation(User $user): BelongsTo
{
return $user->group()->onlyTrashed();
}

public function testWithoutTrashedWithBelongsToRelation(User $user): BelongsTo
{
return $user->group()->withoutTrashed();
}
}

/**
Expand Down

0 comments on commit 72733fe

Please sign in to comment.