Completed
Push — master ( d1535f...93b502 )
by Leny
06:44
created

BlogController::settingsAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 50
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 50
rs 9.3333
cc 3
eloc 28
nc 3
nop 2
1
<?php
2
3
namespace Victoire\Bundle\BlogBundle\Controller;
4
5
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
6
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
7
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
8
use Symfony\Component\HttpFoundation\JsonResponse;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Response;
11
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
12
use Victoire\Bundle\BlogBundle\Entity\Blog;
13
use Victoire\Bundle\BlogBundle\Form\ChooseBlogType;
14
use Victoire\Bundle\BlogBundle\Repository\BlogRepository;
15
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessTemplate;
16
use Victoire\Bundle\PageBundle\Controller\BasePageController;
17
use Victoire\Bundle\PageBundle\Entity\BasePage;
18
use Victoire\Bundle\ViewReferenceBundle\ViewReference\ViewReference;
19
20
/**
21
 * blog Controller.
22
 *
23
 * @Route("/victoire-dcms/blog")
24
 */
25
class BlogController extends BasePageController
26
{
27
    protected $routes;
28
29
    /**
30
     * Constructor.
31
     */
32
    public function __construct()
33
    {
34
        $this->routes = [
35
            'new'       => 'victoire_blog_new',
36
            'show'      => 'victoire_core_page_show',
37
            'settings'  => 'victoire_blog_settings',
38
            'articles'  => 'victoire_blog_articles',
39
            'category'  => 'victoire_blog_category',
40
            'translate' => 'victoire_blog_translate',
41
            'delete'    => 'victoire_blog_delete',
42
        ];
43
    }
44
45
    /**
46
     * New page.
47
     *
48
     * @Route("/index/{blogId}/{tab}", name="victoire_blog_index", defaults={"blogId" = null, "tab" = "articles"})
49
     *
50
     * @param Request $request
51
     *
52
     * @return JsonResponse
53
     */
54
    public function indexAction(Request $request, $blogId = null, $tab = 'articles')
55
    {
56
        /** @var BlogRepository $blogRepo */
57
        $blogRepo = $this->get('doctrine.orm.entity_manager')->getRepository('VictoireBlogBundle:Blog');
58
        $blogs = $blogRepo->getAll()->run();
59
        $blog = reset($blogs);
60
        if (is_numeric($blogId)) {
61
            $blog = $blogRepo->find($blogId);
62
        }
63
        $options['blog'] = $blog;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
64
        $template = $this->getBaseTemplatePath().':index.html.twig';
65
        $chooseBlogForm = $this->createForm(new ChooseBlogType(), null, $options);
66
67
        $chooseBlogForm->handleRequest($request);
68
        if ($chooseBlogForm->isValid()) {
69
            $blog = $chooseBlogForm->getData()['blog'];
70
            $template = $this->getBaseTemplatePath().':_blogItem.html.twig';
71
            $chooseBlogForm = $this->createForm(new ChooseBlogType(), null, ['blog' => $blog]);
72
        }
73
        $businessProperties = [];
74
75
        if ($blog instanceof BusinessTemplate) {
76
            //we can use the business entity properties on the seo
77
            $businessEntity = $this->get('victoire_core.helper.business_entity_helper')->findById($blog->getBusinessEntityId());
78
            $businessProperties = $businessEntity->getBusinessPropertiesByType('seoable');
79
        }
80
81
        return new JsonResponse(
82
            [
83
                'html' => $this->container->get('victoire_templating')->render(
84
                    $template,
85
                    [
86
                        'blog'               => $blog,
87
                        'currentTab'         => $tab,
88
                        'tabs'               => ['articles', 'settings', 'category'],
89
                        'chooseBlogForm'     => $chooseBlogForm->createView(),
90
                        'businessProperties' => $businessProperties,
91
                    ]
92
                ),
93
            ]
94
        );
95
    }
96
97
    /**
98
     * New page.
99
     *
100
     * @Route("/new", name="victoire_blog_new")
101
     * @Template()
102
     *
103
     * @return JsonResponse
104
     */
105
    public function newAction($isHomepage = false)
106
    {
107
        return new JsonResponse(parent::newAction());
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...e(parent::newAction()); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...geController::newAction of type array.

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...
108
    }
109
110
    /**
111
     * Blog settings.
112
     *
113
     * @param Request  $request
114
     * @param BasePage $blog
115
     *
116
     * @return JsonResponse
117
     * @Route("/{id}/settings", name="victoire_blog_settings")
118
     * @ParamConverter("blog", class="VictoirePageBundle:BasePage")
119
     */
120
    public function settingsAction(Request $request, BasePage $blog)
121
    {
122
        $entityManager = $this->getDoctrine()->getManager();
123
        $form = $this->createForm($this->getPageSettingsType(), $blog);
124
        $businessProperties = [];
125
126
        $form->handleRequest($request);
127
128
        if ($form->isValid()) {
129
            $entityManager->persist($blog);
130
            $entityManager->flush();
131
132
            /** @var ViewReference $reference */
133
            $reference = $this->container->get('victoire_view_reference.cache.repository')
134
            ->getOneReferenceByParameters(['viewId' => $blog->getId()]);
135
136
            return new JsonResponse([
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...eference->getUrl())))); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...troller::settingsAction of type array.

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...
137
                'success' => true,
138
                'url'     => $this->generateUrl(
139
                    'victoire_core_page_show', [
140
                        '_locale' => $blog->getLocale(), 'url' => $reference->getUrl(),
141
                ]),
142
            ]);
