Skip to content

Commit

Permalink
[BUGFIX] Create special boot-time TemplatePaths which avoids Configur…
Browse files Browse the repository at this point in the history
…ationManager

Helps partially solve some issues on v12 when loading form instances from
templates before TYPO3 is fully initialized.
  • Loading branch information
NamelessCoder committed Jul 3, 2023
1 parent b3661b6 commit 0be6c62
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 14 deletions.
19 changes: 19 additions & 0 deletions Classes/Integration/Configuration/ConfigurationContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
namespace FluidTYPO3\Flux\Integration\Configuration;

use TYPO3\CMS\Core\SingletonInterface;

class ConfigurationContext implements SingletonInterface
{
private bool $bootMode = false;

public function isBootMode(): bool
{
return $this->bootMode;
}

public function setBootMode(bool $bootMode): void
{
$this->bootMode = $bootMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,25 @@
use FluidTYPO3\Flux\Provider\Provider;
use FluidTYPO3\Flux\Provider\ProviderInterface;
use FluidTYPO3\Flux\Utility\ExtensionNamingUtility;
use FluidTYPO3\Flux\Utility\RequestBuilder;
use TYPO3\CMS\Core\Core\ApplicationContext;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
use TYPO3Fluid\Fluid\Exception;

class SpooledConfigurationApplicator
{
public function __construct(private ConfigurationContext $context)
{
}

protected static ?ContentTypeBuilder $contentTypeBuilder = null;

public function processData(): void
{
$this->context->setBootMode(true);

// Initialize the TCA needed by "template as CType" integrations
static::spoolQueuedContentTypeTableConfigurations(
Core::getQueuedContentTypeRegistrations()
Expand All @@ -47,6 +53,8 @@ public function processData(): void

$this->spoolQueuedContentTypeRegistrations(Core::getQueuedContentTypeRegistrations());
Core::clearQueuedContentTypeRegistrations();

$this->context->setBootMode(false);
}

public static function spoolQueuedContentTypeTableConfigurations(array $queue): void
Expand Down Expand Up @@ -112,15 +120,13 @@ protected function spoolQueuedContentTypeRegistrations(array $queue): void

$self = $this;

// We have to fake a ServerRequest here, since internally Extbase's ConfigurationManager will otherwise always
// instance BackendConfigurationManager and hold on to that instance, which means that any subsequent code that
// injects ConfigurationManager will contain a BackendConfigurationManager even in frontend context.
// This results in various issues such as inability to correctly resolve the correct controller for an Extbase
// plugin on requests that don't already have a cached version of Flux forms / contains dynamic Flux forms.
$GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST'] ?? (new ServerRequest())->withAttribute(
'applicationType',
defined('TYPO3_REQUESTTYPE') ? constant('TYPO3_REQUESTTYPE') : SystemEnvironmentBuilder::REQUESTTYPE_FE
);
$backup = $GLOBALS['TYPO3_REQUEST'] ?? null;

if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '12.3', '<')) {
/** @var RequestBuilder $requestBuilder */
$requestBuilder = GeneralUtility::makeInstance(RequestBuilder::class);
$GLOBALS['TYPO3_REQUEST'] = $requestBuilder->getServerRequest();
}

uasort(
$providers,
Expand All @@ -144,6 +150,8 @@ function (ProviderInterface $item1, ProviderInterface $item2) use ($self) {
}
}
}

$GLOBALS['TYPO3_REQUEST'] = $backup;
}

private function resolveSortingValue(?Form $form): int
Expand All @@ -169,7 +177,7 @@ protected function getApplicationContext(): ApplicationContext
protected static function getContentTypeBuilder(): ContentTypeBuilder
{
/** @var ContentTypeBuilder $contentTypeBuilder */
$contentTypeBuilder = GeneralUtility::makeInstance(ContentTypeBuilder::class);
$contentTypeBuilder = GeneralUtility::makeInstance(ContentTypeBuilder::class, true);
return $contentTypeBuilder;
}

Expand Down
23 changes: 21 additions & 2 deletions Classes/Utility/RenderingContextBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* LICENSE.md file that was distributed with this source code.
*/

use FluidTYPO3\Flux\Integration\Configuration\ConfigurationContext;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
Expand All @@ -21,9 +23,14 @@
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextFactory;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\View\TemplatePaths;

class RenderingContextBuilder
{
public function __construct(private ConfigurationContext $context)
{
}

public function buildRenderingContextFor(
string $extensionIdentity,
string $controllerName,
Expand Down Expand Up @@ -58,8 +65,20 @@ public function buildRenderingContextFor(
$renderingContext->setRequest($request);
}

$templatePaths = $renderingContext->getTemplatePaths();
$templatePaths->fillDefaultsByPackageName($extensionKey);
if (!$this->context->isBootMode()) {
$templatePaths = $renderingContext->getTemplatePaths();
} else {
$resources = ExtensionManagementUtility::extPath($extensionKey) . 'Resources/Private/';
$paths = [
TemplatePaths::CONFIG_TEMPLATEROOTPATHS => [$resources . 'Templates/'],
TemplatePaths::CONFIG_PARTIALROOTPATHS => [$resources . 'Partials/'],
TemplatePaths::CONFIG_LAYOUTROOTPATHS => [$resources . 'Layouts/'],
];
$templatePaths = GeneralUtility::makeInstance(TemplatePaths::class, $paths);
$templatePaths->fillDefaultsByPackageName($extensionKey);
$renderingContext->setTemplatePaths($templatePaths);
}


if ($templatePathAndFilename) {
$templatePaths->setTemplatePathAndFilename($templatePathAndFilename);
Expand Down
4 changes: 4 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ services:
autowire: false
TYPO3\CMS\Backend\View\BackendViewFactory:
public: true
FluidTYPO3\Flux\Integration\Configuration\SpooledConfigurationApplicator:
public: true
FluidTYPO3\Flux\Utility\RenderingContextBuilder:
public: true

FluidTYPO3\Flux\Integration\Event\PageContentPreviewRenderingEventListener:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use FluidTYPO3\Flux\Content\TypeDefinition\ContentTypeDefinitionInterface;
use FluidTYPO3\Flux\Content\TypeDefinition\FluidRenderingContentTypeDefinitionInterface;
use FluidTYPO3\Flux\Form;
use FluidTYPO3\Flux\Integration\Configuration\ConfigurationContext;
use FluidTYPO3\Flux\Integration\Configuration\SpooledConfigurationApplicator;
use FluidTYPO3\Flux\Integration\ContentTypeBuilder;
use FluidTYPO3\Flux\Integration\ViewBuilder;
Expand Down Expand Up @@ -95,8 +96,11 @@ protected function setUp(): void
$this->contentTypeManager->method('fetchContentTypes')
->willReturn([$this->contentTypeDefinition, $this->contentTypeDefinition2]);

$configurationContext = new ConfigurationContext();

$this->subject = $this->getMockBuilder(SpooledConfigurationApplicator::class)
->setMethods(['getApplicationContext', 'getContentTypeManager'])
->setConstructorArgs([$configurationContext])
->getMock();
$this->subject->method('getContentTypeManager')->willReturn($this->contentTypeManager);

Expand Down

0 comments on commit 0be6c62

Please sign in to comment.