Skip to content

Commit 1bdc60c

Browse files
authored
IBX-6554: Prevent Twig errors when location is not defined in Location View (#1517)
1 parent 6fd7513 commit 1bdc60c

File tree

4 files changed

+38
-40
lines changed

4 files changed

+38
-40
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11496,18 +11496,6 @@ parameters:
1149611496
count: 1
1149711497
path: src/lib/Menu/UserSetting/UserSettingUpdateRightSidebarBuilder.php
1149811498

11499-
-
11500-
message: '#^Cannot access property \$attributes on Symfony\\Component\\HttpFoundation\\Request\|null\.$#'
11501-
identifier: property.nonObject
11502-
count: 1
11503-
path: src/lib/Menu/Voter/LocationVoter.php
11504-
11505-
-
11506-
message: '#^Cannot access property \$id on Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Location\|null\.$#'
11507-
identifier: property.nonObject
11508-
count: 1
11509-
path: src/lib/Menu/Voter/LocationVoter.php
11510-
1151111499
-
1151211500
message: '#^Call to an undefined method Symfony\\Component\\HttpFoundation\\Session\\SessionInterface\:\:getFlashBag\(\)\.$#'
1151311501
identifier: method.notFound

src/bundle/Controller/ContentViewController.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
use Ibexa\Contracts\Core\Repository\Values\Content\Location;
4242
use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo;
4343
use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;
44+
use Ibexa\Core\Base\Exceptions\NotFoundException;
4445
use Ibexa\Core\MVC\Symfony\Locale\UserLanguagePreferenceProviderInterface;
4546
use Ibexa\Core\MVC\Symfony\View\ContentView;
4647
use Symfony\Component\Form\FormFactoryInterface;
@@ -158,11 +159,17 @@ public function __construct(
158159
*/
159160
public function locationViewAction(Request $request, ContentView $view): ContentView
160161
{
162+
$location = $view->getLocation();
163+
if ($location === null) {
164+
$contentId = $view->getContent()->getId();
165+
throw new NotFoundException('Location', "content ID {$contentId}");
166+
}
167+
161168
// We should not cache ContentView because we use forms with CSRF tokens in template
162169
// JIRA ref: https://issues.ibexa.co/browse/EZP-28190
163170
$view->setCacheEnabled(false);
164171

165-
if (!$view->getContent()->contentInfo->isTrashed()) {
172+
if (!$view->getContent()->getContentInfo()->isTrashed()) {
166173
$this->supplyPathLocations($view);
167174
$this->subitemsContentViewParameterSupplier->supply($view);
168175
$this->supplyContentActionForms($view);

src/bundle/Resources/views/themes/admin/content/location_view.html.twig

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
{% set location_path = location.pathString %}
2-
31
{% extends "@ibexadesign/ui/layout.html.twig" %}
42

53
{% trans_default_domain 'ibexa_locationview' %}
@@ -29,7 +27,7 @@
2927
{{ ibexa_twig_component_group('admin-ui-content-tree-before') }}
3028
<div class="ibexa-content-tree-container"
3129
data-tree-root-location-id="{{ content_tree_module_root|default(ibexa_admin_ui_config['contentTree']['treeRootLocationId']) }}"
32-
data-current-location-path="{{ location_path|default('') }}"
30+
data-current-location-path="{{ location is defined and location is not null ? location.pathString : '' }}"
3331
style="{{ content_tree_width_style }}"
3432
>
3533
<div class="ibexa-content-tree-container__root"></div>
@@ -57,11 +55,17 @@
5755
{% endblock %}
5856

5957
{% block context_menu %}
60-
{% set content_sidebar_right = knp_menu_get('ezplatform_admin_ui.menu.content.sidebar_right', [], {'location': location, 'content': content, 'content_type': content_type}) %}
58+
{% set content_sidebar_right = knp_menu_get('ezplatform_admin_ui.menu.content.sidebar_right', [], {
59+
'location': location,
60+
'content': content,
61+
'content_type': content_type
62+
}) %}
6163
{{ knp_menu_render(content_sidebar_right, {'template': '@ibexadesign/ui/menu/context_menu.html.twig'}) }}
6264

6365
<div class="ibexa-extra-actions-container">
64-
{% include '@ibexadesign/content/widget/content_create.html.twig' with {'form': form_content_create, content } only %}
66+
{% if form_content_create is defined %}
67+
{% include '@ibexadesign/content/widget/content_create.html.twig' with {'form': form_content_create, content } only %}
68+
{% endif %}
6569
{% if form_content_edit is defined and form_user_edit is not defined %}
6670
{% include '@ibexadesign/content/widget/content_edit.html.twig' with {'form': form_content_edit} only %}
6771
{% endif %}
@@ -164,9 +168,9 @@
164168
</div>
165169
</div>
166170
</div>
167-
{% if content_has_reverse_relations and not location.contentInfo.isHidden %}
168-
{% include '@ibexadesign/content/modal/hide_confirmation.html.twig' %}
169-
{% endif %}
171+
{% if content_has_reverse_relations and not location.contentInfo.isHidden %}
172+
{% include '@ibexadesign/content/modal/hide_confirmation.html.twig' %}
173+
{% endif %}
170174
</div>
171175
{% endblock %}
172176

src/lib/Menu/Voter/LocationVoter.php

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace Ibexa\AdminUi\Menu\Voter;
1010

1111
use Ibexa\Core\MVC\Symfony\View\ContentView;
12+
use Ibexa\Core\Repository\Values\Content\Location;
1213
use Knp\Menu\ItemInterface;
1314
use Knp\Menu\Matcher\Voter\VoterInterface;
1415
use Symfony\Component\HttpFoundation\RequestStack;
@@ -17,35 +18,33 @@ class LocationVoter implements VoterInterface
1718
{
1819
private const CONTENT_VIEW_ROUTE_NAME = 'ibexa.content.view';
1920

20-
/**
21-
* @var \Symfony\Component\HttpFoundation\RequestStack
22-
*/
23-
private $requestStack;
21+
private RequestStack $requestStack;
2422

25-
/**
26-
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
27-
*/
2823
public function __construct(RequestStack $requestStack)
2924
{
3025
$this->requestStack = $requestStack;
3126
}
3227

33-
/**
34-
* {@inheritdoc}
35-
*/
3628
public function matchItem(ItemInterface $item): ?bool
3729
{
38-
$routes = $item->getExtra('routes', []);
30+
foreach ($item->getExtra('routes', []) as $route) {
31+
$routeName = $route['route'] ?? null;
32+
$locationId = isset($route['parameters']['locationId']) ? (int)$route['parameters']['locationId'] : null;
3933

40-
foreach ($routes as $route) {
41-
if (isset($route['route']) && $route['route'] === self::CONTENT_VIEW_ROUTE_NAME) {
42-
$request = $this->requestStack->getCurrentRequest();
43-
$contentView = $request->attributes->get('view');
44-
$locationId = $route['parameters']['locationId'];
34+
if ($routeName !== self::CONTENT_VIEW_ROUTE_NAME || $locationId === null) {
35+
continue;
36+
}
37+
38+
$request = $this->requestStack->getCurrentRequest();
39+
$contentView = $request ? $request->attributes->get('view') : null;
40+
$location = $contentView instanceof ContentView ? $contentView->getLocation() : null;
41+
42+
if (!$location instanceof Location) {
43+
continue;
44+
}
4545

46-
if ($contentView instanceof ContentView && in_array($locationId, $contentView->getLocation()->path ?? [$contentView->getLocation()->id])) {
47-
return true;
48-
}
46+
if (in_array($locationId, array_map('intval', $location->getPath()), true)) {
47+
return true;
4948
}
5049
}
5150

0 commit comments

Comments
 (0)