Completed
Push — master ( 7a6bdd...324ce1 )
by Sébastien
09:34
created

Mapper::extractOne()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
c 1
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Bdf\Prime\Mapper;
4
5
use Bdf\Prime\Behaviors\BehaviorInterface;
0 ignored issues
show
introduced by
Unused use statement
Loading history...
6
use Bdf\Prime\Cache\CacheInterface;
7
use Bdf\Prime\Entity\ImportableInterface;
8
use Bdf\Prime\Entity\Hydrator\MapperHydrator;
9
use Bdf\Prime\Entity\Hydrator\MapperHydratorInterface;
10
use Bdf\Prime\Mapper\Builder\IndexBuilder;
11
use Bdf\Prime\Mapper\Info\MapperInfo;
12
use Bdf\Prime\Platform\PlatformInterface;
13
use Bdf\Prime\Relations\Exceptions\RelationNotFoundException;
14
use Bdf\Prime\Repository\EntityRepository;
15
use Bdf\Prime\Repository\RepositoryInterface;
0 ignored issues
show
introduced by
Unused use statement
Loading history...
16
use Bdf\Prime\ServiceLocator;
17
use Bdf\Prime\IdGenerators\GeneratorInterface;
18
use Bdf\Prime\IdGenerators\AutoIncrementGenerator;
19
use Bdf\Prime\IdGenerators\NullGenerator;
20
use Bdf\Prime\IdGenerators\TableGenerator;
21
use Bdf\Prime\Mapper\Builder\FieldBuilder;
22
use Bdf\Prime\Relations\Builder\RelationBuilder;
23
use Bdf\Serializer\PropertyAccessor\ReflectionAccessor;
24
use LogicException;
25
26
/**
27
 * Mapper
28
 * 
29
 * Contient les méta données de la table.
30
 * 
31
 * @todo Convertir la donnée avec le type approprié sur les methodes setId, hydrateOne
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
Coding Style Documentation introduced by
@todo tag is not allowed in class comment
Loading history...
32
 *
33
 * @package Bdf\Prime\Mapper
0 ignored issues
show
Coding Style Documentation introduced by
@package tag is not allowed in class comment
Loading history...
34
 */
