diff --git a/Documentation/Examples/TYPO3/Index.rst b/Documentation/Examples/TYPO3/Index.rst index 8014ffa7..ddc31572 100644 --- a/Documentation/Examples/TYPO3/Index.rst +++ b/Documentation/Examples/TYPO3/Index.rst @@ -44,3 +44,34 @@ If you would like to deploy a TYPO3 website a good starting point is to use TYPO ->afterStage('switch', \TYPO3\Surf\Task\Php\WebOpcacheResetExecuteTask::class, $application); } ); + +Configuration file in TYPO3 12 and later +======================================== + +Since TYPO3 12 the configuration lives in :file:`config/system/settings.php` +instead of :file:`typo3conf/LocalConfiguration.php`. Replace the symlink of the +example above with:: + + $application->addSymlink('config/system/settings.php', '../../../../shared/Configuration/settings.php'); + +Publishing extension assets (TYPO3 14.2 and later) +================================================== + +For how TYPO3 publishes extension assets, see +`Assets `__ +and +`Feature #109163 `__. + +If the Composer install runs without the complete TYPO3 configuration, skip +the publishing there and publish on the node with the +``AssetPublishTask`` instead:: + + $deployment->onInitialize( + function () use ($deployment, $application) { + $deployment->getWorkflow() + ->setTaskOptions('TYPO3\\Surf\\DefinedTask\\Composer\\LocalInstallTask', [ + 'composerCommandPath' => 'TYPO3_SKIP_ASSET_PUBLISH=1 composer', + ]) + ->addTask(\TYPO3\Surf\Task\TYPO3\CMS\AssetPublishTask::class, 'migrate', $application); + } + ); diff --git a/src/Task/TYPO3/CMS/AssetPublishTask.php b/src/Task/TYPO3/CMS/AssetPublishTask.php new file mode 100644 index 00000000..167577f5 --- /dev/null +++ b/src/Task/TYPO3/CMS/AssetPublishTask.php @@ -0,0 +1,55 @@ + $options + */ + public function execute(Node $node, Application $application, Deployment $deployment, array $options = []): void + { + Assert::isInstanceOf($application, CMS::class); + /** @var CMS $application */ + $options = $this->configureOptions($options); + + $this->executeCliCommand( + array_merge( + [$this->getTypo3CoreCliFileName($node, $application, $deployment, $options), 'asset:publish'], + $options['arguments'] + ), + $node, + $application, + $deployment, + $options + ); + } + + protected function resolveOptions(OptionsResolver $resolver): void + { + $resolver->setDefault('arguments', []) + ->setAllowedTypes('arguments', ['array', 'string']) + ->setNormalizer('arguments', fn (Options $options, $value): array => (array)$value); + } +} diff --git a/tests/Unit/Task/TYPO3/CMS/AssetPublishTaskTest.php b/tests/Unit/Task/TYPO3/CMS/AssetPublishTaskTest.php new file mode 100644 index 00000000..94c3783b --- /dev/null +++ b/tests/Unit/Task/TYPO3/CMS/AssetPublishTaskTest.php @@ -0,0 +1,105 @@ +application = new CMS('TestApplication'); + $this->application->setDeploymentPath('/home/jdoe/app'); + } + + protected function createTask(): AssetPublishTask + { + return new AssetPublishTask(); + } + + /** + * @test + */ + public function wrongApplicationTypeGivenThrowsException(): void + { + $invalidApplication = new BaseApplication('Hello world app'); + $this->expectException(InvalidArgumentException::class); + $this->task->execute($this->node, $invalidApplication, $this->deployment, []); + } + + /** + * @test + */ + public function missingTypo3CliFailsTheDeploymentInsteadOfSkippingThePublishing(): void + { + $this->expectException(InvalidConfigurationException::class); + $this->task->execute($this->node, $this->application, $this->deployment, []); + } + + /** + * @test + */ + public function executeWithWrongArgumentsTypeThrowsException(): void + { + $this->expectException(InvalidConfigurationException::class); + $options = [ + 'typo3CliFileName' => 'typo3', + 'arguments' => 1 + ]; + $this->task->execute($this->node, $this->application, $this->deployment, $options); + } + + /** + * @test + */ + public function executeWithoutArgumentsExecutesAssetPublish(): void + { + $options = [ + 'typo3CliFileName' => 'vendor/bin/typo3' + ]; + $this->task->execute($this->node, $this->application, $this->deployment, $options); + $this->assertCommandExecuted("/^cd '\/releases\/[0-9]+'$/"); + $this->assertCommandExecuted("/php 'vendor\/bin\/typo3' 'asset:publish'$/"); + } + + /** + * @test + */ + public function executeWithArgumentsPassesThemToAssetPublish(): void + { + $options = [ + 'typo3CliFileName' => 'vendor/bin/typo3', + 'arguments' => ['-v'] + ]; + $this->task->execute($this->node, $this->application, $this->deployment, $options); + $this->assertCommandExecuted("/php 'vendor\/bin\/typo3' 'asset:publish' '-v'$/"); + } + + /** + * @test + */ + public function executeWithContextOptionSetsTypo3Context(): void + { + $options = [ + 'typo3CliFileName' => 'vendor/bin/typo3', + 'context' => 'Production' + ]; + $this->task->execute($this->node, $this->application, $this->deployment, $options); + $this->assertCommandExecuted("/TYPO3_CONTEXT='Production' php 'vendor\/bin\/typo3' 'asset:publish'$/"); + } +}