143
        }
144
        //we display the form
145
        $errors = $this->get('victoire_form.error_helper')->getRecursiveReadableErrors($form);
146
        if ($errors != '') {
147
            return new JsonResponse(['html' => $this->container->get('victoire_templating')->render(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...'message' => $errors)); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...troller::settingsAction of type array.

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...
148
                        $this->getBaseTemplatePath().':Tabs/_settings.html.twig',
149
                            [
150
                                'blog'               => $blog,
151
                                'form'               => $form->createView(),
152
                                'businessProperties' => $businessProperties,
153
                            ]
154
                        ),
155
                        'message' => $errors,
156
                    ]
157
                );
158
        }
159
160
        return new Response($this->container->get('victoire_templating')->render(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...$businessProperties))); (Symfony\Component\HttpFoundation\Response) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...troller::settingsAction of type array.

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
                    $this->getBaseTemplatePath().':Tabs/_settings.html.twig',
162
                    [
163
                        'blog'               => $blog,
164
                        'form'               => $form->createView(),
165
                        'businessProperties' => $businessProperties,
166
                    ]
167
                )
168
        );
169
    }
170
171
    /**
172
     * Blog settings.
173
     *
174
     * @param Request  $request
175
     * @param BasePage $blog
176
     *
177
     * @return Response
178
     * @Route("/{id}/category", name="victoire_blog_category")
179
     * @ParamConverter("blog", class="VictoirePageBundle:BasePage")
180
     */
181
    public function categoryAction(Request $request, BasePage $blog)
182
    {
183
        $entityManager = $this->getDoctrine()->getManager();
184
        $form = $this->createForm($this->getPageCategoryType(), $blog);
185
        $businessProperties = [];
186
187
        //if the page is a business entity page
188
        if ($blog instanceof BusinessTemplate) {
189
            //we can use the business entity properties on the seo
190
            $businessEntity = $this->get('victoire_core.helper.business_entity_helper')->findById($blog->getBusinessEntityId());
191
            $businessProperties = $businessEntity->getBusinessPropertiesByType('seoable');
192
        }
193
194
        $form->handleRequest($request);
195
196
        if ($form->isValid()) {
197
            $entityManager->persist($blog);
198
            $entityManager->flush();
199
200
            return new JsonResponse([
201
                'success' => true,
202
                'url'     => $this->generateUrl('victoire_core_page_show', ['_locale' => $blog->getLocale(), 'url' => $blog->getUrl()]), ]);
203
        }
204
        //we display the form
205
        $errors = $this->get('victoire_form.error_helper')->getRecursiveReadableErrors($form);
206
        if ($errors != '') {
207
            return new JsonResponse(['html' => $this->container->get('victoire_templating')->render(
208
                        $this->getBaseTemplatePath().':Tabs/_category.html.twig',
209
                            [
210
                                'blog'               => $blog,
211
                                'form'               => $form->createView(),
212
                                'businessProperties' => $businessProperties,
213
                            ]
214
                        ),
215
                        'message' => $errors,
216
                    ]
217
                );
218
        }
219
220
        return new Response($this->container->get('victoire_templating')->render(
221
                    $this->getBaseTemplatePath().':Tabs/_category.html.twig',
222
                    [
223
                        'blog'               => $blog,
224
                        'form'               => $form->createView(),
225
                        'businessProperties' => $businessProperties,
226
                    ]
227
                )
228
        );
229
    }