35
abstract class Mapper
36
{
37
    /**
38
     * Enable/Disable query result cache on repository
39
     * If null global cache will be set.
40
     * Set it to false to deactivate cache on this repository
41
     * Set the cache instance in configure method
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
42
     * 
43
     * @var false|CacheInterface
44
     */
45
    protected $resultCache;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
46
    
47
    /**
48
     * @var Metadata
49
     */
50
    private $metadata;
51
    
52
    /**
53
     * Id generator
54
     * 
55
     * Could be defined as string (generator class name). It would be instantiated
56
     * by mapper on generator() method
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
57
     * 
58
     * @var \Bdf\Prime\IdGenerators\GeneratorInterface
59
     */
60
    protected $generator;
61
    
62
    /**
63
     * @var string
64
     */
65
    private $repositoryClass = EntityRepository::class;
66
    
67
    /**
68
     * The real name of entity class. Could be an none existing class
69
     * 
70
     * @var string
71
     */
72
    private $entityClass;
73
74
    /**
75
     * The property accessor class name to use by default
76
     *
77
     * @var string
78
     */
79
    private $propertyAccessorClass = ReflectionAccessor::class;
80
81
    /**
82
     * Set repository read only.
83
     * 
84
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
85
     */
86
    private $readOnly = false;
87
    
88
    /**
89
     * Use schema resolver
90
     * Disable if schema has not to be manage by this app
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
91
     * 
92
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
93
     */
94
    private $useSchemaManager = true;
95
96
    /**
97
     * Use quote identifier
98
     * Allows query builder to use quote identifier
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
99
     *
100
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
101
     */
102
    private $useQuoteIdentifier = false;
103
104
    /**
105
     * The relation builder
106
     *
107
     * @var RelationBuilder
108
     */
109
    private $relationBuilder;
110
111
    /**
112
     * The collection of behaviors
113
     *
114
     * @var BehaviorInterface[]
115
     */
116
    private $behaviors;
117
118
    /**
119
     * The service locator
120
     *
121
     * @var ServiceLocator
122
     */
123
    protected $serviceLocator;
124
125
    /**
126
     * @var MapperHydratorInterface
127
     */
128
    protected $hydrator;
129
130
131
    /**
132
     * Mapper constructor
133
     *
134
     * @param ServiceLocator $serviceLocator
135
     * @param string $entityClass
136
     * @param Metadata|null $metadata
137
     * @param MapperHydratorInterface|null $hydrator
138
     * @param CacheInterface|null $resultCache
139
     */
140 220
    public function __construct(ServiceLocator $serviceLocator, $entityClass, $metadata = null, MapperHydratorInterface $hydrator = null, CacheInterface $resultCache = null)
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before function; 2 found
Loading history...
141
    {
142 220
        $this->entityClass = $entityClass;
143 220
        $this->metadata = $metadata ?: new Metadata();
0 ignored issues
show
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
144 220
        $this->serviceLocator = $serviceLocator;
145 220
        $this->resultCache = $resultCache;
146
147 220
        $this->configure();
148
        
149 220
        $this->metadata->build($this);
150
151 220
        $this->setHydrator($hydrator ?: new MapperHydrator());
0 ignored issues
show
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
152 220
    }
153
    
154
    /**
155
     * Custom configuration
156
     */
157 218
    public function configure()
158
    {
159
        // to overwrite
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
160 218
    }
161
162
    /**
163
     * Get entity class
164
     * 
165
     * @return string
166
     */
167 217
    public function getEntityClass()
168
    {
169 217
        return $this->entityClass;
170
    }
171
    
172
    /**
173
     * Get metadata
174
     * 
175
     * @return Metadata
176
     */
177 910
    public function metadata()
178
    {
179 910
        return $this->metadata;
180
    }
181
    
182
    /**
183
     * Set property accessor class name
184
     * 
185
     * @param string $className
186
     */
187 1
    public function setPropertyAccessorClass($className)
188
    {
189 1
        $this->propertyAccessorClass = $className;
190 1
    }
191
    
192
    /**
193
     * Get property accessor class name
194
     * 
195
     * @return string
196
     */
197 217
    public function getPropertyAccessorClass()
198
    {
199 217
        return $this->propertyAccessorClass;
200
    }
201
202
    /**
203
     * Set repository class name
204
     *
205
     * @param string $className
206
     */
207 1
    public function setRepositoryClass($className)
208
    {
209 1
        $this->repositoryClass = $className;
210 1
    }
211
212
    /**
213
     * Get repository class name
214
     *
215
     * @return string
216
     */
217 2
    public function getRepositoryClass()
218
    {
219 2
        return $this->repositoryClass;
220
    }
221
222
    /**
223
     * Set the repository read only
224
     * 
225
     * @param bool $flag
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
226
     */
227 327
    public function setReadOnly($flag)
228
    {
229 327
        $this->readOnly = (bool)$flag;
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
230 327
    }
231
    
232
    /**
233
     * Get repository read only state
234
     * 
235
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
236
     */
237 428
    public function isReadOnly()
238
    {
239 428
        return $this->readOnly;
240
    }
241
    
242
    /**
243
     * Disable schema manager on repository
244
     */
245 1
    public function disableSchemaManager()
246
    {
247 1
        $this->useSchemaManager = false;
248 1
    }
249
    
250
    /**
251
     * Does repository have a schema manager
252
     * 
253
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
254
     */
255 591
    public function hasSchemaManager()
256
    {
257 591
        return $this->useSchemaManager;
258
    }
259
260
    /**
261
     * Set the query builder quote identifier
262
     *
263
     * @param bool $flag
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
264
     */
265 6
    public function setQuoteIdentifier($flag)
266
    {
267 6
        $this->useQuoteIdentifier = (bool)$flag;
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
268 6
    }
269
270
    /**
271
     * Does query builder use quote identifier
272
     *
273
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
274
     */
275 217
    public function hasQuoteIdentifier()
276
    {
277 217
        return $this->useQuoteIdentifier;
278
    }
279
280
    /**
281
     * Set generator ID
282
     * 
283
     * @param string|GeneratorInterface $generator
284
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
285 3
    public function setGenerator($generator)
286
    {
287 3
        if (!is_string($generator) && !$generator instanceof GeneratorInterface) {
0 ignored issues
show
introduced by
$generator is always a sub-type of Bdf\Prime\IdGenerators\GeneratorInterface.
Loading history...
288 1
            throw new LogicException('Trying to set an invalid generator in "' . get_class($this) . '"');
289
        }
290
        
291 2
        $this->generator = $generator;
0 ignored issues
show
Documentation Bug introduced by
It seems like $generator can also be of type string. However, the property $generator is declared as type Bdf\Prime\IdGenerators\GeneratorInterface. 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 $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

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;
}
Loading history...
292 2
    }
293
    
294
    /**
295
     * Get generator ID
296
     * 
297
     * @return object
298
     */
299 401
    public function generator()
300
    {
301 401
        if ($this->generator === null) {
302 70
            if ($this->metadata->isAutoIncrementPrimaryKey()) {
303 28
                $this->generator = new AutoIncrementGenerator($this);
304 44
            } elseif ($this->metadata->isSequencePrimaryKey()) {
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
305 12
                $this->generator = new TableGenerator($this);
306
            } else {
307 70
                $this->generator = new NullGenerator();
308
            }
309 362
        } elseif (is_string($this->generator)) {
0 ignored issues
show
introduced by
The condition is_string($this->generator) is always false.
Loading history...
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
310 1
            $className = $this->generator;
311 1
            $this->generator = new $className($this);
312
        }
313
314 401
        return $this->generator;
315
    }
316
317
    /**
318
     * @return MapperHydratorInterface
319
     */
320 4
    public function hydrator()
321
    {
322 4
        return $this->hydrator;
323
    }
324
325
    /**
326
     * @param MapperHydratorInterface $hydrator
327
     *
328
     * @return $this
329
     */
330 220
    public function setHydrator(MapperHydratorInterface $hydrator)
331
    {
332 220
        $this->hydrator = $hydrator;
333 220
        $this->hydrator->setPrimeInstantiator($this->serviceLocator->instantiator());
334 220
        $this->hydrator->setPrimeMetadata($this->metadata);
335
336 220
        return $this;
337
    }
338
339
    /**
340
     * Set ID value en entity
341
     * Only sequenceable attribute is set (the first one)
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
342
     *
343
     * @param object $entity
344
     * @param mixed $value
345
     */
346 4
    public function setId($entity, $value)
347
    {
348 4
        $this->hydrateOne($entity, $this->metadata->primary['attributes'][0], $value);
349 4
    }
350
351
    /**
352
     * Get ID value of an entity
353
     * Only sequenceable attribute is get (the first one)
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
354
     * 
355
     * @param object $entity
356
     *
357
     * @return mixed
358
     */
359 70
    public function getId($entity)
360
    {
361 70
        return $this->extractOne($entity, $this->metadata->primary['attributes'][0]);
362
    }
363
    
364
    /**
365
     * Get attribute value of an entity
366
     * 
367
     * @param object $entity
368
     * @param string $attribute
369
     *
370
     * @return mixed
371
     */
372 250
    public function extractOne($entity, $attribute)
373
    {
374 250
        return $this->hydrator->extractOne($entity, $attribute);
375
    }
376
    
377
    /**
378
     * Hydrate on property value of an entity
379
     * 
380
     * @param object $entity
381
     * @param string $attribute
382
     * @param mixed  $value
383
     */
384 209
    public function hydrateOne($entity, $attribute, $value)
385
    {
386 209
        $this->hydrator->hydrateOne($entity, $attribute, $value);
387 209
    }
388
    
389
    /**
390
     * Get primary key criteria
391
     * 
392
     * @param object $entity
393
     *
394
     * @return array
395
     */
396 122
    public function primaryCriteria($entity)
397
    {
398 122
        return $this->hydrator->flatExtract($entity, array_flip($this->metadata->primary['attributes']));
399
    }
400
401
    /**
402
     * Instanciate the related class entity
403
     *
404
     * @return object
405
     */
406 315
    public function instantiate()
407
    {
408 315
        return $this->serviceLocator->instantiator()
409 315
            ->instantiate($this->metadata->entityClass, $this->metadata->instantiatorHint);
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
introduced by
Object operator not indented correctly; expected 10 spaces but found 12
Loading history...
410
    }
411
412
    /**
413
     * User api to instantiate related entity
414
     * 
415
     * @param array $data
416
     *
417
     * @return object
418
     */
419 70
    public function entity(array $data)
420
    {
421 70
        $entity = $this->instantiate();
422
423
        // Allows custom import from developpers.
424 70
        if ($entity instanceof ImportableInterface) {
425 69
            $entity->import($data);
426
        } else {
427 1
            $this->serviceLocator->hydrator($this->metadata->entityClass)
428 1
                ->hydrate($entity, $data);
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
introduced by
Object operator not indented correctly; expected 14 spaces but found 16
Loading history...
429
        }
430
431 70
        return $entity;
432
    }
433
434
    /**
435
     * Transform entity to db one dimension array
436
     * 
437
     * @param object $entity      Entity object
438
     * @param array  $attributes  Attribute should be flipped as ['key' => true]
439
     *
440
     * @return array
441
     *
442
     * @throws \Exception
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
443
     */
444 412
    public function prepareToRepository($entity, array $attributes = null)
445
    {
446 412
        return $this->hydrator->flatExtract($entity, $attributes);
447
    }
448
    
449
    /**
450
     * Get valid array for entity
451
     * 
452
     * Inject one dimension array (db field) into entity
453
     * Map attribute and cast value
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
454
     * 
455
     * $optimisation est un tableau donné par le query builder dans le but
456
     * d'optimiser le chargement des relations et des tableaux associatifs. Il contient les entités regroupés par
457
     * la valeur du champs demandé
458
     * 
459
     * @param array             $data  Db data
460
     * @param PlatformInterface $platform
461
     *
462
     * @return object
463
     */
464 274
    public function prepareFromRepository(array $data, PlatformInterface $platform)
465
    {
466 274
        $entity = $this->instantiate();
467
468 274
        $this->hydrator->flatHydrate($entity, $data, $platform->types());
469
470 274
        return $entity;
471
    }
472
    
473
    /**
474
     * Get the repository
475
     * 
476
     * @return RepositoryInterface
477
     */
478 116
    public function repository()
479
    {
480 116
        $className = $this->repositoryClass;
481
482 116
        return new $className($this, $this->serviceLocator, $this->resultCache === false ? null : $this->resultCache);
0 ignored issues
show
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
483
    }
484
485
    /**
486
     * Get the mapper info
487
     *
488
     * @return MapperInfo
489
     */
490 57
    public function info()
491
    {
492 57
        $platform = $this->serviceLocator->connection($this->metadata()->connection)->platform();
493
494 57
        return new MapperInfo($this, $platform->types());
495
    }
496
497
    /**
498
     * Get defined relation
499
     * 
500
     * Build object relation defined by user
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
501
     * 
502
     * @param string $relationName
503
     *
504
     * @return array  Metadata for relation definition
505
     *
506
     * @throws \RuntimeException  If relation or type does not exist
0 ignored issues
show
introduced by
@throws comment must be on the next line
Loading history...
introduced by
@throws tag comment must end with a full stop
Loading history...
507
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag for "RelationNotFoundException" exception
Loading history...
508 48
    public function relation($relationName)
509
    {
510 48
        $relations = $this->relations();
511
        
512 48
        if (!isset($relations[$relationName])) {
513 5
            throw new RelationNotFoundException('Relation "' . $relationName . '" is not set in ' . $this->metadata->entityName);
514
        }
515
        
516 44
        return $relations[$relationName];
517
    }
518
    
519
    //
520
    //------------ API configuration du mapping
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// ------------ API configuration du mapping" but found "//------------ API configuration du mapping"
Loading history...
521
    //
522
    
523
    /**
524
     * Definition du schema
525
     * 
526
     * Definition
527
     *  - connection         : The connection name declare in connection manager (mandatory).
528
     *  - database           : The database name.
529
     *  - table              : The table name (mandatory).
530
     *  - tableOptions       : The table options (ex: engine => myisam).
531
     * 
532
     * <code>
533
     *  return [
534
     *     'connection'   => (string),
535
     *     'database'     => (string),
536
     *     'table'        => (string),
537
     *     'tableOptions' => (array),
538
     *  ];
539
     * </code>
540
     * 
541
     * @return array|null
542
     */
543
    abstract public function schema();
544
    
545
    /**
546
     * Gets repository fields builder
547
     * 
548
     * @return FieldBuilder
549
     *
550
     * @todo should be final
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
551
     */
552 215
    public function fields()
553
    {
554 215
        $builder = new FieldBuilder();
555 215
        $this->buildFields($builder);
556
557 215
        foreach ($this->behaviors() as $behavior) {
558 4
            $behavior->changeSchema($builder);
559
        }
560
561 215
        return $builder;
562
    }
563
    
564
    /**
565
     * Build fields from this mapper.
566
     * 
567
     * To overwrite.
568
     * 
569
     * @param FieldBuilder $builder
570
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
571
    public function buildFields($builder)
0 ignored issues
show
Unused Code introduced by
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 ignore-unused  annotation

571
    public function buildFields(/** @scrutinizer ignore-unused */ $builder)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The method parameter $builder is never used
