Completed
Pull Request — dev (#25)
by Arnaud
16:09
created

CRUDController   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 250
Duplicated Lines 26.8 %

Coupling/Cohesion

Components 1
Dependencies 14

Test Coverage

Coverage 0%

Importance

Changes 11
Bugs 5 Features 0
Metric Value
wmc 17
c 11
b 5
f 0
lcom 1
cbo 14
dl 67
loc 250
ccs 0
cts 142
cp 0
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A listAction() 0 51 3
B batchAction() 0 26 3
B createAction() 35 35 4
B editAction() 32 32 3
A deleteAction() 0 23 2
A forward404IfNotAllowed() 0 18 1
A getAdminFromRequest() 0 6 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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