AdminListController   F
last analyzed

Complexity

Total Complexity 60

Size/Duplication

Total Lines 532
Duplicated Lines 32.33 %

Coupling/Cohesion

Components 1
Dependencies 23

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 60
lcom 1
cbo 23
dl 172
loc 532
ccs 0
cts 341
cp 0
rs 3.6
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getEntityManager() 0 4 1
A doIndexAction() 0 15 1
A doExportAction() 0 12 2
C doAddAction() 43 83 12
F doEditAction() 47 113 18
A doViewAction() 0 27 4
B doDeleteAction() 0 42 7
A doMoveUpAction() 35 35 3
A doMoveDownAction() 35 35 3
A getMaxSortableField() 0 9 1
A isLockableEntityLocked() 0 10 2
A setSortWeightOnNewItem() 0 12 2
A buildSortableFieldActions() 12 25 2
A getAdminListRepositoryName() 0 12 2

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AdminListController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AdminListController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Kunstmaan\AdminListBundle\Controller;
4
5
use Doctrine\ORM\EntityManager;
6
use Kunstmaan\AdminBundle\Entity\EntityInterface;
7
use Kunstmaan\AdminBundle\Event\AdaptSimpleFormEvent;
8
use Kunstmaan\AdminBundle\Event\Events;
9
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
10
use Kunstmaan\AdminListBundle\AdminList\AdminList;
11
use Kunstmaan\AdminListBundle\AdminList\Configurator\AbstractAdminListConfigurator;
12
use Kunstmaan\AdminListBundle\AdminList\ItemAction\SimpleItemAction;
13
use Kunstmaan\AdminListBundle\AdminList\SortableInterface;
14
use Kunstmaan\AdminListBundle\Entity\LockableEntityInterface;
15
use Kunstmaan\AdminListBundle\Event\AdminListEvent;
16
use Kunstmaan\AdminListBundle\Event\AdminListEvents;
17
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
18
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
19
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
20
use Symfony\Component\HttpFoundation\RedirectResponse;
21
use Kunstmaan\AdminListBundle\Service\EntityVersionLockService;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
25
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26
use Symfony\Component\PropertyAccess\PropertyAccess;
27
28
/**
29
 * AdminListController
30
 */