Loading history...
introduced by
Type hint "FieldBuilder" missing for $builder
Loading history...
572
    {
573
        throw new LogicException('Fields must be defined in mapper '.__CLASS__);
574
    }
575
    
576
    /**
577
     * Sequence definition.
578
     *
579
     * The metadata will build the sequence info using this method if the primary key is defined as sequence (Metadata::PK_SEQUENCE).
580
     * Definition:
581
     *  - connection         : The connection name declare in connection manager. The table connection will be used by default.
582
     *  - table              : The table sequence name.
583
     *                         The table name with suffix '_seq' will be used by default.
584
     *  - column             : The sequence column name. Default 'id'.
585
     *  - tableOptions       : The sequence table options (ex: engine => myisam).
586
     *
587
     * <code>
588
     *  return [
589
     *     'connection'   => (string),
590
     *     'table'        => (string),
591
     *     'column'       => (string),
592
     *     'tableOptions' => (array),
593
     *  ];
594
     * </code>
595
     * 
596
     * @return array
597
     */
598 212
    public function sequence()
599
    {
600
        return [
601 212
            'connection'   => null,
602
            'table'        => null,
603
            'column'       => null,
604
            'tableOptions' => [],
605
        ];
606
    }
607
    
608
    /**
609
     * Gets custom filters
610
     * To overwrite
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
611
     * 
612
     * <code>
613
     *  return [
614
     *      'customFilterName' => function(<Bdf\Prime\Query\QueryInterface> $query, <mixed> $value) {
615
     *          return <void>
616
     *      },
617
     *  ];
618
     * </code>
619
     * 
620
     * @return array
621
     */
