Completed
Pull Request — dev (#50)
by Arnaud
02:55
created

AdminFactory::dispatchEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.6699

Importance

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