Completed
Push — dev ( df0c76...243dfc )
by Arnaud
02:38
created

AdminFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 12
cts 12
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 18
nc 1
nop 8
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 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 4
     * @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
    public function __construct(
97
        array $adminConfigurations,
98 4
        EventDispatcherInterface $eventDispatcher,
99 4
        EntityManager $entityManager,
100 4
        ConfigurationFactory $configurationFactory,
101 4
        ActionFactory $actionFactory,
102 4
        MessageHandlerInterface $messageHandler,
103 4
        Registry $registry,
104 4
        RequestFilterFactory $requestFilterFactory
105 4
    ) {
106 4
        $this->eventDispatcher = $eventDispatcher;
107
        $this->entityManager = $entityManager;
108
        $this->configurationFactory = $configurationFactory;
109
        $this->adminConfigurations = $adminConfigurations;
110
        $this->actionFactory = $actionFactory;
111 2
        $this->messageHandler = $messageHandler;
112
        $this->dataProviders = new ParameterBag();
113
        $this->registry = $registry;
114 2
        $this->requestFilterFactory = $requestFilterFactory;
115 1
    }
116
117
    /**
118 2
     * Create admins from configuration and load them into the pool. Dispatch ADMIN_CREATE event.
119 2
     */
120
    public function init()
121 2
    {
122
        // init only once
123
        if ($this->isInit) {
124 2
            return;
125
        }
126
        // dispatch an event to allow configuration modification before resolving and creating admins
127 2
        $event = new BeforeConfigurationEvent($this->adminConfigurations);
128
        $this
129
            ->eventDispatcher
130 1
            ->dispatch(AdminEvents::BEFORE_CONFIGURATION, $event);
131 1
132
        // get the modified configuration
133 1
        $this->adminConfigurations = $event->getAdminConfigurations();
134
135
        // create Admins according to the given configuration
136 1
        foreach ($this->adminConfigurations as $name => $configuration) {
137 1
138
            // dispatch an event to allow modification on a specific admin
139 1
            $event = new AdminCreateEvent($name, $configuration);
140
            $this
141
                ->eventDispatcher
142 1
                ->dispatch(AdminEvents::ADMIN_CREATE, $event);
143 1
144
            // create Admin object and add it to the registry
145 1
            $admin = $this->create($name, $event->getAdminConfiguration());
146 2
            $this
147 2
                ->registry
148 2
                ->add($admin);
149
150
            // dispatch post-create event
151
            $event = new AdminCreatedEvent($admin);
152
            $this
153
                ->eventDispatcher
154
                ->dispatch(AdminEvents::ADMIN_CREATED, $event);
155
        }
156
        $this->isInit = true;
157
    }
158 2
159
    /**
160
     * Create an Admin from configuration values. It will be added to AdminFactory admin's list.
161 2
     *
162
     * @param string $name
163 2
     * @param array $configuration
164
     * @return Admin
165
     * @throws Exception
166 2
     */
167 2
    public function create($name, array $configuration)
168 2
    {
169 2
        // create AdminConfiguration object
170
        $adminConfiguration = $this
171
            ->configurationFactory
172 2
            ->createAdminConfiguration($configuration);
173 2
174 2
        // 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 2
185
        // create Admin object
186 2
        $admin = new Admin(
187
            $name,
188
            $dataProvider,
189
            $adminConfiguration,
190
            $this->messageHandler,
191
            $this->eventDispatcher,
192
            $requestFilter
193
        );
194
195 1
        // adding actions
196
        foreach ($adminConfiguration->getParameter('actions') as $actionName => $actionConfiguration) {
197 1
            // create action and add it to the admin instance
198
            $this->createAction($admin, $actionName, $actionConfiguration);
199 1
        }
200 1
201
        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
    public function addDataProvider($name, DataProviderInterface $dataProvider)
211
    {
212
        $this
213 3
            ->dataProviders
214
            ->set($name, $dataProvider);
215 3
    }
216
217
    /**
218
     * @return boolean
219
     */
220
    public function isInit()
221
    {
222
        return $this->isInit;
223
    }
224
225 2
    /**
226
     * @return Registry
227
     */
228 2
    public function getRegistry()
229
    {
230 2
        return $this->registry;
231
    }
232
233 2
    /**
234 2
     * 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
    protected function createAction(AdminInterface $admin, $actionName, array $actionConfiguration)
241
    {
242
        // creating action from configuration
243
        $action = $this
244 2
            ->actionFactory
245
            ->create($actionName, $actionConfiguration, $admin);
246
247 2
        // adding action to admin
248
        $admin->addAction($action);
249
    }
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
    protected function getDataProvider($entityClass, $name = null)
260
    {
261
        // create or get repository according to the configuration
262
        if ($name) {
263
            // removing arobase if exists
264
            if (substr($name, 0, 1) == '@') {
265 2
                $name = substr($name, 1);
266
            }
267 2
268
            // custom data provider class must be loaded by the compiler pass
269 2
            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 2
                ));
274
            }
275 2
            $dataProvider = $this
276
                ->dataProviders
277
                ->get($name);
278
        } else {
279
            // no data provider is configured, we create a new one
280
            $repository = $this
281
                ->entityManager
282
                ->getRepository($entityClass);
283
284
            if (!($repository instanceof RepositoryInterface)) {
285
                $repositoryClass = get_class($repository);
286
                throw new Exception("Repository {$repositoryClass} should implements ".RepositoryInterface::class);
287
            }
288
            $dataProvider = new DataProvider($repository);
289
        }
290
        return $dataProvider;
291
    }
292
293
}
294