Completed
Pull Request — dev (#50)
by Arnaud
03:27
created

AdminFactory::dispatchEvent()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 3

Importance

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