Completed
Push — master ( 2e195b...9e660e )
by
unknown
02:50
created

CRUDController::defineFormTheme()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Blast Project package.
5
 *
6
 * Copyright (C) 2015-2017 Libre Informatique
7
 *
8
 * This file is licenced under the GNU LGPL v3.
9
 * For the full copyright and license information, please view the LICENSE.md
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Blast\CoreBundle\Controller;
14
15
use Sonata\AdminBundle\Controller\CRUDController as SonataController;
16
use Symfony\Component\HttpFoundation\JsonResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
19
/**
20
 * Class CRUDController.
21
 *
22
 * @author  Thomas Rabaix <[email protected]>
23
 */
24
class CRUDController extends SonataController
25
{
26
    /**
27
     * The related Admin class.
28
     *
29
     * @var AdminInterface
30
     */
31
    protected $admin;
32
33
    /**
34
     * Duplicate action.
35
     *
36
     * @return response
37
     */
38
    public function duplicateAction()
39
    {
40
        $id = $this->getRequest()->get($this->admin->getIdParameter());
41
        $object = clone $this->admin->getObject($id);
42
43
        $preResponse = $this->preDuplicate($object);
44
        if ($preResponse !== null) {
45
            return $preResponse;
46
        }
47
48
        return $this->createAction($object);
49
    }
50
51
    /**
52
     * Create action.
53
     *
54
     * @param object $object
55
     *
56
     * @return Response
57
     *
58
     * @throws AccessDeniedException If access is not granted
59
     */
60
    public function createAction($object = null)
61
    {
62
        $request = $this->getRequest();
63
        // the key used to lookup the template
64
        $templateKey = 'edit';
65
66
        $this->admin->checkAccess('create');
67
68
        $class = new \ReflectionClass($this->admin->hasActiveSubClass() ? $this->admin->getActiveSubClass() : $this->admin->getClass());
69
70
        if ($class->isAbstract()) {
71
            return $this->render(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->render('So...ate'), null, $request); (Symfony\Component\HttpFoundation\Response) is incompatible with the return type documented by Blast\CoreBundle\Control...ontroller::createAction of type Blast\CoreBundle\Controller\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
72
                'SonataAdminBundle:CRUD:select_subclass.html.twig',
73
                array(
74
                    'base_template' => $this->getBaseTemplate(),
75
                    'admin'         => $this->admin,
76
                    'action'        => 'create',
77
                ),
78
                null,
79
                $request
0 ignored issues
show
Unused Code introduced by
The call to CRUDController::render() has too many arguments starting with $request.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
80
            );
81
        }
82
83
        $object = $object ? $object : $this->admin->getNewInstance();
84
85
        $preResponse = $this->preCreate($request, $object);
86
        if ($preResponse !== null) {
87
            return $preResponse;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $preResponse; (Blast\CoreBundle\Controller\Response) is incompatible with the return type of the parent method Sonata\AdminBundle\Contr...ontroller::createAction of type Symfony\Component\HttpFoundation\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
88
        }
89
90
        $this->admin->setSubject($object);
91
92
        /** @var $form \Symfony\Component\Form\Form */
93
        $form = $this->admin->getForm();
94
        $form->setData($object);
95
        $form->handleRequest($request);
96
97
        if ($form->isSubmitted()) {
98
            //TODO: remove this check for 4.0
99
            if (method_exists($this->admin, 'preValidate')) {
100
                $this->admin->preValidate($object);
101
            }
102
            $isFormValid = $form->isValid();
103
104
            // persist if the form was valid and if in preview mode the preview was approved
105
            if ($isFormValid && (!$this->isInPreviewMode($request) || $this->isPreviewApproved($request))) {
0 ignored issues
show
Unused Code introduced by
The call to CRUDController::isInPreviewMode() has too many arguments starting with $request.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
The call to CRUDController::isPreviewApproved() has too many arguments starting with $request.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
106
                $this->admin->checkAccess('create', $object);
107
108
                try {
109
                    $object = $this->admin->create($object);
110
111
                    if ($this->isXmlHttpRequest()) {
112
                        return $this->renderJson(array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->renderJson...bject)), 200, array()); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type documented by Blast\CoreBundle\Control...ontroller::createAction of type Blast\CoreBundle\Controller\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
113
                            'result'   => 'ok',
114
                            'objectId' => $this->admin->getNormalizedIdentifier($object),
115
                        ), 200, array());
116
                    }
117
118
                    $this->addFlash(
119
                        'sonata_flash_success',
120
                        $this->admin->trans(
121
                            'flash_create_success',
122
                            array('%name%' => $this->escapeHtml($this->admin->toString($object))),
123
                            'SonataAdminBundle'
124
                        )
125
                    );
126
127
                    // redirect to edit mode
128
                    return $this->redirectTo($object);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->redirectTo($object); (Symfony\Component\HttpFoundation\RedirectResponse) is incompatible with the return type documented by Blast\CoreBundle\Control...ontroller::createAction of type Blast\CoreBundle\Controller\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
129
                } catch (ModelManagerException $e) {
0 ignored issues
show
Bug introduced by
The class Blast\CoreBundle\Controller\ModelManagerException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
130
                    $this->handleModelManagerException($e);
131
132
                    $isFormValid = false;
133
                }
134
            }
135
136
            // show an error message if the form failed validation
