Completed
Push — master ( b7d603...d97993 )
by Paweł
07:44
created

PackagePreviewController::previewAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 14

Duplication

Lines 5
Ratio 21.74 %

Importance

Changes 0
Metric Value
dl 5
loc 23
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 14
nc 2
nop 3
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
        $metaFactory = $this->get('swp_template_engine_context.factory.meta_factory');
50
        $templateEngineContext = $this->get('swp_template_engine_context');
51
        $templateEngineContext->setPreviewMode(true);
52
        $templateEngineContext->setCurrentPage($metaFactory->create($route));
53
        $templateEngineContext->getMetaForValue($article);
54
55 View Code Duplication
        if (null === $route->getArticlesTemplateName()) {
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...
56
            throw $this->createNotFoundException(
57
                sprintf('Template for route with id "%d" (%s) not found!', $route->getId(), $route->getName())
58
            );
59
        }
60
61
        return $this->render($route->getArticlesTemplateName());
62
    }
63
64
    /**
65
     * Generates package preview token for specific route.
66
     *
67
     * @ApiDoc(
68
     *     resource=true,
69
     *     description="Generate package preview token for specific route",
70
     *     statusCodes={
71
     *         200="Returned on success.",
72
     *         400="Returned when validation failed.",
73
     *         500="Returned when unexpected error."
74
     *     }
75
     * )
76
     * @Route("/api/{version}/preview/package/generate_token/{routeId}", options={"expose"=true}, defaults={"version"="v1"}, name="swp_api_core_preview_package_token", requirements={"routeId"="\d+"})
77
     * @Method("POST")
78
     */
79
    public function generateTokenAction(Request $request, int $routeId)
80
    {
81
        $route = $this->findRouteOr404($routeId);
82
83
        $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...
84
85
        /** @var string $content */
86
        $content = (string) $request->getContent();
87
        $dispatcher = $this->get('event_dispatcher');
88
        $package = $this->get('swp_bridge.transformer.json_to_package')->transform($content);
89
        $dispatcher->dispatch(Events::SWP_VALIDATION, new GenericEvent($package));
90
91
        $existingPreviewToken = $this->get('swp.repository.package_preview_token')->findOneBy(['route' => $route]);
92
93
        if (null === $existingPreviewToken) {
94
            $packagePreviewToken = $this->get('swp.factory.package_preview_token')->createTokenizedWith($route, $content);
95
96
            $this->get('swp.repository.package_preview_token')->persist($packagePreviewToken);
97
            $this->get('swp.repository.package_preview_token')->flush();
98
99
            return $this->returnResponseWithPreviewUrl($packagePreviewToken);
100
        }
101
102
        $this->updatePackagePreviewTokenBody($content, $existingPreviewToken);
103
104
        return $this->returnResponseWithPreviewUrl($existingPreviewToken);
105
    }
106
107
    private function updatePackagePreviewTokenBody(string $content, PackagePreviewTokenInterface $packagePreviewToken)
108
    {
109
        if (md5($content) !== md5($packagePreviewToken->getBody())) {
110
            $packagePreviewToken->setBody($content);
111
112
            $this->get('swp.repository.package_preview_token')->flush();
113
        }
114
    }
115
116
    private function returnResponseWithPreviewUrl(PackagePreviewTokenInterface $packagePreviewToken): SingleResourceResponseInterface
117
    {
118
        $url = $this->generateUrl(
119
            'swp_package_preview_publish',
120
            ['token' => $packagePreviewToken->getToken()],
121
            UrlGeneratorInterface::ABSOLUTE_URL
122
        );
123
124
        return new SingleResourceResponse([
125
            'preview_url' => $url,
126
        ]);
127
    }
128
129
    /**
130
     * @Route("/preview/publish/package/{token}", options={"expose"=true}, requirements={"token"=".+"}, name="swp_package_preview_publish")
131
     * @Method("GET")
132
     */
133
    public function publishPreviewAction(string $token)
134
    {
135
        $existingPreviewToken = $this->get('swp.repository.package_preview_token')->findOneBy(['token' => $token]);
136
137
        if (null === $existingPreviewToken) {
138
            throw $this->createNotFoundException(sprintf('Token %s is not valid.', $token));
139
        }
140
141
        $dispatcher = $this->get('event_dispatcher');
142
        $package = $this->get('swp_bridge.transformer.json_to_package')->transform($existingPreviewToken->getBody());
143
        $dispatcher->dispatch(Events::SWP_VALIDATION, new GenericEvent($package));
144
145
        $articlePreviewer = $this->get(ArticlePreviewer::class);
146
147
        $article = $articlePreviewer->preview($package, $existingPreviewToken->getRoute());
148
        $route = $article->getRoute();
149
150
        $this->ensureRouteTemplateExists($route);
151
152
        return $this->render($route->getArticlesTemplateName());
153
    }
154
155
    private function ensureRouteTemplateExists(RouteInterface $route): void
156
    {
157 View Code Duplication
        if (null === $route->getArticlesTemplateName()) {
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...
158
            throw $this->createNotFoundException(
159
                sprintf('Template for route with id "%d" (%s) not found!', $route->getId(), $route->getName())
160
            );
161
        }
162
    }
163
164
    /**
165
     * @param int $id
166
     *
167
     * @return null|object
168
     */
169
    private function findRouteOr404(int $id)
170
    {
171
        if (null === ($route = $this->get('swp.repository.route')->findOneBy(['id' => $id]))) {
172
            throw $this->createNotFoundException(sprintf('Route with id: "%s" not found!', $id));
173
        }
174
175
        return $route;
176
    }
177
178
    /**
179
     * @param string $id
180
     *
181
     * @return null|object
182
     */
183
    private function findPackageOr404(string $id)
184
    {
185
        if (null === ($package = $this->get('swp.repository.package')->findOneBy(['id' => $id]))) {
186
            throw $this->createNotFoundException(sprintf('Package with id: "%s" not found!', $id));
187
        }
188
189
        return $package;
190
    }
191
}
192