Commit d4fa3bbc authored by Benni Mack's avatar Benni Mack Committed by Christian Kuhn
Browse files

[!!!][TASK] PageRenderer should only render a full page

PageRenderer->render() does not accept any arguments anymore.

This change allows to later-on hand in a Request object
into the PageRenderer and/or continue building a generic
View for rendering content, without marker-based changes.

In addition, the corresponding constants are now marked as
protected.

Resolves: #93003
Releases: master
Change-Id: Ia24c81647d665fdc23a8c961fe89722cf0e5a31d
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67033


Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent c8254c4c
......@@ -43,9 +43,9 @@ use TYPO3\CMS\Core\Utility\PathUtility;
class PageRenderer implements SingletonInterface
{
// Constants for the part to be rendered
const PART_COMPLETE = 0;
const PART_HEADER = 1;
const PART_FOOTER = 2;
protected const PART_COMPLETE = 0;
protected const PART_HEADER = 1;
protected const PART_FOOTER = 2;
const REQUIREJS_SCOPE_CONFIG = 'config';
const REQUIREJS_SCOPE_RESOLVE = 'resolve';
......@@ -1699,22 +1699,19 @@ class PageRenderer implements SingletonInterface
/* */
/*****************************************************/
/**
* Render the section (Header or Footer)
* Render the page
*
* @param int $part Section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
* @return string Content of rendered section
* @return string Content of rendered page
*/
public function render($part = self::PART_COMPLETE)
public function render()
{
$this->prepareRendering();
[$jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs] = $this->renderJavaScriptAndCss();
$metaTags = implode(LF, array_merge($this->metaTags, $this->renderMetaTagsFromAPI()));
$markerArray = $this->getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags);
$template = $this->getTemplateForPart($part);
$template = $this->getTemplate();
// The page renderer needs a full reset, even when only rendering one part of the page
// This means that you can only register footer files *after* the header has been already rendered.
// In case you render the footer part first, header files can only be added *after* the footer has been rendered
// The page renderer needs a full reset when the page was rendered
$this->reset();
$templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
......@@ -1744,13 +1741,13 @@ class PageRenderer implements SingletonInterface
*
* @param string $substituteHash The hash that is used for the placeholder markers
* @internal
* @return string Content of rendered section
* @return string Content of rendered page
*/
public function renderPageWithUncachedObjects($substituteHash)
{
$this->prepareRendering();
$markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
$template = $this->getTemplateForPart(self::PART_COMPLETE);
$template = $this->getTemplate();
$templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
}
......@@ -1939,10 +1936,9 @@ class PageRenderer implements SingletonInterface
/**
* Reads the template file and returns the requested part as string
*
* @param int $part
* @return string
*/
protected function getTemplateForPart($part)
protected function getTemplate()
{
$templateFile = GeneralUtility::getFileAbsFileName($this->templateFile);
if (is_file($templateFile)) {
......@@ -1950,10 +1946,6 @@ class PageRenderer implements SingletonInterface
if ($this->removeLineBreaksFromTemplate) {
$template = strtr($template, [LF => '', CR => '']);
}
if ($part !== self::PART_COMPLETE) {
$templatePart = explode('###BODY###', $template);
$template = $templatePart[$part - 1];
}
} else {
$template = '';
}
......
.. include:: ../../Includes.txt
======================================================================
Breaking: #93003 - Limitation of PageRenderer to only render full page
======================================================================
See :issue:`93003`
Description
===========
TYPO3's main API class to build a ready HTML page for Frontend
and Backend rendering - :php:`PageRenderer` - previously allowed
to only render the header or footer separately, which was built
due to historical reasons when rendering content.
This is however obsolete and TYPO3 Core only renders full pages in
Frontend and Backend internally.
For this reason, PageRenderer's :php:`render` method does not accept
any method arguments anymore and always renders the full HTML page.
In addition, the constants
* :php:`PageRenderer::PART_COMPLETE`
* :php:`PageRenderer::PART_HEADER`
* :php:`PageRenderer::PART_FOOTER`
are now marked as protected and should not be accessed from outside
the PHP class anymore.
Impact
======
Calling :php:`PageRenderer->render()` does not respect any given
method argument anymore.
Affected Installations
======================
TYPO3 installations with custom extensions manipulating the underlying
API to render the page.
Migration
=========
It is recommended for third-party extensions to use custom hooks to
process or manipulate header or footer parts.
.. index:: Backend, Frontend, FullyScanned, ext:core
......@@ -206,7 +206,7 @@ class PageRendererTest extends FunctionalTestCase
]);
$expectedInlineSettingsReturnValue = 'TYPO3.settings = {"myApp":{"myKey":"myValue","myKey1":"myValue1","myKey2":"myValue2","myKey3":"myValue3"}';
$renderedString = $subject->render(PageRenderer::PART_FOOTER);
$renderedString = $subject->render();
self::assertStringContainsString($expectedFooterData, $renderedString);
self::assertRegExp($expectedJsFooterLibraryRegExp, $renderedString);
......
......@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Page;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -33,15 +34,16 @@ class PageRendererTest extends UnitTestCase
$this->resetSingletonInstances = true;
$tsfe = $this->prophesize(TypoScriptFrontendController::class);
/** @var PageRenderer|AccessibleObjectInterface $pageRenderer */
$pageRenderer = $this->getMockBuilder(PageRenderer::class)
->setMethods(['reset', 'prepareRendering', 'renderJavaScriptAndCss', 'getPreparedMarkerArray', 'getTemplateForPart', 'getTypoScriptFrontendController'])
->getMock();
$pageRenderer->expects(self::any())->method('getTypoScriptFrontendController')->willReturn($tsfe->reveal());
$pageRenderer->expects(self::exactly(3))->method('reset');
$pageRenderer->render(PageRenderer::PART_COMPLETE);
$pageRenderer->render(PageRenderer::PART_HEADER);
$pageRenderer->render(PageRenderer::PART_FOOTER);
$pageRenderer->render();
$pageRenderer->render();
$pageRenderer->render();
}
/**
......
......@@ -426,5 +426,20 @@ return [
'restFiles' => [
'Breaking-92497-WorkspacesMovePlaceholdersRemoved.rst'
],
]
],
'TYPO3\CMS\Core\Page\PageRenderer::PART_COMPLETE' => [
'restFiles' => [
'Breaking-93003-LimitationOfPageRendererToOnlyRenderFullPage.rst'
],
],
'TYPO3\CMS\Core\Page\PageRenderer::PART_HEADER' => [
'restFiles' => [
'Breaking-93003-LimitationOfPageRendererToOnlyRenderFullPage.rst'
],
],
'TYPO3\CMS\Core\Page\PageRenderer::PART_FOOTER' => [
'restFiles' => [
'Breaking-93003-LimitationOfPageRendererToOnlyRenderFullPage.rst'
],
],
];
......@@ -249,4 +249,10 @@ return [
'Deprecation-92583-DeprecateLastArgumentsOfWrapClickMenuOnIcon.rst',
],
],
'TYPO3\CMS\Core\Page\PageRenderer->render' => [
'maximumNumberOfArguments' => 0,
'restFiles' => [
'Breaking-93003-LimitationOfPageRendererToOnlyRenderFullPage.rst',
],
],
];
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment