Completed
Push — dev ( 5c06f5...dcd39b )
by Arnaud
09:19
created

CRUDController::editAction()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 32
Code Lines 19

Duplication

Lines 32
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 32
loc 32
ccs 0
cts 25
cp 0
rs 8.8571
cc 3
eloc 19
nc 3
nop 1
crap 12
1
<?php
2
3
namespace LAG\AdminBundle\Controller;
4
5
use LAG\AdminBundle\Admin\AdminInterface;
6
use LAG\AdminBundle\Form\Handler\ListFormHandler;
7
use LAG\AdminBundle\Form\Type\AdminListType;
8
use LAG\AdminBundle\Form\Type\BatchActionType;
9
use BlueBear\BaseBundle\Behavior\ControllerTrait;
10
use DateTime;
11
use Doctrine\ORM\Mapping\MappingException;
12
use EE\DataExporterBundle\Service\DataExporter;
13
use Exception;
14
use LAG\AdminBundle\Form\Type\DeleteType;
15
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
16
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
17
use Symfony\Component\HttpFoundation\RedirectResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
21
use Symfony\Component\PropertyAccess\PropertyAccess;
22
use Symfony\Component\Security\Core\Role\Role;
23
24
/**
25
 * Class CRUDController
26
 *
27
 * Generic CRUD controller
28
 */
