Completed
Push — master ( 53c2c8...517ace )
by Marcel
19:23
created

getRelationshipFromMethodAndModel()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 9.0968
c 0
b 0
f 0
cc 5
nc 16
nop 2
1
<?php
2
3
namespace BeyondCode\ErdGenerator;
4
5
use ReflectionClass;
6
use ReflectionMethod;
7
use Illuminate\Support\Collection;
8
use Illuminate\Database\Eloquent\Relations\Relation;
9
use Illuminate\Database\Eloquent\Relations\BelongsTo;
10
use Illuminate\Database\Eloquent\Relations\MorphToMany;
11
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
12
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
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
     */
22
    public function getModelRelations(string $model)
23
    {
24
        $class = new ReflectionClass($model);
25
26
        $traitMethods = Collection::make($class->getTraits())->map(function ($trait) {
27
            return Collection::make($trait->getMethods(ReflectionMethod::IS_PUBLIC));
28
        })->flatten();
29
30
        $methods = Collection::make($class->getMethods(ReflectionMethod::IS_PUBLIC))
31
            ->merge($traitMethods)
32
            ->reject(function (ReflectionMethod $method) use ($model) {
33
                return $method->class !== $model;
34
            })->reject(function (ReflectionMethod $method) use ($model) {
35
                return $method->getNumberOfParameters() > 0;
36
            });
37
38
        $relations = Collection::make();
39
40
        $methods->map(function (ReflectionMethod $method) use ($model, &$relations) {
41
            $relations = $relations->merge($this->getRelationshipFromMethodAndModel($method, $model));
42
        });
43
44
        $relations = $relations->filter();
45
46
        return $relations;
47
    }
48
49
    protected function getParentKey(string $qualifiedKeyName)
50
    {
51
        $segments = explode('.', $qualifiedKeyName);
52
53
        return end($segments);
54
    }
55
56
    protected function getRelationshipFromMethodAndModel(ReflectionMethod $method, string $model)
57
    {
58
        try {
59
            $return = $method->invoke(app($model));
60
61
            if ($return instanceof Relation) {
62
                $localKey = null;
63
                $foreignKey = null;
64
65
                if ($return instanceof HasOneOrMany) {
66
                    $localKey = $this->getParentKey($return->getQualifiedParentKeyName());
67
                    $foreignKey = $return->getForeignKeyName();
68
                }
69
70
                if ($return instanceof BelongsTo) {
71
                    $foreignKey = $this->getParentKey($return->getQualifiedOwnerKeyName());
72
                    $localKey = $return->getForeignKey();
73
                }
74
75
                return [
76
                    $method->getName() => new ModelRelation(
77
                        $method->getShortName(),
78
                        (new ReflectionClass($return))->getShortName(),
79
                        (new ReflectionClass($return->getRelated()))->getName(),
80
                        $localKey,
81
                        $foreignKey
82
                    )
83
                ];
84
            }
85
        } catch (\Throwable $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
86
        return null;
87
    }
88
    
89
}