Completed
Push — master ( 5d4578...5f67d7 )
by Filipe
02:35
created

Orm::setEmitter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
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 20
    public static function getInstance()
85
    {
86 20
        if (null === self::$instance) {
87 2
            self::$instance = new static;
88 2
        }
89 20
        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 10
    public static function getRepository($entityClass)
117
    {
118 10
        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 6
    public static function getEmitter($entityClass)
129
    {
130 6
        return self::getInstance()->getEmitterFor($entityClass);
131
    }
132
133
    /**
134
     * Sets the emitter for provided class name
135
     *
136
     * @param string $entityClass
137
     * @param EmitterInterface $emitter
138
     * @return $this|self|Orm
139
     */
140 2
    public function setEmitter($entityClass, EmitterInterface $emitter)
141
    {
142 2
        $this->emitters->set($entityClass, $emitter);
143 2
        return $this;
144
    }
145
146
    /**
147
     * Add a listener for an entity event.
148
     *
149
     * The $event parameter should be the event name, and the second should be
150
     * the event listener. It may implement the League\Event\ListenerInterface
151
     * or simply be "callable". In this case, the priority emitter also accepts
152
     * an optional third parameter specifying the priority as an integer. You
153
     * may use one of EmitterInterface predefined constants here if you want.
154
     *
155
     * @param string|EntityInterface     $entityClass
156
     * @param string                     $event
157
     * @param ListenerInterface|callable $listener
158
     * @param int                        $priority
159
     *
160
     * @return EmitterInterface
161
     */
162 2
    public static function addListener(
163
        $entityClass, $event, $listener, $priority = EmitterInterface::P_NORMAL
164
    ) {
165 2
        return self::getInstance()->addListenerFor($entityClass,$event, $listener, $priority);
166
    }
167
168
    /**
169
     * Add a listener for an entity event.
170
     *
171
     * The $event parameter should be the event name, and the second should be
172
     * the event listener. It may implement the League\Event\ListenerInterface
173
     * or simply be "callable". In this case, the priority emitter also accepts
174
     * an optional third parameter specifying the priority as an integer. You
175
     * may use one of EmitterInterface predefined constants here if you want.
176
     *
177
     * @param string|EntityInterface     $entityClass
178
     * @param string                     $event
179
     * @param ListenerInterface|callable $listener
180
     * @param int                        $priority
181
     *
182
     * @return EmitterInterface
183
     */
184 2
    public function addListenerFor(
185
        $entityClass, $event, $listener, $priority = EmitterInterface::P_NORMAL
186
    ) {
187 2
        $className = is_object($entityClass)
188 2
            ? get_class($entityClass)
189 2
            : $entityClass;
190 2
        return $this->getEmitterFor($className)
191 2
            ->addListener($event, $listener, $priority);
0 ignored issues
show
Bug introduced by
It seems like $listener defined by parameter $listener on line 185 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...
192
    }
193
194
    /**
195
     * Gets repository for provided entity class name
196
     *
197
     * @param string $entityClass FQ entity class name
198
     *
199
     * @return EntityRepository
200
     *
201
     * @throws InvalidArgumentException If provide class name is not
202
     *   from a class that implements the EntityInterface interface.
203
     */
204 10
    public function getRepositoryFor($entityClass)
205
    {
206 10
        if (!is_subclass_of($entityClass, EntityInterface::class)) {
207 2
            throw new InvalidArgumentException(
208
                'Cannot create ORM repository for a class that does not '.
209
                'implement EntityInterface.'
210 2
            );
211
        }
212
213 8
        return $this->repositories->containsKey($entityClass)
214 8
            ? $this->repositories->get($entityClass)
215 8
            : $this->createRepository($entityClass);
216
    }
217
218
    /**
219
     * Creates a repository for provided entity class name
220
     *
221
     * @param string $entityClass
222
     * @return EntityRepository
223
     */
224 2
    private function createRepository($entityClass)
225
    {
226 2
        $repository = new EntityRepository();
227 2
        $repository->setAdapter(
228 2
            $this->adapters->get($this->getAdapterAlias($entityClass))
229 2
        )
230 2
            ->setEntityMapper($this->getMapperFor($entityClass))
231 2
            ->setEntityDescriptor(EntityDescriptorRegistry::getInstance()
232 2
                ->getDescriptorFor($entityClass));
233 2
        $this->repositories->set($entityClass, $repository);
234 2
        return $repository;
235
    }
236
237
    /**
238
     * Retrieves the mapper for provided entity
239
     *
240
     * If mapper does not exists it will be created and stored in the
241
     * mapper map.
242
     *
243
     * @param string $entity
244
     * @return EntityMapper
245
     */
246 8
    public function getMapperFor($entity)
247
    {
248 8
        return  $this->mappers->containsKey($entity)
249 8
            ? $this->mappers->get($entity)
250 8
            : $this->createMapper($entity);
251
    }
252
253
    /**
254
     * Gets the event emitter for provided entity
255
     *
256
     * @param string $entity
257
     *
258
     * @return Emitter
259
     */
260 8
    public function getEmitterFor($entity)
261
    {
262 8
        return $this->emitters->containsKey($entity)
263 8
            ? $this->emitters->get($entity)
264 8
            : $this->createEmitter($entity);
265
    }
266
267
    /**
268
     * Sets default adapter
269
     *
270
     * @param AdapterInterface $adapter
271
     * @return $this|Orm|self
272
     */
273 12
    public function setDefaultAdapter(AdapterInterface $adapter)
274
    {
275 12
        return $this->setAdapter('default', $adapter);
276
    }
277
278
    /**
279
     * Sets an adapter mapped with alias name
280
     *
281
     * @param string $alias
282
     * @param AdapterInterface $adapter
283
     *
284
     * @return $this|Orm|self
285
     */
286 12
    public function setAdapter($alias, AdapterInterface $adapter)
287
    {
288 12
        $this->adapters->set($alias, $adapter);
289 12
        return $this;
290
    }
291
292
    /**
293
     * Creates entity map for provided entity
294
     *
295
     * @param string $entity
296
     * @return EntityMapper
297
     */
298 4
    private function createMapper($entity)
299
    {
300 4
        $mapper = new EntityMapper();
301 4
        $mapper->setAdapter(
302 4
            $this->adapters->get(
303 4
                $this->getAdapterAlias($entity)
304 4
            )
305 4
        )
306 4
            ->setEntityClassName($entity);
307 4
        $this->mappers->set($entity, $mapper);
308 4
        return $mapper;
309
    }
310
311
    /**
312
     * Creates an emitter for provided entity class name
313
     *
314
     * @param string $entity
315
     * @return Emitter
316
     */
317 2
    private function createEmitter($entity)
318
    {
319 2
        $emitter = new Emitter();
320 2
        $this->emitters->set($entity, $emitter);
321 2
        return $emitter;
322
    }
323
324
    /**
325
     * Gets the adapter alias for current working entity
326
     *
327
     * @param string $entity
328
     *
329
     * @return EntityDescriptor|string
330
     */
331 6
    private function getAdapterAlias($entity)
332
    {
333 6
        $descriptor = EntityDescriptorRegistry::getInstance()
334 6
            ->getDescriptorFor($entity);
335 6
        return $descriptor->getAdapterAlias()
336 6
            ? $descriptor->getAdapterAlias()
337 6
            : 'default';
338
    }
339
}