Issues (17)

src/Traits/BelongsToThrough.php (8 issues)

1
<?php
2
3
namespace Znck\Eloquent\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Znck\Eloquent\Relations\BelongsToThrough as Relation;
8
9
trait BelongsToThrough
10
{
11
    /**
12
     * Define a belongs-to-through relationship.
13
     *
14
     * @template TRelatedModel of \Illuminate\Database\Eloquent\Model
15
     *
16
     * @param class-string<TRelatedModel> $related
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<TRelatedModel> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<TRelatedModel>.
Loading history...
17
     * @param class-string<\Illuminate\Database\Eloquent\Model>[]|array{0: class-string<\Illuminate\Database\Eloquent\Model>, 1: string}[]|class-string<\Illuminate\Database\Eloquent\Model> $through
18
     * @param string|null $localKey
19
     * @param string $prefix
20
     * @param array<class-string<\Illuminate\Database\Eloquent\Model>, string> $foreignKeyLookup
21
     * @param array<class-string<\Illuminate\Database\Eloquent\Model>, string> $localKeyLookup
22
     * @return \Znck\Eloquent\Relations\BelongsToThrough<TRelatedModel, $this>
23
     */
24
    public function belongsToThrough(
25
        $related,
26
        $through,
27
        $localKey = null,
28
        $prefix = '',
29
        $foreignKeyLookup = [],
30
        array $localKeyLookup = []
31
    ) {
32
        /** @var TRelatedModel $relatedInstance */
33
        $relatedInstance = $this->newRelatedInstance($related);
0 ignored issues
show
It seems like newRelatedInstance() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

33
        /** @scrutinizer ignore-call */ 
34
        $relatedInstance = $this->newRelatedInstance($related);
Loading history...
34
35
        /** @var list<\Illuminate\Database\Eloquent\Model> $throughParents */
36
        $throughParents  = [];
37
        $foreignKeys     = [];
38
39
        foreach ((array) $through as $model) {
40
            $foreignKey = null;
41
42
            if (is_array($model)) {
43
                /** @var string $foreignKey */
44
                $foreignKey = $model[1];
45
46
                /** @var class-string<\Illuminate\Database\Eloquent\Model> $model */
47
                $model = $model[0];
48
            }
49
50
            $instance = $this->belongsToThroughParentInstance($model);
51
52
            if ($foreignKey) {
53
                $foreignKeys[$instance->getTable()] = $foreignKey;
54
            }
55
56
            $throughParents[] = $instance;
57
        }
58
59
        $foreignKeys = array_merge($foreignKeys, $this->mapKeys($foreignKeyLookup));
60
61
        $localKeys = $this->mapKeys($localKeyLookup);
62
63
        return $this->newBelongsToThrough(
64
            $relatedInstance->newQuery(),
65
            $this,
0 ignored issues
show
$this of type Znck\Eloquent\Traits\BelongsToThrough is incompatible with the type Illuminate\Database\Eloquent\Model expected by parameter $parent of Znck\Eloquent\Traits\Bel...::newBelongsToThrough(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            /** @scrutinizer ignore-type */ $this,
Loading history...
66
            $throughParents,
0 ignored issues
show
$throughParents of type Znck\Eloquent\Traits\list is incompatible with the type array expected by parameter $throughParents of Znck\Eloquent\Traits\Bel...::newBelongsToThrough(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

66
            /** @scrutinizer ignore-type */ $throughParents,
Loading history...
67
            $localKey,
68
            $prefix,
69
            $foreignKeys,
70
            $localKeys
71
        );
72
    }
73
74
    /**
75
     * Map keys to an associative array where the key is the table name and the value is the key from the lookup.
76
     *
77
     * @param array<class-string<\Illuminate\Database\Eloquent\Model>, string> $keyLookup
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<\Illu...loquent\Model>, string> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<\Illuminate\Database\Eloquent\Model>, string>.
Loading history...
78
     * @return array<string, string>
79
     */
80
    protected function mapKeys(array $keyLookup): array
81
    {
82
        $keys = [];
83
84
        // Iterate over each model and key in the key lookup
85
        foreach ($keyLookup as $model => $key) {
86
            // Create a new instance of the model
87
            $instance = new $model();
88
89
            // Add the table name and key to the keys array
90
            $keys[$instance->getTable()] = $key;
91
        }
92
93
        return $keys;
94
    }
95
96
    /**
97
     * Create a through parent instance for a belongs-to-through relationship.
98
     *
99
     * @template TModel of \Illuminate\Database\Eloquent\Model
100
     *
101
     * @param class-string<TModel> $model
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<TModel> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<TModel>.
Loading history...
102
     * @return TModel
103
     */
104
    protected function belongsToThroughParentInstance($model)
105
    {
106
        /** @var array{0: class-string<TModel>, 1?: string} $segments */
107
        $segments = preg_split('/\s+as\s+/i', $model);
108
109
        /** @var TModel $instance */
110
        $instance = new $segments[0]();
111
112
        if (isset($segments[1])) {
113
            $instance->setTable($instance->getTable() . ' as ' . $segments[1]);
114
        }
115
116
        return $instance;
117
    }
118
119
    /**
120
     * Instantiate a new BelongsToThrough relationship.
121
     *
122
     * @template TRelatedModel of \Illuminate\Database\Eloquent\Model
123
     * @template TDeclaringModel of \Illuminate\Database\Eloquent\Model
124
     *
125
     * @param \Illuminate\Database\Eloquent\Builder<TRelatedModel> $query
126
     * @param TDeclaringModel $parent
0 ignored issues
show
The type Znck\Eloquent\Traits\TDeclaringModel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
127
     * @param list<\Illuminate\Database\Eloquent\Model> $throughParents
0 ignored issues
show
The type Znck\Eloquent\Traits\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
128
     * @param string|null $localKey
129
     * @param string $prefix
130
     * @param array<string, string> $foreignKeyLookup
131
     * @param array<string, string> $localKeyLookup
132
     * @return \Znck\Eloquent\Relations\BelongsToThrough<TRelatedModel, TDeclaringModel>
133
     */
134
    protected function newBelongsToThrough(
135
        Builder $query,
136
        Model $parent,
137
        array $throughParents,
138
        $localKey,
139
        $prefix,
140
        array $foreignKeyLookup,
141
        array $localKeyLookup
142
    ) {
143
        return new Relation($query, $parent, $throughParents, $localKey, $prefix, $foreignKeyLookup, $localKeyLookup);
144
    }
145
}
146