Completed
Pull Request — master (#90)
by Arnaud
03:18
created

AdminFactory::isInit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace LAG\AdminBundle\Admin\Factory;
4
5
use LAG\AdminBundle\Action\Factory\ActionFactory;
6
use LAG\AdminBundle\Action\Registry\Registry as ActionRegistry;
7
use LAG\AdminBundle\Admin\AdminAwareInterface;
8
use LAG\AdminBundle\Admin\AdminInterface;
9
use LAG\AdminBundle\Admin\Configuration\AdminConfiguration;
10
use LAG\AdminBundle\Admin\Event\AdminCreatedEvent;
11
use LAG\AdminBundle\Admin\Event\AdminCreateEvent;
12
use LAG\AdminBundle\Admin\Event\AdminInjectedEvent;
13
use LAG\AdminBundle\Admin\Event\BeforeConfigurationEvent;
14
use LAG\AdminBundle\Admin\Registry\Registry;
15
use LAG\AdminBundle\Admin\Request\RequestHandler;
16
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
17
use LAG\AdminBundle\Admin\Event\AdminEvents;
18
use LAG\AdminBundle\DataProvider\Factory\DataProviderFactory;
19
use LAG\AdminBundle\DataProvider\Loader\EntityLoader;
20
use LAG\AdminBundle\LAGAdminBundle;
21
use LAG\AdminBundle\Message\MessageHandlerInterface;
22
use LogicException;
23
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
24
use Symfony\Component\HttpFoundation\Request;
25
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
26
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
27
28
/**
29
 * AdminFactory.
30
 *
31
 * This class is responsible for the creation of Admins from configuration array.
32
 */
33
class AdminFactory
34
{
35
    /**
36
     * @var bool
37
     */
38
    private $isInit = false;
39
40
    /**
41
     * @var EventDispatcherInterface
42
     */
43
    private $eventDispatcher;
44
45
    /**
46
     * @var ConfigurationFactory
47
     */
48
    private $configurationFactory;
49
50
    /**
51
     * @var AdminConfiguration[]
52
     */
53
    private $adminConfigurations;
54
55
    /**
56
     * @var ActionFactory
57
     */
58
    private $actionFactory;
59
60
    /**
61
     * @var MessageHandlerInterface
62
     */
63
    private $messageHandler;
64
65
    /**
66
     * @var Registry
67
     */
68
    private $adminRegistry;
69
70
    /**
71
     * @var DataProviderFactory
72
     */
73
    private $dataProviderFactory;
74
    
75
    /**
76
     * @var RequestHandler
77
     */
78
    private $requestHandler;
79
    
80
    /**
81
     * @var AuthorizationCheckerInterface
82
     */
83
    private $authorizationChecker;
84
    
85
    /**
86
     * @var TokenStorageInterface
87
     */
88
    private $tokenStorage;
89
    
90
    /**
91
     * @var ActionRegistry
92
     */
93
    private $actionRegistry;
94
    
95
    /**
96
     * AdminFactory constructor.
97
     *
98
     * @param array                         $adminConfigurations
99
     * @param EventDispatcherInterface      $eventDispatcher
100
     * @param MessageHandlerInterface       $messageHandler
101
     * @param Registry                      $adminRegistry
102
     * @param ActionRegistry                $actionRegistry
103
     * @param ActionFactory                 $actionFactory
104
     * @param ConfigurationFactory          $configurationFactory
105
     * @param DataProviderFactory           $dataProviderFactory
106
     * @param RequestHandler                $requestHandler
107
     * @param AuthorizationCheckerInterface $authorizationChecker
108
     * @param TokenStorageInterface         $tokenStorage
109
     */
110 2
    public function __construct(
111
        array $adminConfigurations,
112
        EventDispatcherInterface $eventDispatcher,
113
        MessageHandlerInterface $messageHandler,
114
        Registry $adminRegistry,
115
        ActionRegistry $actionRegistry,
116
        ActionFactory $actionFactory,
117
        ConfigurationFactory $configurationFactory,
118
        DataProviderFactory $dataProviderFactory,
119
        RequestHandler $requestHandler,
120
        AuthorizationCheckerInterface $authorizationChecker,
121
        TokenStorageInterface $tokenStorage
122
    ) {
123 2
        $this->eventDispatcher = $eventDispatcher;
124 2
        $this->configurationFactory = $configurationFactory;
125 2
        $this->adminConfigurations = $adminConfigurations;
126 2
        $this->actionFactory = $actionFactory;
127 2
        $this->messageHandler = $messageHandler;
128 2
        $this->adminRegistry = $adminRegistry;
129 2
        $this->dataProviderFactory = $dataProviderFactory;
130 2
        $this->requestHandler = $requestHandler;
131 2
        $this->authorizationChecker = $authorizationChecker;
132 2
        $this->tokenStorage = $tokenStorage;
133 2
        $this->actionRegistry = $actionRegistry;
134 2
    }
135
136
    /**
137
     * Create admins from configuration and load them into the pool. Dispatch ADMIN_CREATE event.
138
     */
139 1
    public function init()
140
    {
141
        // init only once
142 1
        if ($this->isInit) {
143 1
            return;
144
        }
145
        // dispatch an event to allow configuration modification before resolving and creating admins
146 1
        $event = new BeforeConfigurationEvent($this->adminConfigurations);
147
        $this
148 1
            ->eventDispatcher
149 1
            ->dispatch(AdminEvents::BEFORE_CONFIGURATION, $event)
150
        ;
151
152
        // get the modified configuration
153 1
        $this->adminConfigurations = $event->getAdminConfigurations();
154
155
        // create Admins according to the given configuration
156 1
        foreach ($this->adminConfigurations as $name => $configuration) {
157
158
            // dispatch an event to allow modification on a specific admin
159 1
            $event = new AdminCreateEvent($name, $configuration);
160
            $this
161 1
                ->eventDispatcher
162 1
                ->dispatch(AdminEvents::ADMIN_CREATE, $event);
163
164
            // create Admin object and add it to the registry
165 1
            $admin = $this->create($name, $event->getAdminConfiguration());
166
            $this
167 1
                ->adminRegistry
168 1
                ->add($admin);
169
170
            // dispatch post-create event
171 1
            $event = new AdminCreatedEvent($admin);
172
            $this
173 1
                ->eventDispatcher
174 1
                ->dispatch(AdminEvents::ADMIN_CREATED, $event);
175
        }
176 1
        $this->isInit = true;
177 1
    }
178
179
    /**
180
     * Create an Admin from configuration values. It will be added to AdminFactory admin's list.
181
     *
182
     * @param string $name
183
     * @param array $configuration
184
     *
185
     * @return AdminInterface
186
     *
187
     * @throws LogicException
188
     */
189 1
    public function create($name, array $configuration)
190
    {
191
        // create AdminConfiguration object
192
        $adminConfiguration = $this
193 1
            ->configurationFactory
194 1
            ->createAdminConfiguration($configuration)
195
        ;
196
        
197
        // retrieve a data provider and load it into the loader
198
        $dataProvider = $this
199 1
            ->dataProviderFactory
200 1
            ->get($adminConfiguration->getParameter('data_provider'), $adminConfiguration->getParameter('entity'))
201
        ;
202 1
        $entityLoader = new EntityLoader($dataProvider);
203
    
204
        // retrieve Admin dynamic class
205
        $adminClass = $this
206 1
            ->configurationFactory
207 1
            ->getApplicationConfiguration()
208 1
            ->getParameter('admin_class')
209
        ;
210
    
211
        // retrieve the actions services
212 1
        $actions = $this->retrieveActions($name, $configuration);
213
214
        // create Admin object
215 1
        $admin = new $adminClass(
216
            $name,
217
            $entityLoader,
218
            $adminConfiguration,
219 1
            $this->messageHandler,
220 1
            $this->eventDispatcher,
221 1
            $this->authorizationChecker,
222 1
            $this->tokenStorage,
223 1
            $actions
224
        );
225
    
226 1
        if (!$admin instanceof AdminInterface) {
227
            throw new LogicException('Class "'.get_class($admin).'" should implements '.AdminInterface::class);
228
        }
229
230 1
        return $admin;
231
    }
232
    
233
    /**
234
     * Inject an Admin into an AdminAware controller. Add this Admin to Twig global parameters.
235
     *
236
     * @param mixed $controller
237
     * @param Request $request
238
     */
239 1
    public function injectAdmin($controller, Request $request)
240
    {
241
        // the controller should be Admin aware to have an Admin injected
242 1
        if (!$controller instanceof AdminAwareInterface) {
243 1
            return;
244
        }
245
        // get admin from the request parameters
246
        $admin = $this
247 1
            ->requestHandler
248 1
            ->handle($request)
249
        ;
250
        
251
        // inject the Admin in the controller
252 1
        $controller->setAdmin($admin);
253
        $this
254 1
            ->eventDispatcher
255 1
            ->dispatch(AdminEvents::ADMIN_INJECTED, new AdminInjectedEvent($admin, $controller))
256
        ;
257 1
    }
258
259
    /**
260
     * Return true if the AdminFactory is initialized.
261
     *
262
     * @return boolean
263
     */
264 1
    public function isInit()
265
    {
266 1
        return $this->isInit;
267
    }
268
    
269
    /**
270
     * @param $adminName
271
     * @param array $configuration
272
     *
273
     * @return array
274
     */
275 1
    private function retrieveActions($adminName, array $configuration)
276
    {
277 1
        $actions = [];
278
    
279 1
        foreach ($configuration['actions'] as $name => $actionConfiguration) {
280 1
            if (null !== $actionConfiguration && array_key_exists('service', $actionConfiguration)) {
281 1
                $serviceId = $actionConfiguration['service'];
282
            } else {
283
                $serviceId = $this->getActionServiceId($name, $adminName);
284
            }
285
            
286 1
            $actions[$name] = $this
287 1
                ->actionRegistry
288 1
                ->get($serviceId)
289
            ;
290
        }
291
    
292 1
        return $actions;
293
    }
294
    
295
    /**
296
     * @param $name
297
     * @param $adminName
298
     *
299
     * @return string
300
     */
301
    private function getActionServiceId($name, $adminName)
302
    {
303
        $mapping = LAGAdminBundle::getDefaultActionServiceMapping();
304
    
305
        if (!array_key_exists($name, $mapping)) {
306
            throw new LogicException('Action "'.$name.'" service id was not found for admin "'.$adminName.'"');
307
        }
308
    
309
        return $mapping[$name];
310
    }
311
}
312