Completed
Push — master ( 0e1003...1276c7 )
by Abdelrahman
61:46 queued 59:06
created

BelongsToMorph   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 6
dl 0
loc 124
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getRelationQuery() 0 7 1
A getResults() 0 6 2
A getMorphs() 0 8 3
A build() 0 26 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cortex\Foundation\Relations;
6
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\Builder;
11
use Illuminate\Database\Eloquent\Relations\Relation;
12
use Illuminate\Database\Eloquent\Relations\BelongsTo;
13
14
class BelongsToMorph extends BelongsTo
15
{
16
    /**
17
     * The name of the polymorphic relation.
18
     *
19
     * @var string
20
     */
21
    protected $morphName;
22
23
    /**
24
     * The type of the polymorphic relation.
25
     *
26
     * @var string
27
     */
28
    protected $morphType;
29
30
    /**
31
     * Create a new belongs to relationship instance.
32
     *
33
     * @param \Illuminate\Database\Eloquent\Builder $query
34
     * @param \Illuminate\Database\Eloquent\Model   $parent
35
     * @param string                                $name
36
     * @param string                                $type
37
     * @param string                                $foreignKey
38
     * @param string                                $ownerKey
39
     * @param string                                $relation
40
     *
41
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
42
     */
43
    public function __construct(Builder $query, Model $parent, $name, $type, $foreignKey, $ownerKey, $relation)
44
    {
45
        $this->morphName = $name;
46
        $this->morphType = $type;
47
48
        parent::__construct($query, $parent, $foreignKey, $ownerKey, $relation);
49
    }
50
51
    /**
52
     * Add the constraints for a relationship query.
53
     *
54
     * @param \Illuminate\Database\Eloquent\Builder $query
55
     * @param \Illuminate\Database\Eloquent\Builder $parent
56
     * @param array|mixed                           $columns
57
     *
58
     * @return \Illuminate\Database\Eloquent\Builder
59
     */
60
    public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
61
    {
62
        $table = $this->getParent()->getTable();
63
        $query = parent::getRelationQuery($query, $parent, $columns);
64
65
        return $query->where("{$table}.{$this->morphType}", '=', $this->morphName);
66
    }
67
68
    /**
69
     * Get the results of the relationship.
70
     *
71
     * @return mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use object|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
72
     */
73
    public function getResults()
74
    {
75
        if ($this->getParent()->{$this->morphType} === $this->morphName) {
76
            return $this->query->first();
77
        }
78
    }
79
80
    /**
81
     * Get the polymorphic relationship columns.
82
     *
83
     * @param string $name
84
     * @param string $type
85
     * @param string $id
86
     *
87
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
88
     */
89
    protected static function getMorphs($name, $type, $id)
90
    {
91
        $type = $type ?: $name.'_type';
92
93
        $id = $id ?: $name.'_id';
94
95
        return [$type, $id];
96
    }
97
98
    /**
99
     * Define an inverse morph relationship.
100
     *
101
     * @param Model  $parent
102
     * @param string $related
103
     * @param string $name
104
     * @param string $type
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
105
     * @param string $id
0 ignored issues
show
Documentation introduced by
Should the type for parameter $id not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
106
     * @param string $otherKey
0 ignored issues
show
Documentation introduced by
Should the type for parameter $otherKey not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
107
     * @param string $relation
0 ignored issues
show
Documentation introduced by
Should the type for parameter $relation not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
108
     *
109
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use BelongsToMorph.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
110
     */
111
    public static function build(Model $parent, $related, $name, $type = null, $id = null, $otherKey = null, $relation = null)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
112
    {
113
        // If no relation name was given, we will use this debug backtrace to extract
114
        // the calling method's name and use that as the relationship name as most
115
        // of the time this will be what we desire to use for the relationships.
116
        if (is_null($relation)) {
117
            [$current, $caller] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
0 ignored issues
show
Bug introduced by
The variable $current does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $caller does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
118
119
            $relation = $caller['function'];
120
        }
121
122
        $morphName = Arr::get(array_flip(Relation::morphMap()), $related, $related);
123
124
        [$type, $id] = self::getMorphs(Str::snake($name), $type, $id);
125
126
        $instance = new $related();
127
128
        // Once we have the foreign key names, we'll just create a new Eloquent query
129
        // for the related models and returns the relationship instance which will
130
        // actually be responsible for retrieving and hydrating every relations.
131
        $query = $instance->newQuery();
132
133
        $otherKey = $otherKey ?: $instance->getKeyName();
134
135
        return new self($query, $parent, $morphName, $type, $id, $otherKey, $relation);
136
    }
137
}
138