Completed
Push — master ( af7081...8b532e )
by Андрей
05:28 queued 03:12
created

EntityMapAbstractFactory::setModuleOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
/**
3
 * @link    https://github.com/nnx-framework/doctrine
4
 * @author  Malofeykin Andrey  <[email protected]>
5
 */
6
namespace Nnx\Doctrine\EntityManager;
7
8
use Zend\ServiceManager\AbstractFactoryInterface;
9
use Zend\ServiceManager\AbstractPluginManager;
10
use Zend\ServiceManager\ServiceLocatorInterface;
11
use Nnx\Doctrine\Options\ModuleOptionsInterface;
12
use Nnx\ModuleOptions\ModuleOptionsPluginManagerInterface;
13
use Nnx\Doctrine\Utils\DoctrineOrmModuleConfigInterface;
14
use Nnx\Doctrine\Utils\EntityMapCacheInterface;
15
use ReflectionClass;
16
17
/**
18
 * Class OrmAbstractFactory
19
 *
20
 * @package Nnx\Doctrine\EntityManager
21
 */
22
class EntityMapAbstractFactory implements AbstractFactoryInterface
23
{
24
    /**
25
     * Ключем является имя интерфейса сущности, а значением объект прототип, либо false
26
     *
27
     * @var array
28
     */
29
    protected $prototype = [];
30
31
    /**
32
     * Флаг определяет была ли инициированна фабрика
33
     *
34
     * @var bool
35
     */
36
    protected $isInit = false;
37
38
    /**
39
     * Настройки модуля
40
     *
41
     * @var ModuleOptionsInterface
42
     */
43
    protected $moduleOptions;
44
45
    /**
46
     * Ключем является имя objectManager'a, а значением карта сущностей для него
47
     *
48
     * @var array
49
     */
50
    protected $objectManagerToEntityMap = [];
51
52
    /**
53
     * Колличество ObjectManagers для которых есть EntityMap
54
     *
55
     * @var int
56
     */
57
    protected $countObjectManagers = 0;
58
59
    /**
60
     * В случае если EntityMap есть только для одного ObjectManager, то данное свойство будет содержать эту EntityMap
61
     *
62
     * @var array
63
     */
64
    protected $baseEntityMap = [];
65
66
    /**
67
     * Ключем является имя интерфейса,  а значением имя класса сущности
68
     *
69
     * @var array
70
     */
71
    protected $interfaceNameToClassName = [];
72
73
    /**
74
     * @inheritdoc
75
     *
76
     * @param ServiceLocatorInterface $serviceLocator
77
     * @param                         $name
78
     * @param                         $requestedName
79
     *
80
     * @return boolean
81
     *
82
     * @throws \Zend\ServiceManager\Exception\ServiceNotFoundException
83
     */
84
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
85
    {
86
        $this->init($serviceLocator);
87
        if (array_key_exists($requestedName, $this->prototype)) {
88
            return false !== $this->prototype[$requestedName];
89
        }
90
91
        return false !== $this->getClassNameByInterface($requestedName);
92
    }
93
94
    /**
95
     * Попытка получить имя класса, на оснве интерфейса
96
     *
97
     * @param $interfaceName
98
     *
99
     * @return string|false
100
     */
101
    protected function getClassNameByInterface($interfaceName)
102
    {
103
        if (array_key_exists($interfaceName, $this->interfaceNameToClassName)) {
104
            return $this->interfaceNameToClassName[$interfaceName];
105
        }
106
107
        if (0 === $this->countObjectManagers) {
108
            $this->interfaceNameToClassName[$interfaceName] = false;
109
            return false;
110
        } elseif (1 === $this->countObjectManagers) {
111
            $this->interfaceNameToClassName[$interfaceName] = array_key_exists($interfaceName, $this->baseEntityMap) ? $this->baseEntityMap[$interfaceName] : false;
112
            return $this->interfaceNameToClassName[$interfaceName];
113
        }
114
115
        foreach ($this->objectManagerToEntityMap as $entityMap) {
116
            if (array_key_exists($interfaceName, $entityMap)) {
117
                $this->interfaceNameToClassName[$interfaceName] = $entityMap[$interfaceName];
118
                return $this->interfaceNameToClassName[$interfaceName];
119
            }
120
        }
121
        $this->interfaceNameToClassName[$interfaceName] = false;
122
        return $this->interfaceNameToClassName[$interfaceName];
123
    }
124
125
    /**
126
     * @inheritdoc
127
     *
128
     * @param ServiceLocatorInterface $serviceLocator
129
     * @param                         $name
130
     * @param                         $requestedName
131
     *
132
     * @return mixed
133
     *
134
     * @throws Exception\RuntimeException
135
     * @throws \Zend\ServiceManager\Exception\ServiceNotFoundException
136
     */
137
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
138
    {
139
        $this->init($serviceLocator);
140
141 View Code Duplication
        if (array_key_exists($requestedName, $this->prototype)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
            if (!is_object($this->prototype[$requestedName])) {
143
                $errMsg = sprintf('Invalid prototype for %s', $requestedName);
144
                throw new Exception\RuntimeException($errMsg);
145
            }
146
            return clone $this->prototype[$requestedName];
147
        }
148
149
        $className = $this->getClassNameByInterface($requestedName);
150
        if (false === $className) {
151
            $errMsg = sprintf('Invalid cache date for  %s', $requestedName);
152
            throw new Exception\RuntimeException($errMsg);
153
        }
154
155 View Code Duplication
        if ($serviceLocator->has($className)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
            $entity = $serviceLocator->get($className);
157
        } else {
158
            $r = new ReflectionClass($className);
159
            $entity = $r->newInstance();
160
        }
161
        $this->prototype[$requestedName] = $entity;
162
163
        return $entity;
164
    }
165
166
    /**
167
     * @param ServiceLocatorInterface $serviceLocator
168
     *
169
     * @return void
170
     *
171
     * @throws \Zend\ServiceManager\Exception\ServiceNotFoundException
172
     */
173
    public function init(ServiceLocatorInterface $serviceLocator)
174
    {
175
        if (true === $this->isInit) {
176
            return;
177
        }
178
179
        $appServiceLocator = $serviceLocator;
180
        if ($serviceLocator instanceof AbstractPluginManager) {
181
            $appServiceLocator = $serviceLocator->getServiceLocator();
182
        }
183
184
        /** @var ModuleOptionsPluginManagerInterface $moduleOptionsManager */
185
        $moduleOptionsManager = $appServiceLocator->get(ModuleOptionsPluginManagerInterface::class);
186
        /** @var ModuleOptionsInterface $moduleOptions */
187
        $moduleOptions = $moduleOptionsManager->get(ModuleOptionsInterface::class);
188
        $this->setModuleOptions($moduleOptions);
189
190
        /** @var DoctrineOrmModuleConfigInterface $doctrineOrmModuleConfig */
191
        $doctrineOrmModuleConfig = $appServiceLocator->get(DoctrineOrmModuleConfigInterface::class);
192
193
        $listObjectManagerName = $doctrineOrmModuleConfig->getListObjectManagerName();
194
195
        /** @var EntityMapCacheInterface $entityMapCache */
196
        $entityMapCache = $appServiceLocator->get(EntityMapCacheInterface::class);
197
        foreach ($listObjectManagerName as $objectManagerName) {
198
            if ($entityMapCache->hasEntityMap($objectManagerName)) {
199
                $this->objectManagerToEntityMap[$objectManagerName] = $entityMapCache->loadEntityMap($objectManagerName);
200
            }
201
        }
202
203
        $this->countObjectManagers = count($this->objectManagerToEntityMap);
204
205
        if (1 === $this->countObjectManagers) {
206
            reset($this->objectManagerToEntityMap);
207
            $this->baseEntityMap = current($this->objectManagerToEntityMap);
208
        }
209
210
        $this->isInit = true;
211
    }
212
213
    /**
214
     * Возвращает настройки модуля
215
     *
216
     * @return ModuleOptionsInterface
217
     */
218
    public function getModuleOptions()
219
    {
220
        return $this->moduleOptions;
221
    }
222
223
    /**
224
     * Устанавливает настройки модуля
225
     *
226
     * @param ModuleOptionsInterface $moduleOptions
227
     *
228
     * @return $this
229
     */
230
    public function setModuleOptions($moduleOptions)
231
    {
232
        $this->moduleOptions = $moduleOptions;
233
234
        return $this;
235
    }
236
}
237