Commit 8cec795a authored by Benni Mack's avatar Benni Mack
Browse files

[FEATURE] Make PSR-7 Request available in ContentObjectRenderer

This allows to add the current request into ALL userFunctions, including
Extbase, where we can then convert the request into an Extbase Request.

Plus, it is injected in all ContentObjects, making it available for subsequent
renderings.

Resolves: #92984
Releases: master
Change-Id: I7ac6872db6ea0ed8838a0d63c18b5fa53407ebed
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/66080


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Tested-by: default avatarAlexander Schnitzler <git@alexanderschnitzler.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: default avatarAlexander Schnitzler <git@alexanderschnitzler.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 785ff682
.. include:: ../../Includes.txt
====================================================================
Feature: #92984 - PSR-7 Request available in Frontend ContentObjects
====================================================================
See :issue:`92984`
Description
===========
The main Request object of a web-based PHP process is now handed into all
ContentObjects and ContentObjectRenderer classes.
In addition, any kind of "userFunc" methods initiated from ContentObjectRenderer,
basically all custom Frontend PHP code, now receive the request object that was
handed in as third method argument.
The ContentObjectRenderer API now has a :php: `getRequest()` method.
Example:
.. code-block:: typoscript
page.10 = USER
page.10.userFunc = MyVendor\MyPackage\Frontend\MyClass->myMethod
.. code-block:: php
<?php
namespace MyVendor\MyPackage\Frontend;
class MyClass
{
public function myMethod(string $content, array $configuration, ServerRequestInterface $request)
{
$myValue = $request->getQueryParams()['myGetParameter'];
$normalizedParams = $request->getAttribute('normalizedParams');
}
}
This functionality should be used in PHP code related to Frontend code instead of
the superglobal variables like `$_GET` / `$_POST` / `$_SERVER`, or TYPO3's
API methods `GeneralUtility::_GP()` and `GeneralUtility::getIndpEnv()`.
Impact
======
Any kind of custom Content Object in PHP code can now access the PSR-7 Request
object to fetch information about the current request, making TYPO3 Frontend
aware of PSR-7 standardized request objects.
.. index:: Frontend, PHP-API, ext:frontend
......@@ -174,16 +174,17 @@ class Bootstrap
* @param array $configuration The TS configuration array
* @return string $content The processed content
*/
public function run(string $content, array $configuration): string
public function run(string $content, array $configuration, ?ServerRequestInterface $request = null): string
{
$request = $request ?? $GLOBALS['TYPO3_REQUEST'];
$this->initialize($configuration);
return $this->handleRequest();
return $this->handleRequest($request);
}
/**
* @return string
*/
protected function handleRequest(): string
protected function handleRequest(ServerRequestInterface $request): string
{
$extbaseRequest = $this->extbaseRequestBuilder->build();
$requestHandler = $this->requestHandlerResolver->resolveRequestHandler($extbaseRequest);
......
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Frontend\ContentObject;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
......@@ -33,6 +34,8 @@ abstract class AbstractContentObject
*/
protected $pageRenderer;
protected ?ServerRequestInterface $request = null;
/**
* Default constructor.
*
......@@ -61,6 +64,11 @@ abstract class AbstractContentObject
return $this->cObj;
}
public function setRequest(ServerRequestInterface $request): void
{
$this->request = $request;
}
/**
* @return PageRenderer
*/
......
......@@ -88,7 +88,7 @@ class ContentContentObject extends AbstractContentObject
$cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
$frontendController->currentRecord = $conf['table'] . ':' . $row['uid'];
$this->cObj->lastChanged($row['tstamp']);
$cObj->start($row, $conf['table']);
$cObj->start($row, $conf['table'], $this->request);
$tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
$cobjValue .= $tmpValue;
}
......
......@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Frontend\ContentObject;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\Statement;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
......@@ -427,6 +428,13 @@ class ContentObjectRenderer implements LoggerAwareInterface
*/
protected $typoScriptFrontendController;
/**
* Request pointer, if injected. Use getRequest() instead of reading this property directly.
*
* @var ServerRequestInterface|null
*/
private ?ServerRequestInterface $request = null;
/**
* Indicates that object type is USER.
*
......@@ -451,6 +459,11 @@ class ContentObjectRenderer implements LoggerAwareInterface
$this->container = $container;
}
public function setRequest(ServerRequestInterface $request): void
{
$this->request = $request;
}
/**
* Prevent several objects from being serialized.
* If currentFile is set, it is either a File or a FileReference object. As the object itself can't be serialized,
......@@ -461,7 +474,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
public function __sleep()
{
$vars = get_object_vars($this);
unset($vars['typoScriptFrontendController'], $vars['logger'], $vars['container']);
unset($vars['typoScriptFrontendController'], $vars['logger'], $vars['container'], $vars['request']);
if ($this->currentFile instanceof FileReference) {
$this->currentFile = 'FileReference:' . $this->currentFile->getUid();
} elseif ($this->currentFile instanceof File) {
......@@ -496,6 +509,10 @@ class ContentObjectRenderer implements LoggerAwareInterface
}
$this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
$this->container = GeneralUtility::getContainer();
// We do not derive $this->request from globals here. The request is expected to be injected
// using setRequest() after deserialization or with start().
// (A fallback to $GLOBALS['TYPO3_REQUEST'] is available in getRequest() for BC)
}
/**
......@@ -534,9 +551,11 @@ class ContentObjectRenderer implements LoggerAwareInterface
*
* @param array $data The record data that is rendered.
* @param string $table The table that the data record is from.
* @param ServerRequestInterface|null $request
*/
public function start($data, $table = '')
public function start($data, $table = '', ?ServerRequestInterface $request = null)
{
$this->request = $request ?? $this->request;
$this->data = $data;
$this->table = $table;
$this->currentRecord = $table !== ''
......@@ -728,6 +747,7 @@ class ContentObjectRenderer implements LoggerAwareInterface
if (!($contentObject instanceof AbstractContentObject)) {
throw new ContentRenderingException(sprintf('Registered content object class name "%s" must be an instance of AbstractContentObject, but is not!', $fullyQualifiedClassName), 1422564295);
}
$contentObject->setRequest($this->getRequest());
return $contentObject;
}
......@@ -5176,7 +5196,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
$classObj->cObj = $this;
$content = call_user_func_array($callable, [
$content,
$conf
$conf,
$this->getRequest()
]);
} else {
$this->getTimeTracker()->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3);
......@@ -6647,4 +6668,17 @@ class ContentObjectRenderer implements LoggerAwareInterface
return $endingOffset;
}
public function getRequest(): ServerRequestInterface
{
if ($this->request instanceof ServerRequestInterface) {
return $this->request;
}
if (isset($GLOBALS['TYPO3_REQUEST']) && $GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
return $GLOBALS['TYPO3_REQUEST'];
}
throw new ContentRenderingException('PSR-7 request is missing in ContentObjectRenderer. Inject with start(), setRequest() or provide via $GLOBALS[\'TYPO3_REQUEST\'].', 1607172972);
}
}
......@@ -46,7 +46,7 @@ class HierarchicalMenuContentObject extends AbstractContentObject
$GLOBALS['TSFE']->register['count_HMENU_MENUOBJ'] = 0;
$GLOBALS['TSFE']->register['count_MENUOBJ'] = 0;
$menu->parent_cObj = $this->cObj;
$menu->start($GLOBALS['TSFE']->tmpl, $GLOBALS['TSFE']->sys_page, '', $conf, 1);
$menu->start($GLOBALS['TSFE']->tmpl, $GLOBALS['TSFE']->sys_page, '', $conf, 1, '', $this->request);
$menu->makeMenu();
$theValue .= $menu->writeMenu();
} catch (NoSuchMenuTypeException $e) {
......
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\LanguageAspect;
......@@ -175,6 +176,8 @@ abstract class AbstractMenuContentObject
*/
protected $WMcObj;
protected ?ServerRequestInterface $request = null;
/**
* Can be set to contain menu item arrays for sub-levels.
*
......@@ -219,15 +222,17 @@ abstract class AbstractMenuContentObject
* @param array $conf The TypoScript configuration for the HMENU cObject
* @param int $menuNumber Menu number; 1,2,3. Should probably be 1
* @param string $objSuffix Submenu Object suffix. This offers submenus a way to use alternative configuration for specific positions in the menu; By default "1 = TMENU" would use "1." for the TMENU configuration, but if this string is set to eg. "a" then "1a." would be used for configuration instead (while "1 = " is still used for the overall object definition of "TMENU")
* @param ServerRequestInterface|null $request
* @return bool Returns TRUE on success
* @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::HMENU()
*/
public function start($tmpl, $sys_page, $id, $conf, $menuNumber, $objSuffix = '')
public function start($tmpl, $sys_page, $id, $conf, $menuNumber, $objSuffix = '', ?ServerRequestInterface $request = null)
{
$tsfe = $this->getTypoScriptFrontendController();
$this->conf = $conf;
$this->menuNumber = $menuNumber;
$this->mconf = $conf[$this->menuNumber . $objSuffix . '.'];
$this->request = $request;
$this->WMcObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
// Sets the internal vars. $tmpl MUST be the template-object. $sys_page MUST be the PageRepository object
if ($this->conf[$this->menuNumber . $objSuffix] && is_object($tmpl) && is_object($sys_page)) {
......
......@@ -66,7 +66,7 @@ class TextMenuContentObject extends AbstractMenuContentObject
$GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
$GLOBALS['TSFE']->register['count_MENUOBJ']++;
// Initialize the cObj with the page record of the menu item
$this->WMcObj->start($this->menuArr[$key], 'pages');
$this->WMcObj->start($this->menuArr[$key], 'pages', $this->request);
$this->I = [];
$this->I['key'] = $key;
$this->I['val'] = $val;
......
......@@ -115,7 +115,7 @@ class RecordsContentObject extends AbstractContentObject
$cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
$GLOBALS['TSFE']->currentRecord = $val['table'] . ':' . $val['id'];
$this->cObj->lastChanged($row['tstamp']);
$cObj->start($row, $val['table']);
$cObj->start($row, $val['table'], $this->request);
$tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
$theValue .= $tmpValue;
}
......
......@@ -2489,7 +2489,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
}
// Global content object
$this->newCObj();
$this->newCObj($request);
$this->getTimeTracker()->pull();
}
......@@ -2647,9 +2647,12 @@ class TypoScriptFrontendController implements LoggerAwareInterface
/**
* Processes the INTinclude-scripts
*
* @param ServerRequestInterface|null $request
*/
public function INTincScript()
public function INTincScript(ServerRequestInterface $request = null)
{
$request = $request ?? $GLOBALS['TYPO3_REQUEST'];
$this->additionalHeaderData = $this->config['INTincScript_ext']['additionalHeaderData'] ?? [];
$this->additionalFooterData = $this->config['INTincScript_ext']['additionalFooterData'] ?? [];
if (empty($this->config['INTincScript_ext']['pageRenderer'])) {
......@@ -2665,7 +2668,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
GeneralUtility::makeInstance(AssetCollector::class)->updateState($assetCollector->getState());
}
$this->recursivelyReplaceIntPlaceholdersInContent();
$this->recursivelyReplaceIntPlaceholdersInContent($request);
$this->getTimeTracker()->push('Substitute header section');
$this->INTincScript_loadJSCode();
$this->generatePageTitle();
......@@ -2682,7 +2685,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
$this->pageRenderer->renderJavaScriptAndCssForProcessingOfUncachedContentObjects($this->content, $this->config['INTincScript_ext']['divKey'])
);
// Replace again, because header and footer data and page renderer replacements may introduce additional placeholders (see #44825)
$this->recursivelyReplaceIntPlaceholdersInContent();
$this->recursivelyReplaceIntPlaceholdersInContent($request);
$this->setAbsRefPrefix();
$this->getTimeTracker()->pull();
}
......@@ -2692,11 +2695,11 @@ class TypoScriptFrontendController implements LoggerAwareInterface
* In case the replacement adds additional placeholders, it loops
* until no new placeholders are found any more.
*/
protected function recursivelyReplaceIntPlaceholdersInContent()
protected function recursivelyReplaceIntPlaceholdersInContent(ServerRequestInterface $request)
{
do {
$nonCacheableData = $this->config['INTincScript'];
$this->processNonCacheableContentPartsAndSubstituteContentMarkers($nonCacheableData);
$this->processNonCacheableContentPartsAndSubstituteContentMarkers($nonCacheableData, $request);
// Check if there were new items added to INTincScript during the previous execution:
// array_diff_assoc throws notices if values are arrays but not strings. We suppress this here.
$nonCacheableData = @array_diff_assoc($this->config['INTincScript'], $nonCacheableData);
......@@ -2713,7 +2716,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
* @param array $nonCacheableData $GLOBALS['TSFE']->config['INTincScript'] or part of it
* @see INTincScript()
*/
protected function processNonCacheableContentPartsAndSubstituteContentMarkers(array $nonCacheableData)
protected function processNonCacheableContentPartsAndSubstituteContentMarkers(array $nonCacheableData, ServerRequestInterface $request)
{
$timeTracker = $this->getTimeTracker();
$timeTracker->push('Split content');
......@@ -2732,6 +2735,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
$nonCacheableContent = '';
$contentObjectRendererForNonCacheable = unserialize($nonCacheableData[$nonCacheableKey]['cObj']);
/* @var ContentObjectRenderer $contentObjectRendererForNonCacheable */
$contentObjectRendererForNonCacheable->setRequest($request);
switch ($nonCacheableData[$nonCacheableKey]['type']) {
case 'COA':
$nonCacheableContent = $contentObjectRendererForNonCacheable->cObjGetSingle('COA', $nonCacheableData[$nonCacheableKey]['conf']);
......@@ -2903,12 +2907,12 @@ class TypoScriptFrontendController implements LoggerAwareInterface
* Creates an instance of ContentObjectRenderer in $this->cObj
* This instance is used to start the rendering of the TypoScript template structure
*
* @see RequestHandler
* @param ServerRequestInterface|null $request
*/
public function newCObj()
public function newCObj(ServerRequestInterface $request = null)
{
$this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class, $this);
$this->cObj->start($this->page, 'pages');
$this->cObj->start($this->page, 'pages', $request);
}
/**
......
......@@ -92,11 +92,12 @@ class DatabaseQueryProcessor implements DataProcessorInterface
// Execute a SQL statement to fetch the records
$records = $cObj->getRecords($tableName, $processorConfiguration);
$request = $cObj->getRequest();
$processedRecordVariables = [];
foreach ($records as $key => $record) {
/** @var ContentObjectRenderer $recordContentObjectRenderer */
$recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$recordContentObjectRenderer->start($record, $tableName);
$recordContentObjectRenderer->start($record, $tableName, $request);
$processedRecordVariables[$key] = ['data' => $record];
$processedRecordVariables[$key] = $this->contentDataProcessor->process($recordContentObjectRenderer, $processorConfiguration, $processedRecordVariables[$key]);
}
......
......@@ -472,9 +472,10 @@ class MenuProcessor implements DataProcessorInterface
$page['children'][$key] = $this->processAdditionalDataProcessors($item, $processorConfiguration);
}
}
$request = $this->cObj->getRequest();
/** @var ContentObjectRenderer $recordContentObjectRenderer */
$recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$recordContentObjectRenderer->start($page['data'], 'pages');
$recordContentObjectRenderer->start($page['data'], 'pages', $request);
$processedPage = $this->contentDataProcessor->process($recordContentObjectRenderer, $processorConfiguration, $page);
return $processedPage;
}
......
......@@ -146,7 +146,7 @@ class RequestHandler implements RequestHandlerInterface
$controller->preparePageContentGeneration($request);
}
$this->timeTracker->push('Non-cached objects');
$controller->INTincScript();
$controller->INTincScript($request);
$this->timeTracker->pull();
}
......
......@@ -78,10 +78,10 @@ class DatabaseRecordLinkBuilder extends AbstractTypolinkBuilder
if (!empty($linkDetails['fragment'])) {
$typoScriptConfiguration['section'] = $linkDetails['fragment'];
}
// Build the full link to the record
$request = $this->contentObjectRenderer->getRequest();
$localContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$localContentObjectRenderer->start($record, $linkHandlerConfiguration['table']);
$localContentObjectRenderer->start($record, $linkHandlerConfiguration['table'], $request);
$localContentObjectRenderer->parameters = $this->contentObjectRenderer->parameters;
$link = $localContentObjectRenderer->typoLink($linkText, $typoScriptConfiguration);
......
......@@ -16,6 +16,7 @@
namespace TYPO3\CMS\Frontend\Tests\Functional\ContentObject;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\NullLogger;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\ConnectionPool;
......@@ -85,6 +86,7 @@ class ContentObjectRendererTest extends FunctionalTestCase
$this->typoScriptFrontendController->sys_page = GeneralUtility::makeInstance(PageRepository::class);
$this->typoScriptFrontendController->tmpl = GeneralUtility::makeInstance(TemplateService::class);
$this->subject = GeneralUtility::makeInstance(ContentObjectRenderer::class, $this->typoScriptFrontendController);
$this->subject->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
}
/**
......@@ -598,6 +600,7 @@ class ContentObjectRendererTest extends FunctionalTestCase
{
$tsfe = $this->getMockBuilder(TypoScriptFrontendController::class)->disableOriginalConstructor()->getMock();
$subject = new ContentObjectRenderer($tsfe);
$subject->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
$subject->setLogger(new NullLogger());
$input = 'This is a simple inline text, no wrapping configured';
$result = $subject->parseFunc($input, $this->getLibParseFunc());
......
......@@ -15,6 +15,7 @@
namespace TYPO3\CMS\Frontend\Tests\Functional\ContentObject;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\FluidTemplateContentObject;
......@@ -71,6 +72,7 @@ class FluidTemplateContentObjectTest extends FunctionalTestCase
$expectedResult = 'ABC';
$contentObjectRenderer = new ContentObjectRenderer();
$contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
$contentObjectRenderer->setContentObjectClassMap([
'FLUIDTEMPLATE' => FluidTemplateContentObject::class,
'TEXT' => TextContentObject::class,
......@@ -119,6 +121,7 @@ class FluidTemplateContentObjectTest extends FunctionalTestCase
$expectedResult = 'DefaultLayoutLayoutOverride';
$contentObjectRenderer = new ContentObjectRenderer();
$contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
$contentObjectRenderer->setContentObjectClassMap([
'FLUIDTEMPLATE' => FluidTemplateContentObject::class,
'TEXT' => TextContentObject::class,
......
......@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Frontend\ContentObject\CaseContentObject;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\TextContentObject;
......@@ -51,6 +52,7 @@ class CaseContentObjectTest extends UnitTestCase
->getMock();
$contentObjectRenderer = new ContentObjectRenderer($tsfe);
$contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
$contentObjectRenderer->setContentObjectClassMap([
'CASE' => CaseContentObject::class,
'TEXT' => TextContentObject::class,
......
......@@ -19,6 +19,7 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
use PHPUnit\Framework\Exception;
use Prophecy\Argument;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface as CacheFrontendInterface;
......@@ -182,6 +183,8 @@ class ContentObjectRendererTest extends UnitTestCase
$logger = $this->prophesize(Logger::class);
$this->subject->setLogger($logger->reveal());
$request = $this->prophesize(ServerRequestInterface::class);
$this->subject->setRequest($request->reveal());
$this->subject->setContentObjectClassMap($this->contentObjectMap);
$this->subject->start([], 'tt_content');
}
......
......@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\Resource\Collection\StaticFileCollection;
use TYPO3\CMS\Core\Resource\File;
......@@ -70,6 +71,7 @@ class FilesContentObjectTest extends UnitTestCase
$tsfe->tmpl = $templateService;
$contentObjectRenderer = new ContentObjectRenderer($tsfe);
$contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
$contentObjectRenderer->setContentObjectClassMap([
'FILES' => FilesContentObject::class,
'TEXT' => TextContentObject::class,
......
......@@ -19,6 +19,7 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\Controller;
use Prophecy\Argument;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Cache\Backend\NullBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Context\Context;
......@@ -86,7 +87,7 @@ class TypoScriptFrontendControllerTest extends UnitTestCase
$contentObjectRendererProphecy = $this->prophesize(ContentObjectRenderer::class);
$contentObjectRendererProphecy->stdWrapValue(Argument::cetera())->willReturn('');
$GLOBALS['TSFE']->cObj = $contentObjectRendererProphecy->reveal();
$GLOBALS['TSFE']->INTincScript();
$GLOBALS['TSFE']->INTincScript($this->prophesize(ServerRequestInterface::class)->reveal());
self::assertStringContainsString('headerData', $GLOBALS['TSFE']->content);
self::assertStringContainsString('footerData', $GLOBALS['TSFE']->content);
}
......
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