Completed
Pull Request — master (#71)
by Arnaud
05:11 queued 02:54
created

CRUDController::forward404Unless()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 2
crap 6
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 Exception;
10
use LAG\AdminBundle\Form\Type\DeleteType;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
12
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
13
use Symfony\Component\HttpFoundation\RedirectResponse;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16
use Symfony\Component\PropertyAccess\PropertyAccess;
17
use Symfony\Component\Security\Core\Role\Role;
18
19
/**
20
 * Class CRUDController
21
 *
22
 * Generic CRUD controller
23
 */
24
class CRUDController extends Controller
25
{
26
    /**
27
     * Generic list action.
28
     *
29
     * @Template("LAGAdminBundle:CRUD:list.html.twig")
30
     * @param Request $request
31
     * @return array
32
     */
33
    public function listAction(Request $request)
34
    {
35
        // retrieve admin from request route parameters
36
        $admin = $this->getAdminFromRequest($request);
37
        $admin->handleRequest($request, $this->getUser());
38
39
        // retrieve batch actions from configuration
40
        $batchActions = $admin
41
            ->getCurrentAction()
42
            ->getConfiguration()
43
            ->getParameter('batch');
44
45
        // pass admin and current action to the view
46
        $viewParameters = [
47
            'admin' => $admin,
48
            'action' => $admin->getCurrentAction(),
49
        ];
50
51
        // if batch are configured, we handle a list of checkboxes
52
        if ($batchActions) {
53
            // creating list form
54
            $form = $this->createForm(AdminListType::class, [
55
                'entities' => $admin->getEntities()
56
            ], [
57
                'batch_actions' => $batchActions['items'],
58
                'admin' => $admin
59
            ]);
60
            $form->handleRequest($request);
61
62
            if ($form->isValid()) {
63
                // get ids and batch action from list form data
64
                $formHandler = new ListFormHandler();
65
                $data = $formHandler->handle($form);
66
                $batchForm = $this->createForm(BatchActionType::class, [
67
                    'batch_action' => $data['batch_action'],
68
                    'entity_ids' => $data['ids']
69
                ], [
70
                    'labels' => $data['labels']
71
                ]);
72
73
                // render batch view
74
                return $this->render('LAGAdminBundle:CRUD:batch.html.twig', [
75
                    'admin' => $admin,
76
                    'form' => $batchForm->createView()
77
                ]);
78
            }
79
            $viewParameters['form'] = $form->createView();
80
        }
81
82
        return $viewParameters;
83
    }
84
85
    /**
86
     * @param Request $request
87
     * @return RedirectResponse
88
     */
89
    public function batchAction(Request $request)
90
    {
91
        $admin = $this->getAdminFromRequest($request);
92
        $admin->handleRequest($request, $this->getUser());
93
        // create batch action form
94
        $form = $this->createForm(BatchActionType::class, [
95
            'batch_action' => [],
96
            'entity_ids' => []
97
        ]);
98
        $form->handleRequest($request);
99
100
        if ($form->isValid()) {
101
            $data = $form->getData();
102
            $admin->load([
103
                'id' => $data['entity_ids']
104
            ]);
105
106
            if ($data['batch_action'] == 'delete') {
107
                $admin->remove();
108
            }
109
        } else {
110
            throw new NotFoundHttpException('Invalid batch parameters : '.$form->getErrors(true, false));
111
        }
112
        // redirect to list view
113
        return $this->redirectToRoute($admin->generateRouteName('list'));
114
    }
115
116
    /**
117
     * Generic create action.
118
     *
119
     * @Template("LAGAdminBundle:CRUD:edit.html.twig")
120
     * @param Request $request
121
     * @return array|RedirectResponse
122
     */
123 View Code Duplication
    public function createAction(Request $request)
124
    {
125
        $admin = $this->getAdminFromRequest($request);
126
        $admin->handleRequest($request, $this->getUser());
127
        
128
        // check permissions
129
        $this->forward404IfNotAllowed($admin);
130
        
131
        // create form
132
        $form = $this->createForm($admin->getConfiguration()->getParameter('form'), $admin->create());
133
        $form->handleRequest($request);
134
135
        if ($form->isValid()) {
136
            // save entity
137
            $success = $admin->save();
138
139
            if ($success) {
140
                // if save is pressed, user stay on the edit view
141
                if ($request->request->get('submit') == 'save') {
142
                    $editRoute = $admin->generateRouteName('edit');
143
144
                    return $this->redirectToRoute($editRoute, [
145
                        'id' => $admin->getUniqueEntity()->getId(),
146
                    ]);
147
                } else {
148
                    // otherwise user is redirected to list view
149
                    $listRoute = $admin->generateRouteName('list');
150
151
                    return $this->redirectToRoute($listRoute);
152
                }
153
            }
154
        }
155
        return [
156
            'admin' => $admin,
157
            'form' => $form->createView(),
158
        ];
159
    }
160
161
    /**
162
     * Generic edit action.
163
     *
164
     * @Template("LAGAdminBundle:CRUD:edit.html.twig")
165
     *
166
     * @param Request $request
167
     *
168
     * @return array|RedirectResponse
169
     */
170 View Code Duplication
    public function editAction(Request $request)
171
    {
172
        $admin = $this->getAdminFromRequest($request);
173
        $admin->handleRequest($request, $this->getUser());
174
        // check permissions
175
        $this->forward404IfNotAllowed($admin);
176
        // create form
177
        $form = $this->createForm($admin->getConfiguration()->getParameter('form'), $admin->getUniqueEntity());
178
        $form->handleRequest($request);
179
        $accessor = PropertyAccess::createPropertyAccessor();
180
181
        if ($form->isValid()) {
182
            $admin->save();
183
184
            if ($request->request->get('submit') == 'save') {
185
                $saveRoute = $admin->generateRouteName('edit');
186
187
                return $this->redirectToRoute($saveRoute, [
188
                    'id' => $accessor->getValue($admin->getUniqueEntity(), 'id'),
189
                ]);
190
            } else {
191
                $listRoute = $admin->generateRouteName('list');
192
                // redirect to list
193
                return $this->redirectToRoute($listRoute);
194
            }
195
        }
196
197
        return [
198
            'admin' => $admin,
199
            'form' => $form->createView(),
200
        ];
201
    }
202
203
    /**
204
     * Generic delete action.
205
     *
206
     * @Template("LAGAdminBundle:CRUD:delete.html.twig")
207
     * @param Request $request
208
     * @return RedirectResponse|array
209
     */
210
    public function deleteAction(Request $request)
211
    {
212
        $admin = $this->getAdminFromRequest($request);
213
        $admin->handleRequest($request, $this->getUser());
214
        // check permissions
215
        $this->forward404IfNotAllowed($admin);
216
        // create form to avoid deletion by url
217
        $form = $this->createForm(DeleteType::class, $admin->getUniqueEntity());
218
        $form->handleRequest($request);
219
220
        if ($form->isValid()) {
221
            $admin->remove();
222
            // redirect to list
223
            $listRoute = $admin->generateRouteName('list');
224
225
            return $this->redirectToRoute($listRoute);
226
        }
227
228
        return [
229
            'admin' => $admin,
230
            'form' => $form->createView(),
231
        ];
232
    }
233
234
    /**
235
     * Throw a 404 Exception if $boolean is false or null
236
     *
237
     * @param $boolean
238
     * @param string $message
239
     */
240
    protected function forward404Unless($boolean, $message = '404 Not Found')
241
    {
242
        if (!$boolean) {
243
            throw $this->createNotFoundException($message);
244
        }
245
    }
246
247
    /**
248
     * Forward to 404 if user is not allowed by configuration for an action.
249
     *
250
     * @param AdminInterface $admin
251
     */
252
    protected function forward404IfNotAllowed(AdminInterface $admin)
253
    {
254
        $this->forward404Unless($this->getUser(), 'You must be logged to access to this url');
255
        $roles = $this
256
            ->getUser()
257
            ->getRoles();
258
        // check permissions and actions
259
        $this->forward404Unless(
260
            $admin->isActionGranted($admin->getCurrentAction()->getName(), $roles),
261
            sprintf('User with roles %s not allowed for action "%s"',
262
                implode(', ', array_map(function(Role $role) {
263
                    return $role->getRole();
264
                }, $roles)),
265
                $admin->getCurrentAction()->getName()
266
            )
267
        );
268
    }
269
270
    /**
271
     * Return an Admin object according to the request route parameters.
272
     *
273
     * @param Request $request
274
     * @return AdminInterface
275
     * @throws Exception
276
     */
277
    protected function getAdminFromRequest(Request $request)
278
    {
279
        return $this
280
            ->get('lag.admin.request_handler')
281
            ->handle($request);
282
    }
283
}
284