Test Failed
Pull Request — master (#31)
by Sébastien
07:15
created

Prime   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 411
Duplicated Lines 0 %

Test Coverage

Coverage 92.38%

Importance

Changes 0
Metric Value
wmc 44
eloc 83
c 0
b 0
f 0
dl 0
loc 411
rs 8.8798
ccs 97
cts 105
cp 0.9238

18 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 3 1
A one() 0 10 3
A find() 0 10 3
A exists() 0 17 4
A repository() 0 7 2
A push() 0 3 1
A truncate() 0 3 1
A callSchemaResolverMethod() 0 8 3
B initialize() 0 46 8
B callRepositoryMethod() 0 19 8
A drop() 0 3 1
A save() 0 3 1
A remove() 0 3 1
A isConfigured() 0 3 1
A refresh() 0 5 1
A connection() 0 3 1
A configure() 0 8 2
A service() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like Prime often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Prime, and based on these observations, apply Extract Interface, too.

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 95
     */
43
    public static function configure($config)
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before function; 2 found
Loading history...
44 95
    {
45 1
        if ($config instanceof ServiceLocator) {
46 1
            static::$config = null;
47
            static::$serviceLocator = $config;
48 94
        } else {
49 94
            static::$config = $config;
50
            static::$serviceLocator = null;
51 95
        }
52
    }
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 1336
     */
59
    public static function isConfigured()
60 1336
    {
61
        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 741
     */
75
    public static function repository($repository)
76 741
    {
77 6
        if ($repository instanceof RepositoryInterface) {
78
            return $repository;
79
        }
80 741
81
        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 860
     */
91
    public static function create($repositories, $force = false)
92 860
    {
93 860
        static::callSchemaResolverMethod('migrate', $repositories, $force);
94
    }
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 846
     */
103
    public static function drop($repositories, $force = false)
104 846
    {
105 846
        static::callSchemaResolverMethod('drop', $repositories, $force);
106
    }
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 1
     */
115
    public static function truncate($repositories, $force = false)
116 1
    {
117 1
        static::callSchemaResolverMethod('truncate', $repositories, $force);
118
    }
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 872
     */
129
    protected static function callSchemaResolverMethod($method, $repositories, $force)
130 872
    {
131 8
        if (!is_array($repositories)) {
132
            $repositories = [$repositories];
133
        }
134 872
        
135 623
        foreach ($repositories as $repository) {
136
            static::repository($repository)->schema($force)->$method();
137 872
        }
138
    }
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 33
     */
166
    public static function push($repositoryName, $entities = null)
167 33
    {
168 33
        static::callRepositoryMethod('replace', $repositoryName, $entities);
169
    }
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 3
     */
193
    public static function save($repositoryName, $entities = null)
194 3
    {
195 3
        static::callRepositoryMethod('save', $repositoryName, $entities);
196
    }
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 1
     */
219
    public static function remove($repositoryName, $entities = null)
220 1
    {
221 1
        static::callRepositoryMethod('delete', $repositoryName, $entities);
222
    }
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 36
     */
233
    protected static function callRepositoryMethod($method, $repositoryName, $entities)
234 36
    {
235 19
        if (!is_string($repositoryName) && !$repositoryName instanceof RepositoryInterface) {
236 19
            $entities = $repositoryName;
237
            $repositoryName = null;
238
        }
239 36
        
240 36
        if (!is_array($entities) || !isset($entities[0])) {
241
            $entities = [$entities];
242
        }
243 36
        
244 36
        foreach ($entities as $entity) {
245
            $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 36
            
247 23
            if (is_array($entity)) {
248
                $entity = $repository->entity($entity);
249
            }
250 36
            
251
            $repository->$method($entity);
252 36
        }
253
    }
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 11
     */
265
    public static function exists($entity, $compare = true)
266 11
    {
267
        $repository = static::repository($entity);
268 11
        
269
        $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 11
        
271
        if ($expected === null) {
272
            return false;
273
        }
274 11
        
275 4
        if (!$compare) {
276
            return true;
277
        }
278 8
        
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
                : 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 1
     */
300
    public static function find($repositoryName, $criteria = null)
301 1
    {
302
        $repository = static::repository($repositoryName);
303
        
304 1
        // 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
        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 1
        
309
        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 2
     */
328
    public static function one($repositoryName, $criteria = null)
329 2
    {
330
        $repository = static::repository($repositoryName);
331
        
332 2
        // 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 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...
334
            $criteria = $repository->mapper()->prepareToRepository($repositoryName);
335
        }
336 2
        
337
        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 1
     */
350
    public static function refresh($entity, $additionnalCriteria = [])
0 ignored issues
show
introduced by
Type hint "array" missing for $additionnalCriteria
Loading history...
351 1
    {
352
        $repository = static::repository($entity);
353 1
        
354
        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 302
     */
368
    public static function connection($name = null)
369 302
    {
370
        return static::service()->connection($name);
371
    }
372
373
    /**
374
     * Get service locator
375
     * 
376
     * @return ServiceLocator
377 1350
     */
378
    public static function service()
379 1350
    {
380 88
        if (static::$serviceLocator === null) {
381
            static::initialize();
382
        }
383 1350
384
        return static::$serviceLocator;
385
    }
386
387
    /**
388
     * Initializes the service locator
389 88
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
390
    protected static function initialize()
391 88
    {
392
        if (static::$config instanceof ContainerInterface) {
393
            static::$serviceLocator = static::$config->get('prime');
394
            
395
            return;
396
        }
397 88
        
398
        if (!is_array(static::$config)) {
399
            throw new RuntimeException('Prime is not configured');
400
        }
401 88
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
                $factory,
409
            ]),
410
            new ConfigurationResolver([], $configuration = new Configuration())
411 88
        );
412 88
413 88
        $mapperFactory = new MapperFactory(
414 88
            null,
415
            static::$config['metadataCache'] ?? null,
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
416
            static::$config['resultCache'] ?? null
0 ignored issues
show
Coding Style introduced by
Operation must be bracketed
Loading history...
417 88
        );
418 88
419 88
        static::$serviceLocator = new ServiceLocator(
420
            new ConnectionManager($registry),
421
            $mapperFactory
422 88
        );
423
424
        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 88
428
        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
            foreach ($types as $alias => $type) {
430
                $configuration->getTypes()->register($type, is_string($alias) ? $alias : null);
431 88
            }
432
        }
433
434
        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 88
            static::$serviceLocator->setSerializer($serializer);
436
        }
437
    }
438
}
439