Completed
Push — master ( 57b531...5d4578 )
by Filipe
02:14
created

Orm::getEmitterFor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
/**
4
 * This file is part of slick/orm package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Orm;
11
12
use League\Event\Emitter;
13
use League\Event\EmitterInterface;
14
use League\Event\ListenerInterface;
15
use Slick\Database\Adapter\AdapterInterface;
16
use Slick\Orm\Descriptor\EntityDescriptor;
17
use Slick\Orm\Descriptor\EntityDescriptorRegistry;
18
use Slick\Orm\Event\EmittersMap;
19
use Slick\Orm\Exception\InvalidArgumentException;
20
use Slick\Orm\Mapper\EntityMapper;
21
use Slick\Orm\Mapper\MappersMap;
22
use Slick\Orm\Repository\EntityRepository;
23
use Slick\Orm\Repository\RepositoryMap;
24
25
/**
26
 * Orm registry
27
 *
28
 * @package Slick\Orm
29
 * @author  Filipe Silva <[email protected]>
30
 */
31
final class Orm
32
{
33
34
    /**
35
     * @var MappersMap|EntityMapperInterface[]
36
     */
37
    private $mappers;
38
39
    /**
40
     * @var Orm
41
     */
42
    private static $instance;
43
44
    /**
45
     * @var AdaptersMap
46
     */
47
    private $adapters;
48
49
    /**
50
     * @var RepositoryMap
51
     */
52
    private $repositories;
53
54
    /**
55
     * @var EmittersMap
56
     */
57
    private $emitters;
58
59
    /**
60
     * Initialize Orm registry with empty lists
61
     */
62 2
    private function __construct()
63
    {
64 2
        $this->mappers = new MappersMap();
65 2
        $this->adapters = new AdaptersMap();
66 2
        $this->repositories = new RepositoryMap();
67 2
        $this->emitters = new EmittersMap();
68 2
    }
69
70
    /**
71
     * Avoid clone on a singleton
72
     * @codeCoverageIgnore
73
     */
74
    private function __clone()
75
    {
76
77
    }
78
79
    /**
80
     * Gets a ORM registry instance
81
     *
82
     * @return Orm
83
     */
84 16
    public static function getInstance()
85
    {
86 16
        if (null === self::$instance) {
87 2
            self::$instance = new static;
88 1
        }
89 16
        return self::$instance;
90
    }
91
92
    /**
93
     * Retrieves the mapper for provided entity
94
     *
95
     * If mapper does not exists it will be created and stored in the
96
     * mapper map.
97
     *
98
     * @param String $entity
99
     * @return EntityMapper
100
     */
101 6
    public static function getMapper($entity)
102
    {
103 6
        return self::getInstance()->getMapperFor($entity);
104
    }
105
106
    /**
107
     * Gets repository for provided entity class name
108
     *
109
     * @param string $entityClass FQ entity class name
110
     *
111
     * @return EntityRepository
112
     *
113
     * @throws InvalidArgumentException If provide class name is not
114
     *   from a class that implements the EntityInterface interface.
115
     */
116 8
    public static function getRepository($entityClass)
117
    {
118 8
        return self::getInstance()->getRepositoryFor($entityClass);
119
    }
120
121
    /**
122
     * Gets event emitter for provided entity class
123
     *
124
     * @param string $entityClass FQ entity class name
125
     *
126
     * @return Emitter
127
     */
128 4
    public static function getEmitter($entityClass)
129
    {
130 4
        return self::getInstance()->getEmitterFor($entityClass);
131
    }
132
133
    /**
134
     * Add a listener for an entity event.
135
     *
136
     * The $event parameter should be the event name, and the second should be
137
     * the event listener. It may implement the League\Event\ListenerInterface
138
     * or simply be "callable". In this case, the priority emitter also accepts
139
     * an optional third parameter specifying the priority as an integer. You
140
     * may use one of EmitterInterface predefined constants here if you want.
141
     *
142
     * @param string|EntityInterface     $entityClass
143
     * @param string                     $event
144
     * @param ListenerInterface|callable $listener
145
     * @param int                        $priority
146
     *
147
     * @return EmitterInterface
148
     */
149
    public static function addListener(
150
        $entityClass, $event, $listener, $priority = EmitterInterface::P_NORMAL
151
    ) {
152
        return self::getInstance()->addListenerFor($entityClass,$event, $listener, $priority);
153
    }
154
155
    /**
156
     * Add a listener for an entity event.
157
     *
158
     * The $event parameter should be the event name, and the second should be
159
     * the event listener. It may implement the League\Event\ListenerInterface
160
     * or simply be "callable". In this case, the priority emitter also accepts
161
     * an optional third parameter specifying the priority as an integer. You
162
     * may use one of EmitterInterface predefined constants here if you want.
163
     *
164
     * @param string|EntityInterface     $entityClass
165
     * @param string                     $event
166
     * @param ListenerInterface|callable $listener
167
     * @param int                        $priority
168
     *
169
     * @return EmitterInterface
170
     */
171
    public function addListenerFor(
172
        $entityClass, $event, $listener, $priority = EmitterInterface::P_NORMAL
173
    ) {
174
        $className = is_object($entityClass)
175
            ? get_class($entityClass)
176
            : $entityClass;
177
        return $this->getEmitterFor($className)
178
            ->addListener($event, $listener, $priority);
0 ignored issues
show
Bug introduced by
It seems like $listener defined by parameter $listener on line 172 can also be of type object<League\Event\ListenerInterface>; however, League\Event\Emitter::addListener() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
179
    }
180
181
    /**
182
     * Gets repository for provided entity class name
183
     *
184
     * @param string $entityClass FQ entity class name
185
     *
186
     * @return EntityRepository
187
     *
188
     * @throws InvalidArgumentException If provide class name is not
189
     *   from a class that implements the EntityInterface interface.
190
     */
191 8
    public function getRepositoryFor($entityClass)
192
    {
193 8
        if (!is_subclass_of($entityClass, EntityInterface::class)) {
194 2
            throw new InvalidArgumentException(
195
                'Cannot create ORM repository for a class that does not '.
196 1
                'implement EntityInterface.'
197 1
            );
198
        }
199
200 6
        return $this->repositories->containsKey($entityClass)
201 5
            ? $this->repositories->get($entityClass)
202 6
            : $this->createRepository($entityClass);
203
    }
204
205
    /**
206
     * Creates a repository for provided entity class name
207
     *
208
     * @param string $entityClass
209
     * @return EntityRepository
210
     */
211 2
    private function createRepository($entityClass)
212
    {
213 2
        $repository = new EntityRepository();
214 2
        $repository->setAdapter(
215 2
            $this->adapters->get($this->getAdapterAlias($entityClass))
216 1
        )
217 2
            ->setEntityMapper($this->getMapperFor($entityClass))
218 2
            ->setEntityDescriptor(EntityDescriptorRegistry::getInstance()
219 2
                ->getDescriptorFor($entityClass));
220 2
        $this->repositories->set($entityClass, $repository);
221 2
        return $repository;
222
    }
223
224
    /**
225
     * Retrieves the mapper for provided entity
226
     *
227
     * If mapper does not exists it will be created and stored in the
228
     * mapper map.
229
     *
230
     * @param string $entity
231
     * @return EntityMapper
232
     */
233 8
    public function getMapperFor($entity)
234
    {
235 8
        return  $this->mappers->containsKey($entity)
236 6
            ? $this->mappers->get($entity)
237 8
            : $this->createMapper($entity);
238
    }
239
240
    /**
241
     * Gets the event emitter for provided entity
242
     *
243
     * @param string $entity
244
     *
245
     * @return Emitter
246
     */
247 4
    public function getEmitterFor($entity)
248
    {
249 4
        return $this->emitters->containsKey($entity)
250 4
            ? $this->emitters->get($entity)
251 4
            : $this->createEmitter($entity);
252
    }
253
254
    /**
255
     * Sets default adapter
256
     *
257
     * @param AdapterInterface $adapter
258
     * @return $this|Orm|self
259
     */
260 10
    public function setDefaultAdapter(AdapterInterface $adapter)
261
    {
262 10
        return $this->setAdapter('default', $adapter);
263
    }
264
265
    /**
266
     * Sets an adapter mapped with alias name
267
     *
268
     * @param string $alias
269
     * @param AdapterInterface $adapter
270
     *
271
     * @return $this|Orm|self
272
     */
273 10
    public function setAdapter($alias, AdapterInterface $adapter)
274
    {
275 10
        $this->adapters->set($alias, $adapter);
276 10
        return $this;
277
    }
278
279
    /**
280
     * Creates entity map for provided entity
281
     *
282
     * @param string $entity
283
     * @return EntityMapper
284
     */
285 4
    private function createMapper($entity)
286
    {
287 4
        $mapper = new EntityMapper();
288 4
        $mapper->setAdapter(
289 4
            $this->adapters->get(
290 4
                $this->getAdapterAlias($entity)
291 2
            )
292 2
        )
293 4
            ->setEntityClassName($entity);
294 4
        $this->mappers->set($entity, $mapper);
295 4
        return $mapper;
296
    }
297
298
    /**
299
     * Creates an emitter for provided entity class name
300
     *
301
     * @param string $entity
302
     * @return Emitter
303
     */
304 2
    private function createEmitter($entity)
305
    {
306 2
        $emitter = new Emitter();
307 2
        $this->emitters->set($entity, $emitter);
308 2
        return $emitter;
309
    }
310
311
    /**
312
     * Gets the adapter alias for current working entity
313
     *
314
     * @param string $entity
315
     *
316
     * @return EntityDescriptor|string
317
     */
318 6
    private function getAdapterAlias($entity)
319
    {
320 6
        $descriptor = EntityDescriptorRegistry::getInstance()
321 6
            ->getDescriptorFor($entity);
322 6
        return $descriptor->getAdapterAlias()
323 6
            ? $descriptor->getAdapterAlias()
324 6
            : 'default';
325
    }
326
}