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

AdminFactory::getRegistry()   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 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