Completed
Push — master ( 2115d0...4a6545 )
by Laurent
03:21
created

AbstractController::getArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 1
eloc 16
nc 1
nop 2
1
<?php
2
/**
3
 * AbstractController controller des méthodes communes.
4
 *
5
 * PHP Version 5
6
 *
7
 * @author    Quétier Laurent <[email protected]>
8
 * @copyright 2014 Dev-Int GLSR
9
 * @license   http://opensource.org/licenses/gpl-license.php GNU Public License
10
 *
11
 * @version since 1.0.0
12
 *
13
 * @link      https://github.com/Dev-Int/glsr
14
 */
15
namespace AppBundle\Controller;
16
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Session\Session;
19
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
20
use Doctrine\ORM\QueryBuilder;
21
22
/**
23
 * Abstract controller.
24
 *
25
 * @category Controller
26
 */
27
abstract class AbstractController extends Controller
28
{
29
    /**
30
     * Lists all items entity.
31
     *
32
     * @param string $entityName Name of Entity
33
     * @param \Symfony\Component\HttpFoundation\Request $request Sort request
34
     * @return array
35
     */
36
    public function abstractIndexAction($entityName, Request $request = null)
37
    {
38
        $etm = $this->getDoctrine()->getManager();
39
        $paginator = '';
40
        $entities = $this->getEntity($entityName, $etm);
41
        
42
        if ($request !== null) {
43
            $item = $this->container->getParameter('knp_paginator.page_range');
44
            $this->addQueryBuilderSort($entities, strtolower($entityName));
45
            $paginator = $this->get('knp_paginator')->paginate($entities, $request->query->get('page', 1), $item);
46
        }
47
48
        return array('entities'  => $entities, 'ctEntity' => count($entities), 'paginator' => $paginator,);
49
    }
50
51
    /**
52
     * Get the entity
53
     *
54
     * @param string $entityName Name of Entity
55
     * @param \Doctrine\Common\Persistence\ObjectManager[] $etm An array of ObjectManager instances
56
     * @return type
57
     */
58
    protected function getEntity($entityName, $etm) {
59
        switch ($entityName) {
60
            case 'Article':
61
                $entities = $etm->getRepository('AppBundle:'.$entityName)->getArticles();
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
62
                break;
63
            case 'Supplier':
64
                $entities = $etm->getRepository('AppBundle:'.$entityName)->getSuppliers();
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
65
                break;
66
            case 'User':
67
                $entities = $etm->getRepository('AppBundle:'.$entityName)->getUsers();
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
68
                break;
69
            case 'FamilyLog':
70
                $entities = $etm->getRepository('AppBundle:'.$entityName)->childrenHierarchy();
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
71
                break;
72
            case 'UnitStorage':
73
                $entities = $etm->getRepository('AppBundle:'.$entityName)->createQueryBuilder('u');
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
74
                break;
75
            default:
76
                $entities = $etm->getRepository('AppBundle:'.$entityName)->findAll();
0 ignored issues
show
Bug introduced by
The method getRepository cannot be called on $etm (of type array<integer,object<Doc...istence\ObjectManager>>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
77
        }
78
        return $entities;
79
    }
80
81
    /**
82
     * Finds and displays an item entity.
83
     *
84
     * @param Object $entity     Entity
85
     * @param string $entityName Name of Entity
86
     * @return array
87
     */
88
    public function abstractShowAction($entity, $entityName)
89
    {
90
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
91
92
        return array(
93
            $entityName => $entity,
94
            'delete_form' => $deleteForm->createView(),
95
        );
96
    }
97
98
    /**
99
     * Displays a form to create a new item entity.
100
     *
101
     * @param string $entity     Entity
102
     * @param string $entityPath Path of Entity
103
     * @param string $typePath   Path of FormType
104
     * @return array
105
     */
106
    public function abstractNewAction($entity, $entityPath, $typePath)
107
    {
108
        $etm = $this->getDoctrine()->getManager();
109
        $ctEntity = count($etm->getRepository('AppBundle:'.$entity)->findAll());
110
        
111
        if ($entity === 'Company' || $entity === 'Settings' && $ctEntity >= 1) {
112
            $return = $this->redirectToRoute('_home');
113
            $this->addFlash('danger', 'gestock.settings.'.strtolower($entity).'.add2');
114
        }
115
116
        $entityNew = $etm->getClassMetadata($entityPath)->newInstance();
117
        $form = $this->createForm($typePath, $entityNew, array(
118
            'action' => $this->generateUrl(strtolower($entity).'_create'),
119
        ));
120
121
        $return = array(strtolower($entity) => $entityNew, 'form'   => $form->createView(),);
122
123
        return $return;
124
    }
125
126
    /**
127
     * Creates a new item entity.
128
     *
129
     * @param Request $request   Request in progress
130
     * @param string $entity     Entity <i>First letter Upper</i>
131
     * @param string $entityPath Path of Entity
132
     * @param string $typePath   Path of FormType
133
     * @return array
134
     */
135
    public function abstractCreateAction(Request $request, $entity, $entityPath, $typePath)
136
    {
137
        $param = array();
138
        $etm = $this->getDoctrine()->getManager();
139
        $entityNew = $etm->getClassMetadata($entityPath)->newInstance();
140
        $form = $this->createForm($typePath, $entityNew, array(
141
            'action' => $this->generateUrl(strtolower($entity).'_create'),
142
        ));
143
144
        if ($form->handleRequest($request)->isValid()) {
145
            $etm = $this->getDoctrine()->getManager();
146
            $etm->persist($entityNew);
147
            $etm->flush();
148
            $this->addFlash('info', 'gestock.create.ok');
149
150
            $param = $this->testReturnParam($entityNew, strtolower($entity));
151
            $return = $form->get('addmore')->isClicked() ? strtolower($entity).'_new' : strtolower($entity).'_show';
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Form\FormInterface as the method isClicked() does only exist in the following implementations of said interface: Symfony\Component\Form\SubmitButton.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
152
153
            return $this->redirectToRoute($return, $param);
154
        }
155
156
        return array($entity => $entityNew, 'form' => $form->createView(),);
157
    }
158
159
    /**
160
     * Displays a form to edit an existing item entity.
161
     *
162
     * @param Object $entity     Entity
163
     * @param string $entityName Name of Entity
164
     * @param string $typePath   Path of FormType
165
     * @return array
166
     */
167
    public function abstractEditAction($entity, $entityName, $typePath)
168
    {
169
        $param = $this->testReturnParam($entity, $entityName);
170
        $editForm = $this->createForm($typePath, $entity, array(
171
            'action' => $this->generateUrl($entityName.'_update', $param),
172
            'method' => 'PUT',
173
        ));
174
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
175
176
        return array(
177
            $entityName => $entity,
178
            'edit_form'   => $editForm->createView(),
179
            'delete_form' => $deleteForm->createView(),
180
        );
181
    }
182
183
    /**
184
     * Edits an existing item entity.
185
     *
186
     * @param Object $entity     Entity
187
     * @param Request $request   Request in progress
188
     * @param string $entityName Name of Entity
189
     * @param string $typePath   Path of FormType
190
     * @return array
191
     */
192
    public function abstractUpdateAction($entity, Request $request, $entityName, $typePath)
193
    {
194
        $param = $this->testReturnParam($entity, $entityName);
195
        $editForm = $this->createForm($typePath, $entity, array(
196
            'action' => $this->generateUrl($entityName.'_update', $param),
197
            'method' => 'PUT',
198
        ));
199
        if ($editForm->handleRequest($request)->isValid()) {
200
            $this->getDoctrine()->getManager()->flush();
201
            $this->addFlash('info', 'gestock.edit.ok');
202
203
            return $this->redirectToRoute($entityName.'_edit', $param);
204
        }
205
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
206
207
        return array(
208
            $entityName => $entity,
209
            'edit_form'   => $editForm->createView(),
210
            'delete_form' => $deleteForm->createView(),
211
        );
212
    }
213
214
    /**
215
     * Deletes an item entity.
216
     *
217
     * @param Object $entity     Entity
218
     * @param Request $request   Request in progress
219
     * @param string $entityName Name of Entity
220
     * @return array
221
     */
222
    public function abstractDeleteAction($entity, Request $request, $entityName)
223
    {
224
        $form = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
225
        if ($form->handleRequest($request)->isValid()) {
226
            $etm = $this->getDoctrine()->getManager();
227
            $etm->remove($entity);
228
            $etm->flush();
229
        }
230
    }
231
232
    private function testReturnParam($entity, $entityName)
233
    {
234
        if ($entityName === 'company' || $entityName === 'settings' || $entityName === 'tva') {
235
            $param = array('id' => $entity->getId());
236
        } else {
237
            $param = array('slug' => $entity->getSlug());
238
        }
239
240
        return $param;
241
    }
242
    /**
243
     * SetOrder for the SortAction in views.
244
     *
245
     * @param string $name   session name
246
     * @param string $entity entity name
247
     * @param string $field  field name
248
     * @param string $type   sort type ("ASC"/"DESC")
249
     */
250
    protected function setOrder($name, $entity, $field, $type = 'ASC')
251
    {
252
        $session = new Session();
253
254
        $session->set('sort.'.$name, array('entity' => $entity, 'field' => $field, 'type' => $type));
255
    }
256
257
    /**
258
     * GetOrder for the SortAction in views.
259
     *
260
     * @param string $name session name
261
     *
262
     * @return array
263
     */
264
    protected function getOrder($name)
265
    {
266
        $session = new Session();
267
268
        return $session->has('sort.' . $name) ? $session->get('sort.' . $name) : null;
269
    }
270
271
    /**
272
     * AddQueryBuilderSort for the SortAction in views.
273
     *
274
     * @param QueryBuilder $qbd
275
     * @param string       $name
276
     */
277
    protected function addQueryBuilderSort(QueryBuilder $qbd, $name)
278
    {
279
        $alias = '';
280
        if (is_array($order = $this->getOrder($name))) {
281
            if ($name !== $order['entity']) {
282
                $rootAlias = current($qbd->getDQLPart('from'))->getAlias();
283
                $join = current($qbd->getDQLPart('join'));
284
                foreach ($join as $item) {
285
                    if ($item->getJoin() === $rootAlias.'.'.$order['entity']) {
286
                        $alias = $item->getAlias();
287
                    }
288
                }
289
            } else {
290
                $alias = current($qbd->getDQLPart('from'))->getAlias();
291
            }
292
            $qbd->orderBy($alias . '.' . $order['field'], $order['type']);
293
        }
294
    }
295
296
    /**
297
     * Create Delete form.
298
     *
299
     * @param int    $id
300
     * @param string $route
301
     *
302
     * @return \Symfony\Component\Form\Form
303
     */
304
    protected function createDeleteForm($id, $route)
305
    {
306
        return $this->createFormBuilder(null, array('attr' => array('id' => 'delete')))
307
            ->setAction($this->generateUrl($route, array('id' => $id)))
308
            ->setMethod('DELETE')
309
            ->getForm()
310
        ;
311
    }
312
313
    /**
314
     * Array of file (`pdf`) layout.
315
     *
316
     * @param string $date File date
317
     * @param string $title Tile title
318
     * @return array<string,integer|string|boolean>
319
     */
320
    protected function getArray($date, $title)
321
    {
322
        $array = array(
323
            'margin-top' => 15,
324
            'header-spacing' => 5,
325
            'header-font-size' => 8,
326
            'header-left' => 'G.L.S.R.',
327
            'header-center' => $title,
328
            'header-right' => $date,
329
            'header-line' => true,
330
            'margin-bottom' => 15,
331
            'footer-spacing' => 5,
332
            'footer-font-size' => 8,
333
            'footer-left' => 'GLSR &copy 2014 and beyond.',
334
            'footer-right' => 'Page [page]/[toPage]',
335
            'footer-line' => true,
336
        );
337
        return $array;
338
    }
339
}
340