Issues (590)

src/Entity/Model.php (2 issues)

1
<?php
2
3
namespace Bdf\Prime\Entity;
4
5
use Bdf\Prime\Exception\PrimeException;
6
use Bdf\Prime\PrimeSerializable;
7
use Bdf\Prime\Query\Contract\ReadOperation;
8
use Bdf\Prime\Query\Contract\WriteOperation;
9
use Bdf\Prime\Query\QueryInterface;
10
use Bdf\Prime\Relations\EntityRelation;
11
use Bdf\Prime\Repository\EntityRepository;
12
use Bdf\Prime\Repository\RepositoryEventsSubscriberInterface;
13
use Bdf\Prime\Repository\RepositoryInterface;
14
use Bdf\Serializer\Metadata\Builder\ClassMetadataBuilder;
15
16
/**
17
 * Model
18
 *
19
 * Active record pattern
20
 *
21
 * @psalm-type EntityCollection = \Bdf\Prime\Collection\EntityCollection<static>
22
 * @psalm-type EntityQuery = QueryInterface<\Bdf\Prime\Connection\ConnectionInterface, static>
23
 *
24
 * @method static \Bdf\Prime\Collection\EntityCollection collection(array $entities = [])
25
 * @psalm-method static EntityCollection collection(array<self> $entities = [])
26
 * @method static Criteria criteria(array $criteria = [])
27
 *
28
 * @method static static|null get(mixed $key)
29
 * @method static static getOrNew(mixed $key)
30
 * @method static static getOrFail(mixed $key)
31
 * @method static static|null findById(mixed $key)
32
 * @method static static|null findOne(array $criteria, ?array $attributes = null)
33
 *
34
 * @method static QueryInterface where(string|array|callable $column, mixed|null $operator = null, mixed $value = null)
35
 * @psalm-method static EntityQuery where(string|array|callable $column, mixed|null $operator = null, mixed $value = null)
36
 * @method static QueryInterface with(string|array $relations)
37
 * @psalm-method static EntityQuery with(string|array $relations)
38
 * @method static QueryInterface by(string $attribute, bool $combine = false)
39
 * @psalm-method static EntityQuery by(string $attribute, bool $combine = false)
40
 *
41
 * @method static int updateBy(array $attributes, array $criteria = [])
42
 * @method static int count(array $criteria = [], $attributes = null)
43
 * @method static bool exists(self $entity)
44
 * @method static static|null refresh(self $entity)
45
 */
