File: Builder.php

package info (click to toggle)
php-laravel-framework 11.46.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,276 kB
  • sloc: php: 266,630; sh: 167; javascript: 51; makefile: 46
file content (285 lines) | stat: -rw-r--r-- 19,779 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<?php

namespace Illuminate\Types\Builder;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\HasBuilder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Query\Builder as QueryBuilder;

use function PHPStan\Testing\assertType;

/** @param \Illuminate\Database\Eloquent\Builder<User> $query */
function test(
    Builder $query,
    User $user,
    Post $post,
    ChildPost $childPost,
    Comment $comment,
    QueryBuilder $queryBuilder
): void {
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->where('id', 1));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhere('name', 'John'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereNot('status', 'active'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->with('relation'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->with(['relation' => ['foo' => fn ($q) => $q]]));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->with(['relation' => function ($query) {
        // assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
    }]));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->without('relation'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->withOnly(['relation']));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->withOnly(['relation' => ['foo' => fn ($q) => $q]]));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->withOnly(['relation' => function ($query) {
        // assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
    }]));
    assertType('array<int, Illuminate\Types\Builder\User>', $query->getModels());
    assertType('array<int, Illuminate\Types\Builder\User>', $query->eagerLoadRelations([]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->get());
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->hydrate([]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->fromQuery('foo', []));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->findMany([1, 2, 3]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->findOrFail([1]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->findOrNew([1]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->find([1]));
    assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Builder\User>', $query->findOr([1], callback: fn () => 42));
    assertType('Illuminate\Types\Builder\User', $query->findOrFail(1));
    assertType('Illuminate\Types\Builder\User|null', $query->find(1));
    assertType('42|Illuminate\Types\Builder\User', $query->findOr(1, fn () => 42));
    assertType('42|Illuminate\Types\Builder\User', $query->findOr(1, callback: fn () => 42));
    assertType('Illuminate\Types\Builder\User|null', $query->first());
    assertType('42|Illuminate\Types\Builder\User', $query->firstOr(fn () => 42));
    assertType('42|Illuminate\Types\Builder\User', $query->firstOr(callback: fn () => 42));
    assertType('Illuminate\Types\Builder\User', $query->firstOrNew(['id' => 1]));
    assertType('Illuminate\Types\Builder\User', $query->findOrNew(1));
    assertType('Illuminate\Types\Builder\User', $query->firstOrCreate(['id' => 1]));
    assertType('Illuminate\Types\Builder\User', $query->create(['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->forceCreate(['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->forceCreateQuietly(['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->getModel());
    assertType('Illuminate\Types\Builder\User', $query->make(['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->forceCreate(['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->updateOrCreate(['id' => 1], ['name' => 'John']));
    assertType('Illuminate\Types\Builder\User', $query->firstOrFail());
    assertType('Illuminate\Types\Builder\User', $query->sole());
    assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Builder\User>', $query->cursor());
    assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Builder\User>', $query->cursor());
    assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Builder\User>', $query->lazy());
    assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Builder\User>', $query->lazyById());
    assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Builder\User>', $query->lazyByIdDesc());
    assertType('Illuminate\Support\Collection<(int|string), mixed>', $query->pluck('foo'));
    assertType('Illuminate\Database\Eloquent\Relations\Relation<Illuminate\Database\Eloquent\Model, Illuminate\Types\Builder\User, *>', $query->getRelation('foo'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query->setModel(new Post()));

    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->has('foo', callback: function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->has($user->posts(), callback: function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orHas($user->posts()));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->doesntHave($user->posts(), callback: function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orDoesntHave($user->posts()));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereHas($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->withWhereHas('posts', function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<*>|Illuminate\Database\Eloquent\Relations\Relation<*, *, *>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereHas($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereDoesntHave($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereDoesntHave($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->hasMorph($post->taggable(), 'taggable', callback: function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orHasMorph($post->taggable(), 'taggable'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->doesntHaveMorph($post->taggable(), 'taggable', callback: function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orDoesntHaveMorph($post->taggable(), 'taggable'));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereHasMorph($post->taggable(), 'taggable', function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereHasMorph($post->taggable(), 'taggable', function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereDoesntHaveMorph($post->taggable(), 'taggable', function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereDoesntHaveMorph($post->taggable(), 'taggable', function ($query, $type) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
        assertType('string', $type);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereRelation($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereRelation($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereDoesntHaveRelation($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereDoesntHaveRelation($user->posts(), function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\Post>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereMorphRelation($post->taggable(), 'taggable', function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereMorphRelation($post->taggable(), 'taggable', function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereMorphDoesntHaveRelation($post->taggable(), 'taggable', function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereMorphDoesntHaveRelation($post->taggable(), 'taggable', function ($query) {
        assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Database\Eloquent\Model>', $query);
    }));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereMorphedTo($post->taggable(), new Post()));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->whereNotMorphedTo($post->taggable(), new Post()));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereMorphedTo($post->taggable(), new Post()));
    assertType('Illuminate\Database\Eloquent\Builder<Illuminate\Types\Builder\User>', $query->orWhereNotMorphedTo($post->taggable(), new Post()));

    $query->chunk(1, function ($users, $page) {
        assertType('Illuminate\Support\Collection<int, Illuminate\Types\Builder\User>', $users);
        assertType('int', $page);
    });
    $query->chunkById(1, function ($users, $page) {
        assertType('Illuminate\Support\Collection<int, Illuminate\Types\Builder\User>', $users);
        assertType('int', $page);
    });
    $query->chunkMap(function ($users) {
        assertType('Illuminate\Types\Builder\User', $users);
    });
    $query->chunkByIdDesc(1, function ($users, $page) {
        assertType('Illuminate\Support\Collection<int, Illuminate\Types\Builder\User>', $users);
        assertType('int', $page);
    });
    $query->each(function ($users, $page) {
        assertType('Illuminate\Types\Builder\User', $users);
        assertType('int', $page);
    });
    $query->eachById(function ($users, $page) {
        assertType('Illuminate\Types\Builder\User', $users);
        assertType('int', $page);
    });

    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', Post::query());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', Post::on());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', Post::onWriteConnection());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', Post::with([]));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQuery());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newEloquentBuilder($queryBuilder));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newModelQuery());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQueryWithoutRelationships());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQueryWithoutScopes());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQueryWithoutScope('foo'));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQueryForRestoration(1));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQuery()->where('foo', 'bar'));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\Post>', $post->newQuery()->foo());
    assertType('Illuminate\Types\Builder\Post', $post->newQuery()->create(['name' => 'John']));

    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', ChildPost::query());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', ChildPost::on());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', ChildPost::onWriteConnection());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', ChildPost::with([]));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQuery());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newEloquentBuilder($queryBuilder));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newModelQuery());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQueryWithoutRelationships());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQueryWithoutScopes());
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQueryWithoutScope('foo'));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQueryForRestoration(1));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQuery()->where('foo', 'bar'));
    assertType('Illuminate\Types\Builder\CommonBuilder<Illuminate\Types\Builder\ChildPost>', $childPost->newQuery()->foo());
    assertType('Illuminate\Types\Builder\ChildPost', $childPost->newQuery()->create(['name' => 'John']));

    assertType('Illuminate\Types\Builder\CommentBuilder', Comment::query());
    assertType('Illuminate\Types\Builder\CommentBuilder', Comment::on());
    assertType('Illuminate\Types\Builder\CommentBuilder', Comment::onWriteConnection());
    assertType('Illuminate\Types\Builder\CommentBuilder', Comment::with([]));
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQuery());
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newEloquentBuilder($queryBuilder));
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newModelQuery());
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQueryWithoutRelationships());
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQueryWithoutScopes());
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQueryWithoutScope('foo'));
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQueryForRestoration(1));
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQuery()->where('foo', 'bar'));
    assertType('Illuminate\Types\Builder\CommentBuilder', $comment->newQuery()->foo());
    assertType('Illuminate\Types\Builder\Comment', $comment->newQuery()->create(['name' => 'John']));
}

class User extends Model
{
    /** @return HasMany<Post, $this> */
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

class Post extends Model
{
    /** @use HasBuilder<CommonBuilder<static>> */
    use HasBuilder;

    protected static string $builder = CommonBuilder::class;

    /** @return BelongsTo<User, $this> */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /** @return MorphTo<\Illuminate\Database\Eloquent\Model, $this> */
    public function taggable(): MorphTo
    {
        return $this->morphTo();
    }
}

class ChildPost extends Post
{
}

class Comment extends Model
{
    /** @use HasBuilder<CommentBuilder> */
    use HasBuilder;

    protected static string $builder = CommentBuilder::class;
}

/**
 * @template TModel of \Illuminate\Database\Eloquent\Model
 *
 * @extends \Illuminate\Database\Eloquent\Builder<TModel>
 */
class CommonBuilder extends Builder
{
    /** @return $this */
    public function foo(): static
    {
        return $this->where('foo', 'bar');
    }
}

/** @extends CommonBuilder<Comment> */
class CommentBuilder extends CommonBuilder
{
}