31
abstract class AdminListController extends Controller
0 ignored issues
show
Deprecated Code introduced by Jeroen Thora
The class Symfony\Bundle\Framework...e\Controller\Controller has been deprecated with message: since Symfony 4.2, use "Symfony\Bundle\FrameworkBundle\Controller\AbstractController" instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
32
{
33
    /**
34
     * You can override this method to return the correct entity manager when using multiple databases ...
35
     *
36
     * @return \Doctrine\Common\Persistence\ObjectManager|object
0 ignored issues
show
Documentation introduced by Wim Vandersmissen
Consider making the return type a bit more specific; maybe use \Doctrine\Common\Persistence\ObjectManager.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
37
     */
38
    protected function getEntityManager()
39
    {
40
        return $this->getDoctrine()->getManager();
41
    }
42
43
    /**
44
     * Shows the list of entities
45
     *
46
     * @param AbstractAdminListConfigurator $configurator
47
     * @param null|Request                  $request
0 ignored issues
show
Documentation introduced by Sander Goossens
Consider making the type for parameter $request a bit more specific; maybe use Request.
Loading history...
48
     *
49
     * @return Response
50
     */
51
    protected function doIndexAction(AbstractAdminListConfigurator $configurator, Request $request)
52
    {
53
        /* @var AdminList $adminList */
54
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createList($configurator);
55
        $adminList->bindRequest($request);
56
57
        $this->buildSortableFieldActions($configurator);
58
59
        return new Response(
60
            $this->renderView(
61
                $configurator->getListTemplate(),
62
                array('adminlist' => $adminList, 'adminlistconfigurator' => $configurator, 'addparams' => array())
63
            )
64
        );
65
    }
66
67
    /**
68
     * Export a list of Entities
69
     *
70
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
71
     * @param string                        $_format      The format to export to
72
     * @param null|Request                  $request
73
     *
74
     * @throws AccessDeniedHttpException
75
     *
76
     * @return Response
77
     */
78
    protected function doExportAction(AbstractAdminListConfigurator $configurator, $_format, Request $request = null)
79
    {
80
        if (!$configurator->canExport()) {
81
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
82
        }
83
84
        /* @var AdminList $adminList */
85
        $adminList = $this->container->get('kunstmaan_adminlist.factory')->createExportList($configurator);
86
        $adminList->bindRequest($request);
0 ignored issues
show
Bug introduced by Kim Ausloos
It seems like $request defined by parameter $request on line 78 can be null; however, Kunstmaan\AdminListBundl...dminList::bindRequest() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
87
88
        return $this->container->get('kunstmaan_adminlist.service.export')->getDownloadableResponse($adminList, $_format);
89
    }
90
91
    /**
92
     * Creates and processes the form to add a new Entity
93
     *
94
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
95
     * @param string                        $type         The type to add
0 ignored issues
show
Documentation introduced by Sander Goossens
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
96
     * @param null|Request                  $request
0 ignored issues
show
Documentation introduced by Sander Goossens
Consider making the type for parameter $request a bit more specific; maybe use Request.
Loading history...
97
     *
98
     * @throws AccessDeniedHttpException
99
     *
100
     * @return Response
101
     */
102
    protected function doAddAction(AbstractAdminListConfigurator $configurator, $type = null, Request $request)
103
    {
104
        if (!$configurator->canAdd()) {
105
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
106
        }
107
108
        /* @var EntityManager $em */
109
        $em = $this->getEntityManager();
110
        $entityName = isset($type) ? $type : $configurator->getRepositoryName();
111
112
        $classMetaData = $em->getClassMetadata($entityName);
113
        // Creates a new instance of the mapped class, without invoking the constructor.
114
        $classname = $classMetaData->getName();
115
        $helper = new $classname();
116
        $helper = $configurator->decorateNewEntity($helper);
117
118
        $formType = $configurator->getAdminType($helper);
119
120
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
121
        $event = $this->container->get('event_dispatcher')->dispatch(Events::ADAPT_SIMPLE_FORM, $event);
122
        $tabPane = $event->getTabPane();
123
124
        $form = $this->createForm($formType, $helper, $event->getOptions());
125
126 View Code Duplication
        if ($request->isMethod('POST')) {
0 ignored issues
show
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
            if ($tabPane) {
128
                $tabPane->bindRequest($request);
129
                $form = $tabPane->getForm();
130
            } else {
131
                $form->handleRequest($request);
132
            }
133
134
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
135
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
136
                $adminListEvent = new AdminListEvent($helper, $request, $form);
137
                $this->container->get('event_dispatcher')->dispatch(
138
                    AdminListEvents::PRE_ADD,
139
                    $adminListEvent
140
                );
141
142
                // Check if Response is given
143
                if ($adminListEvent->getResponse() instanceof Response) {
144
                    return $adminListEvent->getResponse();
145
                }
146
147
                // Set sort weight
148
                $helper = $this->setSortWeightOnNewItem($configurator, $helper);
149
150
                $em->persist($helper);
151
                $em->flush();
152
                $this->container->get('event_dispatcher')->dispatch(
153
                    AdminListEvents::POST_ADD,
154
                    $adminListEvent
155
                );
156
157
                // Check if Response is given
158
                if ($adminListEvent->getResponse() instanceof Response) {
159
                    return $adminListEvent->getResponse();
160
                }
161
162
                $indexUrl = $configurator->getIndexUrl();
163
164
                return new RedirectResponse(
165
                    $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
166
                );
167
            }
168
        }
169
170
        $params = [
171
            'form' => $form->createView(),
172
            'adminlistconfigurator' => $configurator,
173
            'entityVersionLockCheck' => false,
174
            'entity' => $helper,
175
        ];
176
177
        if ($tabPane) {
178
            $params = array_merge($params, array('tabPane' => $tabPane));
179
        }
180
181
        return new Response(
182
            $this->renderView($configurator->getAddTemplate(), $params)
183
        );
184
    }
