1 | <?php |
||||
2 | |||||
3 | namespace Bdf\Prime\Mapper; |
||||
4 | |||||
5 | use Bdf\Prime\Behaviors\BehaviorInterface; |
||||
6 | use Bdf\Prime\Cache\CacheInterface; |
||||
7 | use Bdf\Prime\Entity\Hydrator\MapperHydrator; |
||||
8 | use Bdf\Prime\Entity\Hydrator\MapperHydratorInterface; |
||||
9 | use Bdf\Prime\Entity\ImportableInterface; |
||||
10 | use Bdf\Prime\Exception\PrimeException; |
||||
11 | use Bdf\Prime\IdGenerators\AutoIncrementGenerator; |
||||
12 | use Bdf\Prime\IdGenerators\GeneratorInterface; |
||||
13 | use Bdf\Prime\IdGenerators\NullGenerator; |
||||
14 | use Bdf\Prime\IdGenerators\TableGenerator; |
||||
15 | use Bdf\Prime\Mapper\Builder\FieldBuilder; |
||||
16 | use Bdf\Prime\Mapper\Builder\IndexBuilder; |
||||
17 | use Bdf\Prime\Mapper\Info\MapperInfo; |
||||
18 | use Bdf\Prime\Platform\PlatformInterface; |
||||
19 | use Bdf\Prime\Relations\Builder\RelationBuilder; |
||||
20 | use Bdf\Prime\Relations\Exceptions\RelationNotFoundException; |
||||
21 | use Bdf\Prime\Repository\EntityRepository; |
||||
22 | use Bdf\Prime\Repository\RepositoryEventsSubscriberInterface; |
||||
23 | use Bdf\Prime\Repository\RepositoryInterface; |
||||
24 | use Bdf\Prime\ServiceLocator; |
||||
25 | use Bdf\Serializer\PropertyAccessor\PropertyAccessorInterface; |
||||
26 | use Bdf\Serializer\PropertyAccessor\ReflectionAccessor; |
||||
27 | use LogicException; |
||||
28 | |||||
29 | /** |
||||
30 | * Mapper |
||||
31 | * |
||||
32 | * Contient les méta données de la table. |
||||
33 | * |
||||
34 | * @todo Convertir la donnée avec le type approprié sur les methodes setId, hydrateOne |
||||
35 | * |
||||
36 | * @template E as object |
||||
37 | * |
||||
38 | * @psalm-import-type FieldDefinition from FieldBuilder |
||||
39 | * @psalm-import-type RelationDefinition from RelationBuilder |
||||
40 | */ |
||||
41 | abstract class Mapper |
||||
42 | { |
||||
43 | /** |
||||
44 | * Enable/Disable query result cache on repository |
||||
45 | * If null global cache will be set. |
||||
46 | * Set it to false to deactivate cache on this repository |
||||
47 | * Set the cache instance in configure method |
||||
48 | * |
||||
49 | * @var false|CacheInterface |
||||
50 | */ |
||||
51 | protected $resultCache; |
||||
52 | |||||
53 | /** |
||||
54 | * @var Metadata |
||||
55 | */ |
||||
56 | private $metadata; |
||||
57 | |||||
58 | /** |
||||
59 | * Id generator |
||||
60 | * |
||||
61 | * Could be defined as string (generator class name). It would be instantiated |
||||
62 | * by mapper on generator() method |
||||
63 | * |
||||
64 | * @var \Bdf\Prime\IdGenerators\GeneratorInterface|null |
||||
65 | */ |
||||
66 | protected $generator; |
||||
67 | |||||
68 | /** |
||||
69 | * @var class-string |
||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||
70 | */ |
||||
71 | private $repositoryClass = EntityRepository::class; |
||||
72 | |||||
73 | /** |
||||
74 | * The real name of entity class. Could be an none existing class |
||||
75 | * |
||||
76 | * @var class-string<E> |
||||
0 ignored issues
–
show
|
|||||
77 | */ |
||||
78 | private $entityClass; |
||||
79 | |||||
80 | /** |
||||
81 | * The property accessor class name to use by default |
||||
82 | * |
||||
83 | * @var class-string<PropertyAccessorInterface> |
||||
0 ignored issues
–
show
|
|||||
84 | */ |
||||
85 | private $propertyAccessorClass = ReflectionAccessor::class; |
||||
86 | |||||
87 | /** |
||||
88 | * Set repository read only. |
||||
89 | * |
||||
90 | * @var bool |
||||
91 | */ |
||||
92 | private $readOnly = false; |
||||
93 | |||||
94 | /** |
||||
95 | * Use schema resolver |
||||
96 | * Disable if schema has not to be manage by this app |
||||
97 | * |
||||
98 | * @var bool |
||||
99 | */ |
||||
100 | private $useSchemaManager = true; |
||||
101 | |||||
102 | /** |
||||
103 | * Use quote identifier |
||||
104 | * Allows query builder to use quote identifier |
||||
105 | * |
||||
106 | * @var bool |
||||
107 | */ |
||||
108 | private $useQuoteIdentifier = false; |
||||
109 | |||||
110 | /** |
||||
111 | * The relation builder |
||||
112 | * |
||||
113 | * @var RelationBuilder |
||||
114 | */ |
||||
115 | private $relationBuilder; |
||||
116 | |||||
117 | /** |
||||
118 | * The collection of behaviors |
||||
119 | * |
||||
120 | * @var BehaviorInterface<E>[] |
||||
121 | */ |
||||
122 | private $behaviors; |
||||
123 | |||||
124 | /** |
||||
125 | * The service locator |
||||
126 | * |
||||
127 | * @var ServiceLocator |
||||
128 | */ |
||||
129 | protected $serviceLocator; |
||||
130 | |||||
131 | /** |
||||
132 | * @var MapperHydratorInterface<E> |
||||
133 | */ |
||||
134 | protected $hydrator; |
||||
135 | |||||
136 | |||||
137 | /** |
||||
138 | * Mapper constructor |
||||
139 | * |
||||
140 | * @param ServiceLocator $serviceLocator |
||||
141 | * @param class-string<E> $entityClass |
||||
0 ignored issues
–
show
|
|||||
142 | * @param Metadata|null $metadata |
||||
143 | * @param MapperHydratorInterface<E>|null $hydrator |
||||
144 | * @param CacheInterface|null $resultCache |
||||
145 | */ |
||||
146 | 516 | public function __construct(ServiceLocator $serviceLocator, string $entityClass, ?Metadata $metadata = null, MapperHydratorInterface $hydrator = null, CacheInterface $resultCache = null) |
|||
147 | { |
||||
148 | 516 | $this->entityClass = $entityClass; |
|||
149 | 516 | $this->metadata = $metadata ?: new Metadata(); |
|||
150 | 516 | $this->serviceLocator = $serviceLocator; |
|||
151 | 516 | $this->resultCache = $resultCache; |
|||
152 | |||||
153 | 516 | $this->configure(); |
|||
154 | |||||
155 | 516 | $this->metadata->build($this); |
|||
156 | |||||
157 | 516 | $this->setHydrator($hydrator ?: new MapperHydrator()); |
|||
158 | } |
||||
159 | |||||
160 | /** |
||||
161 | * Custom configuration |
||||
162 | */ |
||||
163 | 514 | public function configure(): void |
|||
164 | { |
||||
165 | // to overwrite |
||||
166 | 514 | } |
|||
167 | |||||
168 | /** |
||||
169 | * Get entity class |
||||
170 | * |
||||
171 | * @return class-string<E> |
||||
0 ignored issues
–
show
|
|||||
172 | * @final |
||||
173 | */ |
||||
174 | 531 | public function getEntityClass(): string |
|||
175 | { |
||||
176 | 531 | return $this->entityClass; |
|||
177 | } |
||||
178 | |||||
179 | /** |
||||
180 | * Get metadata |
||||
181 | * |
||||
182 | * @return Metadata |
||||
183 | * @final |
||||
184 | */ |
||||
185 | 1253 | public function metadata(): Metadata |
|||
186 | { |
||||
187 | 1253 | return $this->metadata; |
|||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Set property accessor class name |
||||
192 | * |
||||
193 | * @param class-string<PropertyAccessorInterface> $className |
||||
0 ignored issues
–
show
|
|||||
194 | * @final |
||||
195 | */ |
||||
196 | 1 | public function setPropertyAccessorClass(string $className): void |
|||
197 | { |
||||
198 | 1 | $this->propertyAccessorClass = $className; |
|||
199 | } |
||||
200 | |||||
201 | /** |
||||
202 | * Get property accessor class name |
||||
203 | * |
||||
204 | * @return class-string<PropertyAccessorInterface> |
||||
0 ignored issues
–
show
|
|||||
205 | * @final |
||||
206 | */ |
||||
207 | 513 | public function getPropertyAccessorClass(): string |
|||
208 | { |
||||
209 | 513 | return $this->propertyAccessorClass; |
|||
210 | } |
||||
211 | |||||
212 | /** |
||||
213 | * Set repository class name |
||||
214 | * |
||||
215 | * @param class-string $className |
||||
0 ignored issues
–
show
|
|||||
216 | * @final |
||||
217 | */ |
||||
218 | 1 | public function setRepositoryClass(string $className): void |
|||
219 | { |
||||
220 | 1 | $this->repositoryClass = $className; |
|||
221 | } |
||||
222 | |||||
223 | /** |
||||
224 | * Get repository class name |
||||
225 | * |
||||
226 | * @return class-string |
||||
0 ignored issues
–
show
|
|||||
227 | * @final |
||||
228 | */ |
||||
229 | 2 | public function getRepositoryClass(): string |
|||
230 | { |
||||
231 | 2 | return $this->repositoryClass; |
|||
232 | } |
||||
233 | |||||
234 | /** |
||||
235 | * Set the repository read only |
||||
236 | * |
||||
237 | * @param bool $flag |
||||
238 | * @final |
||||
239 | */ |
||||
240 | 557 | public function setReadOnly(bool $flag): void |
|||
241 | { |
||||
242 | 557 | $this->readOnly = $flag; |
|||
243 | } |
||||
244 | |||||
245 | /** |
||||
246 | * Get repository read only state |
||||
247 | * |
||||
248 | * @return bool |
||||
249 | * @final |
||||
250 | */ |
||||
251 | 666 | public function isReadOnly(): bool |
|||
252 | { |
||||
253 | 666 | return $this->readOnly; |
|||
254 | } |
||||
255 | |||||
256 | /** |
||||
257 | * Disable schema manager on repository |
||||
258 | * @final |
||||
259 | */ |
||||
260 | 1 | public function disableSchemaManager(): void |
|||
261 | { |
||||
262 | 1 | $this->useSchemaManager = false; |
|||
263 | } |
||||
264 | |||||
265 | /** |
||||
266 | * Does repository have a schema manager |
||||
267 | * |
||||
268 | * @return bool |
||||
269 | * @final |
||||
270 | */ |
||||
271 | 873 | public function hasSchemaManager(): bool |
|||
272 | { |
||||
273 | 873 | return $this->useSchemaManager; |
|||
274 | } |
||||
275 | |||||
276 | /** |
||||
277 | * Set the query builder quote identifier |
||||
278 | * |
||||
279 | * @param bool $flag |
||||
280 | * @final |
||||
281 | */ |
||||
282 | 3 | public function setQuoteIdentifier(bool $flag): void |
|||
283 | { |
||||
284 | 3 | $this->useQuoteIdentifier = $flag; |
|||
285 | } |
||||
286 | |||||
287 | /** |
||||
288 | * Does query builder use quote identifier |
||||
289 | * |
||||
290 | * @return bool |
||||
291 | * @final |
||||
292 | */ |
||||
293 | 513 | public function hasQuoteIdentifier(): bool |
|||
294 | { |
||||
295 | 513 | return $this->useQuoteIdentifier; |
|||
296 | } |
||||
297 | |||||
298 | /** |
||||
299 | * Set generator ID |
||||
300 | * |
||||
301 | * @param string|GeneratorInterface $generator |
||||
302 | * @final |
||||
303 | */ |
||||
304 | 3 | public function setGenerator($generator): void |
|||
305 | { |
||||
306 | 3 | if (!is_string($generator) && !$generator instanceof GeneratorInterface) { |
|||
0 ignored issues
–
show
|
|||||
307 | 1 | throw new LogicException('Trying to set an invalid generator in "' . get_class($this) . '"'); |
|||
308 | } |
||||
309 | |||||
310 | 2 | $this->generator = $generator; |
|||
0 ignored issues
–
show
It seems like
$generator can also be of type string . However, the property $generator is declared as type Bdf\Prime\IdGenerators\GeneratorInterface|null . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||||
311 | } |
||||
312 | |||||
313 | /** |
||||
314 | * Get generator ID |
||||
315 | * |
||||
316 | * @return GeneratorInterface |
||||
317 | * @final |
||||
318 | */ |
||||
319 | 648 | public function generator(): GeneratorInterface |
|||
320 | { |
||||
321 | 648 | if ($this->generator === null) { |
|||
322 | 305 | if ($this->metadata->isAutoIncrementPrimaryKey()) { |
|||
323 | 208 | $this->generator = new AutoIncrementGenerator($this); |
|||
324 | 261 | } elseif ($this->metadata->isSequencePrimaryKey()) { |
|||
325 | 229 | $this->generator = new TableGenerator($this); |
|||
326 | } else { |
||||
327 | 305 | $this->generator = new NullGenerator(); |
|||
328 | } |
||||
329 | 605 | } elseif (is_string($this->generator)) { |
|||
0 ignored issues
–
show
|
|||||
330 | 1 | $className = $this->generator; |
|||
331 | 1 | $this->generator = new $className($this); |
|||
332 | } |
||||
333 | |||||
334 | 648 | return $this->generator; |
|||
335 | } |
||||
336 | |||||
337 | /** |
||||
338 | * @return MapperHydratorInterface<E> |
||||
339 | * @final |
||||
340 | */ |
||||
341 | 4 | public function hydrator(): MapperHydratorInterface |
|||
342 | { |
||||
343 | 4 | return $this->hydrator; |
|||
344 | } |
||||
345 | |||||
346 | /** |
||||
347 | * @param MapperHydratorInterface<E> $hydrator |
||||
348 | * |
||||
349 | * @return $this |
||||
350 | * @final |
||||
351 | */ |
||||
352 | 516 | public function setHydrator(MapperHydratorInterface $hydrator) |
|||
353 | { |
||||
354 | 516 | $this->hydrator = $hydrator; |
|||
355 | 516 | $this->hydrator->setPrimeInstantiator($this->serviceLocator->instantiator()); |
|||
356 | 516 | $this->hydrator->setPrimeMetadata($this->metadata); |
|||
357 | |||||
358 | 516 | return $this; |
|||
359 | } |
||||
360 | |||||
361 | /** |
||||
362 | * Set ID value en entity |
||||
363 | * Only sequenceable attribute is set (the first one) |
||||
364 | * |
||||
365 | * @param E $entity |
||||
0 ignored issues
–
show
The type
Bdf\Prime\Mapper\E 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
366 | * @param mixed $value |
||||
367 | * |
||||
368 | * @return void |
||||
369 | * @final |
||||
370 | */ |
||||
371 | 4 | public function setId($entity, $value): void |
|||
372 | { |
||||
373 | 4 | $this->hydrateOne($entity, $this->metadata->primary['attributes'][0], $value); |
|||
374 | } |
||||
375 | |||||
376 | /** |
||||
377 | * Get ID value of an entity |
||||
378 | * Only sequenceable attribute is get (the first one) |
||||
379 | * |
||||
380 | * @param E $entity |
||||
381 | * |
||||
382 | * @return mixed |
||||
383 | * @final |
||||
384 | */ |
||||
385 | 108 | public function getId($entity) |
|||
386 | { |
||||
387 | 108 | return $this->extractOne($entity, $this->metadata->primary['attributes'][0]); |
|||
388 | } |
||||
389 | |||||
390 | /** |
||||
391 | * Get attribute value of an entity |
||||
392 | * |
||||
393 | * @param E $entity |
||||
394 | * @param string $attribute |
||||
395 | * |
||||
396 | * @return mixed |
||||
397 | * @final |
||||
398 | */ |
||||
399 | 451 | public function extractOne($entity, string $attribute) |
|||
400 | { |
||||
401 | 451 | return $this->hydrator->extractOne($entity, $attribute); |
|||
402 | } |
||||
403 | |||||
404 | /** |
||||
405 | * Hydrate on property value of an entity |
||||
406 | * |
||||
407 | * @param E $entity |
||||
408 | * @param string $attribute |
||||
409 | * @param mixed $value |
||||
410 | * |
||||
411 | * @return void |
||||
412 | * @final |
||||
413 | */ |
||||
414 | 374 | public function hydrateOne($entity, string $attribute, $value): void |
|||
415 | { |
||||
416 | 374 | $this->hydrator->hydrateOne($entity, $attribute, $value); |
|||
417 | } |
||||
418 | |||||
419 | /** |
||||
420 | * Get primary key criteria |
||||
421 | * |
||||
422 | * @param E $entity |
||||
423 | * |
||||
424 | * @return array |
||||
425 | * @final |
||||
426 | */ |
||||
427 | 172 | public function primaryCriteria($entity): array |
|||
428 | { |
||||
429 | 172 | return $this->hydrator->flatExtract($entity, array_flip($this->metadata->primary['attributes'])); |
|||
430 | } |
||||
431 | |||||
432 | /** |
||||
433 | * Instanciate the related class entity |
||||
434 | * |
||||
435 | * @return E |
||||
436 | * @final |
||||
437 | */ |
||||
438 | 529 | public function instantiate() |
|||
439 | { |
||||
440 | /** @var E */ |
||||
441 | 529 | return $this->serviceLocator->instantiator() |
|||
442 | 529 | ->instantiate($this->metadata->entityClass, $this->metadata->instantiatorHint); |
|||
443 | } |
||||
444 | |||||
445 | /** |
||||
446 | * User api to instantiate related entity |
||||
447 | * |
||||
448 | * @param array $data |
||||
449 | * |
||||
450 | * @return E |
||||
451 | * @final |
||||
452 | */ |
||||
453 | 97 | public function entity(array $data) |
|||
454 | { |
||||
455 | 97 | $entity = $this->instantiate(); |
|||
456 | |||||
457 | // Allows custom import from developpers. |
||||
458 | 97 | if ($entity instanceof ImportableInterface) { |
|||
459 | 96 | $entity->import($data); |
|||
460 | } else { |
||||
461 | 1 | $this->serviceLocator->hydrator($this->metadata->entityClass) |
|||
462 | 1 | ->hydrate($entity, $data); |
|||
463 | } |
||||
464 | |||||
465 | 97 | return $entity; |
|||
466 | } |
||||
467 | |||||
468 | /** |
||||
469 | * Transform entity to db one dimension array |
||||
470 | * |
||||
471 | * @param E $entity Entity object |
||||
472 | * @param array|null $attributes Attribute should be flipped as ['key' => true] |
||||
473 | * |
||||
474 | * @return array |
||||
475 | * @final |
||||
476 | */ |
||||
477 | 659 | public function prepareToRepository($entity, array $attributes = null): array |
|||
478 | { |
||||
479 | 659 | return $this->hydrator->flatExtract($entity, $attributes); |
|||
480 | } |
||||
481 | |||||
482 | /** |
||||
483 | * Get valid array for entity |
||||
484 | * |
||||
485 | * Inject one dimension array (db field) into entity |
||||
486 | * Map attribute and cast value |
||||
487 | * |
||||
488 | * $optimisation est un tableau donné par le query builder dans le but |
||||
489 | * d'optimiser le chargement des relations et des tableaux associatifs. Il contient les entités regroupés par |
||||
490 | * la valeur du champs demandé |
||||
491 | * |
||||
492 | * @param array $data Db data |
||||
493 | * @param PlatformInterface $platform |
||||
494 | * |
||||
495 | * @return E |
||||
496 | */ |
||||
497 | 472 | public function prepareFromRepository(array $data, PlatformInterface $platform) |
|||
498 | { |
||||
499 | 472 | $entity = $this->instantiate(); |
|||
500 | |||||
501 | 472 | $this->hydrator->flatHydrate($entity, $data, $platform->types()); |
|||
502 | |||||
503 | 472 | return $entity; |
|||
504 | } |
||||
505 | |||||
506 | /** |
||||
507 | * Get the repository |
||||
508 | * |
||||
509 | * @return RepositoryInterface<E> |
||||
510 | * @final |
||||
511 | */ |
||||
512 | 411 | public function repository(): RepositoryInterface |
|||
513 | { |
||||
514 | 411 | $className = $this->repositoryClass; |
|||
515 | |||||
516 | 411 | return new $className($this, $this->serviceLocator, $this->resultCache === false ? null : $this->resultCache); |
|||
517 | } |
||||
518 | |||||
519 | /** |
||||
520 | * Get the mapper info |
||||
521 | * |
||||
522 | * @return MapperInfo |
||||
523 | * @throws PrimeException |
||||
524 | * @final |
||||
525 | */ |
||||
526 | 73 | public function info(): MapperInfo |
|||
527 | { |
||||
528 | 73 | $platform = $this->serviceLocator->connection($this->metadata()->connection)->platform(); |
|||
529 | |||||
530 | 73 | return new MapperInfo($this, $platform->types()); |
|||
531 | } |
||||
532 | |||||
533 | /** |
||||
534 | * Get defined relation |
||||
535 | * |
||||
536 | * Build object relation defined by user |
||||
537 | * |
||||
538 | * @param string $relationName |
||||
539 | * |
||||
540 | * @return array Metadata for relation definition |
||||
541 | * |
||||
542 | * @throws \RuntimeException If relation or type does not exist |
||||
543 | */ |
||||
544 | 266 | public function relation(string $relationName): array |
|||
545 | { |
||||
546 | 266 | $relations = $this->relations(); |
|||
547 | |||||
548 | 266 | if (!isset($relations[$relationName])) { |
|||
549 | 7 | throw new RelationNotFoundException('Relation "' . $relationName . '" is not set in ' . $this->metadata->entityName); |
|||
550 | } |
||||
551 | |||||
552 | 261 | return $relations[$relationName]; |
|||
0 ignored issues
–
show
|
|||||
553 | } |
||||
554 | |||||
555 | // |
||||
556 | //------------ API configuration du mapping |
||||
557 | // |
||||
558 | |||||
559 | /** |
||||
560 | * Definition du schema |
||||
561 | * |
||||
562 | * Definition |
||||
563 | * - connection : The connection name declare in connection manager (mandatory). |
||||
564 | * - database : The database name. |
||||
565 | * - table : The table name (mandatory). |
||||
566 | * - tableOptions : The table options (ex: engine => myisam). |
||||
567 | * |
||||
568 | * <code> |
||||
569 | * return [ |
||||
570 | * 'connection' => (string), |
||||
571 | * 'database' => (string), |
||||
572 | * 'table' => (string), |
||||
573 | * 'tableOptions' => (array), |
||||
574 | * ]; |
||||
575 | * </code> |
||||
576 | * |
||||
577 | * @return array |
||||
578 | */ |
||||
579 | abstract public function schema(): array; |
||||
580 | |||||
581 | /** |
||||
582 | * Gets repository fields builder |
||||
583 | * |
||||
584 | * @return iterable<string, FieldDefinition> |
||||
585 | * @final |
||||
586 | * |
||||
587 | * @todo should be final |
||||
588 | */ |
||||
589 | 511 | public function fields(): iterable |
|||
590 | { |
||||
591 | 511 | $builder = new FieldBuilder(); |
|||
592 | 511 | $this->buildFields($builder); |
|||
593 | |||||
594 | 511 | foreach ($this->behaviors() as $behavior) { |
|||
595 | 4 | $behavior->changeSchema($builder); |
|||
596 | } |
||||
597 | |||||
598 | 511 | return $builder; |
|||
599 | } |
||||
600 | |||||
601 | /** |
||||
602 | * Build fields from this mapper. |
||||
603 | * |
||||
604 | * To overwrite. |
||||
605 | * |
||||
606 | * @param FieldBuilder $builder |
||||
607 | */ |
||||
608 | public function buildFields(FieldBuilder $builder): void |
||||
0 ignored issues
–
show
The parameter
$builder is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
609 | { |
||||
610 | throw new LogicException('Fields must be defined in mapper '.__CLASS__); |
||||
611 | } |
||||
612 | |||||
613 | /** |
||||
614 | * Sequence definition. |
||||
615 | * |
||||
616 | * The metadata will build the sequence info using this method if the primary key is defined as sequence (Metadata::PK_SEQUENCE). |
||||
617 | * Definition: |
||||
618 | * - connection : The connection name declare in connection manager. The table connection will be used by default. |
||||
619 | * - table : The table sequence name. |
||||
620 | * The table name with suffix '_seq' will be used by default. |
||||
621 | * - column : The sequence column name. Default 'id'. |
||||
622 | * - tableOptions : The sequence table options (ex: engine => myisam). |
||||
623 | * |
||||
624 | * <code> |
||||
625 | * return [ |
||||
626 | * 'connection' => (string), |
||||
627 | * 'table' => (string), |
||||
628 | * 'column' => (string), |
||||
629 | * 'tableOptions' => (array), |
||||
630 | * ]; |
||||
631 | * </code> |
||||
632 | * |
||||
633 | * @return array{ |
||||
0 ignored issues
–
show
|
|||||
634 | * connection?: string|null, |
||||
635 | * table?: string|null, |
||||
636 | * column?: string|null, |
||||
637 | * tableOptions?: array, |
||||
638 | * } |
||||
639 | */ |
||||
640 | 506 | public function sequence(): array |
|||
641 | { |
||||
642 | 506 | return [ |
|||
643 | 506 | 'connection' => null, |
|||
644 | 506 | 'table' => null, |
|||
645 | 506 | 'column' => null, |
|||
646 | 506 | 'tableOptions' => [], |
|||
647 | 506 | ]; |
|||
648 | } |
||||
649 | |||||
650 | /** |
||||
651 | * Gets custom filters |
||||
652 | * To overwrite |
||||
653 | * |
||||
654 | * <code> |
||||
655 | * return [ |
||||
656 | * 'customFilterName' => function(<Bdf\Prime\Query\QueryInterface> $query, <mixed> $value) { |
||||
657 | * return <void> |
||||
658 | * }, |
||||
659 | * ]; |
||||
660 | * </code> |
||||
661 | * |
||||
662 | * @return array<string, callable> |
||||
663 | */ |
||||
664 | 459 | public function filters(): array |
|||
665 | { |
||||
666 | 459 | return []; |
|||
667 | } |
||||
668 | |||||
669 | /** |
||||
670 | * Array of index |
||||
671 | * |
||||
672 | * <code> |
||||
673 | * return [ |
||||
674 | * ['attribute1', 'attribute2'] |
||||
675 | * ]; |
||||
676 | * </code> |
||||
677 | * |
||||
678 | * @return array |
||||
679 | * @final |
||||
680 | * |
||||
681 | * @todo Make final |
||||
682 | */ |
||||
683 | 509 | public function indexes(): array |
|||
684 | { |
||||
685 | 509 | $builder = new IndexBuilder(); |
|||
686 | |||||
687 | 509 | $this->buildIndexes($builder); |
|||
688 | |||||
689 | 509 | return $builder->build(); |
|||
690 | } |
||||
691 | |||||
692 | /** |
||||
693 | * Build the table indexes |
||||
694 | * Note: Indexes can be added on undeclared fields |
||||
695 | * |
||||
696 | * <code> |
||||
697 | * public function buildIndexes(IndexBuilder $builder) |
||||
698 | * { |
||||
699 | * $builder |
||||
700 | * ->add()->on('name')->unique() |
||||
701 | * ->add()->on('reference', ['length' => 12]) |
||||
702 | * ->add()->on(['type', 'date']) |
||||
703 | * } |
||||
704 | * </code> |
||||
705 | * |
||||
706 | * @param IndexBuilder $builder |
||||
707 | */ |
||||
708 | 499 | public function buildIndexes(IndexBuilder $builder): void |
|||
0 ignored issues
–
show
The parameter
$builder is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
709 | { |
||||
710 | 499 | } |
|||
711 | |||||
712 | /** |
||||
713 | * Repository extension |
||||
714 | * returns additional methods in repository |
||||
715 | * |
||||
716 | * <code> |
||||
717 | * return [ |
||||
718 | * 'customMethod' => function($query, $test) { |
||||
719 | * |
||||
720 | * }, |
||||
721 | * ]; |
||||
722 | * |
||||
723 | * $repository->customMethod('test'); |
||||
724 | * </code> |
||||
725 | * |
||||
726 | * @return array<string, callable> |
||||
727 | */ |
||||
728 | public function scopes(): array |
||||
729 | { |
||||
730 | throw new LogicException('No scopes have been defined in "' . get_class($this) . '"'); |
||||
731 | } |
||||
732 | |||||
733 | /** |
||||
734 | * Get custom queries for repository |
||||
735 | * A custom query works mostly like scopes, but with some differences : |
||||
736 | * - Cannot be called using a query (i.e. $query->where(...)->myScope()) |
||||
737 | * - The function has responsability of creating the query instance |
||||
738 | * - The first argument is the repository |
||||
739 | * |
||||
740 | * <code> |
||||
741 | * return [ |
||||
742 | * 'findByCustom' => function (EntityRepository $repository, $search) { |
||||
743 | * return $repository->make(MyCustomQuery::class)->where('first', $search)->first(); |
||||
744 | * } |
||||
745 | * ]; |
||||
746 | * </code> |
||||
747 | * |
||||
748 | * @return array<string, callable(\Bdf\Prime\Repository\RepositoryInterface<E>,mixed...):mixed> |
||||
0 ignored issues
–
show
|
|||||
749 | */ |
||||
750 | 394 | public function queries(): array |
|||
751 | { |
||||
752 | 394 | return []; |
|||
753 | } |
||||
754 | |||||
755 | /** |
||||
756 | * Register event on notifier |
||||
757 | * |
||||
758 | * @param RepositoryEventsSubscriberInterface<E> $notifier |
||||
759 | * @final |
||||
760 | */ |
||||
761 | 411 | public function events(RepositoryEventsSubscriberInterface $notifier): void |
|||
762 | { |
||||
763 | 411 | $this->customEvents($notifier); |
|||
764 | |||||
765 | 411 | foreach ($this->behaviors() as $behavior) { |
|||
766 | 4 | $behavior->subscribe($notifier); |
|||
767 | } |
||||
768 | } |
||||
769 | |||||
770 | /** |
||||
771 | * Register custom event on notifier |
||||
772 | * |
||||
773 | * To overwrite. |
||||
774 | * |
||||
775 | * @param RepositoryEventsSubscriberInterface<E> $notifier |
||||
776 | */ |
||||
777 | 379 | public function customEvents(RepositoryEventsSubscriberInterface $notifier): void |
|||
778 | { |
||||
779 | // To overwrite |
||||
780 | 379 | } |
|||
781 | |||||
782 | /** |
||||
783 | * Get all behaviors |
||||
784 | * |
||||
785 | * @return BehaviorInterface<E>[] |
||||
786 | */ |
||||
787 | 513 | final public function behaviors(): array |
|||
788 | { |
||||
789 | 513 | if ($this->behaviors === null) { |
|||
790 | 513 | $this->behaviors = $this->getDefinedBehaviors(); |
|||
0 ignored issues
–
show
It seems like
$this->getDefinedBehaviors() of type array is incompatible with the declared type Bdf\Prime\Behaviors\BehaviorInterface of property $behaviors .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
791 | } |
||||
792 | |||||
793 | 513 | return $this->behaviors; |
|||
0 ignored issues
–
show
|
|||||
794 | } |
||||
795 | |||||
796 | /** |
||||
797 | * Custom definition of behaviors |
||||
798 | * |
||||
799 | * To overwrite. |
||||
800 | * |
||||
801 | * @return BehaviorInterface<E>[] |
||||
802 | */ |
||||
803 | 510 | public function getDefinedBehaviors(): array |
|||
804 | { |
||||
805 | 510 | return []; |
|||
0 ignored issues
–
show
|
|||||
806 | } |
||||
807 | |||||
808 | /** |
||||
809 | * Get all relations |
||||
810 | * |
||||
811 | * @return array<string, RelationDefinition> |
||||
812 | * @final |
||||
813 | * |
||||
814 | * @todo should be final |
||||
815 | */ |
||||
816 | 648 | public function relations(): array |
|||
817 | { |
||||
818 | 648 | if ($this->relationBuilder === null) { |
|||
819 | 512 | $this->relationBuilder = new RelationBuilder(); |
|||
820 | 512 | $this->buildRelations($this->relationBuilder); |
|||
821 | } |
||||
822 | |||||
823 | 648 | return $this->relationBuilder->relations(); |
|||
824 | } |
||||
825 | |||||
826 | /** |
||||
827 | * Build relations from this mapper. |
||||
828 | * |
||||
829 | * To overwrite. |
||||
830 | * |
||||
831 | * @param RelationBuilder $builder |
||||
832 | */ |
||||
833 | 207 | public function buildRelations(RelationBuilder $builder): void |
|||
0 ignored issues
–
show
The parameter
$builder is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
834 | { |
||||
835 | // to overwrite |
||||
836 | 207 | } |
|||
837 | |||||
838 | /** |
||||
839 | * Get all constraints |
||||
840 | * |
||||
841 | * @return array |
||||
842 | */ |
||||
843 | 513 | final public function constraints(): array |
|||
844 | { |
||||
845 | 513 | $constraints = $this->customConstraints(); |
|||
846 | |||||
847 | 513 | foreach ($this->behaviors() as $behavior) { |
|||
848 | 4 | $constraints += $behavior->constraints(); |
|||
849 | } |
||||
850 | |||||
851 | 513 | return $constraints; |
|||
852 | } |
||||
853 | |||||
854 | /** |
||||
855 | * Register custom event on notifier |
||||
856 | * |
||||
857 | * To overwrite. |
||||
858 | * |
||||
859 | * <code> |
||||
860 | * return [ |
||||
861 | * 'attribute' => 'value' |
||||
862 | * ] |
||||
863 | * </code> |
||||
864 | * |
||||
865 | * @return array |
||||
866 | */ |
||||
867 | 491 | public function customConstraints(): array |
|||
868 | { |
||||
869 | 491 | return []; |
|||
870 | } |
||||
871 | |||||
872 | /** |
||||
873 | * Clear dependencies for break cyclic references |
||||
874 | * |
||||
875 | * @internal |
||||
876 | */ |
||||
877 | 1 | public function destroy(): void |
|||
878 | { |
||||
879 | 1 | $this->serviceLocator = null; |
|||
880 | 1 | $this->generator = null; |
|||
881 | 1 | $this->hydrator = null; |
|||
882 | 1 | $this->metadata = null; |
|||
883 | } |
||||
884 | } |
||||
885 |