622 223
    public function filters()
623
    {
624 223
        return [];
625
    }
626
    
627
    /**
628
     * Array of index
629
     * 
630
     * <code>
631
     *  return [
632
     *      ['attribute1', 'attribute2']
633
     *  ];
634
     * </code>
635
     * 
636
     * @return array
637
     *
638
     * @todo Make final
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
639
     */
640 213
    public function indexes()
641
    {
642 213
        $builder = new IndexBuilder();
643
644 213
        $this->buildIndexes($builder);
645
646 213
        return $builder->build();
647
    }
648
649
    /**
650
     * Build the table indexes
651
     * Note: Indexes can be added on undeclared fields
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
652
     *
653
     * <code>
654
     * public function buildIndexes(IndexBuilder $builder)
655
     * {
656
     *     $builder
657
     *         ->add()->on('name')->unique()
658
     *         ->add()->on('reference', ['length' => 12])
659
     *         ->add()->on(['type', 'date'])
660
     * }
661
     * </code>
662
     *
663
     * @param IndexBuilder $builder
664
     */
665 203
    public function buildIndexes(IndexBuilder $builder)
0 ignored issues
show
Unused Code introduced by
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 ignore-unused  annotation

665
    public function buildIndexes(/** @scrutinizer ignore-unused */ IndexBuilder $builder)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
