Completed
Push — ezp-30882-thumbnail-strategy-i... ( b3e424...83a23b )
by
unknown
13:58
created

ViewController::handleViewException()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 6
dl 0
loc 24
rs 9.536
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the ViewController class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\MVC\Symfony\Controller\Content;
10
11
use eZ\Publish\API\Repository\Values\Content\Content;
12
use eZ\Publish\API\Repository\Values\Content\Location;
13
use eZ\Publish\Core\MVC\Symfony\Controller\Controller;
14
use eZ\Publish\Core\MVC\Symfony\MVCEvents;
15
use eZ\Publish\Core\MVC\Symfony\Event\APIContentExceptionEvent;
16
use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute as AuthorizationAttribute;
17
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
18
use eZ\Publish\Core\MVC\Symfony\View\ViewManagerInterface;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
21
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
22
use DateTime;
23
use Exception;
24
25
/**
26
 * This controller provides the content view feature.
27
 *
28
 * @since 6.0.0 All methods except `view()` are deprecated and will be removed in the future.
29
 */
30
class ViewController extends Controller
31
{
32
    /** @var \eZ\Publish\Core\MVC\Symfony\View\ViewManagerInterface */
33
    protected $viewManager;
34
35
    /** @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface */
36
    private $authorizationChecker;
37
38
    public function __construct(ViewManagerInterface $viewManager, AuthorizationCheckerInterface $authorizationChecker)
39
    {
40
        $this->viewManager = $viewManager;
41
        $this->authorizationChecker = $authorizationChecker;
42
    }
43
44
    /**
45
     * This is the default view action or a ContentView object.
46
     *
47
     * It doesn't do anything by itself: the returned View object is rendered by the ViewRendererListener
48
     * into an HttpFoundation Response.
49
     *
50
     * This action can be selectively replaced by a custom action by means of content_view
51
     * configuration. Custom actions can add parameters to the view and customize the Response the View will be
52
     * converted to. They may also bypass the ViewRenderer by returning an HttpFoundation Response.
53
     *
54
     * Cache is in both cases handled by the CacheViewResponseListener.
55
     *
56
     * @param \eZ\Publish\Core\MVC\Symfony\View\ContentView $view
57
     *
58
     * @return \eZ\Publish\Core\MVC\Symfony\View\ContentView
59
     */
60
    public function viewAction(ContentView $view)
61
    {
62
        return $view;
63
    }
64
65
    /**
66
     * Embed a content.
67
     * Behaves mostly like viewAction(), but with specific content load permission handling.
68
     *
69
     * @param \eZ\Publish\Core\MVC\Symfony\View\ContentView $view
70
     *
71
     * @return \eZ\Publish\Core\MVC\Symfony\View\ContentView
72
     */
73
    public function embedAction(ContentView $view)
74
    {
75
        return $view;
76
    }
77
78
    /**
79
     * Build the response so that depending on settings it's cacheable.
80
     *
81
     * @param string|null $etag
82
     * @param \DateTime|null $lastModified
83
     *
84
     * @return \Symfony\Component\HttpFoundation\Response
85
     */
86
    protected function buildResponse($etag = null, DateTime $lastModified = null)
87
    {
88
        $request = $this->getRequest();
89
        $response = new Response();
90
        if ($this->getParameter('content.view_cache') === true) {
91
            $response->setPublic();
92
            if ($etag !== null) {
93
                $response->setEtag($etag);
94
            }
95
96
            if ($this->getParameter('content.ttl_cache') === true) {
97
                $response->setSharedMaxAge(
98
                    $this->getParameter('content.default_ttl')
99
                );
100
            }
101
102
            // Make the response vary against X-User-Context-Hash header ensures that an HTTP
103
            // reverse proxy caches the different possible variations of the
104
            // response as it can depend on user role for instance.
105
            if ($request->headers->has('X-User-Context-Hash')) {
106
                $response->setVary('X-User-Context-Hash');
107
            }
108
109
            if ($lastModified != null) {
110
                $response->setLastModified($lastModified);
111
            }
112
        }
113
114
        return $response;
115
    }
116
117
    protected function handleViewException(Response $response, $params, Exception $e, $viewType, $contentId = null, $locationId = null)
118
    {
119
        $event = new APIContentExceptionEvent(
120
            $e,
121
            [
122
                'contentId' => $contentId,
123
                'locationId' => $locationId,
124
                'viewType' => $viewType,
125
            ]
126
        );
127
        $this->getEventDispatcher()->dispatch(MVCEvents::API_CONTENT_EXCEPTION, $event);
128
        if ($event->hasContentView()) {
129
            $response->setContent(
130
                $this->viewManager->renderContentView(
131
                    $event->getContentView(),
132
                    $params
133
                )
134
            );
135
136
            return $response;
137
        }
138
139
        throw $e;
140
    }
141
142
    /**
143
     * Creates the content to be returned when viewing a Location.
144
     *
145
     * @param Location $location
146
     * @param string $viewType
147
     * @param bool $layout
148
     * @param array $params
149
     *
150
     * @return string
151
     */
152
    protected function renderLocation(Location $location, $viewType, $layout = false, array $params = [])
153
    {
154
        return $this->viewManager->renderLocation($location, $viewType, $params + ['no_layout' => !$layout]);
155
    }
156
157
    /**
158
     * Creates the content to be returned when viewing a Content.
159
     *
160
     * @param Content $content
161
     * @param string $viewType
162
     * @param bool $layout
163
     * @param array $params
164
     *
165
     * @return string
166
     */
167
    protected function renderContent(Content $content, $viewType, $layout = false, array $params = [])
168
    {
169
        return $this->viewManager->renderContent($content, $viewType, $params + ['no_layout' => !$layout]);
170
    }
171
172
    /**
173
     * Performs the access checks.
174
     */
175
    protected function performAccessChecks()
176
    {
177
        if (!$this->isGranted(new AuthorizationAttribute('content', 'read'))) {
178
            throw new AccessDeniedException();
179
        }
180
    }
181
}
182