Completed
Push — master ( 5f63e3...7c7b22 )
by Laurent
17:19
created

AbstractController::addQueryBuilderSort()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 17
rs 8.8571
cc 5
eloc 11
nc 3
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\Bundle\FrameworkBundle\Controller\Controller;
19
use Doctrine\ORM\QueryBuilder;
20
21
/**
22
 * Abstract controller.
23
 *
24
 * @category Controller
25
 */
26
abstract class AbstractController extends Controller
27
{
28
    /**
29
     * Lists all items entity.
30
     *
31
     * @param string $entityName Name of Entity
32
     * @return array
33
     */
34
    public function abstractIndexAction($entityName)
35
    {
36
        $etm = $this->getDoctrine()->getManager();
37
        $entities = $etm->getRepository('AppBundle:'.$entityName)->findAll();
38
39
        return array(
40
            'entities'  => $entities,
41
            'ctEntity' => count($entities),
42
        );
43
    }
44
45
    /**
46
     * Finds and displays an item entity.
47
     *
48
     * @param Object $entity     Entity
49
     * @param string $entityName Name of Entity
50
     * @return array
51
     */
52
    public function abstractShowAction($entity, $entityName)
53
    {
54
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
55
56
        return array(
57
            $entityName => $entity,
58
            'delete_form' => $deleteForm->createView(),
59
        );
60
    }
61
62
    /**
63
     * Displays a form to create a new item entity.
64
     *
65
     * @param string $entity     Entity
66
     * @param string $entityPath Path of Entity
67
     * @param string $typePath   Path of FormType
68
     * @return array
69
     */
70
    public function abstractNewAction($entity, $entityPath, $typePath)
71
    {
72
        $etm = $this->getDoctrine()->getManager();
73
        $ctEntity = count($etm->getRepository('AppBundle:'.$entity)->findAll());
74
        
75
        if ($entity === 'Company' || $entity === 'Settings' && $ctEntity >= 1) {
76
            $return = $this->redirectToRoute('_home');
1 ignored issue
show
Unused Code introduced by
$return is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
77
            $this->addFlash('danger', 'gestock.settings.'.strtolower($entity).'.add2');
78
        }
79
80
        $entityNew = $etm->getClassMetadata($entityPath)->newInstance();
81
        $form = $this->createForm(new $typePath(), $entityNew, array(
82
            'action' => $this->generateUrl(strtolower($entity).'_create'),
83
        ));
84
85
        $return = array(strtolower($entity) => $entityNew, 'form'   => $form->createView(),);
86
87
        return $return;
88
    }
89
90
    /**
91
     * Creates a new item entity.
92
     *
93
     * @param Request $request   Request in progress
94
     * @param string $entity     Entity <i>First letter Upper</i>
95
     * @param string $entityPath Path of Entity
96
     * @param string $typePath   Path of FormType
97
     * @return array
98
     */
99
    public function abstractCreateAction(Request $request, $entity, $entityPath, $typePath)
100
    {
101
        $param = array();
1 ignored issue
show
Unused Code introduced by
$param is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
102
        $etm = $this->getDoctrine()->getManager();
103
        $entityNew = $etm->getClassMetadata($entityPath)->newInstance();
104
        $form = $this->createForm(new $typePath(), $entityNew, array(
105
            'action' => $this->generateUrl(strtolower($entity).'_create'),
106
        ));
107
108
        if ($form->handleRequest($request)->isValid()) {
109
            $etm = $this->getDoctrine()->getManager();
110
            $etm->persist($entityNew);
111
            $etm->flush();
112
            $this->addFlash('info', 'gestock.create.ok');
113
114
            $param = $this->testReturnParam($entityNew, strtolower($entity));
115
            $return = $form->get('addmore')->isClicked()
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...
116
                ? $entity.'_new'
117
                : $entity.'_show';
118
119
            return $this->redirectToRoute($return, $param);
120
        }
121
122
        return array($entity => $entityNew, 'form' => $form->createView(),);
123
    }
124
125
    /**
126
     * Displays a form to edit an existing item entity.
127
     *
128
     * @param Object $entity     Entity
129
     * @param string $entityName Name of Entity
130
     * @param string $typePath   Path of FormType
131
     * @return array
132
     */
133
    public function abstractEditAction($entity, $entityName, $typePath)
134
    {
135
        $param = $this->testReturnParam($entity, $entityName);
136
        $editForm = $this->createForm(new $typePath(), $entity, array(
137
            'action' => $this->generateUrl($entityName.'_update', $param),
138
            'method' => 'PUT',
139
        ));
140
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
141
142
        return array(
143
            $entityName => $entity,
144
            'edit_form'   => $editForm->createView(),
145
            'delete_form' => $deleteForm->createView(),
146
        );
147
    }
148
149
    /**
150
     * Edits an existing item entity.
151
     *
152
     * @param Object $entity     Entity
153
     * @param Request $request   Request in progress
154
     * @param string $entityName Name of Entity
155
     * @param string $typePath   Path of FormType
156
     * @return array
157
     */
158
    public function abstractUpdateAction($entity, Request $request, $entityName, $typePath)
159
    {
160
        $param = $this->testReturnParam($entity, $entityName);
161
        $editForm = $this->createForm(new $typePath(), $entity, array(
162
            'action' => $this->generateUrl($entityName.'_update', $param),
163
            'method' => 'PUT',
164
        ));
165
        if ($editForm->handleRequest($request)->isValid()) {
166
            $this->getDoctrine()->getManager()->flush();
167
            $this->addFlash('info', 'gestock.edit.ok');
168
169
            return $this->redirectToRoute($entityName.'_edit', $param);
170
        }
171
        $deleteForm = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
172
173
        return array(
174
            $entityName => $entity,
175
            'edit_form'   => $editForm->createView(),
176
            'delete_form' => $deleteForm->createView(),
177
        );
178
    }
179
180
    /**
181
     * Deletes an item entity.
182
     *
183
     * @param Object $entity     Entity
184
     * @param Request $request   Request in progress
185
     * @param string $entityName Name of Entity
186
     * @return array
187
     */
188
    public function abstractDeleteAction($entity, Request $request, $entityName)
189
    {
190
        $form = $this->createDeleteForm($entity->getId(), $entityName.'_delete');
191
        if ($form->handleRequest($request)->isValid()) {
192
            $etm = $this->getDoctrine()->getManager();
193
            $etm->remove($entity);
194
            $etm->flush();
195
        }
196
    }
197
198
    private function testReturnParam($entity, $entityName)
199
    {
200
        if ($entityName === 'company' || $entityName === 'settings' || $entityName === 'tva') {
201
            $param = array('id' => $entity->getId());
202
        } else {
203
            $param = array('slug' => $entity->getSlug());
204
        }
205
206
        return $param;
207
    }
208
    /**
209
     * SetOrder for the SortAction in views.
210
     *
211
     * @param string $name   session name
212
     * @param string $entity entity name
213
     * @param string $field  field name
214
     * @param string $type   sort type ("ASC"/"DESC")
215
     */
216
    protected function setOrder($name, $entity, $field, $type = 'ASC')
217
    {
218
        $this->getRequest()->getSession()->set('sort.'.$name, array(
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Bundle\Framework...ontroller::getRequest() has been deprecated with message: since version 2.4, to be removed in 3.0. Ask Symfony to inject the Request object into your controller method instead by type hinting it in the method's signature.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
219
            'entity' => $entity,
220
            'field' => $field,
221
            'type' => $type
222
        ));
223
    }
224
225
    /**
226
     * GetOrder for the SortAction in views.
227
     *
228
     * @param string $name
229
     *
230
     * @return array
231
     */
232
    protected function getOrder($name)
233
    {
234
        $session = $this->getRequest()->getSession();
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Bundle\Framework...ontroller::getRequest() has been deprecated with message: since version 2.4, to be removed in 3.0. Ask Symfony to inject the Request object into your controller method instead by type hinting it in the method's signature.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
235
236
        return $session->has('sort.' . $name) ? $session->get('sort.' . $name) : null;
237
    }
238
239
    /**
240
     * AddQueryBuilderSort for the SortAction in views.
241
     *
242
     * @param QueryBuilder $qbd
243
     * @param string       $name
244
     */
245
    protected function addQueryBuilderSort(QueryBuilder $qbd, $name)
246
    {
247
        if (is_array($order = $this->getOrder($name))) {
248
            if ($name !== $order['entity']) {
249
                $rootAlias = current($qbd->getDQLPart('from'))->getAlias();
250
                $join = current($qbd->getDQLPart('join'));
251
                foreach ($join as $item) {
252
                    if ($item->getJoin() === $rootAlias.'.'.$order['entity']) {
253
                        $alias = $item->getAlias();
254
                    }
255
                }
256
            } else {
257
                $alias = current($qbd->getDQLPart('from'))->getAlias();
258
            }
259
            $qbd->orderBy($alias . '.' . $order['field'], $order['type']);
0 ignored issues
show
Bug introduced by
The variable $alias does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
260
        }
261
    }
262
263
    /**
264
     * Create Delete form.
265
     *
266
     * @param int    $id
267
     * @param string $route
268
     *
269
     * @return \Symfony\Component\Form\Form
270
     */
271
    protected function createDeleteForm($id, $route)
272
    {
273
        return $this->createFormBuilder(null, array('attr' => array('id' => 'delete')))
274
            ->setAction($this->generateUrl($route, array('id' => $id)))
275
            ->setMethod('DELETE')
276
            ->getForm()
277
        ;
278
    }
279
280
    /**
281
     * Test Inventory.
282
     *
283
     * @return string|null
284
     */
285
    protected function testInventory()
286
    {
287
        $url = null;
288
        $etm = $this->getDoctrine()->getManager();
289
        $inventories = $etm->getRepository('AppBundle:Inventory')->getInventory();
290
291
        if (empty($inventories)) {
292
            $url = 'gs_install_st7';
293
        } else {
294
            foreach ($inventories as $inventory) {
295
                if ($inventory->getstatus() === 1 || $inventory->getStatus() === 2) {
296
                    $message = $this->get('translator')
297
                        ->trans('yet', array(), 'gs_inventories');
298
                    $this->addFlash('danger', $message);
299
                    $url = 'inventory';
300
                    break;
301
                }
302
            }
303
        }
304
305
        return $url;
306
    }
307
}
308