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

AdminFactory::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 13
cts 13
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 23
nc 1
nop 11
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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