Completed
Push — master ( 530ce9...1b2ae5 )
by Paweł
23:42 queued 20:31
created

ContainerController::linkUnlinkToContainerAction()   C

Complexity

Conditions 19
Paths 32

Size

Total Lines 78
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 78
rs 5.1186
cc 19
eloc 49
nc 32
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the Superdesk Web Publisher Template Engine Bundle.
5
 *
6
 * Copyright 2015 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú.
12
 * @license http://www.superdesk.org/license
13
 */
14
namespace SWP\Bundle\TemplateEngineBundle\Controller;
15
16
use FOS\RestBundle\Controller\FOSRestController;
17
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
19
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
20
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
21
use FOS\RestBundle\View\View;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
24
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
25
use SWP\Bundle\TemplateEngineBundle\Form\Type\ContainerType;
26
use SWP\Bundle\TemplateEngineBundle\Model\Widget;
27
use SWP\Bundle\TemplateEngineBundle\Model\ContainerWidget;
28
use SWP\Bundle\TemplateEngineBundle\Model\ContainerData;
29
use SWP\Component\Common\Event\HttpCacheEvent;
30
31
class ContainerController extends FOSRestController
32
{
33
    /**
34
     * Lists all registered containers.
35
     *
36
     * @ApiDoc(
37
     *     resource=true,
38
     *     description="Lists all registered containers",
39
     *     statusCodes={
40
     *         200="Returned on success."
41
     *     }
42
     * )
43
     * @Route("/api/{version}/templates/containers/", options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_list_containers")
44
     * @Method("GET")
45
     * @Cache(expires="10 minutes", public=true)
46
     */
47 View Code Duplication
    public function listAction(Request $request)
0 ignored issues
show
Duplication introduced by
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...
48
    {
49
        $entityManager = $this->get('doctrine')->getManager();
50
        $paginator = $this->get('knp_paginator');
51
        $containers = $paginator->paginate($entityManager->getRepository('SWP\Bundle\TemplateEngineBundle\Model\Container')->getAll());
52
53
        if (count($containers) == 0) {
54
            throw new NotFoundHttpException('Containers were not found.');
55
        }
56
57
        return $this->handleView(View::create($this->container->get('swp_pagination_rep')->createRepresentation($containers, $request), 200));
58
    }
59
60
    /**
61
     * Get single container.
62
     *
63
     * @ApiDoc(
64
     *     resource=true,
65
     *     description="Get single container",
66
     *     statusCodes={
67
     *         200="Returned on success.",
68
     *         404="Container not found",
69
     *         422="Container id is not number"
70
     *     }
71
     * )
72
     * @Route("/api/{version}/templates/containers/{id}", requirements={"id"="\d+"}, options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_get_container")
73
     * @Method("GET")
74
     * @Cache(expires="10 minutes", public=true)
75
     */
76
    public function getAction(Request $request, $id)
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...
77
    {
78
        $container = $this->get('doctrine')->getManager()
79
            ->getRepository('SWP\Bundle\TemplateEngineBundle\Model\Container')
80
            ->getById($id)
81
            ->getOneOrNullResult();
82
83
        if (!$container) {
84
            throw new NotFoundHttpException('Container with this id was not found.');
85
        }
86
87
        $this->get('event_dispatcher')
88
            ->dispatch(HttpCacheEvent::EVENT_NAME, new HttpCacheEvent($container));
89
90
        return $this->handleView(View::create($container, 200));
91
    }
92
93
    /**
94
     * Update single container.
95
     *
96
     * @ApiDoc(
97
     *     resource=true,
98
     *     description="Update single container",
99
     *     statusCodes={
100
     *         201="Returned on success.",
101
     *         404="Container not found",
102
     *         422="Container id is not number"
103
     *     },
104
     *     input="SWP\Bundle\TemplateEngineBundle\Form\Type\ContainerType"
105
     * )
106
     * @Route("/api/{version}/templates/containers/{id}", requirements={"id"="\d+"}, options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_update_container")
107
     * @Method("PATCH")
108
     */
109
    public function updateAction(Request $request, $id)
110
    {
111
        $entityManager = $this->get('doctrine')->getManager();
112
        $container = $entityManager->getRepository('SWP\Bundle\TemplateEngineBundle\Model\Container')
113
            ->getById($id)
114
            ->getOneOrNullResult();
115
116
        if (!$container) {
117
            throw new NotFoundHttpException('Container with this id was not found.');
118
        }
119
120
        $form = $this->createForm(ContainerType::class, $container, array(
121
            'method' => $request->getMethod(),
122
        ));
123
124
        $form->handleRequest($request);
125
        if ($form->isValid()) {
126
            $extraData = $form->get('data')->getExtraData();
127
            if ($extraData && is_array($extraData)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extraData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
128
                // Remove old containerData's
129
                foreach ($container->getData() as $containerData) {
130
                    $entityManager->remove($containerData);
131
                }
132
133
                // Apply new containerData's
134
                foreach ($extraData as $key => $value) {
135
                    $containerData = new ContainerData($key, $value);
136
                    $containerData->setContainer($container);
137
                    $entityManager->persist($containerData);
138
                    $container->addData($containerData);
139
                }
140
            }
141
142
            $entityManager->flush($container);
143
            $entityManager->refresh($container);
144
            $this->get('event_dispatcher')
145
                ->dispatch(HttpCacheEvent::EVENT_NAME, new HttpCacheEvent($container));
146
147
            return $this->handleView(View::create($container, 201));
148
        }
149
150
        return $this->handleView(View::create($form, 200));
151
    }
152
153
    /**
154
     * Link or Unlink resource with Container.
155
     *
156
     * **link or unlink widget**:
157
     *
158
     *     header name: "link"
159
     *     header value: "</api/{version}/templates/widgets/{id}; rel="widget">"
160
     *
161
     * or with specific position:
162
     *
163
     *     header name: "link"
164
     *     header value: "</api/{version}/templates/widgets/{id}; rel="widget">,<1; rel="widget-position">"
165
     *
166
     * @ApiDoc(
167
     *     statusCodes={
168
     *         201="Returned when successful",
169
     *         404="Returned when resource not found",
170
     *         409={
171
     *           "Returned when the link already exists",
172
     *         }
173
     *     }
174
     * )
175
     *
176
     * @Route("/api/{version}/templates/containers/{id}", requirements={"id"="\d+"}, defaults={"version"="v1"}, name="swp_api_templates_link_container")
177
     *
178
     * @Method("LINK|UNLINK")
179
     *
180
     * @return \Symfony\Component\HttpFoundation\Response
181
     */
182
    public function linkUnlinkToContainerAction(Request $request, $id)
183
    {
184
        if (!$id) {
185
            throw new UnprocessableEntityHttpException('You need to provide container Id (integer).');
186
        }
187
188
        $entityManager = $this->get('doctrine')->getManager();
189
        $container = $entityManager->getRepository('SWP\Bundle\TemplateEngineBundle\Model\Container')
190
            ->getById($id)
191
            ->getOneOrNullResult();
192
193
        if (!$container) {
194
            throw new NotFoundHttpException('Container with this id was not found.');
195
        }
196
197
        $matched = false;
198
        foreach ($request->attributes->get('links', array()) as $key => $objectArray) {
199
            if (!is_array($objectArray)) {
200
                continue;
201
            }
202
203
            $resourceType = $objectArray['resourceType'];
0 ignored issues
show
Unused Code introduced by
$resourceType 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...
204
            $object = $objectArray['object'];
205
206
            if ($object instanceof \Exception) {
207
                throw $object;
208
            }
209
210
            if ($object instanceof Widget) {
211
                $containerWidget = $entityManager->getRepository('SWP\Bundle\TemplateEngineBundle\Model\ContainerWidget')
212
                    ->findOneBy([
213
                        'widget' => $object,
214
                        'container' => $container,
215
                    ]);
216
                if ($request->getMethod() === 'LINK') {
217
                    $position = false;
218
                    if (count($notConvertedLinks = $this->getNotConvertedLinks($request)) > 0) {
219
                        foreach ($notConvertedLinks as $link) {
220
                            if (isset($link['resourceType']) && $link['resourceType'] == 'widget-position') {
221
                                $position = $link['resource'];
222
                            }
223
                        }
224
                    }
225
226
                    if ($position === false && $containerWidget) {
227
                        throw new \Exception('Widget is already linked to container', 409);
228
                    }
229
230
                    if (!$containerWidget) {
231
                        $containerWidget = new ContainerWidget($container, $object);
232
                        $entityManager->persist($containerWidget);
233
                    }
234
235
                    if ($position !== false) {
236
                        $containerWidget->setPosition($position);
237
                        $entityManager->persist($containerWidget);
238
                        $entityManager->flush($containerWidget);
239
                    }
240
                } elseif ($request->getMethod() === 'UNLINK') {
241
                    if (!$container->getWidgets()->contains($containerWidget)) {
242
                        throw new \Exception('Widget is not linked to container', 409);
243
                    }
244
                    $entityManager->remove($containerWidget);
245
                }
246
247
                $entityManager->flush();
248
                $this->get('event_dispatcher')
249
                    ->dispatch(HttpCacheEvent::EVENT_NAME, new HttpCacheEvent($container));
250
                $matched = true;
251
                break;
252
            }
253
        }
254
        if ($matched === false) {
255
            throw new NotFoundHttpException('Any supported link object was not found');
256
        }
257
258
        return $this->handleView(View::create($container, 201));
259
    }
260
261
    /**
262
     * @param Request $request
263
     */
264
    private function getNotConvertedLinks($request)
265
    {
266
        $links = array();
267
        foreach ($request->attributes->get('links') as $idx => $link) {
268
            if (is_string($link)) {
269
                $linkParams = explode(';', trim($link));
270
                $resourceType = null;
271 View Code Duplication
                if (count($linkParams) > 1) {
0 ignored issues
show
Duplication introduced by
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...
272
                    $resourceType = trim(preg_replace('/<|>/', '', $linkParams[1]));
273
                    $resourceType = str_replace('"', '', str_replace('rel=', '', $resourceType));
274
                }
275
                $resource = array_shift($linkParams);
276
                $resource = preg_replace('/<|>/', '', $resource);
277
278
                $links[] = array(
279
                    'resource' => $resource,
280
                    'resourceType' => $resourceType,
281
                );
282
            }
283
        }
284
285
        return $links;
286
    }
287
}
288