185
186
    /**
187
     * Creates and processes the edit form for an Entity using its ID
188
     *
189
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
190
     * @param string                        $entityId     The id of the entity that will be edited
191
     * @param null|Request                  $request
0 ignored issues
show
Documentation introduced by Sander Goossens
Consider making the type for parameter $request a bit more specific; maybe use Request.
Loading history...
192
     *
193
     * @throws NotFoundHttpException
194
     * @throws AccessDeniedHttpException
195
     *
196
     * @return Response
197
     */
198
    protected function doEditAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
199
    {
200
        /* @var EntityManager $em */
201
        $em = $this->getEntityManager();
202
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
0 ignored issues
show
Bug introduced by Daan Poron
The method findOneById() does not exist on Doctrine\Common\Persistence\ObjectRepository. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
203
204
        if ($helper === null) {
205
            throw new NotFoundHttpException('Entity not found.');
206
        }
207
208
        if (!$configurator->canEdit($helper)) {
209
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
210
        }
211
212
        // This entity is locked
213
        if (($helper instanceof LockableEntityInterface) && $this->isLockableEntityLocked($helper)) {
214
            $indexUrl = $configurator->getIndexUrl();
215
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
216
            if (!$request->isXmlHttpRequest()) {
217
                /** @var EntityVersionLockService $entityVersionLockService */
218
                $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
219
220
                $user = $entityVersionLockService->getUsersWithEntityVersionLock($helper, $this->getUser());
221
                $message = $this->container->get('translator')->trans('kuma_admin_list.edit.flash.locked', array('%user%' => implode(', ', $user)));
222
                $this->addFlash(
223
                    FlashTypes::WARNING,
224
                    $message
225
                );
226
227
                return new RedirectResponse(
228
                    $this->generateUrl(
229
                        $indexUrl['path'],
230
                        isset($indexUrl['params']) ? $indexUrl['params'] : array()
231
                    )
232
                );
233
            }
234
        }
235
236
        $formType = $configurator->getAdminType($helper);
237
238
        $event = new AdaptSimpleFormEvent($request, $formType, $helper, $configurator->getAdminTypeOptions());
239
        $event = $this->container->get('event_dispatcher')->dispatch(Events::ADAPT_SIMPLE_FORM, $event);
240
        $tabPane = $event->getTabPane();
241
242
        $form = $this->createForm($formType, $helper, $event->getOptions());
243
244 View Code Duplication
        if ($request->isMethod('POST')) {
0 ignored issues
show
Duplication introduced by Wim Vandersmissen
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
            if ($tabPane) {
246
                $tabPane->bindRequest($request);
247
                $form = $tabPane->getForm();
248
            } else {
249
                $form->handleRequest($request);
250
            }
251
252
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
253
            if ($form->isSubmitted() && $form->isValid() && !$request->isXmlHttpRequest()) {
254
                $adminListEvent = new AdminListEvent($helper, $request, $form);
255
                $this->container->get('event_dispatcher')->dispatch(
256
                    AdminListEvents::PRE_EDIT,
257
                    $adminListEvent
258
                );
259
260
                // Check if Response is given
261
                if ($adminListEvent->getResponse() instanceof Response) {
262
                    return $adminListEvent->getResponse();
263
                }
264
265
                $em->persist($helper);
266
                $em->flush();
267
                $this->container->get('event_dispatcher')->dispatch(
268
                    AdminListEvents::POST_EDIT,
269
                    $adminListEvent
270
                );
271
272
                // Check if Response is given
273
                if ($adminListEvent->getResponse() instanceof Response) {
274
                    return $adminListEvent->getResponse();
275
                }
276
277
                $indexUrl = $configurator->getIndexUrl();
278
279
                // Don't redirect to listing when coming from ajax request, needed for url chooser.
280
                if (!$request->isXmlHttpRequest()) {
281
                    return new RedirectResponse(
282
                        $this->generateUrl(
283
                            $indexUrl['path'],
284
                            isset($indexUrl['params']) ? $indexUrl['params'] : array()
285
                        )
286
                    );
287
                }
288
            }
289
        }
290
291
        $configurator->buildItemActions();
292
293
        $params = [
294
            'form' => $form->createView(),
295
            'entity' => $helper, 'adminlistconfigurator' => $configurator,
296
            'entityVersionLockInterval' => $this->container->getParameter('kunstmaan_entity.lock_check_interval'),
297
            'entityVersionLockCheck' => $this->container->getParameter('kunstmaan_entity.lock_enabled') && $helper instanceof LockableEntityInterface,
298
        ];
299
300
        if ($tabPane) {
301
            $params = array_merge($params, array('tabPane' => $tabPane));
302
        }
303
304
        return new Response(
305
            $this->renderView(
306
                $configurator->getEditTemplate(),
307
                $params
308
            )
309
        );
310
    }