666
    {
667
668 203
    }
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
669
    
670
    /**
671
     * Repository extension
672
     * returns additionnals methods in repository
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
673
     * 
674
     * <code>
675
     * return [
676
     *     'customMethod' => function($query, $test) {
677
     *         
678
     *     },
679
     * ];
680
     * 
681
     * $repository->customMethod('test');
682
     * </code>
683
     * @return array
0 ignored issues
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
introduced by
Function return type is not void, but function has no return statement
Loading history...
introduced by
@return doc comment specified, but function has no return statement
Loading history...
684
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
685
    public function scopes()
686
    {
687
        throw new LogicException('No scopes have been defined in "' . get_class($this) . '"');
688
    }
689
690
    /**
691
     * Get custom queries for repository
692
     * A custom query works mostly like scopes, but with some differences :
693
     * - Cannot be called using a query (i.e. $query->where(...)->myScope())
694
     * - The function has responsability of creating the query instance
695
     * - The first argument is the repository
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
696
     *
697
     * <code>
698
     * return [
699
     *     'findByCustom' => function (EntityRepository $repository, $search) {
700
     *         return $repository->make(MyCustomQuery::class)->where('first', $search)->first();
701
     *     }
702
     * ];
703
     * </code>
704
     *
705
     * @return callable[]
706
     */
