Passed
Pull Request — master (#31)
by Sébastien
12:54 queued 06:01
created

Prime::initialize()   B

Complexity

Conditions 8
Paths 10

Size

Total Lines 46
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 8.3646

Importance

Changes 0
Metric Value
eloc 27
c 0
b 0
f 0
dl 0
loc 46
ccs 23
cts 28
cp 0.8214
rs 8.4444
cc 8
nc 10
nop 0
crap 8.3646
1
<?php
2
3
namespace Bdf\Prime;
4
5
use Bdf\Prime\Connection\Configuration\ConfigurationResolver;
6
use Bdf\Prime\Connection\ConnectionInterface;
7
use Bdf\Prime\Connection\ConnectionRegistry;
8
use Bdf\Prime\Connection\Factory\ChainFactory;
9
use Bdf\Prime\Connection\Factory\ConnectionFactory;
10
use Bdf\Prime\Connection\Factory\MasterSlaveConnectionFactory;
11
use Bdf\Prime\Connection\Factory\ShardingConnectionFactory;
12
use Bdf\Prime\Exception\PrimeException;
13
use Bdf\Prime\Mapper\MapperFactory;
14
use Bdf\Prime\Repository\RepositoryInterface;
15
use Psr\Container\ContainerInterface;
16
use RuntimeException;
17
18
/**
19
 * Prime
20
 * 
21
 * Usefull facade to manipulate repositories
22
 * Allow user to create, drop, truncate repositories
23
 * Allow user to find, insert entities
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
24
 */
25
class Prime
26
{
27
    /**
28
     * @var mixed
29
     */
30
    protected static $config;
31
32
    /**
33
     * @var ServiceLocator
34
     */
35
    protected static $serviceLocator;
36
37
38
    /**
39
     * Configure the locator
40
     * 
41
     * @param array|ContainerInterface|ServiceLocator $config
42
     */
43 95
    public static function configure($config)
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before function; 2 found
Loading history...
44
    {
45 95
        if ($config instanceof ServiceLocator) {
46 1
            static::$config = null;
47 1
            static::$serviceLocator = $config;
48
        } else {
49 94
            static::$config = $config;
50 94
            static::$serviceLocator = null;
51
        }
52 95
    }
53
54
    /**
55
     * Check whether prime is configured
56
     *
57
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
58
     */
59 1336
    public static function isConfigured()
60
    {
61 1336
        return static::$config !== null;
62
    }
63
64
    //
65
    //--------- repository
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// --------- repository" but found "//--------- repository"
Loading history...
66
    //
67
    
68
    /**
69
     * Get a repository
70
     * 
71
     * @param string|object|RepositoryInterface $repository
72
     *
73
     * @return RepositoryInterface
74
     */
75 741
    public static function repository($repository)
76
    {
77 741
        if ($repository instanceof RepositoryInterface) {
78 6
            return $repository;
79
        }
80
81 741
        return static::service()->repository($repository);
82
    }
83
    
84
    /**
85
     * Create repositories
86
     * 
87
     * @param string|array|RepositoryInterface $repositories
88
     * @param boolean                          $force @see EntityRepository::schema
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for parameter type
Loading history...
introduced by
Parameter comment must start with a capital letter
Loading history...
89
     * @throws PrimeException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
90
     */
91 860
    public static function create($repositories, $force = false)
92
    {
93 860
        static::callSchemaResolverMethod('migrate', $repositories, $force);
94 860
    }
95
96
    /**
97
     * Drop repositories
98
     * 
99
     * @param string|array|RepositoryInterface $repositories
100
     * @param boolean                          $force @see EntityRepository::schema
0 ignored issues
show
introduced by
Parameter comment must start with a capital letter
Loading history...
introduced by
Expected "bool" but found "boolean" for parameter type
Loading history...
101
     * @throws PrimeException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
102
     */
103 846
    public static function drop($repositories, $force = false)
104
    {
105 846
        static::callSchemaResolverMethod('drop', $repositories, $force);
106 846
    }
107
108
    /**
109
     * Truncate repositories
110
     * 
111
     * @param string|array|RepositoryInterface $repositories
112
     * @param boolean                          $force @see EntityRepository::schema
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for parameter type
Loading history...
introduced by
Parameter comment must start with a capital letter
Loading history...
113
     * @throws PrimeException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
114
     */
115 1
    public static function truncate($repositories, $force = false)
116
    {
117 1
        static::callSchemaResolverMethod('truncate', $repositories, $force);
118 1
    }
119
120
    /**
121
     * Call schema resolver method
122
     * 
123
     * @param string  $method
124
     * @param mixed   $repositories
125
     * @param boolean $force
0 ignored issues
show
introduced by
Expected "bool" but found "boolean" for parameter type
Loading history...
126
     *
127
     * @throws PrimeException
128
     */
129 872
    protected static function callSchemaResolverMethod($method, $repositories, $force)
130
    {
131 872
        if (!is_array($repositories)) {
132 8
            $repositories = [$repositories];
133
        }
134
        
135 872
        foreach ($repositories as $repository) {
136 623
            static::repository($repository)->schema($force)->$method();
137
        }
138 872
    }
139
    
140
    //
141
    //--------- entities
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// --------- entities" but found "//--------- entities"
Loading history...
142
    //
143
144
    /**
145
     * Push multiple entities in repository
146
     * launch replace method from repository
147
     * 
148
     * User can add
149
     *  * entity object
150
     *  * collection of entity object
151
     *  * an array of entity attributes
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
152
     * 
153
     * <code>
154
     *  Prime::push(new EntityClass());
155
     *  Prime::push([new EntityClass()]);
156
     *  Prime::push($repository, ['id' => '...']);
157
     *  Prime::push('EntityClass', ['id' => '...']);
158
     *  Prime::push('EntityClass', [['id' => '...']]);
159
     * </code>
160
     * 
161
     * @param mixed $repositoryName
162
     * @param mixed $entities
163
     *
164
     * @throws PrimeException
165
     */
166 33
    public static function push($repositoryName, $entities = null)
167
    {
168 33
        static::callRepositoryMethod('replace', $repositoryName, $entities);
169 33
    }
170
171
    /**
172
     * Save multiple entities in repository
173
     * launch save method from repository
174
     * 
175
     * User can add
176
     *  * entity object
177
     *  * collection of entity object
178
     *  * an array of entity attributes
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
179
     * 
180
     * <code>
181
     *  Prime::save(new EntityClass());
182
     *  Prime::save([new EntityClass()]);
183
     *  Prime::save($repository, ['id' => '...']);
184
     *  Prime::save('EntityClass', ['id' => '...']);
185
     *  Prime::save('EntityClass', [['id' => '...']]);
186
     * </code>
187
     * 
188
     * @param mixed $repositoryName
189
     * @param mixed $entities
190
     *
191
     * @throws PrimeException
192
     */
193 3
    public static function save($repositoryName, $entities = null)
194
    {
195 3
        static::callRepositoryMethod('save', $repositoryName, $entities);
196 3
    }
197
198
    /**
199
     * Remove multiple entities in repository
200
     * 
201
     * User can add
202
     *  * entity object
203
     *  * collection of entity object
204
     *  * an array of entity attributes
0 ignored issues
show
introduced by
Doc comment long description must end with a full stop
Loading history...
205
     * 
206
     * <code>
207
     *  Prime::remove(new EntityClass());
208
     *  Prime::remove([new EntityClass()]);
209
     *  Prime::remove($repository, ['id' => '...']);
210
     *  Prime::remove('EntityClass', ['id' => '...']);
211
     *  Prime::remove('EntityClass', [['id' => '...']]);
212
     * </code>
213
     * 
214
     * @param mixed $repositoryName
215
     * @param mixed $entities
216
     *
217
     * @throws PrimeException
218
     */
219 1
    public static function remove($repositoryName, $entities = null)
220
    {
221 1
        static::callRepositoryMethod('delete', $repositoryName, $entities);
222 1
    }
223
    
224
    /**
225
     * Call repository method for entities
226
     *  
227
     * @param string $method
228
     * @param mixed $repositoryName
229
     * @param mixed $entities
230
     *
231
     * @throws PrimeException
232
     */
233 36
    protected static function callRepositoryMethod($method, $repositoryName, $entities)
234
    {
235 36
        if (!is_string($repositoryName) && !$repositoryName instanceof RepositoryInterface) {
236 19
            $entities = $repositoryName;
237 19
            $repositoryName = null;
238
        }
239
        
240 36
        if (!is_array($entities) || !isset($entities[0])) {
241 36
            $entities = [$entities];
242
        }
243
        
244 36
        foreach ($entities as $entity) {
245 36
            $repository = static::repository($repositoryName ?: $entity);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
Coding Style introduced by
The value of a comparison must not be assigned to a variable
Loading history...
246
            
247 36
            if (is_array($entity)) {
248 23
                $entity = $repository->entity($entity);
249
            }
250
            
251 36
            $repository->$method($entity);
252
        }
253 36
    }
254
255
    /**
256
     * Assert that entity exists
257
     * 
258
     * @param object $entity
259
     * @param bool   $compare  Will compare entity with the expected one
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for parameter type
Loading history...
260
     * 
261
     * @return bool
0 ignored issues
show
Coding Style introduced by
Expected "boolean" but found "bool" for function return type
Loading history...
262
     *
263
     * @throws PrimeException
264
     */
265 11
    public static function exists($entity, $compare = true)
266
    {
267 11
        $repository = static::repository($entity);
268
        
269 11
        $expected = $repository->findOne($repository->mapper()->primaryCriteria($entity));
0 ignored issues
show
Bug introduced by
The method findOne() does not exist on Bdf\Prime\Repository\RepositoryInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Bdf\Prime\Repository\RepositoryInterface. ( Ignorable by Annotation )

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

269
        /** @scrutinizer ignore-call */ 
270
        $expected = $repository->findOne($repository->mapper()->primaryCriteria($entity));
Loading history...
270
        
271 11
        if ($expected === null) {
272
            return false;
273
        }
274
        
275 11
        if (!$compare) {
276 4
            return true;
277
        }
278
        
279 8
        return $entity == $expected 
280 8
                ? true
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
281 8
                : serialize($entity) === serialize($expected);
282
    }
283
284
    /**
285
     * Find entity
286
     * 
287
     * <code>
288
     *  Prime::find(new EntityClass());
289
     *  Prime::find('EntityClass', ['id' => '...']);
290
     *  Prime::find($repository, ['id' => '...']);
291
     * </code>
292
     * 
293
     * @param string|RepositoryInterface  $repositoryName     Repo name or Entity instance
294
     * @param array|object                $criteria           Array of criteria. Optionnal if repository name is an object
295
     * 
296
     * @return object|array
297
     *
298
     * @throws PrimeException
299
     */
300 1
    public static function find($repositoryName, $criteria = null)
301
    {
302 1
        $repository = static::repository($repositoryName);
303
        
304
        // if $repositoryName is an entity
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
305 1
        if (is_object($repositoryName) && !$repositoryName instanceof RepositoryInterface) {
0 ignored issues
show
introduced by
$repositoryName is always a sub-type of Bdf\Prime\Repository\RepositoryInterface.
Loading history...
306
            $criteria = $repository->mapper()->prepareToRepository($repositoryName);
307
        }
308
        
309 1
        return $repository->find($criteria);
0 ignored issues
show
Bug introduced by
The method find() does not exist on Bdf\Prime\Repository\RepositoryInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Bdf\Prime\Repository\RepositoryInterface. ( Ignorable by Annotation )

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

309
        return $repository->/** @scrutinizer ignore-call */ find($criteria);
Loading history...
310
    }
311
312
    /**
313
     * Find one entity
314
     * 
315
     * <code>
316
     *  Prime::one(new EntityClass());
317
     *  Prime::one('EntityClass', ['id' => '...']);
318
     *  Prime::one($repository, ['id' => '...']);
319
     * </code>
320
     * 
321
     * @param string|RepositoryInterface  $repositoryName     Repo name or Entity instance
322
     * @param array|object                $criteria           Array of criteria. Optionnal if repository name is an object
323
     * 
324
     * @return object|array
325
     *
326
     * @throws PrimeException
327
     */
328 2
    public static function one($repositoryName, $criteria = null)
329
    {
330 2
        $repository = static::repository($repositoryName);
331
        
332
        // if $repositoryName is an entity
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
333 2
        if (is_object($repositoryName) && !$repositoryName instanceof RepositoryInterface) {
0 ignored issues
show
introduced by
$repositoryName is always a sub-type of Bdf\Prime\Repository\RepositoryInterface.
Loading history...
334 1
            $criteria = $repository->mapper()->prepareToRepository($repositoryName);
335
        }
336
        
337 2
        return $repository->findOne($criteria);
338
    }
339
340
    /**
341
     * Refresh entity from repository
342
     * 
343
     * @param object $entity
344
     * @param array  $additionnalCriteria  Criteria to add to primary key
345
     * 
346
     * @return object New refresh entity
347
     *
348
     * @throws PrimeException
349
     */
350 1
    public static function refresh($entity, $additionnalCriteria = [])
0 ignored issues
show
introduced by
Type hint "array" missing for $additionnalCriteria
Loading history...
351
    {
352 1
        $repository = static::repository($entity);
353
        
354 1
        return $repository->findOne($repository->mapper()->primaryCriteria($entity) + $additionnalCriteria);
355
    }
356
    
357
    //
358
    //--------- service
0 ignored issues
show
Coding Style introduced by
No space found before comment text; expected "// --------- service" but found "//--------- service"
Loading history...
359
    //
360
    
361
    /**
362
     * Get active connection from profile name
363
     * 
364
     * @param string $name
365
     * 
366
     * @return ConnectionInterface
367
     */
368 302
    public static function connection($name = null)
369
    {
370 302
        return static::service()->connection($name);
371
    }
372
373
    /**
374
     * Get service locator
375
     * 
376
     * @return ServiceLocator
377
     */
378 1350
    public static function service()
379
    {
380 1350
        if (static::$serviceLocator === null) {
381 88
            static::initialize();
382
        }
383
384 1350
        return static::$serviceLocator;
385
    }
386
387
    /**
388
     * Initializes the service locator
389
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
390 88
    protected static function initialize()
391
    {
392 88
        if (static::$config instanceof ContainerInterface) {
393
            static::$serviceLocator = static::$config->get('prime');
394
            
395
            return;
396
        }
397
        
398 88
        if (!is_array(static::$config)) {
399
            throw new RuntimeException('Prime is not configured');
400
        }
401
402 88
        $factory = new ConnectionFactory();
403 88
        $registry = new ConnectionRegistry(
404 88
            static::$config['connection']['config'] ?? [],
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
405 88
            new ChainFactory([
406 88
                new MasterSlaveConnectionFactory($factory),
407 88
                new ShardingConnectionFactory($factory),
408 88
                $factory,
409
            ]),
410 88
            new ConfigurationResolver([], $configuration = new Configuration())
411
        );
412
413 88
        $mapperFactory = new MapperFactory(
414 88
            null,
415 88
            static::$config['metadataCache'] ?? null,
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
416 88
            static::$config['resultCache'] ?? null
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
417
        );
418
419 88
        static::$serviceLocator = new ServiceLocator(
420 88
            new ConnectionManager($registry),
421 88
            $mapperFactory
422
        );
423
424 88
        if ($logger = static::$config['logger'] ?? null) {
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
425
            $configuration->setSQLLogger($logger);
426
        }
427
428 88
        if ($types = static::$config['types'] ?? null) {
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
429 88
            foreach ($types as $alias => $type) {
430 88
                $configuration->getTypes()->register($type, is_string($alias) ? $alias : null);
431
            }
432
        }
433
434 88
        if ($serializer = static::$config['serializer'] ?? null) {
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
435
            static::$serviceLocator->setSerializer($serializer);
436
        }
437 88
    }
438
}
439