Completed
Push — master ( fd8111...e0db1d )
by Paweł
08:21
created

PackagePreviewController   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 0
loc 164
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
B previewAction() 0 29 3
B generateTokenAction() 0 27 2
A updatePackagePreviewTokenBody() 0 8 2
A returnResponseWithPreviewUrl() 0 12 1
A publishPreviewAction() 0 21 2
A ensureRouteTemplateExists() 0 8 2
A findRouteOr404() 0 8 2
A findPackageOr404() 0 8 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Content Bundle.
7
 *
8
 * Copyright 2017 Sourcefabric z.ú. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2017 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\CoreBundle\Controller;
18
19
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
20
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
21
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
22
use SWP\Bundle\ContentBundle\Model\RouteInterface;
23
use SWP\Bundle\CoreBundle\Model\PackageInterface;
24
use SWP\Bundle\CoreBundle\Model\PackagePreviewTokenInterface;
25
use SWP\Bundle\CoreBundle\Service\ArticlePreviewer;
26
use SWP\Component\Bridge\Events;
27
use SWP\Component\Common\Response\SingleResourceResponse;
28
use SWP\Component\Common\Response\SingleResourceResponseInterface;
29
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
30
use Symfony\Component\EventDispatcher\GenericEvent;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
33
34
class PackagePreviewController extends Controller
35
{
36
    /**
37
     * @Route("/preview/package/{routeId}/{id}", options={"expose"=true}, requirements={"id"="\d+", "routeId"="\d+", "token"=".+"}, name="swp_package_preview")
38
     * @Method("GET")
39
     */
40
    public function previewAction(Request $request, int $routeId, $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...
41
    {
42
        /** @var RouteInterface $route */
43
        $route = $this->findRouteOr404($routeId);
44
        /** @var PackageInterface $package */
45
        $package = $this->findPackageOr404($id);
46
        $article = $this->get('swp.factory.article')->createFromPackage($package);
47
        $this->get('swp_content_bundle.processor.article_body')->fillArticleMedia($package, $article);
48
49
        $article->setRoute($route);
50
        $metaFactory = $this->get('swp_template_engine_context.factory.meta_factory');
51
        $templateEngineContext = $this->get('swp_template_engine_context');
52
        $templateEngineContext->setPreviewMode(true);
53
        $templateEngineContext->setCurrentPage($metaFactory->create($route));
54
        $templateEngineContext->getMetaForValue($article);
55
56
        if (null === $route->getArticlesTemplateName()) {
57
            $templateNameResolver = $this->get('swp_core.theme.resolver.template_name');
58
            $route->setArticlesTemplateName($templateNameResolver->resolve($article));
59
        }
60
61
        try {
62
            return $this->render($route->getArticlesTemplateName());
63
        } catch (\Exception $e) {
64
            throw $this->createNotFoundException(
65
                sprintf('Template for route with id "%d" (%s) not found!', $route->getId(), $route->getName())
66
            );
67
        }
68
    }
69
70
    /**
71
     * Generates package preview token for specific route.
72
     *
73
     * @ApiDoc(
74
     *     resource=true,
75
     *     description="Generate package preview token for specific route",
76
     *     statusCodes={
77
     *         200="Returned on success.",
78
     *         400="Returned when validation failed.",
79
     *         500="Returned when unexpected error."
80
     *     }
81
     * )
82
     * @Route("/api/{version}/preview/package/generate_token/{routeId}", options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_core_preview_package_token", requirements={"routeId"="\d+"})
83
     * @Method("POST")
84
     */
85
    public function generateTokenAction(Request $request, int $routeId)
86
    {
87
        $route = $this->findRouteOr404($routeId);
88
89
        $this->ensureRouteTemplateExists($route);
0 ignored issues
show
Documentation introduced by
$route is of type null|object, but the function expects a object<SWP\Bundle\Conten...e\Model\RouteInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
90
91
        /** @var string $content */
92
        $content = (string) $request->getContent();
93
        $dispatcher = $this->get('event_dispatcher');
94
        $package = $this->get('swp_bridge.transformer.json_to_package')->transform($content);
95
        $dispatcher->dispatch(Events::SWP_VALIDATION, new GenericEvent($package));
96
97
        $existingPreviewToken = $this->get('swp.repository.package_preview_token')->findOneBy(['route' => $route]);
98
99
        if (null === $existingPreviewToken) {
100
            $packagePreviewToken = $this->get('swp.factory.package_preview_token')->createTokenizedWith($route, $content);
101
102
            $this->get('swp.repository.package_preview_token')->persist($packagePreviewToken);
103
            $this->get('swp.repository.package_preview_token')->flush();
104
105
            return $this->returnResponseWithPreviewUrl($packagePreviewToken);
106
        }
107
108
        $this->updatePackagePreviewTokenBody($content, $existingPreviewToken);
109
110
        return $this->returnResponseWithPreviewUrl($existingPreviewToken);
111
    }
112
113
    private function updatePackagePreviewTokenBody(string $content, PackagePreviewTokenInterface $packagePreviewToken)
114
    {
115
        if (md5($content) !== md5($packagePreviewToken->getBody())) {
116
            $packagePreviewToken->setBody($content);
117
118
            $this->get('swp.repository.package_preview_token')->flush();
119
        }
120
    }
121
122
    private function returnResponseWithPreviewUrl(PackagePreviewTokenInterface $packagePreviewToken): SingleResourceResponseInterface
123
    {
124
        $url = $this->generateUrl(
125
            'swp_package_preview_publish',
126
            ['token' => $packagePreviewToken->getToken()],
127
            UrlGeneratorInterface::ABSOLUTE_URL
128
        );
129
130
        return new SingleResourceResponse([
131
            'preview_url' => $url,
132
        ]);
133
    }
134
135
    /**
136
     * @Route("/preview/publish/package/{token}", options={"expose"=true}, requirements={"token"=".+"}, name="swp_package_preview_publish")
137
     * @Method("GET")
138
     */
139
    public function publishPreviewAction(string $token)
140
    {
141
        $existingPreviewToken = $this->get('swp.repository.package_preview_token')->findOneBy(['token' => $token]);
142
143
        if (null === $existingPreviewToken) {
144
            throw $this->createNotFoundException(sprintf('Token %s is not valid.', $token));
145
        }
146
147
        $dispatcher = $this->get('event_dispatcher');
148
        $package = $this->get('swp_bridge.transformer.json_to_package')->transform($existingPreviewToken->getBody());
149
        $dispatcher->dispatch(Events::SWP_VALIDATION, new GenericEvent($package));
150
151
        $articlePreviewer = $this->get(ArticlePreviewer::class);
152
153
        $article = $articlePreviewer->preview($package, $existingPreviewToken->getRoute());
154
        $route = $article->getRoute();
155
156
        $this->ensureRouteTemplateExists($route);
157
158
        return $this->render($route->getArticlesTemplateName());
159
    }
160
161
    private function ensureRouteTemplateExists(RouteInterface $route): void
162
    {
163
        if (null === $route->getArticlesTemplateName()) {
164
            throw $this->createNotFoundException(
165
                sprintf('Template for route with id "%d" (%s) not found!', $route->getId(), $route->getName())
166
            );
167
        }
168
    }
169
170
    /**
171
     * @param int $id
172
     *
173
     * @return null|object
174
     */
175
    private function findRouteOr404(int $id)
176
    {
177
        if (null === ($route = $this->get('swp.repository.route')->findOneBy(['id' => $id]))) {
178
            throw $this->createNotFoundException(sprintf('Route with id: "%s" not found!', $id));
179
        }
180
181
        return $route;
182
    }
183
184
    /**
185
     * @param string $id
186
     *
187
     * @return null|object
188
     */
189
    private function findPackageOr404(string $id)
190
    {
191
        if (null === ($package = $this->get('swp.repository.package')->findOneBy(['id' => $id]))) {
192
            throw $this->createNotFoundException(sprintf('Package with id: "%s" not found!', $id));
193
        }
194
195
        return $package;
196
    }
197
}
198