311
312
    protected function doViewAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
313
    {
314
        /* @var EntityManager $em */
315
        $em = $this->getEntityManager();
316
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
0 ignored issues
show
Bug introduced by whitewhidow
The method findOneById() does not exist on Doctrine\Common\Persistence\ObjectRepository. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
317
        if ($helper === null) {
318
            throw new NotFoundHttpException('Entity not found.');
319
        }
320
321
        if (!$configurator->canView($helper)) {
322
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
323
        }
324
325
        $MetaData = $em->getClassMetadata($configurator->getRepositoryName());
326
        $fields = array();
327
        $accessor = PropertyAccess::createPropertyAccessor();
328
        foreach ($MetaData->fieldNames as $value) {
329
            $fields[$value] = $accessor->getValue($helper, $value);
330
        }
331
332
        return new Response(
333
            $this->renderView(
334
                $configurator->getViewTemplate(),
335
                array('entity' => $helper, 'adminlistconfigurator' => $configurator, 'fields' => $fields)
336
            )
337
        );
338
    }
339
340
    /**
341
     * Delete the Entity using its ID
342
     *
343
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
344
     * @param int                           $entityId     The id to delete
345
     * @param null|Request                  $request
0 ignored issues
show
Documentation introduced by Sander Goossens
Consider making the type for parameter $request a bit more specific; maybe use Request.
Loading history...
346
     *
347
     * @throws NotFoundHttpException
348
     * @throws AccessDeniedHttpException
349
     *
350
     * @return Response
351
     */
352
    protected function doDeleteAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
353
    {
354
        /* @var $em EntityManager */
355
        $em = $this->getEntityManager();
356
        $helper = $em->getRepository($configurator->getRepositoryName())->findOneById($entityId);
0 ignored issues
show
Bug introduced by Daan Poron
The method findOneById() does not exist on Doctrine\Common\Persistence\ObjectRepository. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
357
        if ($helper === null) {
358
            throw new NotFoundHttpException('Entity not found.');
359
        }
360
        if (!$configurator->canDelete($helper)) {
361
            throw $this->createAccessDeniedException('You do not have sufficient rights to access this page.');
362
        }
363
364
        $indexUrl = $configurator->getIndexUrl();
365
        if ($request->isMethod('POST')) {
366
            $adminListEvent = new AdminListEvent($helper, $request);
367
            $this->container->get('event_dispatcher')->dispatch(
368
                AdminListEvents::PRE_DELETE,
369
                $adminListEvent
370
            );
371
372
            // Check if Response is given
373
            if ($adminListEvent->getResponse() instanceof Response) {
374
                return $adminListEvent->getResponse();
375
            }
376
377
            $em->remove($helper);
378
            $em->flush();
379
            $this->container->get('event_dispatcher')->dispatch(
380
                AdminListEvents::POST_DELETE,
381
                $adminListEvent
382
            );
383
384
            // Check if Response is given
385
            if ($adminListEvent->getResponse() instanceof Response) {
386
                return $adminListEvent->getResponse();
387
            }
388
        }
389
390
        return new RedirectResponse(
391
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
392
        );
393
    }
