1 | <?php |
||||
2 | |||||
3 | namespace LaravelFreelancerNL\Aranguent\Eloquent; |
||||
4 | |||||
5 | use Illuminate\Contracts\Container\BindingResolutionException; |
||||
6 | use Illuminate\Database\Eloquent\ModelInspector as IlluminateModelInspector; |
||||
7 | use Illuminate\Support\Collection; |
||||
8 | use LaravelFreelancerNL\Aranguent\Connection; |
||||
9 | |||||
10 | use function Illuminate\Support\enum_value; |
||||
11 | |||||
12 | class ModelInspector extends IlluminateModelInspector |
||||
13 | { |
||||
14 | /** |
||||
15 | * The methods that can be called in a model to indicate a relation. |
||||
16 | * |
||||
17 | * @var array<int, string> |
||||
18 | */ |
||||
19 | protected $relationMethods = [ |
||||
20 | 'hasMany', |
||||
21 | 'hasManyThrough', |
||||
22 | 'hasOneThrough', |
||||
23 | 'belongsToMany', |
||||
24 | 'hasOne', |
||||
25 | 'belongsTo', |
||||
26 | 'morphOne', |
||||
27 | 'morphTo', |
||||
28 | 'morphMany', |
||||
29 | 'morphToMany', |
||||
30 | 'morphedByMany', |
||||
31 | ]; |
||||
32 | |||||
33 | /** |
||||
34 | * Extract model details for the given model. |
||||
35 | * |
||||
36 | * @param class-string<\Illuminate\Database\Eloquent\Model>|string $model |
||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||
37 | * @param string|null $connection |
||||
38 | * @return array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: Collection, relations: Collection, events: Collection, observers: Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>} |
||||
0 ignored issues
–
show
The doc comment
array{"class": class-str...abase\Eloquent\Model>>} at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: Collection, relations: Collection, events: Collection, observers: Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>}.
![]() |
|||||
39 | * |
||||
40 | * @throws BindingResolutionException |
||||
41 | */ |
||||
42 | 4 | public function inspect($model, $connection = null) |
|||
43 | { |
||||
44 | 4 | $class = $this->qualifyModel($model); |
|||
45 | |||||
46 | /** @var \Illuminate\Database\Eloquent\Model $model */ |
||||
47 | 4 | $model = $this->app->make($class); |
|||
48 | |||||
49 | 4 | if ($connection !== null) { |
|||
50 | $model->setConnection($connection); |
||||
51 | } |
||||
52 | |||||
53 | |||||
54 | /* @phpstan-ignore-next-line */ |
||||
55 | 4 | return [ |
|||
56 | 4 | 'class' => get_class($model), |
|||
57 | 4 | 'database' => $model->getConnection()->getName() ?? '', |
|||
58 | 4 | 'table' => $model->getConnection()->getTablePrefix() . $model->getTable(), |
|||
59 | 4 | 'policy' => $this->getPolicy($model) ?? '', |
|||
60 | 4 | 'attributes' => $this->getAttributes($model), |
|||
61 | 4 | 'relations' => $this->getRelations($model), |
|||
62 | 4 | 'events' => $this->getEvents($model), |
|||
63 | 4 | 'observers' => $this->getObservers($model), |
|||
64 | 4 | 'collection' => $this->getCollectedBy($model), |
|||
65 | 4 | 'builder' => $this->getBuilder($model), |
|||
66 | 4 | ]; |
|||
67 | } |
||||
68 | |||||
69 | /** |
||||
70 | * Get the column attributes for the given model. |
||||
71 | * |
||||
72 | * @param \Illuminate\Database\Eloquent\Model $model |
||||
73 | * @return Collection<int, array<string, mixed>> |
||||
74 | */ |
||||
75 | 4 | protected function getAttributes($model) |
|||
76 | { |
||||
77 | 4 | $connection = $model->getConnection(); |
|||
78 | assert($connection instanceof Connection); |
||||
79 | |||||
80 | 4 | $schema = $connection->getSchemaBuilder(); |
|||
81 | 4 | $table = $model->getTable(); |
|||
82 | 4 | $tableData = $schema->getTable($table); |
|||
83 | 4 | $columns = $schema->getColumns($table); |
|||
84 | 4 | $indexes = $schema->getIndexes($table); |
|||
85 | |||||
86 | 4 | $columns = $this->addSystemAttributes($columns, $tableData); |
|||
87 | |||||
88 | /* @phpstan-ignore-next-line */ |
||||
89 | 4 | return collect($columns) |
|||
0 ignored issues
–
show
$columns of type array<mixed,mixed> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
90 | 4 | ->map(fn($column) => [ |
|||
91 | 4 | 'name' => $column['name'], |
|||
92 | 4 | 'type' => $column['type'], |
|||
93 | 4 | 'increments' => $column['auto_increment'] ?? null, |
|||
94 | 4 | 'nullable' => $column['nullable'] ?? null, |
|||
95 | 4 | 'default' => $this->getColumnDefault($column, $model) ?? null, |
|||
96 | 4 | 'unique' => $this->columnIsUnique($column['name'], $indexes), |
|||
97 | 4 | 'fillable' => $model->isFillable($column['name']), |
|||
98 | 4 | 'computed' => $this->columnIsComputed($column['name'], $tableData), |
|||
99 | 4 | 'hidden' => $this->attributeIsHidden($column['name'], $model), |
|||
100 | 4 | 'appended' => null, |
|||
101 | 4 | 'cast' => $this->getCastType($column['name'], $model), |
|||
102 | 4 | ]) |
|||
103 | 4 | ->merge($this->getVirtualAttributes($model, $columns)); |
|||
104 | } |
||||
105 | |||||
106 | /** |
||||
107 | * Get the default value for the given column. |
||||
108 | * |
||||
109 | * @param array<string, mixed> $column |
||||
110 | * @param \Illuminate\Database\Eloquent\Model $model |
||||
111 | * @return mixed|null |
||||
112 | */ |
||||
113 | 4 | protected function getColumnDefault($column, $model) |
|||
114 | { |
||||
115 | 4 | $attributeDefault = $model->getAttributes()[$column['name']] ?? null; |
|||
116 | |||||
117 | 4 | return enum_value($attributeDefault, $column['default'] ?? null); |
|||
118 | } |
||||
119 | |||||
120 | /** |
||||
121 | * Determine if the given attribute is unique. |
||||
122 | * |
||||
123 | * @param string $column |
||||
124 | * @param mixed[] $indexes |
||||
125 | * @return bool |
||||
126 | */ |
||||
127 | 4 | protected function columnIsUnique($column, $indexes) |
|||
128 | { |
||||
129 | 4 | return collect($indexes)->contains( |
|||
0 ignored issues
–
show
$indexes of type array<mixed,mixed> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
130 | 4 | fn($index) => count($index['fields']) === 1 && $index['fields'][0] === $column && $index['unique'], |
|||
131 | 4 | ); |
|||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * @param string $name |
||||
136 | * @param array<string, mixed> $tableData |
||||
137 | * @return bool |
||||
138 | */ |
||||
139 | 4 | protected function columnIsComputed($name, $tableData) |
|||
140 | { |
||||
141 | 4 | $computedValues = (new Collection($tableData['computedValues']))->pluck('name')->toArray(); |
|||
142 | |||||
143 | 4 | return in_array($name, $computedValues); |
|||
144 | } |
||||
145 | |||||
146 | /** |
||||
147 | * @param mixed[] $columns |
||||
148 | * @param mixed[] $tableData |
||||
149 | * @return mixed[] |
||||
150 | */ |
||||
151 | 4 | protected function addSystemAttributes(array $columns, $tableData) |
|||
152 | { |
||||
153 | // edges add _from, _to |
||||
154 | 4 | if ($tableData['type'] === 3) { |
|||
155 | 1 | array_unshift( |
|||
156 | 1 | $columns, |
|||
157 | 1 | [ |
|||
158 | 1 | 'name' => '_to', |
|||
159 | 1 | 'type' => 'string', |
|||
160 | 1 | 'nullable' => false, |
|||
161 | 1 | ], |
|||
162 | 1 | ); |
|||
163 | 1 | array_unshift( |
|||
164 | 1 | $columns, |
|||
165 | 1 | [ |
|||
166 | 1 | 'name' => '_from', |
|||
167 | 1 | 'type' => 'string', |
|||
168 | 1 | 'nullable' => false, |
|||
169 | 1 | ], |
|||
170 | 1 | ); |
|||
171 | } |
||||
172 | |||||
173 | // Prepend id, |
||||
174 | 4 | array_unshift( |
|||
175 | 4 | $columns, |
|||
176 | 4 | [ |
|||
177 | 4 | 'name' => 'id', |
|||
178 | 4 | 'type' => $tableData['keyOptions']->type, |
|||
179 | 4 | 'nullable' => false, |
|||
180 | 4 | 'allowUserKeys' => $tableData['keyOptions']->allowUserKeys, |
|||
181 | 4 | 'unique' => true, |
|||
182 | 4 | ], |
|||
183 | 4 | ); |
|||
184 | |||||
185 | 4 | return $columns; |
|||
186 | } |
||||
187 | } |
||||
188 |