|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of the Superdesk Web Publisher Core 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
|
|
|
|
|
15
|
|
|
namespace SWP\Bundle\CoreBundle\Controller; |
|
16
|
|
|
|
|
17
|
|
|
use SWP\Component\Common\Criteria\Criteria; |
|
18
|
|
|
use SWP\Component\Common\Pagination\PaginationData; |
|
19
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Model\ContainerInterface; |
|
20
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Model\WidgetModelInterface; |
|
21
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
|
22
|
|
|
use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
|
23
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; |
|
24
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; |
|
25
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
|
26
|
|
|
use SWP\Component\Common\Response\ResourcesListResponse; |
|
27
|
|
|
use SWP\Component\Common\Response\ResponseContext; |
|
28
|
|
|
use SWP\Component\Common\Response\SingleResourceResponse; |
|
29
|
|
|
use SWP\Bundle\TemplatesSystemBundle\Form\Type\ContainerType; |
|
30
|
|
|
use SWP\Bundle\TemplatesSystemBundle\Model\ContainerData; |
|
31
|
|
|
use SWP\Bundle\TemplatesSystemBundle\Model\ContainerWidget; |
|
32
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
33
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
|
34
|
|
|
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; |
|
35
|
|
|
|
|
36
|
|
|
class ContainerController extends Controller |
|
37
|
|
|
{ |
|
38
|
|
|
/** |
|
39
|
|
|
* Lists all registered containers. |
|
40
|
|
|
* |
|
41
|
|
|
* @ApiDoc( |
|
42
|
|
|
* resource=true, |
|
43
|
|
|
* description="Lists all registered containers", |
|
44
|
|
|
* statusCodes={ |
|
45
|
|
|
* 200="Returned on success." |
|
46
|
|
|
* } |
|
47
|
|
|
* ) |
|
48
|
|
|
* @Route("/api/{version}/templates/containers/", options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_list_containers") |
|
49
|
|
|
* @Method("GET") |
|
50
|
1 |
|
* @Cache(expires="10 minutes", public=true) |
|
51
|
|
|
*/ |
|
52
|
1 |
|
public function listAction(Request $request) |
|
53
|
1 |
|
{ |
|
54
|
1 |
|
$repository = $this->get('swp.repository.container'); |
|
55
|
1 |
|
|
|
56
|
1 |
|
$containers = $repository->getPaginatedByCriteria(new Criteria(), [], new PaginationData($request)); |
|
57
|
1 |
|
|
|
58
|
|
|
return new ResourcesListResponse($containers); |
|
59
|
|
|
} |
|
60
|
1 |
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* Get single container. |
|
63
|
|
|
* |
|
64
|
1 |
|
* @ApiDoc( |
|
65
|
|
|
* resource=true, |
|
66
|
|
|
* description="Get single container", |
|
67
|
|
|
* statusCodes={ |
|
68
|
|
|
* 200="Returned on success.", |
|
69
|
|
|
* 404="Container not found" |
|
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($id) |
|
77
|
|
|
{ |
|
78
|
|
|
$container = $this->get('doctrine')->getManager() |
|
79
|
|
|
->getRepository('SWP\Bundle\CoreBundle\Model\Container') |
|
80
|
|
|
->getById($id) |
|
81
|
|
|
->getOneOrNullResult(); |
|
82
|
|
|
|
|
83
|
1 |
|
if (!$container) { |
|
84
|
|
|
throw new NotFoundHttpException('Container with this id was not found.'); |
|
85
|
1 |
|
} |
|
86
|
1 |
|
|
|
87
|
1 |
|
return new SingleResourceResponse($container); |
|
88
|
1 |
|
} |
|
89
|
|
|
|
|
90
|
1 |
|
/** |
|
91
|
|
|
* Render single container and it's widgets. |
|
92
|
|
|
* |
|
93
|
|
|
* @ApiDoc( |
|
94
|
1 |
|
* resource=true, |
|
95
|
|
|
* description="Render single container and it's widgets.", |
|
96
|
|
|
* statusCodes={ |
|
97
|
|
|
* 200="Returned on success.", |
|
98
|
|
|
* 404="Container not found" |
|
99
|
|
|
* } |
|
100
|
|
|
* ) |
|
101
|
|
|
* @Route("/api/{version}/templates/containers/{id}/render", requirements={"id"="\d+"}, options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_render_container") |
|
102
|
|
|
* @Method("GET") |
|
103
|
|
|
* @Cache(expires="10 minutes", public=true) |
|
104
|
|
|
*/ |
|
105
|
|
|
public function renderAction($id) |
|
106
|
|
|
{ |
|
107
|
|
|
/** @var ContainerInterface $container */ |
|
108
|
|
|
$container = $this->get('swp.repository.container') |
|
109
|
|
|
->getById($id) |
|
110
|
|
|
->getOneOrNullResult(); |
|
111
|
|
|
|
|
112
|
|
|
if (!$container) { |
|
113
|
3 |
|
throw new NotFoundHttpException('Container with this id was not found.'); |
|
114
|
|
|
} |
|
115
|
3 |
|
|
|
116
|
3 |
|
$content = $this->get('templating') |
|
117
|
3 |
|
->render('SWPCoreBundle:Container:render.html.twig', ['containerName' => $container->getName()]); |
|
118
|
3 |
|
|
|
119
|
|
|
return new SingleResourceResponse(['content' => $content]); |
|
120
|
3 |
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Update single container. |
|
124
|
3 |
|
* |
|
125
|
3 |
|
* @ApiDoc( |
|
126
|
|
|
* resource=true, |
|
127
|
|
|
* description="Update single container", |
|
128
|
3 |
|
* statusCodes={ |
|
129
|
3 |
|
* 201="Returned on success.", |
|
130
|
3 |
|
* 404="Container not found", |
|
131
|
3 |
|
* 422="Container id is not number" |
|
132
|
|
|
* }, |
|
133
|
1 |
|
* input="SWP\Bundle\TemplatesSystemBundle\Form\Type\ContainerType" |
|
134
|
1 |
|
* ) |
|
135
|
|
|
* @Route("/api/{version}/templates/containers/{id}", requirements={"id"="\d+"}, options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_templates_update_container") |
|
136
|
|
|
* @Method("PATCH") |
|
137
|
|
|
*/ |
|
138
|
1 |
|
public function updateAction(Request $request, $id) |
|
139
|
1 |
|
{ |
|
140
|
1 |
|
$entityManager = $this->get('doctrine')->getManager(); |
|
141
|
1 |
|
$container = $entityManager->getRepository('SWP\Bundle\CoreBundle\Model\Container') |
|
142
|
1 |
|
->getById($id) |
|
143
|
|
|
->getOneOrNullResult(); |
|
144
|
|
|
|
|
145
|
|
|
if (!$container) { |
|
146
|
3 |
|
throw new NotFoundHttpException('Container with this id was not found.'); |
|
147
|
3 |
|
} |
|
148
|
|
|
|
|
149
|
3 |
|
$form = $this->createForm(ContainerType::class, $container, [ |
|
150
|
|
|
'method' => $request->getMethod(), |
|
151
|
|
|
]); |
|
152
|
|
|
|
|
153
|
|
|
$form->handleRequest($request); |
|
154
|
|
|
if ($form->isValid()) { |
|
155
|
|
|
$extraData = $form->get('data')->getExtraData(); |
|
156
|
|
|
if (!empty($extraData) && is_array($extraData)) { |
|
157
|
|
|
// Remove old containerData's |
|
158
|
|
|
foreach ($container->getData() as $containerData) { |
|
159
|
|
|
$entityManager->remove($containerData); |
|
160
|
|
|
} |
|
161
|
|
|
|
|
162
|
|
|
// Apply new containerData's |
|
163
|
|
|
foreach ($extraData as $key => $value) { |
|
164
|
|
|
$containerData = new ContainerData($key, $value); |
|
165
|
|
|
$containerData->setContainer($container); |
|
166
|
|
|
$entityManager->persist($containerData); |
|
167
|
|
|
$container->addData($containerData); |
|
168
|
|
|
} |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
$entityManager->flush($container); |
|
172
|
|
|
$entityManager->refresh($container); |
|
173
|
|
|
|
|
174
|
|
|
return new SingleResourceResponse($container, new ResponseContext(201)); |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
return new SingleResourceResponse($form); |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
/** |
|
181
|
|
|
* Link or Unlink resource with Container. |
|
182
|
|
|
* |
|
183
|
|
|
* **link or unlink widget**: |
|
184
|
|
|
* |
|
185
|
|
|
* header name: "link" |
|
186
|
|
|
* header value: "</api/{version}/templates/widgets/{id}; rel="widget">" |
|
187
|
|
|
* |
|
188
|
|
|
* or with specific position: |
|
189
|
|
|
* |
|
190
|
2 |
|
* header name: "link" |
|
191
|
|
|
* header value: "</api/{version}/templates/widgets/{id}; rel="widget">,<1; rel="widget-position">" |
|
192
|
2 |
|
* |
|
193
|
|
|
* @ApiDoc( |
|
194
|
|
|
* statusCodes={ |
|
195
|
|
|
* 201="Returned when successful", |
|
196
|
2 |
|
* 404="Returned when resource not found", |
|
197
|
2 |
|
* 409={ |
|
198
|
2 |
|
* "Returned when the link already exists", |
|
199
|
2 |
|
* } |
|
200
|
|
|
* } |
|
201
|
2 |
|
* ) |
|
202
|
|
|
* |
|
203
|
|
|
* @Route("/api/{version}/templates/containers/{id}", requirements={"id"="\d+"}, defaults={"version"="v1"}, name="swp_api_templates_link_container") |
|
204
|
|
|
* |
|
205
|
2 |
|
* @Method("LINK|UNLINK") |
|
206
|
2 |
|
* |
|
207
|
2 |
|
* @param Request $request |
|
208
|
|
|
* @param string $id |
|
209
|
|
|
* |
|
210
|
|
|
* @throws NotFoundHttpException |
|
211
|
2 |
|
* @throws \Exception |
|
212
|
2 |
|
* |
|
213
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
|
214
|
|
|
*/ |
|
215
|
|
|
public function linkUnlinkToContainerAction(Request $request, $id) |
|
216
|
2 |
|
{ |
|
217
|
2 |
|
if (!$id) { |
|
218
|
2 |
|
throw new UnprocessableEntityHttpException('You need to provide container Id (integer).'); |
|
219
|
2 |
|
} |
|
220
|
2 |
|
|
|
221
|
|
|
$entityManager = $this->get('doctrine')->getManager(); |
|
222
|
2 |
|
$container = $entityManager->getRepository('SWP\Bundle\CoreBundle\Model\Container') |
|
223
|
2 |
|
->getById($id) |
|
224
|
2 |
|
->getOneOrNullResult(); |
|
225
|
1 |
|
|
|
226
|
1 |
|
if (!$container) { |
|
227
|
1 |
|
throw new NotFoundHttpException('Container with this id was not found.'); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
$matched = false; |
|
231
|
|
|
foreach ($request->attributes->get('links', []) as $key => $objectArray) { |
|
232
|
2 |
|
if (!is_array($objectArray)) { |
|
233
|
|
|
continue; |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
2 |
|
$object = $objectArray['object']; |
|
237
|
2 |
|
if ($object instanceof \Exception) { |
|
238
|
2 |
|
throw $object; |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
2 |
|
if ($object instanceof WidgetModelInterface) { |
|
242
|
1 |
|
$containerWidget = $entityManager->getRepository('SWP\Bundle\TemplatesSystemBundle\Model\ContainerWidget') |
|
243
|
1 |
|
->findOneBy([ |
|
244
|
1 |
|
'widget' => $object, |
|
245
|
2 |
|
'container' => $container, |
|
246
|
|
|
]); |
|
247
|
1 |
|
if ($request->getMethod() === 'LINK') { |
|
248
|
1 |
|
$position = false; |
|
249
|
|
|
if (count($notConvertedLinks = $this->getNotConvertedLinks($request)) > 0) { |
|
250
|
|
|
foreach ($notConvertedLinks as $link) { |
|
251
|
1 |
|
if (isset($link['resourceType']) && $link['resourceType'] == 'widget-position') { |
|
252
|
|
|
$position = $link['resource']; |
|
253
|
|
|
} |
|
254
|
2 |
|
} |
|
255
|
2 |
|
} |
|
256
|
|
|
|
|
257
|
|
|
if ($position === false && $containerWidget) { |
|
258
|
2 |
|
throw new \Exception('WidgetModel is already linked to container', 409); |
|
259
|
|
|
} |
|
260
|
|
|
|
|
261
|
|
|
if (!$containerWidget) { |
|
262
|
2 |
|
$containerWidget = new ContainerWidget($container, $object); |
|
263
|
|
|
$entityManager->persist($containerWidget); |
|
264
|
2 |
|
} |
|
265
|
|
|
|
|
266
|
|
|
if ($position !== false) { |
|
267
|
|
|
$containerWidget->setPosition($position); |
|
268
|
|
|
$entityManager->persist($containerWidget); |
|
269
|
|
|
$container->addWidget($containerWidget); |
|
270
|
|
|
$entityManager->flush(); |
|
271
|
|
|
} |
|
272
|
2 |
|
} elseif ($request->getMethod() === 'UNLINK') { |
|
273
|
|
|
if (!$container->getWidgets()->contains($containerWidget)) { |
|
274
|
2 |
|
throw new \Exception('WidgetModel is not linked to container', 409); |
|
275
|
2 |
|
} |
|
276
|
2 |
|
$entityManager->remove($containerWidget); |
|
277
|
1 |
|
} |
|
278
|
1 |
|
|
|
279
|
1 |
|
$matched = true; |
|
280
|
1 |
|
break; |
|
281
|
1 |
|
} |
|
282
|
|
|
} |
|
283
|
1 |
|
if ($matched === false) { |
|
284
|
1 |
|
throw new NotFoundHttpException('Any supported link object was not found'); |
|
285
|
|
|
} |
|
286
|
1 |
|
|
|
287
|
1 |
|
$entityManager->flush(); |
|
288
|
2 |
|
|
|
289
|
|
|
return new SingleResourceResponse($container, new ResponseContext(201)); |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
|
|
/** |
|
293
|
2 |
|
* @param Request $request |
|
294
|
|
|
* |
|
295
|
|
|
* @return array |
|
296
|
|
|
*/ |
|
297
|
|
|
private function getNotConvertedLinks($request) |
|
298
|
|
|
{ |
|
299
|
|
|
$links = []; |
|
300
|
|
|
foreach ($request->attributes->get('links') as $idx => $link) { |
|
301
|
|
|
if (is_string($link)) { |
|
302
|
|
|
$linkParams = explode(';', trim($link)); |
|
303
|
|
|
$resourceType = null; |
|
304
|
|
View Code Duplication |
if (count($linkParams) > 1) { |
|
|
|
|
|
|
305
|
|
|
$resourceType = trim(preg_replace('/<|>/', '', $linkParams[1])); |
|
306
|
|
|
$resourceType = str_replace('"', '', str_replace('rel=', '', $resourceType)); |
|
307
|
|
|
} |
|
308
|
|
|
$resource = array_shift($linkParams); |
|
309
|
|
|
$resource = preg_replace('/<|>/', '', $resource); |
|
310
|
|
|
|
|
311
|
|
|
$links[] = [ |
|
312
|
|
|
'resource' => $resource, |
|
313
|
|
|
'resourceType' => $resourceType, |
|
314
|
|
|
]; |
|
315
|
|
|
} |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
return $links; |
|
319
|
|
|
} |
|
320
|
|
|
} |
|
321
|
|
|
|
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.