1 | <?php |
||||
2 | |||||
3 | namespace BeyondCode\ErdGenerator; |
||||
4 | |||||
5 | use Illuminate\Database\Eloquent\Relations\BelongsTo; |
||||
6 | use Illuminate\Database\Eloquent\Relations\HasOneOrMany; |
||||
7 | use Illuminate\Database\Eloquent\Relations\Relation; |
||||
8 | use Illuminate\Support\Collection; |
||||
9 | use ReflectionClass; |
||||
10 | use ReflectionMethod; |
||||
11 | use Illuminate\Support\Arr; |
||||
12 | |||||
13 | |||||
14 | class RelationFinder |
||||
15 | { |
||||
16 | /** |
||||
17 | * Return all relations from a fully qualified model class name. |
||||
18 | * |
||||
19 | * @param string $model |
||||
20 | * @return Collection |
||||
21 | * @throws \ReflectionException |
||||
22 | */ |
||||
23 | public function getModelRelations(string $model) |
||||
24 | { |
||||
25 | $class = new ReflectionClass($model); |
||||
26 | |||||
27 | $traitMethods = Collection::make($class->getTraits())->map(function (ReflectionClass $trait) { |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
28 | return Collection::make($trait->getMethods(ReflectionMethod::IS_PUBLIC)); |
||||
0 ignored issues
–
show
$trait->getMethods(ReflectionMethod::IS_PUBLIC) of type ReflectionMethod[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::make() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
29 | })->flatten(); |
||||
30 | |||||
31 | $methods = Collection::make($class->getMethods(ReflectionMethod::IS_PUBLIC)) |
||||
0 ignored issues
–
show
$class->getMethods(ReflectionMethod::IS_PUBLIC) of type ReflectionMethod[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::make() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
32 | ->merge($traitMethods) |
||||
33 | ->reject(function (ReflectionMethod $method) use ($model) { |
||||
34 | return $method->class !== $model || $method->getNumberOfParameters() > 0 || $method->isStatic();; |
||||
35 | }); |
||||
36 | |||||
37 | $relations = Collection::make(); |
||||
38 | |||||
39 | $methods->map(function (ReflectionMethod $method) use ($model, &$relations) { |
||||
40 | $relations = $relations->merge($this->getRelationshipFromMethodAndModel($method, $model)); |
||||
41 | }); |
||||
42 | |||||
43 | $relations = $relations->filter(); |
||||
44 | |||||
45 | if ($ignoreRelations = Arr::get(config('erd-generator.ignore', []),$model)) |
||||
46 | { |
||||
47 | $relations = $relations->diffKeys(array_flip($ignoreRelations)); |
||||
48 | } |
||||
49 | |||||
50 | return $relations; |
||||
51 | } |
||||
52 | |||||
53 | /** |
||||
54 | * @param string $qualifiedKeyName |
||||
55 | * @return mixed |
||||
56 | */ |
||||
57 | protected function getParentKey(string $qualifiedKeyName) |
||||
58 | { |
||||
59 | $segments = explode('.', $qualifiedKeyName); |
||||
60 | |||||
61 | return end($segments); |
||||
62 | } |
||||
63 | |||||
64 | /** |
||||
65 | * @param ReflectionMethod $method |
||||
66 | * @param string $model |
||||
67 | * @return array|null |
||||
68 | */ |
||||
69 | protected function getRelationshipFromMethodAndModel(ReflectionMethod $method, string $model) |
||||
70 | { |
||||
71 | try { |
||||
72 | $return = $method->invoke(app($model)); |
||||
73 | |||||
74 | if ($return instanceof Relation) { |
||||
75 | $localKey = null; |
||||
76 | $foreignKey = null; |
||||
77 | |||||
78 | if ($return instanceof HasOneOrMany) { |
||||
79 | $localKey = $this->getParentKey($return->getQualifiedParentKeyName()); |
||||
80 | $foreignKey = $return->getForeignKeyName(); |
||||
81 | } |
||||
82 | |||||
83 | if ($return instanceof BelongsTo) { |
||||
84 | $foreignKey = $this->getParentKey($return->getQualifiedOwnerKeyName()); |
||||
85 | $localKey = method_exists($return, 'getForeignKeyName') ? $return->getForeignKeyName() : $return->getForeignKey(); |
||||
86 | } |
||||
87 | |||||
88 | return [ |
||||
89 | $method->getName() => new ModelRelation( |
||||
90 | $method->getShortName(), |
||||
91 | (new ReflectionClass($return))->getShortName(), |
||||
92 | (new ReflectionClass($return->getRelated()))->getName(), |
||||
93 | $localKey, |
||||
94 | $foreignKey |
||||
95 | ) |
||||
96 | ]; |
||||
97 | } |
||||
98 | } catch (\Throwable $e) {} |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||||
99 | return null; |
||||
100 | } |
||||
101 | |||||
102 | } |
||||
103 |