Skip to content

Commit c2cd476

Browse files
committed
[RELEASE] Version 13.2.0
Related: https://projekte.in2code.de/issues/76482
2 parents 8fb6296 + c75cb3d commit c2cd476

File tree

7 files changed

+265
-8
lines changed

7 files changed

+265
-8
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# In2publish Core Change Log
22

3+
13.2.2
4+
- [META] Set the EM conf version number to 13.2.2
5+
- [DOCS] Update Changelog.md
6+
- [BUGFIX][WORKAROUND] allow template override of backend module "publish files"
7+
- [TASK] set minimal TYPO3 core version to 13.4.19 due to API adjustments to the schema information
8+
39
13.2.1
410
- [META] Set the EM conf version number to 13.2.1
511
- [DOCS] Update Changelog.md
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace In2code\In2publishCore\Backend\Template;
5+
6+
use In2code\In2publishCore\Backend\View\BackendViewFactory;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
9+
use TYPO3\CMS\Backend\Module\ModuleProvider;
10+
use TYPO3\CMS\Backend\Routing\UriBuilder;
11+
use TYPO3\CMS\Backend\Template\ModuleTemplate;
12+
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
13+
use TYPO3\CMS\Core\Imaging\IconFactory;
14+
use TYPO3\CMS\Core\Messaging\FlashMessageService;
15+
use TYPO3\CMS\Core\Page\PageRenderer;
16+
17+
/**
18+
* WORKAROUND!
19+
*
20+
* this ModuleTemplateFactory is only used in the PublishFiles Backend Module (FileController).
21+
* This Factory can be removed if the core supports a way to override templates for backend modules which use
22+
* the id parameter to store the current selected folder (like filelist)
23+
*/
24+
#[Autoconfigure(public: true, shared: false)]
25+
final class ModuleTemplateFactory
26+
{
27+
public function __construct(
28+
protected readonly PageRenderer $pageRenderer,
29+
protected readonly IconFactory $iconFactory,
30+
protected readonly UriBuilder $uriBuilder,
31+
protected readonly ModuleProvider $moduleProvider,
32+
protected readonly FlashMessageService $flashMessageService,
33+
protected readonly ExtensionConfiguration $extensionConfiguration,
34+
protected readonly BackendViewFactory $viewFactory,
35+
)
36+
{
37+
}
38+
39+
public function create(ServerRequestInterface $request): ModuleTemplate
40+
{
41+
return new ModuleTemplate(
42+
$this->pageRenderer,
43+
$this->iconFactory,
44+
$this->uriBuilder,
45+
$this->moduleProvider,
46+
$this->flashMessageService,
47+
$this->extensionConfiguration,
48+
$this->viewFactory->create($request),
49+
$request
50+
);
51+
}
52+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace In2code\In2publishCore\Backend\View;
5+
6+
use Psr\Http\Message\ServerRequestInterface;
7+
use TYPO3\CMS\Backend\Routing\Route;
8+
use TYPO3\CMS\Backend\Utility\BackendUtility;
9+
use TYPO3\CMS\Core\Package\PackageManager;
10+
use TYPO3\CMS\Core\Utility\GeneralUtility;
11+
use TYPO3\CMS\Core\Utility\MathUtility;
12+
use TYPO3\CMS\Core\View\ViewInterface as CoreViewInterface;
13+
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextFactory;
14+
use TYPO3\CMS\Fluid\View\FluidViewAdapter;
15+
use TYPO3Fluid\Fluid\View\TemplateView as FluidTemplateView;
16+
17+
/**
18+
* WORKAROUND!
19+
*
20+
* this ModuleTemplateFactory is only used in the PublishFiles Backend Module (FileController).
21+
* This Factory can be removed if the core supports a way to override templates for backend modules which use
22+
* the id parameter to store the current selected folder (like filelist)
23+
*/
24+
final readonly class BackendViewFactory
25+
{
26+
public function __construct(
27+
protected RenderingContextFactory $renderingContextFactory,
28+
protected PackageManager $packageManager,
29+
)
30+
{
31+
}
32+
33+
/**
34+
* This backend view is capable of overriding templates, partials and layouts via TsConfig
35+
* based on the composer package name of the route and optional additional package names.
36+
*/
37+
public function create(ServerRequestInterface $request, array $packageNames = []): CoreViewInterface
38+
{
39+
if (empty($packageNames)) {
40+
// Extensions *may* provide path lookup package names as second argument. In most cases, this is not
41+
// needed, and the package name will be fetched from current route. However, there are scenarios
42+
// where extensions 'hook' into existing functionality of a different extension that defined a
43+
// route, and then deliver own templates from the own extension. In those cases, they need to
44+
// supply an additional base package name.
45+
// Examples are backend toolbar items: The toolbar items are rendered through a typo3/cms-backend
46+
// route, so this is picked as base from the route. workspaces delivers an additional toolbar item,
47+
// so 'typo3/cms-workspaces' needs to be added as additional path to look up. The dashboard extension
48+
// and FormEngine have similar cases.
49+
/** @var Route $route */
50+
$route = $request->getAttribute('route');
51+
$packageNameFromRoute = $route->getOption('packageName');
52+
if (!empty($packageNameFromRoute)) {
53+
$packageNames[] = $packageNameFromRoute;
54+
}
55+
}
56+
// Always add EXT:backend/Resources/Private/ as first default path to resolve
57+
// default Layouts/Module.html and its partials.
58+
if (!in_array('typo3/cms-backend', $packageNames, true)) {
59+
array_unshift($packageNames, 'typo3/cms-backend');
60+
}
61+
62+
// @todo: This assumes the pageId is *always* given as 'id' in request.
63+
// @todo: It would be cool if a middleware adds final pageTS - already overlayed by userTS - as attribute to request, to use it here.
64+
$pageTs = [];
65+
$pageId = $request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0;
66+
if (MathUtility::canBeInterpretedAsInteger($pageId)) {
67+
// Some BE controllers misuse the 'id' argument for something else than the page-uid (especially filelist module).
68+
// We check if 'id' is an integer here to skip pageTsConfig calculation if that is the case.
69+
// @todo: Mid-term, misuses should vanish, making 'id' a Backend convention. Affected is
70+
// at least ext:filelist, plus record linking modals that use 'pid'.
71+
$pageTs = BackendUtility::getPagesTSconfig((int)$pageId);
72+
} else {
73+
$pageTs = BackendUtility::getPagesTSconfig(0);
74+
}
75+
76+
$templatePaths = [
77+
'templateRootPaths' => [],
78+
'layoutRootPaths' => [],
79+
'partialRootPaths' => [],
80+
];
81+
foreach ($packageNames as $packageName) {
82+
// Add paths for package.
83+
$packagePath = $this->packageManager->getPackage($packageName)->getPackagePath();
84+
$templatePaths['templateRootPaths'][] = $packagePath . 'Resources/Private/Templates';
85+
$templatePaths['layoutRootPaths'][] = $packagePath . 'Resources/Private/Layouts';
86+
$templatePaths['partialRootPaths'][] = $packagePath . 'Resources/Private/Partials';
87+
// Add possible overrides.
88+
if (is_array($pageTs['templates.'][$packageName . '.'] ?? false)) {
89+
$overrides = $pageTs['templates.'][$packageName . '.'];
90+
ksort($overrides);
91+
foreach ($overrides as $override) {
92+
$pathParts = GeneralUtility::trimExplode(':', $override, true);
93+
if (count($pathParts) < 2) {
94+
throw new \RuntimeException(
95+
'When overriding template paths, the syntax is "composer-package-name:path", example: "typo3/cms-seo:Resources/Private/TemplateOverrides/typo3/cms-backend"',
96+
1643798660
97+
);
98+
}
99+
$composerPackageName = $pathParts[0];
100+
$overridePackagePath = $this->packageManager->getPackage($composerPackageName)->getPackagePath();
101+
$overridePath = rtrim($pathParts[1], '/');
102+
$templatePaths['templateRootPaths'][] = $overridePackagePath . $overridePath . '/Templates';
103+
$templatePaths['layoutRootPaths'][] = $overridePackagePath . $overridePath . '/Layouts';
104+
$templatePaths['partialRootPaths'][] = $overridePackagePath . $overridePath . '/Partials';
105+
}
106+
}
107+
}
108+
109+
// @todo: Inject ViewFactoryInterface instead, and use it.
110+
$renderingContext = $this->renderingContextFactory->create($templatePaths, $request);
111+
$fluidView = new FluidTemplateView($renderingContext);
112+
return new FluidViewAdapter($fluidView);
113+
}
114+
}

Classes/Controller/FileController.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
* This copyright notice MUST APPEAR in all copies of the script!
3131
*/
3232

33-
use In2code\In2publishCore\CommonInjection\ModuleTemplateFactoryInjection;
3433
use In2code\In2publishCore\CommonInjection\PageRendererInjection;
3534
use In2code\In2publishCore\Component\Core\FileHandling\DefaultFalFinderInjection;
3635
use In2code\In2publishCore\Component\Core\FileHandling\Exception\FolderDoesNotExistOnBothSidesException;
@@ -39,8 +38,8 @@
3938
use In2code\In2publishCore\Component\Core\RecordTree\RecordTree;
4039
use In2code\In2publishCore\Controller\Traits\CommonViewVariables;
4140
use In2code\In2publishCore\Controller\Traits\ControllerFilterStatus;
42-
use In2code\In2publishCore\Controller\Traits\ControllerModuleTemplate;
4341
use In2code\In2publishCore\Controller\Traits\DeactivateErrorFlashMessage;
42+
use In2code\In2publishCore\Controller\Traits\FileControllerModuleTemplate;
4443
use In2code\In2publishCore\Service\Error\FailureCollectorInjection;
4544
use In2code\In2publishCore\Utility\BackendUtility;
4645
use In2code\In2publishCore\Utility\LogUtility;
@@ -68,11 +67,10 @@ class FileController extends ActionController
6867
{
6968
use CommonViewVariables;
7069
use ControllerFilterStatus;
71-
use ControllerModuleTemplate;
70+
use FileControllerModuleTemplate;
7271
use DeactivateErrorFlashMessage;
7372
use DefaultFalFinderInjection;
7473
use FailureCollectorInjection;
75-
use ModuleTemplateFactoryInjection;
7674
use PageRendererInjection {
7775
injectPageRenderer as actualInjectPageRenderer;
7876
}
@@ -118,8 +116,6 @@ public function indexAction(): ResponseInterface
118116
$this->pageRenderer->addInlineLanguageLabelFile(
119117
'EXT:in2publish_core/Resources/Private/Language/locallang_m3_js.xlf',
120118
);
121-
$moduleTemplate = $this->moduleTemplateFactory->create($this->request);
122-
$moduleTemplate->setFlashMessageQueue($this->getFlashMessageQueue());
123119

124120
/** @see packages/in2publish_core/Resources/Private/Templates/File/Index.html */
125121
return $this->htmlResponse();
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace In2code\In2publishCore\Controller\Traits;
6+
7+
use In2code\In2publishCore\Backend\Button\ModuleShortcutButton;
8+
use In2code\In2publishCore\Backend\Template\ModuleTemplateFactory;
9+
use In2code\In2publishCore\Event\ModuleTemplateWasPreparedForRendering;
10+
use Psr\EventDispatcher\EventDispatcherInterface;
11+
use Psr\Http\Message\ResponseInterface;
12+
use Psr\Http\Message\ServerRequestInterface;
13+
use TYPO3\CMS\Backend\Template\ModuleTemplate;
14+
use TYPO3\CMS\Core\Utility\GeneralUtility;
15+
use TYPO3\CMS\Extbase\Mvc\Request;
16+
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
17+
18+
use function str_replace;
19+
use function strtolower;
20+
21+
/**
22+
* WORKAROUND:
23+
*
24+
* this ModuleTemplateFactory is only used in the PublishFiles Backend Module (FileController).
25+
* This Factory can be removed if the core supports a way to override templates for backend modules which use
26+
* the id parameter to store the current selected folder (like filelist)
27+
*
28+
* override the "misuse" of the "id" argument (see: typo3/cms-backend/Classes/View/BackendViewFactory.php:70).
29+
* Otherwise, a template override is not possible because the PageTs is not loaded.
30+
*
31+
* The "filelist" and therefore the "publish files" modules use the "id" parameter to specify the currently selected
32+
* folder instead of the selected page.
33+
*
34+
* @see: https://projekte.in2code.de/issues/76154
35+
* @property Request $request
36+
* @property EventDispatcherInterface $eventDispatcher
37+
* @property string $actionMethodName
38+
*/
39+
trait FileControllerModuleTemplate
40+
{
41+
protected ModuleTemplateFactory $moduleTemplateFactory;
42+
43+
protected ModuleTemplate $moduleTemplate;
44+
45+
/**
46+
* @noinspection PhpUnused
47+
*/
48+
public function injectModuleTemplateFactory(ModuleTemplateFactory $moduleTemplateFactory): void
49+
{
50+
$this->moduleTemplateFactory = $moduleTemplateFactory;
51+
}
52+
53+
/**
54+
* @param RequestInterface $request
55+
* @return ResponseInterface
56+
*/
57+
public function processRequest(RequestInterface $request): ResponseInterface
58+
{
59+
if ($request instanceof ServerRequestInterface) {
60+
$this->moduleTemplate = $this->moduleTemplateFactory->create($request, );
61+
$this->moduleTemplate->setModuleId(strtolower(str_replace('\\', '_', static::class)));
62+
}
63+
return parent::processRequest($request);
64+
}
65+
66+
protected function htmlResponse(?string $html = null): ResponseInterface
67+
{
68+
return $this->render();
69+
}
70+
71+
protected function render(): ResponseInterface
72+
{
73+
$docHeader = $this->moduleTemplate->getDocHeaderComponent();
74+
$buttonBar = $docHeader->getButtonBar();
75+
76+
$moduleShortcutButton = GeneralUtility::makeInstance(ModuleShortcutButton::class);
77+
$moduleShortcutButton->setRequest($this->request);
78+
$buttonBar->addButton($moduleShortcutButton);
79+
80+
$event = new ModuleTemplateWasPreparedForRendering(
81+
$this->moduleTemplate,
82+
static::class,
83+
$this->actionMethodName
84+
);
85+
$this->eventDispatcher->dispatch($event);
86+
87+
return $this->moduleTemplate->renderResponse($this->request->getControllerName() . '/' . ucfirst($this->request->getControllerActionName()));
88+
}
89+
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"ext-json": "*",
4242
"ext-pdo": "*",
4343
"ext-zip": "*",
44-
"typo3/cms-core": "^13.4",
44+
"typo3/cms-core": "^13.4.19",
4545
"symfony/yaml": "^7.1"
4646
},
4747
"autoload": {

ext_emconf.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'title' => 'in2publish Core',
1010
'description' => 'Content publishing extension to connect stage and production server',
1111
'category' => 'plugin',
12-
'version' => '13.2.1',
12+
'version' => '13.2.2',
1313
'state' => 'stable',
1414
'author' => 'Alex Kellner, Oliver Eglseder, Thomas Scheibitz, Stefan Busemann',
1515
'author_email' => '[email protected]',

0 commit comments

Comments
 (0)