707 118
    public function queries()
708
    {
709 118
        return [];
710
    }
711
    
712
    /**
713
     * Register event on notifier
714
     * 
715
     * @param \Bdf\Event\EventNotifier $notifier
716
     */
717 116
    public function events($notifier)
0 ignored issues
show
introduced by
Type hint "\Bdf\Event\EventNotifier" missing for $notifier
Loading history...
718
    {
719 116
        $this->customEvents($notifier);
720
721 116
        foreach ($this->behaviors() as $behavior) {
722 4
            $behavior->subscribe($notifier);
723
        }
724 116
    }
725
726
    /**
727
     * Register custom event on notifier
728
     *
729
     * To overwrite.
730
     *
731
     * @param \Bdf\Event\EventNotifier $notifier
732
     */
733 110
    public function customEvents($notifier)
0 ignored issues
show
Unused Code introduced by
The parameter $notifier 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 ignore-unused  annotation

733
    public function customEvents(/** @scrutinizer ignore-unused */ $notifier)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
introduced by
Type hint "\Bdf\Event\EventNotifier" missing for $notifier
Loading history...
734
    {
735
        // To overwrite
736 110
    }
737
738
    /**
739
     * Get all behaviors
740
     *
741
     * @return BehaviorInterface[]
742
     */
743 217
    final public function behaviors()
744
    {
745 217
        if ($this->behaviors === null) {
746 217
            $this->behaviors = $this->getDefinedBehaviors();
747
        }
748
749 217
        return $this->behaviors;
750
    }
751
752
    /**
753
     * Custom definition of behaviors
754
     *
755
     * To overwrite.
756
     *
757
     * @return BehaviorInterface[]
758
     */
759 214
    public function getDefinedBehaviors()
760
    {
761 214
        return [];
762
    }
763
764
    /**
765
     * Get all relations
766
     *
767
     * @return RelationBuilder
768
     *
769
     * @todo should be final
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
770
     */
771 337
    public function relations()
772
    {
773 337
        if ($this->relationBuilder === null) {
774 216
            $this->relationBuilder = new RelationBuilder();
775 216
            $this->buildRelations($this->relationBuilder);
776
        }
777
778 337
        return $this->relationBuilder;
779
    }
780
781
    /**
782
     * Build relations from this mapper.
783
     *
784
     * To overwrite.
785
     *
786
     * @param RelationBuilder $builder
787
     */
788 52
    public function buildRelations($builder)
0 ignored issues
show
Unused Code introduced by
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 ignore-unused  annotation

788
    public function buildRelations(/** @scrutinizer ignore-unused */ $builder)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
introduced by
Type hint "RelationBuilder" missing for $builder
Loading history...
789
    {
790
        // to overwrite
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
791 52
    }
792
793
    /**
794
     * Get all constraints
795
     * 
796
     * @return array
797
     */
798 217
    final public function constraints()
799
    {
800 217
        $constraints = $this->customConstraints();
801
802 217
        foreach ($this->behaviors() as $behavior) {
803 4
            $constraints += $behavior->constraints();
804
        }
805
        
806 217
        return $constraints;
807
    }
808
809
    /**
810
     * Register custom event on notifier
811
     *
812
     * To overwrite.
813
     * 
814
     * <code>
815
     * return [
816
     *     'attribute' => 'value'
817
     * ]
818
     * </code>
819
     * 
820
     * @return array
821
     */
822 197
    public function customConstraints()
823
    {
824 197
        return [];
825
    }
826
827
    /**
828
     * Clear dependencies for break cyclic references
829
     *
830
     * @internal
831
     */
832 1
    public function destroy()
833
    {
834 1
        $this->serviceLocator = null;
835 1
        $this->generator = null;
836 1
        $this->hydrator = null;
837 1
        $this->metadata = null;
838 1
    }
839
}
840