Passed
Push — dev_2x ( 3e8772...896177 )
by Adrian
06:45
created

Orm::buildMapper()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 22
rs 9.5555
cc 5
nc 9
nop 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A Orm::createRelation() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm;
5
6
use InvalidArgumentException;
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Sirius\Orm\Behaviour\Events;
9
use Sirius\Orm\Contract\MapperLocatorInterface;
10
use Sirius\Orm\Entity\CollectionCaster;
11
use Sirius\Orm\Entity\EntityCaster;
12
use Sirius\Orm\Relation\Relation;
13
use Sirius\Orm\Relation\RelationBuilder;
14
15
class Orm
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $mappers = [];
21
22
    /**
23
     * @var array
24
     */
25
    protected $lazyMappers = [];
26
27
    /**
28
     * @var ConnectionLocator
29
     */
30
    protected $connectionLocator;
31
32
    /**
33
     * @var CastingManager
34
     */
35
    protected $castingManager;
36
37
    /**
38
     * @var MapperLocatorInterface|null
39
     */
40
    protected $mapperLocator;
41
    /**
42
     * @var RelationBuilder
43
     */
44
    protected $relationBuilder;
45
    /**
46
     * @var EventDispatcherInterface|null
47
     */
48
    protected $events;
49
50
    public function __construct(
51
        ConnectionLocator $connectionLocator,
52
        RelationBuilder $relationBuilder = null,
53
        CastingManager $castingManager = null,
54
        EventDispatcherInterface $events = null,
55
        MapperLocatorInterface $mapperLocator = null
56
    ) {
57
        $this->connectionLocator = $connectionLocator;
58
        $this->relationBuilder   = $relationBuilder ?? new RelationBuilder();
59
        $this->castingManager    = $castingManager ?? new CastingManager();
60
        $this->events            = $events;
61
        $this->mapperLocator     = $mapperLocator;
62
    }
63
64
    /**
65
     * Register a mapper with a name
66
     *
67
     * @param string $name
68
     * @param Mapper|callable|string $mapper
69
     */
70
    public function register(string $name, $mapper)
71
    {
72
        if ($mapper instanceof Mapper) {
73
            $this->mappers[$name] = $mapper;
74
        } elseif (is_callable($mapper) || is_string($mapper) || $mapper instanceof MapperConfig) {
75
            $this->lazyMappers[$name] = $mapper;
76
        } else {
77
            throw new \InvalidArgumentException('The $mapper argument must be a Mapper object, 
78
                a MapperConfig object, a callable or a string that can be used by the mapper locator');
79
        }
80
81
        $this->addCastingMethodsForMapper($name);
82
    }
83
84
    /**
85
     * Check if a mapper is registered within the ORM
86
     *
87
     * @param $name
88
     *
89
     * @return bool
90
     */
91
    public function has($name): bool
92
    {
93
        return isset($this->mappers[$name]) || isset($this->lazyMappers[$name]);
94
    }
95
96
    /**
97
     * Return a mapper instance by it's registered name
98
     *
99
     * @param $name
100
     *
101
     * @return Mapper
102
     */
103
    public function get($name): Mapper
104
    {
105
        if (isset($this->lazyMappers[$name])) {
106
            $this->mappers[$name] = $this->createMapper($name);
107
            unset($this->lazyMappers[$name]);
108
        }
109
110
        if (! isset($this->mappers[$name]) || ! $this->mappers[$name]) {
111
            throw new InvalidArgumentException(sprintf('Mapper named %s is not registered', $name));
112
        }
113
114
        return $this->mappers[$name];
115
    }
116
117
    public function getCastingManager(): CastingManager
118
    {
119
        return $this->castingManager;
120
    }
121
122
    public function getConnectionLocator(): ConnectionLocator
123
    {
124
        return $this->connectionLocator;
125
    }
126
127
    public function createRelation(Mapper $mapper, string $name, array $options): Relation
128
    {
129
        return $this->relationBuilder->build($this, $mapper, $name, $options);
130
    }
131
132
    protected function createMapper($name): Mapper
133
    {
134
        $definition = $this->lazyMappers[$name];
135
136
        $mapper = null;
137
        if (is_callable($definition)) {
138
            $mapper = $definition($this);
139
        } elseif ($this->mapperLocator) {
140
            $mapper = $this->mapperLocator->get($definition);
141
        }
142
143
        if (! $mapper) {
144
            throw new InvalidArgumentException(
145
                'The mapper could not be generated/retrieved.'
146
            );
147
        }
148
149
        if (! $mapper instanceof Mapper) {
150
            throw new InvalidArgumentException(
151
                'The mapper generated from the factory is not a valid `Mapper` instance.'
152
            );
153
        }
154
155
        if ($this->events) {
156
            $mapper->use(new Events($this->events, $name));
157
        }
158
159
        return $mapper;
160
    }
161
162
    protected function addCastingMethodsForMapper(string $name)
163
    {
164
        $this->castingManager->register('entity_' . $name, new EntityCaster($this, $name));
165
        $this->castingManager->register('collection_of_' . $name, new CollectionCaster($this, $name));
166
    }
167
}
168