Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-6312: View matcher ParentContentType should not throw execption if parent is not available #383

2 changes: 2 additions & 0 deletions eZ/Bundle/EzPublishCoreBundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ services:
$authorizationChecker: '@security.authorization_checker'
$locationProvider: '@ezpublish.content_preview.location_provider'
$controllerChecker: '@ezpublish.view.custom_location_controller_checker'
$debugMode: '%kernel.debug%'
$logger: '@logger'
tags:
- { name: controller.service_arguments }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowadays we try to send logs to specific monolog channels. To do so please add:

Suggested change
- { name: controller.service_arguments }
- { name: controller.service_arguments }
- { name: monolog.logger, channel: ibexa.controller }

note that channel is arbitrary / gut feeling choice. I briefly discussed this with @Steveb-p and we've chosen here ibexa.controller.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

use Exception;
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\Core\Base\Exceptions\BadStateException;
use eZ\Publish\Core\Helper\ContentPreviewHelper;
use eZ\Publish\Core\Helper\PreviewLocationProvider;
use eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator;
Expand All @@ -21,13 +23,19 @@
use eZ\Publish\Core\MVC\Symfony\SiteAccess;
use eZ\Publish\Core\MVC\Symfony\View\CustomLocationControllerChecker;
use eZ\Publish\Core\MVC\Symfony\View\ViewManagerInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class PreviewController
{
use LoggerAwareTrait;

public const PREVIEW_PARAMETER_NAME = 'isPreview';
public const CONTENT_VIEW_ROUTE = '_ez_content_view';

Expand All @@ -52,14 +60,19 @@ class PreviewController
/** @var \eZ\Publish\Core\MVC\Symfony\View\CustomLocationControllerChecker */
private $controllerChecker;

/** @var bool */
private $debugMode;

public function __construct(
ContentService $contentService,
LocationService $locationService,
HttpKernelInterface $kernel,
ContentPreviewHelper $previewHelper,
AuthorizationCheckerInterface $authorizationChecker,
PreviewLocationProvider $locationProvider,
CustomLocationControllerChecker $controllerChecker
CustomLocationControllerChecker $controllerChecker,
bool $debugMode,
?LoggerInterface $logger = null
) {
$this->contentService = $contentService;
$this->locationService = $locationService;
Expand All @@ -68,12 +81,14 @@ public function __construct(
$this->authorizationChecker = $authorizationChecker;
$this->locationProvider = $locationProvider;
$this->controllerChecker = $controllerChecker;
$this->debugMode = $debugMode;
$this->logger = $logger ?? new NullLogger();
}

/**
* @throws \eZ\Publish\API\Repository\Exceptions\NotImplementedException If Content is missing location as this is not supported in current version
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
*/
public function previewContentAction(
Request $request,
Expand All @@ -82,7 +97,7 @@ public function previewContentAction(
$language,
$siteAccessName = null,
?int $locationId = null
) {
): Response {
$this->previewHelper->setPreviewActive(true);

try {
Expand Down Expand Up @@ -117,19 +132,21 @@ public function previewContentAction(
HttpKernelInterface::SUB_REQUEST,
false
);
} catch (\Exception $e) {
if ($location->isDraft() && $this->controllerChecker->usesCustomController($content, $location)) {
// @todo This should probably be an exception that embeds the original one
$message = <<<EOF
<p>The view that rendered this location draft uses a custom controller, and resulted in a fatal error.</p>
<p>Location View is deprecated, as it causes issues with preview, such as an empty location id when previewing the first version of a content.</p>
EOF;

throw new Exception($message, 0, $e);
} else {
throw $e;
} catch (APINotFoundException $e) {
$message = 'Location not found or not available in requested language';
$this->logger->warning(
'Location not found or not available in requested language when loading the preview page',
['exception' => $e]
);
if ($this->debugMode) {
throw new BadStateException($message, 1, $e);
}

return new Response($message);
} catch (Exception $e) {
return $this->buildResponseForGenericPreviewError($location, $content, $e);
}

$response->setPrivate();

$this->previewHelper->restoreConfigScope();
Expand Down Expand Up @@ -186,4 +203,39 @@ protected function getForwardRequest(Location $location, Content $content, SiteA
$forwardRequestParameters
);
}

/**
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
*/
private function buildResponseForGenericPreviewError(Location $location, Content $content, Exception $e): Response
{
$message = '';
try {
if ($location->isDraft() && $this->controllerChecker->usesCustomController($content, $location)) {
$message = <<<EOF
<p>The view that rendered this location draft uses a custom controller, and resulted in a fatal error.</p>
<p>Location View is deprecated, as it causes issues with preview, such as an empty location id when previewing the first version of a content.</p>
EOF;
}
} catch (Exception $innerException) {
$message = 'An exception occurred when handling page preview exception';
$this->logger->warning(
'Unable to check if location uses a custom controller when loading the preview page',
['exception' => $innerException]
);
}

$this->logger->warning('Unable to load the preview page', ['exception' => $e]);

$message .= <<<EOF
<p>Unable to load the preview page</p>
<p>See logs for more information</p>
EOF;

if ($this->debugMode) {
throw new BadStateException($message, 1, $e);
}

return new Response($message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ protected function getPreviewController(): PreviewController
$this->previewHelper,
$this->authorizationChecker,
$this->locationProvider,
$this->controllerChecker
$this->controllerChecker,
false,
null
);
}

Expand Down
Loading