29
class CRUDController extends Controller
30
{
31
    use ControllerTrait;
32
33
    /**
34
     * Generic list action
35
     *
36
     * @Template("LAGAdminBundle:CRUD:list.html.twig")
37
     * @param Request $request
38
     * @return array
39
     */
40
    public function listAction(Request $request)
41
    {
42
        // retrieve admin from request route parameters
43
        $admin = $this->getAdminFromRequest($request);
44
        $admin->handleRequest($request, $this->getUser());
45
        // creating list form
46
        $form = $this->createForm(AdminListType::class, [
47
            'entities' => $admin->getEntities()
48
        ], [
49
            'batch_actions' => $admin
50
                ->getCurrentAction()
51
                ->getBatchActions()
52
        ]);
53
        $form->handleRequest($request);
54
55
        if ($request->get('export')) {
56
            return $this->exportEntities($admin, $request->get('export'));
57
        }
58
        if ($form->isValid()) {
59
            // get ids and batch action from list form data
60
            $formHandler = new ListFormHandler();
61
            $data = $formHandler->handle($form);
62
            $batchForm = $this->createForm(BatchActionType::class, [
63
                'batch_action' => $data['batch_action'],
64
                'entity_ids' => $data['ids']
65
            ], [
66
                'labels' => $data['labels']
67
            ]);
68
69
            // render batch view
70
            return $this->render('LAGAdminBundle:CRUD:batch.html.twig', [
71
                'admin' => $admin,
72
                'form' => $batchForm->createView()
73
            ]);
74
        }
75
        return [
76
            'admin' => $admin,
77
            'action' => $admin->getCurrentAction(),
78
            'form' => $form->createView()
79
        ];
80
    }
81
82
    /**
83
     * @param Request $request
84
     * @return RedirectResponse
85
     */
86
    public function batchAction(Request $request)
87
    {
88
        $admin = $this->getAdminFromRequest($request);
89
        $admin->handleRequest($request, $this->getUser());
90
        // create batch action form
91
        $form = $this->createForm(BatchActionType::class, [
92
            'batch_action' => [],
93
            'entity_ids' => []
94
        ]);
95
        $form->handleRequest($request);
96
97
        if ($form->isValid()) {
98
            $data = $form->getData();
99
            $admin->load([
100
                'id' => $data['entity_ids']
101
            ]);
102
103
            if ($data['batch_action'] == 'delete') {
104
                $admin->remove();
105
            }
106
        } else {
107
            throw new NotFoundHttpException('Invalid batch parameters');
108
        }
109
        // redirect to list view
110
        return $this->redirectToRoute($admin->generateRouteName('list'));
111
    }
112
113
    /**
114
     * Generic create action
115
     *
116
     * @Template("LAGAdminBundle:CRUD:edit.html.twig")
117
     * @param Request $request
118
     * @return array
119
     */
120 View Code Duplication
    public function createAction(Request $request)
121
    {
122
        $admin = $this->getAdminFromRequest($request);
123
        $admin->handleRequest($request, $this->getUser());
124
        // check permissions
125
        $this->forward404IfNotAllowed($admin);
126
        // create form
127
        $form = $this->createForm($admin->getConfiguration()->getFormType(), $admin->create());
128
        $form->handleRequest($request);
129
130
        if ($form->isValid()) {
131
            // save entity
132
            $success = $admin->save();
133
134
            if ($success) {
135
                // if save is pressed, user stay on the edit view
136
                if ($request->request->get('submit') == 'save') {
137
                    $editRoute = $admin->generateRouteName('edit');
138
139
                    return $this->redirectToRoute($editRoute, [
140
                        'id' => $admin->getUniqueEntity()->getId(),
141
                    ]);
142
                } else {
143
                    // otherwise user is redirected to list view
144
                    $listRoute = $admin->generateRouteName('list');
145
146
                    return $this->redirectToRoute($listRoute);
147
                }
148
            }
149
        }
150
        return [
151
            'admin' => $admin,
152
            'form' => $form->createView(),
153
        ];
154
    }
155
156
    /**
157
     * Generic edit action.
158
     *
159
     * @Template("LAGAdminBundle:CRUD:edit.html.twig")
160
     *
161
     * @param Request $request
162
     *
163
     * @return array|RedirectResponse
164
     */
165 View Code Duplication
    public function editAction(Request $request)
166
    {
167
        $admin = $this->getAdminFromRequest($request);
168
        $admin->handleRequest($request, $this->getUser());
169
        // check permissions
170
        $this->forward404IfNotAllowed($admin);
171
        // create form
172
        $form = $this->createForm($admin->getConfiguration()->getFormType(), $admin->getUniqueEntity());
173
        $form->handleRequest($request);
174
        $accessor = PropertyAccess::createPropertyAccessor();
175
176
        if ($form->isValid()) {
177
            $admin->save();
178
179
            if ($request->request->get('submit') == 'save') {
180
                $saveRoute = $admin->generateRouteName('edit');
181
182
                return $this->redirectToRoute($saveRoute, [
183
                    'id' => $accessor->getValue($admin->getUniqueEntity(), 'id'),
184
                ]);
185
            } else {
186
                $listRoute = $admin->generateRouteName('list');
187
                // redirect to list
188
                return $this->redirectToRoute($listRoute);
189
            }
190
        }
191
192
        return [
193
            'admin' => $admin,
194
            'form' => $form->createView(),
195
        ];
196
    }
197
198
    /**
199
     * Generic delete action
200
     *
201
     * @Template("LAGAdminBundle:CRUD:delete.html.twig")
202
     *
203
     * @param Request $request
204
     *
205
     * @return RedirectResponse|array
206
     */
207
    public function deleteAction(Request $request)
208
    {
209
        $admin = $this->getAdminFromRequest($request);
210
        $admin->handleRequest($request, $this->getUser());
211
        // check permissions
212
        $this->forward404IfNotAllowed($admin);
213
        // create form to avoid deletion by url
214
        $form = $this->createForm(DeleteType::class, $admin->getUniqueEntity());
215
        $form->handleRequest($request);
216
217
        if ($form->isValid()) {
218
            $admin->remove();
219
            // redirect to list
220
            $listRoute = $admin->generateRouteName('list');
221
222
            return $this->redirectToRoute($listRoute);
223
        }
224
225
        return [
226
            'admin' => $admin,
227
            'form' => $form->createView(),
228
        ];
229
    }
230
231
    /**
232
     * Export entities according to a type (json, csv, xls...)
233
     *
234
     * @param AdminInterface $admin
235
     * @param $exportType
236
     *
237
     * @return Response
238
     *
239
     * @throws MappingException
240
     */
241
    protected function exportEntities(AdminInterface $admin, $exportType)
242
    {
243
        // check allowed export types
244
        $this->forward404Unless(in_array($exportType, ['json', 'html', 'xls', 'csv', 'xml']));
245
        /** @var DataExporter $exporter */
246
        $exporter = $this->get('ee.dataexporter');
247
        $metadata = $this
248
            ->getEntityManager()
249
            ->getClassMetadata($admin->getConfiguration()->getEntityName());
250
        $exportColumns = [];
251
        $fields = $metadata->getFieldNames();
252
        $hooks = [];
253
254
        foreach ($fields as $fieldName) {
255
            $exporter->addHook(function ($fieldValue) {
256
                // if field is an array
257
                if (is_array($fieldValue)) {
258
                    $value = recursiveImplode(', ', $fieldValue);
259
                } elseif ($fieldValue instanceof DateTime) {
260
                    // format date in string
261
                    $value = $fieldValue->format('c');
262
                } else {
263
                    $value = $fieldValue;
264
                }
265
266
                return $value;
267
            }, "{$fieldName}");
268
            // add field column to export
269
            $exportColumns[$fieldName] = $fieldName;
270
        }
271
        $exporter
272
            ->setOptions($exportType, [
273
                'fileName' => $admin->getName() . '-export-' . date('Y-m-d'),
274
            ])
275
            ->setColumns($exportColumns)
276
            ->setData($admin->getEntities());
277
        foreach ($hooks as $hookName => $hook) {
278
            $exporter->addHook($hook, $hookName);
279
        }
280
281
        return $exporter->render();
282
    }
283
284
    /**
285
     * Forward to 404 if user is not allowed by configuration for an action.
286
     *
287
     * @param AdminInterface $admin
288
     */
289
    protected function forward404IfNotAllowed(AdminInterface $admin)
290
    {
291
        // TODO move authorizations logic into kernel.request event
292
        $this->forward404Unless($this->getUser(), 'You must be logged to access to this url');
293
        $roles = $this
294
            ->getUser()
295
            ->getRoles();
296
        // check permissions and actions
297
        $this->forward404Unless(
298
            $admin->isActionGranted($admin->getCurrentAction()->getName(), $roles),
299
            sprintf('User with roles %s not allowed for action "%s"',
300
                implode(', ', array_map(function (Role $role) {
301
                    return $role->getRole();
302
                }, $roles)),
303
                $admin->getCurrentAction()->getName()
304
            )
305
        );
306
    }
307
308
    /**
309
     * Return an Admin object according to the request route parameters.
310
     *
311
     * @param Request $request
312
     * @return AdminInterface
313
     * @throws Exception
314
     */
315
    protected function getAdminFromRequest(Request $request)
316
    {
317
        return $this
318
            ->get('lag.admin.factory')
319
            ->getAdminFromRequest($request);
320
    }
321
}
322