Completed
Pull Request — master (#71)
by Arnaud
03:02
created

AdminFactory   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 264
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 15

Test Coverage

Coverage 83.13%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 15
dl 0
loc 264
ccs 69
cts 83
cp 0.8313
rs 9.1666
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getRegistry() 0 4 1
A __construct() 0 20 1
B init() 0 38 3
B create() 0 36 2
A addDataProvider() 0 6 1
A isInit() 0 4 1
A createAction() 0 10 1
B getDataProvider() 0 33 5
1
<?php
2
3
namespace LAG\AdminBundle\Admin\Factory;
4
5
use Doctrine\ORM\EntityManager;
6
use LAG\AdminBundle\Action\Factory\ActionFactory;
7
use LAG\AdminBundle\Admin\Admin;
8
use LAG\AdminBundle\Admin\AdminInterface;
9
use LAG\AdminBundle\Admin\Event\AdminCreatedEvent;
10
use LAG\AdminBundle\Admin\Event\AdminCreateEvent;
11
use LAG\AdminBundle\Admin\Event\BeforeConfigurationEvent;
12
use LAG\AdminBundle\Admin\Registry\Registry;
13
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
14
use LAG\AdminBundle\DataProvider\DataProvider;
15
use LAG\AdminBundle\DataProvider\DataProviderInterface;
16
use LAG\AdminBundle\Admin\Event\AdminEvents;
17
use Exception;
18
use LAG\AdminBundle\Filter\Factory\RequestFilterFactory;
19
use LAG\AdminBundle\Message\MessageHandlerInterface;
20
use LAG\AdminBundle\Repository\RepositoryInterface;
21
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
22
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
23
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
24
25
/**
26
 * AdminFactory.
27
 *
28
 * Create admin from configuration
29
 */
30
class AdminFactory
31
{
32
    /**
33
     * @var bool
34
     */
35
    protected $isInit = false;
36
37
    /**
38
     * @var EventDispatcherInterface
39
     */
40
    protected $eventDispatcher;
41
42
    /**
43
     * @var EntityManager
44
     */
45
    protected $entityManager;
46
47
    /**
48
     * @var ConfigurationFactory
49
     */
50
    protected $configurationFactory;
51
52
    /**
53
     * User custom data provider, indexed by service id
54
     *
55
     * @var ParameterBagInterface
56
     */
57
    protected $dataProviders;
58
59
    /**
60
     * @var array
61
     */
62
    protected $adminConfigurations;
63
64
    /**
65
     * @var ActionFactory
66
     */
67
    protected $actionFactory;
68
69
    /**
70
     * @var MessageHandlerInterface
71
     */
72
    protected $messageHandler;
73
74
    /**
75
     * @var Registry
76
     */
77
    protected $registry;
78
79
    /**
80
     * @var RequestFilterFactory
81
     */
82
    protected $requestFilterFactory;
83
84
    /**
85
     * AdminFactory constructor.
86
     *
87
     * @param array $adminConfigurations
88
     * @param EventDispatcherInterface $eventDispatcher
89
     * @param EntityManager $entityManager
90
     * @param ConfigurationFactory $configurationFactory
91
     * @param ActionFactory $actionFactory
92
     * @param MessageHandlerInterface $messageHandler
93
     * @param Registry $registry
94
     * @param RequestFilterFactory $requestFilterFactory
95
     */
96 4
    public function __construct(
97
        array $adminConfigurations,
98
        EventDispatcherInterface $eventDispatcher,
99
        EntityManager $entityManager,
100
        ConfigurationFactory $configurationFactory,
101
        ActionFactory $actionFactory,
102
        MessageHandlerInterface $messageHandler,
103
        Registry $registry,
104
        RequestFilterFactory $requestFilterFactory
105
    ) {
106 4
        $this->eventDispatcher = $eventDispatcher;
107 4
        $this->entityManager = $entityManager;
108 4
        $this->configurationFactory = $configurationFactory;
109 4
        $this->adminConfigurations = $adminConfigurations;
110 4
        $this->actionFactory = $actionFactory;
111 4
        $this->messageHandler = $messageHandler;
112 4
        $this->dataProviders = new ParameterBag();
113 4
        $this->registry = $registry;
114 4
        $this->requestFilterFactory = $requestFilterFactory;
115 4
    }
116
117
    /**
118
     * Create admins from configuration and load them into the pool. Dispatch ADMIN_CREATE event.
119
     */
120 2
    public function init()
121
    {
122
        // init only once
123 2
        if ($this->isInit) {
124 1
            return;
125
        }
126
        // dispatch an event to allow configuration modification before resolving and creating admins
127 2
        $event = new BeforeConfigurationEvent($this->adminConfigurations);
128 2
        $this
129
            ->eventDispatcher
130 2
            ->dispatch(AdminEvents::BEFORE_CONFIGURATION, $event);
131
132
        // get the modified configuration
133 2
        $this->adminConfigurations = $event->getAdminConfigurations();
134
135
        // create Admins according to the given configuration
136 2
        foreach ($this->adminConfigurations as $name => $configuration) {
137
138
            // dispatch an event to allow modification on a specific admin
139 1
            $event = new AdminCreateEvent($name, $configuration);
140 1
            $this
141
                ->eventDispatcher
142 1
                ->dispatch(AdminEvents::ADMIN_CREATE, $event);
143
144
            // create Admin object and add it to the registry
145 1
            $admin = $this->create($name, $event->getAdminConfiguration());
146 1
            $this
147
                ->registry
148 1
                ->add($admin);
149
150
            // dispatch post-create event
151 1
            $event = new AdminCreatedEvent($admin);
152 1
            $this
153
                ->eventDispatcher
154 1
                ->dispatch(AdminEvents::ADMIN_CREATED, $event);
155 2
        }
156 2
        $this->isInit = true;
157 2
    }
158
159
    /**
160
     * Create an Admin from configuration values. It will be added to AdminFactory admin's list.
161
     *
162
     * @param string $name
163
     * @param array $configuration
164
     * @return Admin
165
     * @throws Exception
166
     */
167 2
    public function create($name, array $configuration)
168
    {
169
        // create AdminConfiguration object
170 2
        $adminConfiguration = $this
171
            ->configurationFactory
172 2
            ->createAdminConfiguration($configuration);
173
174
        // retrieve a data provider
175 2
        $dataProvider = $this->getDataProvider(
176 2
            $adminConfiguration->getParameter('entity'),
177 2
            $adminConfiguration->getParameter('data_provider')
178 2
        );
179
180
        // retrieve a request filter
181 2
        $requestFilter = $this
182
            ->requestFilterFactory
183 2
            ->create($adminConfiguration);
184
185
        // create Admin object
186 2
        $admin = new Admin(
187 2
            $name,
188 2
            $dataProvider,
189 2
            $adminConfiguration,
190 2
            $this->messageHandler,
191 2
            $this->eventDispatcher,
192
            $requestFilter
193 2
        );
194
195
        // adding actions
196 2
        foreach ($adminConfiguration->getParameter('actions') as $actionName => $actionConfiguration) {
197
            // create action and add it to the admin instance
198 2
            $this->createAction($admin, $actionName, $actionConfiguration);
199 2
        }
200
201 2
        return $admin;
202
    }
203
204
    /**
205
     * Add user custom repositories (called in the repository compiler pass), to avoid injecting the service container
206
     *
207
     * @param string $name
208
     * @param DataProviderInterface $dataProvider
209
     */
210 1
    public function addDataProvider($name, DataProviderInterface $dataProvider)
211
    {
212 1
        $this
213
            ->dataProviders
214 1
            ->set($name, $dataProvider);
215 1
    }
216
217
    /**
218
     * @return boolean
219
     */
220
    public function isInit()
221
    {
222
        return $this->isInit;
223
    }
224
225
    /**
226
     * @return Registry
227
     */
228 3
    public function getRegistry()
229
    {
230 3
        return $this->registry;
231
    }
232
233
    /**
234
     * Create an Action from the configuration, and add it to the Admin.
235
     *
236
     * @param AdminInterface $admin
237
     * @param $actionName
238
     * @param array $actionConfiguration
239
     */
240 2
    protected function createAction(AdminInterface $admin, $actionName, array $actionConfiguration)
241
    {
242
        // creating action from configuration
243 2
        $action = $this
244
            ->actionFactory
245 2
            ->create($actionName, $actionConfiguration, $admin);
246
247
        // adding action to admin
248 2
        $admin->addAction($action);
249 2
    }
250
251
    /**
252
     * Return a configured data provider or create an new instance of the default one.
253
     *
254
     * @param string $entityClass
255
     * @param string|null $name
256
     * @return DataProvider|mixed
257
     * @throws Exception
258
     */
259 2
    protected function getDataProvider($entityClass, $name = null)
260
    {
261
        // create or get repository according to the configuration
262 2
        if ($name) {
263
            // removing arobase if exists
264
            if (substr($name, 0, 1) == '@') {
265
                $name = substr($name, 1);
266
            }
267
268
            // custom data provider class must be loaded by the compiler pass
269
            if (!$this->dataProviders->has($name)) {
270
                throw new Exception(sprintf(
271
                    'Data provider %s not found. Did you add the @data_provider tag in your service ?',
272
                    $name
273
                ));
274
            }
275
            $dataProvider = $this
276
                ->dataProviders
277
                ->get($name);
278
        } else {
279
            // no data provider is configured, we create a new one
280 2
            $repository = $this
281
                ->entityManager
282 2
                ->getRepository($entityClass);
283
284 2
            if (!($repository instanceof RepositoryInterface)) {
285
                $repositoryClass = get_class($repository);
286
                throw new Exception("Repository {$repositoryClass} should implements ".RepositoryInterface::class);
287
            }
288 2
            $dataProvider = new DataProvider($repository);
289
        }
290 2
        return $dataProvider;
291
    }
292
293
}
294