46
class Model extends PrimeSerializable implements EntityInterface, ImportableInterface
47
{
48
    /**
49
     * Exclude all properties from serialization
50
     *
51
     * @param ClassMetadataBuilder $builder
52
     *
53
     * @throws PrimeException
54
     *
55
     * @return void
56
     */
57 12
    public static function loadSerializerMetadata(ClassMetadataBuilder $builder): void
58
    {
59 12
        if (!$repository = self::locator()->repository($builder->name())) {
60
            return;
61
        }
62
63 12
        $mapperInfo = $repository->mapper()->info();
64
65 12
        foreach ($mapperInfo->all() as $property) {
66 12
            $groups = ['all'];
67
68 12
            if ($property->isObject()) {
69
                /** @var \Bdf\Prime\Mapper\Info\ObjectPropertyInfo $property */
70 12
                if (!$property->belongsToRoot()) {
71 1
                    continue;
72
                }
73
74 12
                $type = $property->className();
75
76 12
                if ($property->isArray()) {
77 8
                    $wrapper = $property->wrapper();
78
79
                    // Set wrapper class, if can be resolved (a custom wrapper, with a closure, cannot be serialized)
80 8
                    if ($wrapper && is_string($wrapper)) {
81 2
                        $type = self::locator()->repository($type)->collectionFactory()->wrapperClass($wrapper).'<'.ltrim($type, '\\').'>';
0 ignored issues
show
It seems like $type can also be of type null; however, parameter $string of ltrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

81
                        $type = self::locator()->repository($type)->collectionFactory()->wrapperClass($wrapper).'<'.ltrim(/** @scrutinizer ignore-type */ $type, '\\').'>';
Loading history...
82
                    } else {
83 12
                        $type .= '[]';
84
                    }
85
                }
86
            } else {
87
                /** @var \Bdf\Prime\Mapper\Info\PropertyInfo $property */
88 12
                $type = $property->phpType();
89
90 12
                if ($property->isPrimary()) {
91 12
                    $groups[] = 'identifier';
92
                }
93
            }
94
95 12
            $builder->add($property->name(), ltrim($type, '\\'), ['groups' => $groups]);
96
        }
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 784
    public function import(array $data): void
103
    {
104 784
        if (empty($data)) {
105 746
            return;
106
        }
107
108 740
        self::locator()->hydrator($this)->hydrate($this, $data);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 11
    public function export(array $attributes = []): array
115
    {
116 11
        return self::locator()->hydrator($this)->extract($this, $attributes);
117
    }
118
119
    /**
120
     * Get the associated repository
121
     *
122
     * @return EntityRepository<static>
123
     */
124 721
    public static function repository()
125
    {
126 721
        return self::locator()->repository(static::class);
127
    }
128
129
    /**
130
     * Call method on this entity's repository
131
     *
132
     * @param string $name
133
     * @param array $arguments
134
     *
135
     * @return EntityRepository|QueryInterface|mixed
136
     */
137 330
    public static function __callStatic($name, $arguments)
138
    {
139 330
        return static::repository()->$name(...$arguments);
140
    }
141
142
    /**
143
     * Save this entity
144
     *
145
     * @return int
146
     * @throws PrimeException
147
     */
148
    #[WriteOperation]
149 11
    public function save(): int
150
    {
151 11
        return static::repository()->save($this);
152
    }
153
154
    /**
155
     * Insert this entity
156
     *
157
     * @param bool $ignore
158
     *
159
     * @return int
160
     * @throws PrimeException
161
     */
162
    #[WriteOperation]
163 46
    public function insert(bool $ignore = false): int
164
    {
165 46
        return static::repository()->insert($this, $ignore);
166
    }
167
168
    /**
169
     * Update this entity
170
     *
171
     * @param list<string>|null $attributes
0 ignored issues
show
The type Bdf\Prime\Entity\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...
172
     *
173
     * @return int
174
     * @throws PrimeException
175
     */
176
    #[WriteOperation]
177 11
    public function update(array $attributes = null): int
178
    {
179 11
        return static::repository()->update($this, $attributes);
180
    }
181
182
    /**
183
     * Replace this entity
184
     *
185
     * @return int
186
     * @throws PrimeException
187
     */
188
    #[WriteOperation]
189 1
    public function replace(): int
190
    {
191 1
        return static::repository()->replace($this);
192
    }
193
194
    /**
195
     * Duplicate this entity
196
     *
197
     * @return int
198
     * @throws PrimeException
199
     */
200
    #[WriteOperation]
201 1
    public function duplicate(): int
202
    {
203 1
        return static::repository()->duplicate($this);
204
    }
205
206
    /**
207
     * Delete this entity
208
     *
209
     * @return int
210
     * @throws PrimeException
211
     */
212
    #[WriteOperation]
213 9
    public function delete(): int
214
    {
215 9
        return static::repository()->delete($this);
216
    }
217
218
    //---- relations
219
220
    /**
221
     * Load entity relations
222
     * If a relation is already loaded, the entity will be kept
223
     * You can force loading using reload()
224
     *
225
     * @param string|array $relations
226
     *
227
     * @return $this
228
     * @throws PrimeException
229
     *
230
     * @see Model::reload() For force loading
231
     */
232
    #[ReadOperation]
233 61
    public function load($relations)
234
    {
235 61
        static::repository()->loadRelations($this, $relations);
236
237 58
        return $this;
238
    }
239
240
    /**
241
     * For loading entity relations
242
     *
243
     * @param string|array $relations
244
     *
245
     * @return $this
246
     * @throws PrimeException
247
     */
248
    #[ReadOperation]
249 8
    public function reload($relations)
250
    {
251 8
        static::repository()->reloadRelations($this, $relations);
252
253 8
        return $this;
254
    }
255
256
    /**
257
     * Load entity relations
258
     *
259
     * @param string $relation
260
     *
261
     * @return EntityRelation<static, object>
262
     */
263 153
    public function relation(string $relation): EntityRelation
264
    {
265 153
        return static::repository()->onRelation($relation, $this);
266
    }
267
268
    /**
269
     * Save this entity and its relations
270
     *
271
     * @param string|array $relations
272
     *
273
     * @return int
274
     * @throws PrimeException
275
     */
276
    #[WriteOperation]
277 9
    public function saveAll($relations): int
278
    {
279 9
        return static::repository()->saveAll($this, $relations);
280
    }
281
282
    /**
283
     * Delete this entity and its relations
284
     *
285
     * @param string|array $relations
286
     *
287
     * @return int
288
     * @throws PrimeException
289
     */
290
    #[WriteOperation]
291 6
    public function deleteAll($relations): int
292
    {
293 6
        return static::repository()->deleteAll($this, $relations);
294
    }
295
296
    /**
297
     * @deprecated This method is empty and will be removed in 3.0
298
     */
299 803
    public function __destruct()
300
    {
301
        // No-op
302 803
    }
303
304
    //---- events
305
306
    /**
307
     * Register post load event
308
     *
309
     * @param callable(static,RepositoryInterface<static>):(bool|null) $listener
310
     * @param bool $once Register on event once
311
     *
312
     * @return EntityRepository<static>
313
     */
314 1
    public static function loaded(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
315
    {
316 1
        return static::repository()->loaded($listener, $once);
317
    }
318
319
    /**
320
     * Register pre save event
321
     *
322
     * @param callable(static,RepositoryInterface<static>,bool):(bool|null) $listener
323
     * @param bool $once Register on event once
324
     *
325
     * @return EntityRepository<static>
326
     */
327 1
    public static function saving(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
328
    {
329 1
        return static::repository()->saving($listener, $once);
330
    }
331
332
    /**
333
     * Register post save event
334
     *
335
     * @param callable(static,RepositoryInterface<static>,int,bool):(bool|null) $listener
336
     * @param bool $once Register on event once
337
     *
338
     * @return EntityRepository<static>
339
     */
340 1
    public static function saved(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
341
    {
342 1
        return static::repository()->saved($listener, $once);
343
    }
344
345
    /**
346
     * Register post insert event
347
     *
348
     * @param callable(static,RepositoryInterface<static>):(bool|null) $listener
349
     * @param bool $once Register on event once
350
     *
351
     * @return EntityRepository<static>
352
     */
353 1
    public static function inserting(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
354
    {
355 1
        return static::repository()->inserting($listener, $once);
356
    }
357
358
    /**
359
     * Register post insert event
360
     *
361
     * @param callable(static,RepositoryInterface<static>,int):(bool|null) $listener
362
     * @param bool $once Register on event once
363
     *
364
     * @return EntityRepository<static>
365
     */
366 1
    public static function inserted(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
367
    {
368 1
        return static::repository()->inserted($listener, $once);
369
    }
370
371
    /**
372
     * Register post update event
373
     *
374
     * @param callable(static,RepositoryInterface<static>,\ArrayObject<int,string>):(bool|null) $listener
375
     * @param bool $once Register on event once
376
     *
377
     * @return EntityRepository<static>
378
     */
379 2
    public static function updating(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
380
    {
381 2
        return static::repository()->updating($listener, $once);
382
    }
383
384
    /**
385
     * Register post update event
386
     *
387
     * @param callable(static,RepositoryInterface<static>,int):(bool|null) $listener
388
     * @param bool $once Register on event once
389
     *
390
     * @return EntityRepository<static>
391
     */
392 1
    public static function updated(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
393
    {
394 1
        return static::repository()->updated($listener, $once);
395
    }
396
397
    /**
398
     * Register post delete event
399
     *
400
     * @param callable(static,RepositoryInterface<static>):(bool|null) $listener
401
     * @param bool $once Register on event once
402
     *
403
     * @return EntityRepository<static>
404
     */
405 1
    public static function deleting(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
406
    {
407 1
        return static::repository()->deleting($listener, $once);
408
    }
409
410
    /**
411
     * Register post delete event
412
     *
413
     * @param callable(static,RepositoryInterface<static>,int):(bool|null) $listener
414
     * @param bool $once Register on event once
415
     *
416
     * @return EntityRepository<static>
417
     */
418 1
    public static function deleted(callable $listener, bool $once = true): RepositoryEventsSubscriberInterface
419
    {
420 1
        return static::repository()->deleted($listener, $once);
421
    }
422
}
423