230
231
    /**
232
     * Blog settings.
233
     *
234
     * @param Request  $request
235
     * @param BasePage $blog
236
     *
237
     * @return Response
238
     * @Route("/{id}/articles", name="victoire_blog_articles")
239
     * @ParamConverter("blog", class="VictoirePageBundle:BasePage")
240
     */
241
    public function articlesAction(Request $request, BasePage $blog)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
242
    {
243
        return new Response($this->container->get('victoire_templating')->render(
244
                    $this->getBaseTemplatePath().':Tabs/_articles.html.twig',
245
                    [
246
                        'blog' => $blog,
247
                    ]
248
                )
249
        );
250
    }
251
252
    /**
253
     * Blog translation.
254
     *
255
     * @param Request  $request
256
     * @param BasePage $blog
257
     *
258
     * @return JsonResponse
259
     * @Route("/{id}/translate", name="victoire_blog_translate")
260
     * @Template()
261
     * @ParamConverter("blog", class="VictoirePageBundle:BasePage")
262
     */
263
    public function translateAction(Request $request, BasePage $blog)
264
    {
265
        return new JsonResponse(parent::translateAction($request, $blog));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...tion($request, $blog)); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...roller::translateAction of type array.

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...
266
    }
267
268
    /**
269
     * Page delete.
270
     *
271
     * @param Blog $blog
272
     *
273
     * @return JsonResponse
274
     * @Route("/{id}/delete", name="victoire_blog_delete")
275
     * @Template()
276
     * @ParamConverter("blog", class="VictoirePageBundle:BasePage")
277
     */
278
    public function deleteAction(BasePage $blog)
279
    {
280
        if (!$this->get('security.authorization_checker')->isGranted('ROLE_VICTOIRE', $blog)) {
281
            throw new AccessDeniedException("Nop ! you can't do such an action");
282
        }
283
284
        foreach ($blog->getArticles() as $_article) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Victoire\Bundle\PageBundle\Entity\BasePage as the method getArticles() does only exist in the following sub-classes of Victoire\Bundle\PageBundle\Entity\BasePage: Victoire\Bundle\BlogBundle\Entity\Blog. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
285
            $bep = $this->get('victoire_page.page_helper')->findPageByParameters(
286
                [
287
                    'templateId' => $_article->getTemplate()->getId(),
288
                    'entityId'   => $_article->getId(),
289
                ]
290
            );
291
            $this->get('victoire_blog.manager.article')->delete($_article, $bep);
292
        }
293
294
        return new JsonResponse(parent::deleteAction($blog));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Symfony\Comp...::deleteAction($blog)); (Symfony\Component\HttpFoundation\JsonResponse) is incompatible with the return type of the parent method Victoire\Bundle\PageBund...ontroller::deleteAction of type array.

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...
295
    }
296
297
    /**
298
     * @return string
299
     */
300
    protected function getPageSettingsType()
301
    {
302
        return 'victoire_blog_settings_type';
303
    }
304
305
    /**
306
     * @return string
307
     */
308
    protected function getPageCategoryType()
309
    {
310
        return 'victoire_blog_category_type';
311
    }
312
313
    /**
314
     * @return string
315
     */
316
    protected function getPageTranslateType()
317
    {
318
        return 'victoire_view_translate_type';
319
    }
320
321
    /**
322
     * @return string
323
     */
324
    protected function getNewPageType()
325
    {
326
        return 'victoire_blog_type';
327
    }
328
329
    /**
330
     * @return \Victoire\Bundle\BlogBundle\Entity\Blog
331
     */
332
    protected function getNewPage()
333
    {
334
        return new Blog();
335
    }
336
337
    /**
338
     * @return string
339
     */
340
    protected function getBaseTemplatePath()
341
    {
342
        return 'VictoireBlogBundle:Blog';
343
    }
344
345
    /**
346
     * @param unknown $action
347
     */
348
    protected function getRoutes($action)
349
    {
350
        return $this->routes[$action];
351
    }
352
}
353