394
395
    /**
396
     * Move an item up in the list.
397
     *
398
     * @return RedirectResponse
399
     */
400 View Code Duplication
    protected function doMoveUpAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
0 ignored issues
show
Duplication introduced by Sander Goossens
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
    {
402
        $em = $this->getEntityManager();
403
        $sortableField = $configurator->getSortableField();
0 ignored issues
show
Bug introduced by Sander Goossens
The method getSortableField() does not seem to exist on object<Kunstmaan\AdminLi...tAdminListConfigurator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
404
405
        $repositoryName = $this->getAdminListRepositoryName($configurator);
406
407
        $repo = $em->getRepository($repositoryName);
408
        $item = $repo->find($entityId);
409
410
        $setter = 'set'.ucfirst($sortableField);
411
        $getter = 'get'.ucfirst($sortableField);
412
413
        $nextItem = $repo->createQueryBuilder('i')
414
            ->where('i.'.$sortableField.' < :weight')
415
            ->setParameter('weight', $item->$getter())
416
            ->orderBy('i.'.$sortableField, 'DESC')
417
            ->setMaxResults(1)
418
            ->getQuery()
419
            ->getOneOrNullResult();
420
        if ($nextItem) {
421
            $nextItem->$setter($item->$getter());
422
            $em->persist($nextItem);
423
            $item->$setter($item->$getter() - 1);
424
425
            $em->persist($item);
0 ignored issues
show
Bug introduced by Krisztián Ferenczi
It seems like $item defined by $repo->find($entityId) on line 408 can also be of type null; however, Doctrine\Common\Persiste...bjectManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
426
            $em->flush();
427
        }
428
429
        $indexUrl = $configurator->getIndexUrl();
430
431
        return new RedirectResponse(
432
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
433
        );
434
    }
435
436 View Code Duplication
    protected function doMoveDownAction(AbstractAdminListConfigurator $configurator, $entityId, Request $request)
0 ignored issues
show
Duplication introduced by Sander Goossens
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
437
    {
438
        $em = $this->getEntityManager();
439
        $sortableField = $configurator->getSortableField();
0 ignored issues
show
Bug introduced by Sander Goossens
The method getSortableField() does not seem to exist on object<Kunstmaan\AdminLi...tAdminListConfigurator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
440
441
        $repositoryName = $this->getAdminListRepositoryName($configurator);
442
443
        $repo = $em->getRepository($repositoryName);
444
        $item = $repo->find($entityId);
445
446
        $setter = 'set'.ucfirst($sortableField);
447
        $getter = 'get'.ucfirst($sortableField);
448
449
        $nextItem = $repo->createQueryBuilder('i')
450
            ->where('i.'.$sortableField.' > :weight')
451
            ->setParameter('weight', $item->$getter())
452
            ->orderBy('i.'.$sortableField, 'ASC')
453
            ->setMaxResults(1)
454
            ->getQuery()
455
            ->getOneOrNullResult();
456
        if ($nextItem) {
457
            $nextItem->$setter($item->$getter());
458
            $em->persist($nextItem);
459
            $item->$setter($item->$getter() + 1);
460
461
            $em->persist($item);
0 ignored issues
show
Bug introduced by Krisztián Ferenczi
It seems like $item defined by $repo->find($entityId) on line 444 can also be of type null; however, Doctrine\Common\Persiste...bjectManager::persist() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
462
            $em->flush();
463
        }
464
465
        $indexUrl = $configurator->getIndexUrl();
466
467
        return new RedirectResponse(
468
            $this->generateUrl($indexUrl['path'], isset($indexUrl['params']) ? $indexUrl['params'] : array())
469
        );
470
    }