137
            if (!$isFormValid) {
138
                if (!$this->isXmlHttpRequest()) {
139
                    $this->addFlash(
140
                        'sonata_flash_error',
141
                        $this->admin->trans(
142
                            'flash_create_error',
143
                            array('%name%' => $this->escapeHtml($this->admin->toString($object))),
144
                            'SonataAdminBundle'
145
                        )
146
                    );
147
                }
148
            } elseif ($this->isPreviewRequested()) {
149
                // pick the preview template if the form was valid and preview was requested
150
                $templateKey = 'preview';
151
                $this->admin->getShow();
152
            }
153
        }
154
155
        $view = $form->createView();
156
157
        // set the theme for the current Admin Form
158
        $this->defineFormTheme($view, $this->admin->getFormTheme());
159
160
        return $this->render($this->admin->getTemplate($templateKey), array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->render($th...ct' => $object), null); (Symfony\Component\HttpFoundation\Response) is incompatible with the return type documented by Blast\CoreBundle\Control...ontroller::createAction of type Blast\CoreBundle\Controller\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
161
            'action' => 'create',
162
            'form'   => $view,
163
            'object' => $object,
164
        ), null);
165
    }
166
167
    /**
168
     * Generate Entity Code action.
169
     *
170
     * @param int|string|null $id
171
     *
172
     * @return JsonResponse
173
     */
174
    public function generateEntityCodeAction($id = null)
0 ignored issues
show
Unused Code introduced by
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
175
    {
176
        $request = $this->getRequest();
177
178
        $id = $request->get($this->admin->getIdParameter());
179
        if ($id) {
180
            $subject = $this->admin->getObject($id);
181
            if (!$subject) {
182
                $error = sprintf('unable to find the object with id : %s', $id);
183
184
                return new JsonResponse(['error' => $error]);
185
            }
186
            try {
187
                $this->admin->checkAccess('edit', $subject); // TODO: is it necessary ? (we are not editing the entity)
188
            } catch (Exception $exc) {
0 ignored issues
show
Bug introduced by
The class Blast\CoreBundle\Controller\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
189
                $error = $exc->getMessage();
190
191
                return new JsonResponse(['error' => $error]);
192
            }
193
        } else {
194
            $subject = $this->admin->getNewInstance();
195
        }
196
197
        $this->admin->setSubject($subject);
198
199
        $form = $this->admin->getForm();
200
        $form->setData($subject);
201
        $form->submit($request->request->get($form->getName()));
202
        $entity = $form->getData();
203
204
        $field = $request->query->get('field', 'code');
205
        $registry = $this->get('blast_core.code_generators');
206
        $generator = $registry::getCodeGenerator(get_class($entity), $field);
207
        try {
208
            $code = $generator::generate($entity);
209
210
            return new JsonResponse(['code' => $code]);
211
        } catch (\Exception $exc) {
212
            $error = $this->get('translator')->trans($exc->getMessage());
213
214
            return new JsonResponse(['error' => $error, 'generator' => get_class($generator)]);
215
        }
216
    }
217
218
    /**
219
     * This method can be overloaded in your custom CRUD controller.
220
     * It's called from createAction.
221
     *
222
     * @param Request $request
223
     * @param mixed   $object
224
     *
225
     * @return Response|null
226
     */
227
    protected function preCreate(Request $request, $object)
228
    {
229
    }
230
231
    /**
232
     * This method can be overloaded in your custom CRUD controller.
233
     * It's called from editAction.
234
     *
235
     * @param Request $request
236
     * @param mixed   $object
237
     *
238
     * @return Response|null
239
     */
240
    protected function preEdit(Request $request, $object)
241
    {
242
    }
243
244
    /**
245
     * This method can be overloaded in your custom CRUD controller.
246
     * It's called from deleteAction.
247
     *
248
     * @param Request $request
249
     * @param mixed   $object
250
     *
251
     * @return Response|null
252
     */
253
    protected function preDelete(Request $request, $object)
254
    {
255
    }
256
257
    /**
258
     * This method can be overloaded in your custom CRUD controller.
259
     * It's called from showAction.
260
     *
261
     * @param Request $request
262
     * @param mixed   $object
263
     *
264
     * @return Response|null
265
     */
266
    protected function preShow(Request $request, $object)
267
    {
268
    }
269
270
    /**
271
     * This method can be overloaded in your custom CRUD controller.
272
     * It's called from listAction.
273
     *
274
     * @param Request $request
275
     *
276
     * @return Response|null
277
     */
278
    protected function preList(Request $request)
279
    {
280
    }
281
282
    /**
283
     * This method can be overloaded in your custom CRUD controller.
284
     * It's called from duplicateAction.
285
     *
286
     * @param mixed $object
287
     *
288
     * @return Response|null
289
     */
290
    protected function preDuplicate($object)
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
291
    {
292
    }
293
294
    protected function defineFormTheme($formView, $formTheme)
295
    {
296
        $twig = $this->get('twig');
297
298
        $renderer = ($twig->hasExtension('Symfony\Bridge\Twig\Form\TwigRenderer')) ?
299
                  $twig->getRuntime('Symfony\Bridge\Twig\Form\TwigRenderer') :
300
                  $twig->getExtension('Symfony\Bridge\Twig\Extension\FormExtension')->renderer;
301
        $renderer->setTheme($formView, $formTheme);
302
    }
303
}
304