Passed
Branch master (7599e2)
by Sébastien
12:18 queued 06:01
created

Prime::initialize()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 5.2259

Importance

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

268
        /** @scrutinizer ignore-call */ 
269
        $expected = $repository->findOne($repository->mapper()->primaryCriteria($entity));
Loading history...
269
        
270 11
        if ($expected === null) {
271
            return false;
272
        }
273
        
274 11
        if (!$compare) {
275 4
            return true;
276
        }
277
        
278 8
        return $entity == $expected 
279 8
                ? true
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement must be declared on a single line
Loading history...
280 8
                : serialize($entity) === serialize($expected);
281
    }
282
283
    /**
284
     * Find entity
285
     * 
286
     * <code>
287
     *  Prime::find(new EntityClass());
288
     *  Prime::find('EntityClass', ['id' => '...']);
289
     *  Prime::find($repository, ['id' => '...']);
290
     * </code>
291
     * 
292
     * @param string|RepositoryInterface  $repositoryName     Repo name or Entity instance
293
     * @param array|object                $criteria           Array of criteria. Optionnal if repository name is an object
294
     * 
295
     * @return object|array
296
     *
297
     * @throws PrimeException
298
     */
299 1
    public static function find($repositoryName, $criteria = null)
300
    {
301 1
        $repository = static::repository($repositoryName);
302
        
303
        // if $repositoryName is an entity
0 ignored issues
show
Coding Style Documentation introduced by
Inline comments must start with a capital letter
Loading history...
304 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...
305
            $criteria = $repository->mapper()->prepareToRepository($repositoryName);
306
        }
307
        
308 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

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