471
472
    private function getMaxSortableField($repo, $sort)
473
    {
474
        $maxWeight = $repo->createQueryBuilder('i')
475
            ->select('max(i.'.$sort.')')
476
            ->getQuery()
477
            ->getSingleScalarResult();
478
479
        return (int) $maxWeight;
480
    }
481
482
    /**
483
     * @param LockableEntityInterface $entity
484
     *
485
     * @return bool
486
     */
487
    protected function isLockableEntityLocked(LockableEntityInterface $entity)
488
    {
489
        /** @var EntityVersionLockService $entityVersionLockService */
490
        $entityVersionLockService = $this->container->get('kunstmaan_entity.admin_entity.entity_version_lock_service');
491
492
        return $entityVersionLockService->isEntityBelowThreshold($entity) && $entityVersionLockService->isEntityLocked(
493
                $this->getUser(),
0 ignored issues
show
Documentation introduced by Ruud Denivel
$this->getUser() is of type null|object, but the function expects a object<FOS\UserBundle\Model\User>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
494
                $entity
495
            );
496
    }
497
498
    /**
499
     * Sets the sort weight on a new item. Can be overridden if a non-default sorting implementation is being used.
500
     *
501
     * @param AbstractAdminListConfigurator $configurator The adminlist configurator
502
     * @param $item
503
     *
504
     * @return mixed
505
     */
506
    protected function setSortWeightOnNewItem(AbstractAdminListConfigurator $configurator, $item)
507
    {
508
        if ($configurator instanceof SortableInterface) {
509
            $repo = $this->getEntityManager()->getRepository($configurator->getRepositoryName());
510
            $sort = $configurator->getSortableField();
511
            $weight = $this->getMaxSortableField($repo, $sort);
512
            $setter = 'set'.ucfirst($sort);
513
            $item->$setter($weight + 1);
514
        }
515
516
        return $item;
517
    }
518
519
    protected function buildSortableFieldActions(AbstractAdminListConfigurator $configurator)
520
    {
521
        // Check if Sortable interface is implemented
522
        if ($configurator instanceof SortableInterface) {
523 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
0 ignored issues
show
Duplication introduced by Mattias Delang
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
524
                return array(
525
                    'path' => $configurator->getPathByConvention().'_move_up',
526
                    'params' => array('id' => $item->getId()),
527
                );
528
            };
529
530
            $action = new SimpleItemAction($route, 'arrow-up', 'kuma_admin_list.action.move_up');
531
            $configurator->addItemAction($action);
532
533 View Code Duplication
            $route = function (EntityInterface $item) use ($configurator) {
0 ignored issues
show
Duplication introduced by Mattias Delang
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
534
                return array(
535
                    'path' => $configurator->getPathByConvention().'_move_down',
536
                    'params' => array('id' => $item->getId()),
537
                );
538
            };
539
540
            $action = new SimpleItemAction($route, 'arrow-down', 'kuma_admin_list.action.move_down');
541
            $configurator->addItemAction($action);
542
        }
543
    }
544
545
    /**
546
     * @param AbstractAdminListConfigurator $configurator
547
     *
548
     * @return string
549
     */
550
    protected function getAdminListRepositoryName(AbstractAdminListConfigurator $configurator)
551
    {
552
        $em = $this->getEntityManager();
553
        $className = $em->getClassMetadata($configurator->getRepositoryName())->getName();
554
555
        $implements = class_implements($className);
556
        if (isset($implements[HasNodeInterface::class])) {
557
            return NodeTranslation::class;
558
        }
559
560
        return $configurator->getRepositoryName();
561
    }
562
}
563