Skip to content

Commit e6c4b18

Browse files
authored
Add global page model for fragments (see contao#2506)
Description ----------- | Q | A | -----------------| --- | Fixed issues | Fixes contao#1935 As discussed on Mumble on the 2020-11-19, this should make the (global) page model available in the fragment controllers. Commits ------- 03e7c41 Add global page model for fragments (replaces contao#1935) a5c2326 Cast values for comparison 826748d Added unit tests 00eeb72 CS 29ea202 CS 0e09e4e Merge branch '4.9' into bugfix/page-argument
1 parent ffebcd7 commit e6c4b18

File tree

5 files changed

+68
-2
lines changed

5 files changed

+68
-2
lines changed

core-bundle/src/Controller/AbstractFragmentController.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Contao\CoreBundle\Fragment\FragmentOptionsAwareInterface;
1616
use Contao\FrontendTemplate;
1717
use Contao\Model;
18+
use Contao\PageModel;
1819
use Contao\StringUtil;
1920
use Contao\Template;
2021
use Symfony\Component\DependencyInjection\Container;
@@ -26,11 +27,26 @@ abstract class AbstractFragmentController extends AbstractController implements
2627
*/
2728
protected $options = [];
2829

30+
/**
31+
* @var PageModel|null
32+
*/
33+
private $pageModel;
34+
2935
public function setFragmentOptions(array $options): void
3036
{
3137
$this->options = $options;
3238
}
3339

40+
protected function setPageModel(?PageModel $pageModel): void
41+
{
42+
$this->pageModel = $pageModel;
43+
}
44+
45+
protected function getPageModel(): ?PageModel
46+
{
47+
return $this->pageModel;
48+
}
49+
3450
/**
3551
* Creates a template by name or from the "customTpl" field of the model.
3652
*/

core-bundle/src/Controller/ContentElement/AbstractContentElementController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@
1414

1515
use Contao\ContentModel;
1616
use Contao\CoreBundle\Controller\AbstractFragmentController;
17+
use Contao\PageModel;
1718
use Contao\Template;
1819
use Symfony\Component\HttpFoundation\Request;
1920
use Symfony\Component\HttpFoundation\Response;
2021

2122
abstract class AbstractContentElementController extends AbstractFragmentController
2223
{
23-
public function __invoke(Request $request, ContentModel $model, string $section, array $classes = null): Response
24+
public function __invoke(Request $request, ContentModel $model, string $section, array $classes = null, PageModel $pageModel = null): Response
2425
{
26+
$this->setPageModel($pageModel);
27+
2528
$type = $this->getType();
2629
$template = $this->createTemplate($model, 'ce_'.$type);
2730

core-bundle/src/Controller/FrontendModule/AbstractFrontendModuleController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@
1616
use Contao\CoreBundle\Controller\AbstractFragmentController;
1717
use Contao\CoreBundle\Routing\ScopeMatcher;
1818
use Contao\ModuleModel;
19+
use Contao\PageModel;
1920
use Contao\Template;
2021
use Symfony\Component\HttpFoundation\Request;
2122
use Symfony\Component\HttpFoundation\Response;
2223
use Symfony\Contracts\Translation\TranslatorInterface;
2324

2425
abstract class AbstractFrontendModuleController extends AbstractFragmentController
2526
{
26-
public function __invoke(Request $request, ModuleModel $model, string $section, array $classes = null): Response
27+
public function __invoke(Request $request, ModuleModel $model, string $section, array $classes = null, PageModel $pageModel = null): Response
2728
{
2829
if ($this->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
2930
return $this->getBackendWildcard($model);
3031
}
3132

33+
$this->setPageModel($pageModel);
34+
3235
$type = $this->getType();
3336
$template = $this->createTemplate($model, 'mod_'.$type);
3437

core-bundle/src/HttpKernel/ModelArgumentResolver.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Contao\CoreBundle\Framework\ContaoFramework;
1616
use Contao\CoreBundle\Routing\ScopeMatcher;
1717
use Contao\Model;
18+
use Contao\PageModel;
1819
use Symfony\Component\HttpFoundation\Request;
1920
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
2021
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
@@ -79,6 +80,16 @@ private function fetchModel(Request $request, ArgumentMetadata $argument): ?Mode
7980
return $value;
8081
}
8182

83+
// Special handling for pageModel that could be globally registered
84+
if (
85+
isset($GLOBALS['objPage'])
86+
&& $GLOBALS['objPage'] instanceof PageModel
87+
&& (int) $GLOBALS['objPage']->id === (int) $value
88+
&& is_a($type, PageModel::class, true)
89+
) {
90+
return $GLOBALS['objPage'];
91+
}
92+
8293
/** @var Model $model */
8394
$model = $this->framework->getAdapter($argument->getType());
8495

core-bundle/tests/HttpKernel/ModelArgumentResolverTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
namespace Contao\CoreBundle\Tests\HttpKernel;
1414

1515
use Contao\CoreBundle\ContaoCoreBundle;
16+
use Contao\CoreBundle\Framework\ContaoFramework;
1617
use Contao\CoreBundle\HttpKernel\ModelArgumentResolver;
1718
use Contao\CoreBundle\Tests\TestCase;
1819
use Contao\PageModel;
@@ -27,6 +28,8 @@ class ModelArgumentResolverTest extends TestCase
2728
*/
2829
public function testResolvesTheModel(string $name, string $class): void
2930
{
31+
unset($GLOBALS['objPage']);
32+
3033
System::setContainer($this->getContainerWithContaoConfiguration());
3134

3235
$pageModel = $this->createMock(PageModel::class);
@@ -159,4 +162,34 @@ public function testChecksIfTheModelExistsIfTheArgumentIsNotNullable(): void
159162

160163
$this->assertFalse($resolver->supports($request, $argument));
161164
}
165+
166+
public function testReturnsTheGlobalPageModel(): void
167+
{
168+
$framework = $this->createMock(ContaoFramework::class);
169+
$framework
170+
->expects($this->once())
171+
->method('initialize')
172+
;
173+
174+
$framework
175+
->expects($this->never())
176+
->method('getAdapter')
177+
;
178+
179+
$pageModel = $this->mockClassWithProperties(PageModel::class, ['id' => 42]);
180+
$GLOBALS['objPage'] = $pageModel;
181+
182+
$request = Request::create('/foobar');
183+
$request->attributes->set('pageModel', 42);
184+
$request->attributes->set('_scope', ContaoCoreBundle::SCOPE_FRONTEND);
185+
186+
$argument = new ArgumentMetadata('pageModel', PageModel::class, false, false, '', true);
187+
$resolver = new ModelArgumentResolver($framework, $this->mockScopeMatcher());
188+
189+
$this->assertTrue($resolver->supports($request, $argument));
190+
191+
foreach ($resolver->resolve($request, $argument) as $model) {
192+
$this->assertSame($pageModel, $model);
193+
}
194+
}
162195
}

0 commit comments

Comments
 (0)