From f9c55ee2ab4fb0b8834b6701bedf407f5baf4254 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 31 Oct 2023 13:42:07 +0100 Subject: [PATCH 001/113] [BUGFIX] Require table tx_in2publishcore_filepublisher_instruction instead of _task --- .../Component/ConfigContainer/Definer/In2publishCoreDefiner.php | 1 - Classes/Testing/Data/RequiredTablesDataProvider.php | 1 + Configuration/Yaml/LocalConfiguration.yaml.example | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php index 581b86b27..166ab5a04 100644 --- a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php +++ b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php @@ -52,7 +52,6 @@ class In2publishCoreDefiner implements DefinerServiceInterface 'tx_in2code_in2publish_task', 'tx_in2code_rpc_data', 'tx_in2code_rpc_request', - 'tx_in2publishcore_filepublisher_task', 'tx_in2publishcore_log', 'tx_in2publishcore_running_request', ]; diff --git a/Classes/Testing/Data/RequiredTablesDataProvider.php b/Classes/Testing/Data/RequiredTablesDataProvider.php index ca61bef1b..c9abccae5 100644 --- a/Classes/Testing/Data/RequiredTablesDataProvider.php +++ b/Classes/Testing/Data/RequiredTablesDataProvider.php @@ -49,6 +49,7 @@ public function getRequiredTables(): array 'tx_in2publishcore_running_request', 'tx_in2code_rpc_request', 'tx_in2code_rpc_data', + 'tx_in2publishcore_filepublisher_instruction', ]; $requiredTables = $this->overruleTables($requiredTables); $this->cache = $requiredTables; diff --git a/Configuration/Yaml/LocalConfiguration.yaml.example b/Configuration/Yaml/LocalConfiguration.yaml.example index 18613c035..24e362932 100755 --- a/Configuration/Yaml/LocalConfiguration.yaml.example +++ b/Configuration/Yaml/LocalConfiguration.yaml.example @@ -61,7 +61,6 @@ excludeRelatedTables: - tx_in2code_in2publish_task - tx_in2code_rpc_data - tx_in2code_rpc_request - - tx_in2publishcore_filepublisher_task - tx_in2publishcore_log - tx_in2publishcore_running_request From c32678321dfd1f98f34d4ec53e73d55e797bef93 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 31 Oct 2023 14:15:30 +0100 Subject: [PATCH 002/113] [BUGFIX] Ignore table tx_in2publishcore_filepublisher_instruction by default --- .../Component/ConfigContainer/Definer/In2publishCoreDefiner.php | 1 + Configuration/Yaml/LocalConfiguration.yaml.example | 1 + 2 files changed, 2 insertions(+) diff --git a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php index 166ab5a04..ba42038d6 100644 --- a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php +++ b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php @@ -54,6 +54,7 @@ class In2publishCoreDefiner implements DefinerServiceInterface 'tx_in2code_rpc_request', 'tx_in2publishcore_log', 'tx_in2publishcore_running_request', + 'tx_in2publishcore_filepublisher_instruction', ]; public function getLocalDefinition(): NodeCollection diff --git a/Configuration/Yaml/LocalConfiguration.yaml.example b/Configuration/Yaml/LocalConfiguration.yaml.example index 24e362932..dc428e321 100755 --- a/Configuration/Yaml/LocalConfiguration.yaml.example +++ b/Configuration/Yaml/LocalConfiguration.yaml.example @@ -63,6 +63,7 @@ excludeRelatedTables: - tx_in2code_rpc_request - tx_in2publishcore_log - tx_in2publishcore_running_request + - tx_in2publishcore_filepublisher_instruction # Ignore these fields for difference view (Publish Overview, Record Comparison). From 31d2fe9e4b0f350205e48a11ee4e39409f2c89c6 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 31 Oct 2023 16:31:50 +0100 Subject: [PATCH 003/113] [BUGFIX] Disable the function bar if publishing is not available --- .../Private/Partials/File/FunctionBar.html | 158 +++++++++--------- .../Private/Partials/Record/FunctionBar.html | 76 +++++---- 2 files changed, 119 insertions(+), 115 deletions(-) diff --git a/Resources/Private/Partials/File/FunctionBar.html b/Resources/Private/Partials/File/FunctionBar.html index a90c0db0b..d5a892ddf 100755 --- a/Resources/Private/Partials/File/FunctionBar.html +++ b/Resources/Private/Partials/File/FunctionBar.html @@ -3,84 +3,86 @@ xmlns:publish="http://typo3.org/ns/In2code/In2publishCore/ViewHelpers" data-namespace-typo3-fluid="true" > -
-
- - - -
- + +
+
+ + + +
+ +
+ +

+ +

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
- -

- -

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
+ diff --git a/Resources/Private/Partials/Record/FunctionBar.html b/Resources/Private/Partials/Record/FunctionBar.html index a6240ee49..3ef3eec8e 100755 --- a/Resources/Private/Partials/Record/FunctionBar.html +++ b/Resources/Private/Partials/Record/FunctionBar.html @@ -4,41 +4,43 @@ > ns is removed on reformat code.]]> -
- - Filter buttons - - -
- - - - - - - - - - - - -
-
-
+ +
+ + Filter buttons + + +
+ + + + + + + + + + + + +
+
+
+
From 634d10ba382c54d65a66efe23cb56d42f37d70e7 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 13:04:15 +0100 Subject: [PATCH 004/113] [TESTS] Update unit tests for PublishFileInstructions --- .../AbstractFilesystemPublisherTest.php | 18 + .../Publisher/FileRecordPublisherTest.php | 322 +++++++++++------- .../Publisher/FolderRecordPublisherTest.php | 114 ++++--- .../Core/Record/Model/FileRecordTest.php | 14 +- 4 files changed, 302 insertions(+), 166 deletions(-) create mode 100644 Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php diff --git a/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php b/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php new file mode 100644 index 000000000..b605a70f7 --- /dev/null +++ b/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php @@ -0,0 +1,18 @@ +setAccessible(true); + return $reflectionProperty->getValue($filesystemRecordPublisher); + } +} diff --git a/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php b/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php index e0b361fd5..83a639aad 100644 --- a/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php +++ b/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php @@ -4,23 +4,31 @@ namespace In2code\In2publishCore\Tests\Unit\Component\Core\Publisher; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; use In2code\In2publishCore\Component\Core\Publisher\FileRecordPublisher; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\AddFileInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFileInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\MoveFileInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceAndRenameFileInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceFileInstruction; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseRecord; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; -use In2code\In2publishCore\Component\Core\Record\Model\Record; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse; use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitter; -use In2code\In2publishCore\Tests\UnitTestCase; -use org\bovigo\vfs\vfsStream; -use ReflectionProperty; use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Resource\Driver\DriverInterface; + +use function json_encode; +use function sha1; +use function str_replace; +use function strrpos; +use function substr; +use function trim; /** * @coversDefaultClass \In2code\In2publishCore\Component\Core\Publisher\FileRecordPublisher */ -class FileRecordPublisherTest extends UnitTestCase +class FileRecordPublisherTest extends AbstractFilesystemPublisherTest { /** * @covers ::__construct @@ -45,34 +53,33 @@ public function testCanPublishReturnsTrueForFileRecordsOnly() */ public function testPublishDeletesRemovedFile() { - $fileRecordPublisher = new FileRecordPublisher(); - $foreignDatabase = $this->createMock(Connection::class); - - $deletedFile = $this->createMock(FileRecord::class); - $deletedFile->method('getClassification')->willReturn('_file'); - $deletedFile->method('getState')->willReturn(Record::S_DELETED); - $deletedFile->method('getForeignProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'identifier_hash' => 'baz'], - ); + $fileRecordPublisher = $this->createFileRecordPublisher(); - $reflectionProperty = new ReflectionProperty($fileRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); - - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($fileRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $deletedFile->getForeignProps()['storage'], - 'identifier' => $deletedFile->getForeignProps()['identifier'], - 'identifier_hash' => $deletedFile->getForeignProps()['identifier_hash'], - 'file_action' => $fileRecordPublisher::A_DELETE, + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => DeleteFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'fileIdentifier' => '/foo/bar', + ]), + ], ], ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); + $deletedFile = new FileRecord( + [], + $this->createFileInfo('bar', 1, '23149872364', '/foo'), + ); + $fileRecordPublisher->publish($deletedFile); + $fileRecordPublisher->finish(); } /** @@ -80,104 +87,72 @@ public function testPublishDeletesRemovedFile() */ public function testPublishTransmitsAddedRecord() { - $fileRecordPublisher = new FileRecordPublisher(); - $foreignDatabase = $this->createMock(Connection::class); - $falDriverService = $this->createMock(FalDriverService::class); - $mockDriver = $this->createMock(DriverInterface::class); - - $structure = [ - 'Api.php' => '', - ]; - $root = vfsStream::setup('root', null, $structure); - $file = $root->url() . '/Api.php'; - $mockDriver->method('getFileForLocalProcessing')->willReturn($file); - $falDriverService->method('getDriver')->willReturn($mockDriver); - $assetTransmitter = $this->createMock(AssetTransmitter::class); + $fileRecordPublisher = $this->createFileRecordPublisher('/var/tmp/asdfasdf.tmp'); - $addedFile = $this->createMock(FileRecord::class); - $addedFile->method('getId')->willReturn('1:/bar'); - $addedFile->method('getClassification')->willReturn('_file'); - $addedFile->method('getState')->willReturn(Record::S_ADDED); - $addedFile->method('getLocalProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'identifier_hash' => 'baz'], - ); - - $reflectionProperty = new ReflectionProperty($fileRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); - - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($fileRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $addedFile->getLocalProps()['storage'], - 'identifier' => $addedFile->getLocalProps()['identifier'], - 'identifier_hash' => $addedFile->getLocalProps()['identifier_hash'], - 'file_action' => $fileRecordPublisher::A_INSERT, - 'temp_identifier_hash' => '', + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => AddFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'foreignTemporaryFileIdentifier' => '/var/tmp/asdfasdf.tmp', + 'foreignTargetFileIdentifier' => '/foo/bar', + ]), + ], ], ); - $fileRecordPublisher->injectForeignDatabase($foreignDatabase); - $fileRecordPublisher->injectFalDriverService($falDriverService); - $fileRecordPublisher->injectAssetTransmitter($assetTransmitter); + + $addedFile = new FileRecord( + $this->createFileInfo('bar', 1, '23450978', '/foo'), + [], + ); $fileRecordPublisher->publish($addedFile); + $fileRecordPublisher->finish(); } /** * @covers ::publish */ - public function testPublishTransmitsChangedRecord() + public function testPublishTransmitsRenamedRecord() { - $fileRecordPublisher = new FileRecordPublisher(); - $foreignDatabase = $this->createMock(Connection::class); - $falDriverService = $this->createMock(FalDriverService::class); - $mockDriver = $this->createMock(DriverInterface::class); + $fileRecordPublisher = $this->createFileRecordPublisher(); - $structure = [ - 'Api.php' => '', - ]; - $root = vfsStream::setup('root', null, $structure); - $file = $root->url() . '/Api.php'; - $mockDriver->method('getFileForLocalProcessing')->willReturn($file); - $falDriverService->method('getDriver')->willReturn($mockDriver); $assetTransmitter = $this->createMock(AssetTransmitter::class); + $fileRecordPublisher->injectAssetTransmitter($assetTransmitter); - $changedFile = $this->createMock(FileRecord::class); - $changedFile->method('getId')->willReturn('1:/bar'); - $changedFile->method('getClassification')->willReturn('_file'); - $changedFile->method('getState')->willReturn(Record::S_CHANGED); - $changedFile->method('getLocalProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'identifier_hash' => 'baz'], - ); - $changedFile->method('getForeignProps')->willReturn( - ['storage' => 2, 'identifier' => 'bar2', 'identifier_hash' => 'baz2'], + $changedFile = new FileRecord( + $this->createFileInfo('bar2', 1, '23149872364', '/foo'), + $this->createFileInfo('bar', 1, '23149872364', '/foo'), ); - $reflectionProperty = new ReflectionProperty($fileRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); - - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($fileRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $changedFile->getLocalProps()['storage'], - 'identifier' => $changedFile->getLocalProps()['identifier'], - 'identifier_hash' => $changedFile->getLocalProps()['identifier_hash'], - 'file_action' => $fileRecordPublisher::A_UPDATE, - 'temp_identifier_hash' => '', + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => MoveFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'oldFileIdentifier' => '/foo/bar', + 'newFileIdentifier' => '/foo/bar2', + ]), + ], ], ); - $fileRecordPublisher->injectForeignDatabase($foreignDatabase); - $fileRecordPublisher->injectFalDriverService($falDriverService); - $fileRecordPublisher->injectAssetTransmitter($assetTransmitter); $fileRecordPublisher->publish($changedFile); + $fileRecordPublisher->finish(); } /** @@ -185,37 +160,140 @@ public function testPublishTransmitsChangedRecord() */ public function testPublishTransmitsMovedRecord() { - $fileRecordPublisher = new FileRecordPublisher(); + $fileRecordPublisher = $this->createFileRecordPublisher(); + + $movedFile = new FileRecord( + $this->createFileInfo('foo', 1, '452093485', '/foo'), + $this->createFileInfo('foo', 1, '452093485', '/bar'), + ); + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', + [ + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => MoveFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'oldFileIdentifier' => '/bar/foo', + 'newFileIdentifier' => '/foo/foo', + ]), + ], + ], + ); + $fileRecordPublisher->injectForeignDatabase($foreignDatabase); + + $fileRecordPublisher->publish($movedFile); + $fileRecordPublisher->finish(); + } + + /** + * @covers ::publish + */ + public function testPublishTransmitsReplacedFileWithNewNameRecord() + { + $fileRecordPublisher = $this->createFileRecordPublisher('/var/tmp/transient/sadsdas.tmp'); - $movedFile = $this->createMock(FileRecord::class); - $movedFile->method('getClassification')->willReturn('_file'); - $movedFile->method('getState')->willReturn(Record::S_MOVED); - $movedFile->method('getLocalProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'identifier_hash' => 'baz'], + $movedFile = new FileRecord( + $this->createFileInfo('foo', 1, '452093485', '/foo'), + $this->createFileInfo('bar', 1, '234587', '/bar'), ); - $movedFile->method('getForeignProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar_foreign', 'identifier_hash' => 'baz_foreign'], + + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', + [ + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => ReplaceAndRenameFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'oldFileIdentifier' => '/bar/bar', + 'foreignTargetFileIdentifier' => '/foo/foo', + 'foreignTemporaryFileIdentifier' => '/var/tmp/transient/sadsdas.tmp', + ]), + ], + ], ); + $fileRecordPublisher->injectForeignDatabase($foreignDatabase); - $reflectionProperty = new ReflectionProperty($fileRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); + $fileRecordPublisher->publish($movedFile); + $fileRecordPublisher->finish(); + } - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + /** + * @covers ::publish + */ + public function testPublishTransmitsReplacedFileWithSameNameRecord() + { + $fileRecordPublisher = $this->createFileRecordPublisher('/var/tmp/transient/sadsdas.tmp'); + + $movedFile = new FileRecord( + $this->createFileInfo('foo', 1, '452093485', '/foo'), + $this->createFileInfo('foo', 1, '234587', '/foo'), + ); + + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($fileRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $movedFile->getLocalProps()['storage'], - 'identifier' => $movedFile->getLocalProps()['identifier'], - 'identifier_hash' => $movedFile->getLocalProps()['identifier_hash'], - 'previous_identifier' => $movedFile->getForeignProps()['identifier'], - 'file_action' => $fileRecordPublisher::A_RENAME, + [ + 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => ReplaceFileInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'foreignTargetFileIdentifier' => '/foo/foo', + 'foreignTemporaryFileIdentifier' => '/var/tmp/transient/sadsdas.tmp', + ]), + ], ], ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); $fileRecordPublisher->publish($movedFile); + $fileRecordPublisher->finish(); + } + + protected function createFileInfo( + string $name, + int $storage, + string $hash, + string $folder, + string $mimeType = 'image/jpeg', + int $size = 12345 + ): array { + return [ + 'size' => $size, + 'mimetype' => $mimeType, + 'name' => $name, + 'extension' => strrpos($name, '.') ? substr($name, strrpos($name, '.')) : '', + 'folder_hash' => sha1($folder), + 'identifier' => str_replace('//', '/', '/' . trim($folder, '/') . '/') . $name, + 'storage' => $storage, + 'sha1' => $hash, + 'publicUrl' => 'fileadmin/' . $name, + ]; + } + + protected function createFileRecordPublisher(string $temporaryFileIdentifier = '_undefined_'): FileRecordPublisher + { + $fileRecordPublisher = $this->createPartialMock(FileRecordPublisher::class, ['transmitTemporaryFile']); + $fileRecordPublisher->__construct(); + $remoteCommandResponse = $this->createMock(RemoteCommandResponse::class); + $remoteCommandResponse->method('isSuccessful')->willReturn(true); + $remoteCommandDispatcher = $this->createMock(RemoteCommandDispatcher::class); + $remoteCommandDispatcher->method('dispatch')->willReturn($remoteCommandResponse); + $fileRecordPublisher->injectRemoteCommandDispatcher($remoteCommandDispatcher); + + $fileRecordPublisher->method('transmitTemporaryFile')->willReturn($temporaryFileIdentifier); + + return $fileRecordPublisher; } } diff --git a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php index a31a5e04a..63ee602cc 100644 --- a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php +++ b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php @@ -5,18 +5,21 @@ namespace In2code\In2publishCore\Tests\Unit\Component\Core\Publisher; use In2code\In2publishCore\Component\Core\Publisher\FolderRecordPublisher; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\AddFolderInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFolderInstruction; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseRecord; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; -use In2code\In2publishCore\Component\Core\Record\Model\Record; -use In2code\In2publishCore\Tests\UnitTestCase; -use ReflectionProperty; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse; use TYPO3\CMS\Core\Database\Connection; +use function json_encode; + /** * @coversDefaultClass \In2code\In2publishCore\Component\Core\Publisher\FolderRecordPublisher */ -class FolderRecordPublisherTest extends UnitTestCase +class FolderRecordPublisherTest extends AbstractFilesystemPublisherTest { /** * @covers ::__construct @@ -41,33 +44,39 @@ public function testCanPublishReturnsTrueForFileRecordsOnly() */ public function testPublishRemovesDeletedFolder() { - $folderRecordPublisher = new FolderRecordPublisher(); - $foreignDatabase = $this->createMock(Connection::class); - $deletedFolder = $this->createMock(FileRecord::class); - $deletedFolder->method('getClassification')->willReturn('_folder'); - $deletedFolder->method('getState')->willReturn(Record::S_DELETED); - $deletedFolder->method('getForeignProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'combinedIdentifier' => '1:bar'], - ); + $folderRecordPublisher = $this->createFolderRecordPublisher(); - $reflectionProperty = new ReflectionProperty($folderRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); + $deletedFolder = new FolderRecord( + '1:/foo/bar', + [], + [ + 'combinedIdentifier' => '1:/foo/bar', + 'identifier' => '/foo/bar', + 'name' => 'bar', + 'storage' => 1, + ], + ); - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($folderRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $deletedFolder->getForeignProps()['storage'], - 'identifier' => $deletedFolder->getForeignProps()['combinedIdentifier'], - 'identifier_hash' => '', - 'folder_action' => $folderRecordPublisher::A_DELETE, + [ + 'request_token' => $this->getRequestTokenFromPublisher($folderRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => DeleteFolderInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'folderIdentifier' => '/foo/bar', + ]), + ], ], ); $folderRecordPublisher->injectForeignDatabase($foreignDatabase); $folderRecordPublisher->publish($deletedFolder); + $folderRecordPublisher->finish(); } /** @@ -75,33 +84,52 @@ public function testPublishRemovesDeletedFolder() */ public function testPublishAddsAddedFolder() { - $folderRecordPublisher = new FolderRecordPublisher(); - $foreignDatabase = $this->createMock(Connection::class); - $addedFolder = $this->createMock(FileRecord::class); - $addedFolder->method('getClassification')->willReturn('_folder'); - $addedFolder->method('getState')->willReturn(Record::S_ADDED); - $addedFolder->method('getLocalProps')->willReturn( - ['storage' => 1, 'identifier' => 'bar', 'combinedIdentifier' => '1:bar'], - ); - $addedFolder->method('getForeignProps')->willReturn([]); + $folderRecordPublisher = $this->createFolderRecordPublisher(); - $reflectionProperty = new ReflectionProperty($folderRecordPublisher, 'requestToken'); - $reflectionProperty->setAccessible(true); + $addedFolder = new FolderRecord( + '1:/foo/bar', + [ + 'combinedIdentifier' => '1:/foo/bar', + 'identifier' => '/foo/bar', + 'name' => 'bar', + 'storage' => 1, + ], + [], + ); - $foreignDatabase->expects($this->once())->method('insert')->with( - 'tx_in2publishcore_filepublisher_task', + $foreignDatabase = $this->createMock(Connection::class); + $foreignDatabase->expects($this->once())->method('bulkInsert')->with( + 'tx_in2publishcore_filepublisher_instruction', [ - 'request_token' => $reflectionProperty->getValue($folderRecordPublisher), - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'storage_uid' => $addedFolder->getLocalProps()['storage'], - 'identifier' => $addedFolder->getLocalProps()['combinedIdentifier'], - 'identifier_hash' => '', - 'folder_action' => $folderRecordPublisher::A_INSERT, + [ + 'request_token' => $this->getRequestTokenFromPublisher($folderRecordPublisher), + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => AddFolderInstruction::class, + 'configuration' => json_encode([ + 'storage' => 1, + 'folderIdentifier' => '/foo/bar', + ]), + ], ], ); $folderRecordPublisher->injectForeignDatabase($foreignDatabase); $folderRecordPublisher->publish($addedFolder); + $folderRecordPublisher->finish(); + } + + /** + * @return FolderRecordPublisher + */ + public function createFolderRecordPublisher(): FolderRecordPublisher + { + $folderRecordPublisher = new FolderRecordPublisher(); + $remoteCommandResponse = $this->createMock(RemoteCommandResponse::class); + $remoteCommandResponse->method('isSuccessful')->willReturn(true); + $remoteCommandDispatcher = $this->createMock(RemoteCommandDispatcher::class); + $remoteCommandDispatcher->method('dispatch')->willReturn($remoteCommandResponse); + $folderRecordPublisher->injectRemoteCommandDispatcher($remoteCommandDispatcher); + return $folderRecordPublisher; } } diff --git a/Tests/Unit/Component/Core/Record/Model/FileRecordTest.php b/Tests/Unit/Component/Core/Record/Model/FileRecordTest.php index 00a022bfb..b243c1365 100644 --- a/Tests/Unit/Component/Core/Record/Model/FileRecordTest.php +++ b/Tests/Unit/Component/Core/Record/Model/FileRecordTest.php @@ -59,6 +59,18 @@ public function testCalculateState(): void ['identifier' => 'file1', 'storage' => 42], ['identifier' => 'file2', 'storage' => 42], ); - $this->assertSame(Record::S_MOVED, $changedFileRecord->getState()); + $this->assertSame(Record::S_CHANGED, $changedFileRecord->getState()); + + $movedFileRecord = new FileRecord( + ['identifier' => 'file1', 'folder_hash' => '/bar', 'storage' => 42], + ['identifier' => 'file1', 'folder_hash' => '/foo', 'storage' => 42], + ); + $this->assertSame(Record::S_MOVED, $movedFileRecord->getState()); + + $replacedFileRecord = new FileRecord( + ['identifier' => 'file1', 'folder_hash' => '/bar', 'storage' => 42, 'sha1' => '234572364958734'], + ['identifier' => 'file1', 'folder_hash' => '/foo', 'storage' => 42, 'sha1' => '238497569384765'], + ); + $this->assertSame(Record::S_CHANGED, $replacedFileRecord->getState()); } } From 06fcf56d35569585da8b04412fd458f00eea315d Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 17:37:03 +0100 Subject: [PATCH 005/113] [BUGFIX] Increment logged SQL queries statically This prevents that previous logged queries are overwritten when the logger is instantiated multiple times --- .../Database/Logging/ContentPublisherSqlLogger.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php b/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php index 27a858f7e..d8bf4b303 100644 --- a/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php +++ b/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php @@ -33,7 +33,7 @@ class ContentPublisherSqlLogger implements SQLLogger ]; protected static array $queries = []; protected float $start; - protected int $currentQuery = 0; + protected static int $currentQuery = 0; public function startQuery($sql, array $params = null, array $types = null) { @@ -113,12 +113,12 @@ public function startQuery($sql, array $params = null, array $types = null) $entry['executionNS'] = 0; $entry['backtrace'] = $backtrace; - self::$queries[++$this->currentQuery] = $entry; + self::$queries[++self::$currentQuery] = $entry; } public function stopQuery(): void { - self::$queries[$this->currentQuery]['executionNS'] = (int)(hrtime(true) - $this->start); + self::$queries[self::$currentQuery]['executionNS'] = (int)(hrtime(true) - $this->start); } public static function getQueries(): array From f6c9663ee1e73c21108f27d2e40a907d8c463ea5 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 17:49:52 +0100 Subject: [PATCH 006/113] [BUGFIX] Use runtime cache to prevent multiple cache hits Reduces queries by 10% in the test setup (Publish Overview Module, 10 levels, Start at ID=0) --- Classes/Cache/CachedRuntimeCache.php | 66 +++++++++++++++++++ Classes/Cache/CachedRuntimeCacheInjection.php | 21 ++++++ ...cheableValueCanNotBeGeneratedException.php | 31 +++++++++ .../Logging/ContentPublisherSqlLogger.php | 8 ++- .../Environment/ForeignEnvironmentService.php | 59 +++++++---------- 5 files changed, 150 insertions(+), 35 deletions(-) create mode 100644 Classes/Cache/CachedRuntimeCache.php create mode 100644 Classes/Cache/CachedRuntimeCacheInjection.php create mode 100644 Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php diff --git a/Classes/Cache/CachedRuntimeCache.php b/Classes/Cache/CachedRuntimeCache.php new file mode 100644 index 000000000..0421350b4 --- /dev/null +++ b/Classes/Cache/CachedRuntimeCache.php @@ -0,0 +1,66 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use Closure; +use In2code\In2publishCore\Cache\Exception\CacheableValueCanNotBeGeneratedException; +use In2code\In2publishCore\CommonInjection\CacheInjection; +use TYPO3\CMS\Core\SingletonInterface; + +use function array_key_exists; + +class CachedRuntimeCache implements SingletonInterface +{ + use CacheInjection; + + protected array $rtc = []; + + /** + * @return mixed + */ + public function get(string $key, Closure $valueFactory, int $ttl = 86400) + { + if (!array_key_exists($key, $this->rtc)) { + if (!$this->cache->has($key)) { + try { + $value = $valueFactory(); + $this->cache->set($key, $value, [], $ttl); + } catch (CacheableValueCanNotBeGeneratedException $exception) { + $value = $exception->getValue(); + } + } else { + $value = $this->cache->get($key); + } + $this->rtc[$key] = $value; + } + + return $this->rtc[$key]; + } +} diff --git a/Classes/Cache/CachedRuntimeCacheInjection.php b/Classes/Cache/CachedRuntimeCacheInjection.php new file mode 100644 index 000000000..561c518b4 --- /dev/null +++ b/Classes/Cache/CachedRuntimeCacheInjection.php @@ -0,0 +1,21 @@ +cachedRuntimeCache = $cachedRuntimeCache; + } +} diff --git a/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php b/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php new file mode 100644 index 000000000..eb42d9ce6 --- /dev/null +++ b/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php @@ -0,0 +1,31 @@ +value = $value; + parent::__construct('', 1698857094, $previous); + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->value; + } +} diff --git a/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php b/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php index d8bf4b303..f518fd536 100644 --- a/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php +++ b/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php @@ -5,6 +5,7 @@ namespace In2code\In2publishCore\Features\MetricsAndDebug\Database\Logging; use Doctrine\DBAL\Logging\SQLLogger; +use In2code\In2publishCore\Cache\CachedRuntimeCache; use function array_key_last; use function array_shift; @@ -129,7 +130,12 @@ public static function getQueries(): array protected function findFirstCpFrame(array $backtrace): ?int { foreach ($backtrace as $index => $frame) { - if (isset($frame['class']) && str_starts_with($frame['class'], 'In2code\\In2publish')) { + if ( + isset($frame['class'], $frame['function']) + && $frame['class'] !== CachedRuntimeCache::class + && $frame['function'] !== 'executeCached' + && str_starts_with($frame['class'], 'In2code\\In2publish') + ) { return $index; } } diff --git a/Classes/Service/Environment/ForeignEnvironmentService.php b/Classes/Service/Environment/ForeignEnvironmentService.php index ef3296327..0fd8c0c00 100644 --- a/Classes/Service/Environment/ForeignEnvironmentService.php +++ b/Classes/Service/Environment/ForeignEnvironmentService.php @@ -29,10 +29,11 @@ * This copyright notice MUST APPEAR in all copies of the script! */ +use In2code\In2publishCore\Cache\CachedRuntimeCacheInjection; +use In2code\In2publishCore\Cache\Exception\CacheableValueCanNotBeGeneratedException; use In2code\In2publishCore\Command\Foreign\Status\CreateMasksCommand; use In2code\In2publishCore\Command\Foreign\Status\DbInitQueryEncodedCommand; use In2code\In2publishCore\Command\Foreign\Status\EncryptionKeyCommand; -use In2code\In2publishCore\CommonInjection\CacheInjection; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcherInjection; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandRequest; use Psr\Log\LoggerAwareInterface; @@ -53,20 +54,26 @@ class ForeignEnvironmentService implements LoggerAwareInterface { use LoggerAwareTrait; use RemoteCommandDispatcherInjection; - use CacheInjection; + use CachedRuntimeCacheInjection; public function getDatabaseInitializationCommands(): string { - if ($this->cache->has('foreign_db_init')) { - return $this->cache->get('foreign_db_init'); - } + return $this->cachedRuntimeCache->get('foreign_db_init', function (): string { + $request = new RemoteCommandRequest(DbInitQueryEncodedCommand::IDENTIFIER); + $response = $this->remoteCommandDispatcher->dispatch($request); - $request = new RemoteCommandRequest(DbInitQueryEncodedCommand::IDENTIFIER); - $response = $this->remoteCommandDispatcher->dispatch($request); + if (!$response->isSuccessful()) { + $this->logger->error( + 'Could not get DB init. Falling back to empty configuration value', + [ + 'errors' => $response->getErrors(), + 'exit_status' => $response->getExitStatus(), + 'output' => $response->getOutput(), + ], + ); + throw new CacheableValueCanNotBeGeneratedException(''); + } - $decodedDbInit = ''; - if ($response->isSuccessful()) { - // String (two double quotes): "" $encodedDbInit = 'IiI='; foreach ($response->getOutput() as $line) { if (false !== strpos($line, 'DBinit: ')) { @@ -74,25 +81,13 @@ public function getDatabaseInitializationCommands(): string break; } } - $decodedDbInit = json_decode(base64_decode($encodedDbInit), true, 512, JSON_THROW_ON_ERROR); - $this->cache->set('foreign_db_init', $decodedDbInit, [], 86400); - } else { - $this->logger->error( - 'Could not get DB init. Falling back to empty configuration value', - [ - 'errors' => $response->getErrors(), - 'exit_status' => $response->getExitStatus(), - 'output' => $response->getOutput(), - ], - ); - } - - return $decodedDbInit; + return json_decode(base64_decode($encodedDbInit), true, 512, JSON_THROW_ON_ERROR); + }); } public function getCreateMasks(): array { - if (!$this->cache->has('create_masks')) { + return $this->cachedRuntimeCache->get('create_masks', function (): ?array { $request = new RemoteCommandRequest(CreateMasksCommand::IDENTIFIER); $response = $this->remoteCommandDispatcher->dispatch($request); @@ -124,15 +119,13 @@ public function getCreateMasks(): array ]; } - $this->cache->set('create_masks', $createMasks, [], 86400); - } - - return (array)$this->cache->get('create_masks'); + return $createMasks; + }); } public function getEncryptionKey(): ?string { - if (!$this->cache->has('encryption_key')) { + return $this->cachedRuntimeCache->get('encryption_key', function (): ?string { $encryptionKey = null; $request = new RemoteCommandRequest(EncryptionKeyCommand::IDENTIFIER); @@ -144,10 +137,8 @@ public function getEncryptionKey(): ?string $encryptionKey = base64_decode($values['EKey']); } } - $this->cache->set('encryption_key', $encryptionKey, [], 86400); - } - - return $this->cache->get('encryption_key'); + return $encryptionKey; + }); } protected function tokenizeResponse(array $output): array From eaadca867405f464dabd7fec2e96d180311f6f23 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 17:52:35 +0100 Subject: [PATCH 007/113] [REFACTOR] Use the CachedRuntimeCache instead of the custom implementation in ForeignSiteFinder --- Classes/Service/ForeignSiteFinder.php | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/Classes/Service/ForeignSiteFinder.php b/Classes/Service/ForeignSiteFinder.php index 0fb9d3180..b2680bebf 100644 --- a/Classes/Service/ForeignSiteFinder.php +++ b/Classes/Service/ForeignSiteFinder.php @@ -30,9 +30,9 @@ */ use Closure; +use In2code\In2publishCore\Cache\CachedRuntimeCacheInjection; use In2code\In2publishCore\Command\Foreign\Status\AllSitesCommand; use In2code\In2publishCore\Command\Foreign\Status\SiteConfigurationCommand; -use In2code\In2publishCore\CommonInjection\CacheInjection; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcherInjection; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandRequest; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse; @@ -55,7 +55,7 @@ class ForeignSiteFinder implements LoggerAwareInterface { use LoggerAwareTrait; use RemoteCommandDispatcherInjection; - use CacheInjection; + use CachedRuntimeCacheInjection; private const UNSERIALIZE_ALLOWED_CLASS = [Site::class, Uri::class, SiteLanguage::class]; @@ -87,7 +87,7 @@ public function getSiteByPageId(int $pageId): Site ); throw new In2publishCoreException('An error occurred while fetching a remote site config', 1620723511); }; - return $this->executeCached('site_page_' . $pageId, $closure); + return $this->cachedRuntimeCache->get('site_page_' . $pageId, $closure); } /** @return Site[] */ @@ -110,7 +110,8 @@ public function getAllSites(): array ); throw new AllSitesCommandException($exitStatus, $errors, $output); }; - return $this->executeCached('sites', $closure); + + return $this->cachedRuntimeCache->get('sites', $closure); } public function getSiteByIdentifier(string $identifier): ?Site @@ -133,14 +134,4 @@ protected function processCommandResult(RemoteCommandResponse $response) } return $result; } - - protected function executeCached(string $cacheKey, Closure $closure) - { - if (!$this->cache->has($cacheKey)) { - $result = $closure(); - $this->cache->set($cacheKey, $result); - return $result; - } - return $this->cache->get($cacheKey); - } } From fd1b2d422e967a7accc4c2b05ca55e2897ab3ba0 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 18:06:15 +0100 Subject: [PATCH 008/113] [BUGFIX] Sort grouped queries by amount of calls --- .../MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php index bdf6ec37a..a4b771ad1 100644 --- a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php +++ b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php @@ -19,6 +19,7 @@ use function array_column; use function array_sum; use function date; +use function sort; use function str_replace; use function str_starts_with; @@ -79,6 +80,8 @@ protected function debugSqlQueries(): void unset($query['caller']); $queriesByCaller[$caller][] = $query; } + uksort($queriesByCaller, static fn($a, $b) => count($queriesByCaller[$b]) - count($queriesByCaller[$a])); + foreach ($queriesByCaller as $caller => $callerQueries) { $times = array_column($callerQueries, 'executionNS'); $durationNS = array_sum($times); From 1eeda582b5f5af3e2689fbbcf2fbfde3ed118d37 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 18:28:47 +0100 Subject: [PATCH 009/113] [BUGFIX] Show the sum of query duration when debugging queries --- .../MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php index a4b771ad1..98176b188 100644 --- a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php +++ b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php @@ -95,6 +95,7 @@ protected function debugSqlQueries(): void if (!empty($queries)) { DebugUtility::debug($queries, 'Content Publisher Queries'); DebugUtility::debug($queriesByCaller, 'Queries By Caller'); + DebugUtility::debug(array_sum(array_column($queries, 'executionNS')), 'Timing'); } } } From ac5e4b12debb9e15216abbee5455a7376710e707 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 18:33:33 +0100 Subject: [PATCH 010/113] [BUGFIX] Show debugged queries in separate tab for each request --- .../Middleware/MetricsAndDebugMiddleware.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php index 98176b188..d1a800f75 100644 --- a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php +++ b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php @@ -22,6 +22,7 @@ use function sort; use function str_replace; use function str_starts_with; +use function uniqid; class MetricsAndDebugMiddleware implements MiddlewareInterface { @@ -93,9 +94,11 @@ protected function debugSqlQueries(): void $queriesByCaller["$caller ($duration)"] = $callerQueries; } if (!empty($queries)) { - DebugUtility::debug($queries, 'Content Publisher Queries'); - DebugUtility::debug($queriesByCaller, 'Queries By Caller'); - DebugUtility::debug(array_sum(array_column($queries, 'executionNS')), 'Timing'); + /** @noinspection PhpRedundantOptionalArgumentInspection */ + $requestGroup = uniqid('request_', false); + DebugUtility::debug($queries, 'Content Publisher Queries', $requestGroup); + DebugUtility::debug($queriesByCaller, 'Queries By Caller', $requestGroup); + DebugUtility::debug(array_sum(array_column($queries, 'executionNS')), 'Timing', $requestGroup); } } } From e71dd825fb50b7cd507c72174c863ceda3a1dd88 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 1 Nov 2023 18:51:30 +0100 Subject: [PATCH 011/113] [BUGFIX] Inherit the base Exception from in2publish_core, not in2publish --- .../Exception/CacheableValueCanNotBeGeneratedException.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php b/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php index eb42d9ce6..5c8f3ca8d 100644 --- a/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php +++ b/Classes/Cache/Exception/CacheableValueCanNotBeGeneratedException.php @@ -4,10 +4,10 @@ namespace In2code\In2publishCore\Cache\Exception; -use In2code\In2publish\In2publishException; +use In2code\In2publishCore\In2publishCoreException; use Throwable; -class CacheableValueCanNotBeGeneratedException extends In2publishException +class CacheableValueCanNotBeGeneratedException extends In2publishCoreException { /** @var mixed */ private $value; From 88a33633f1405ff01cf64bcfb5b171aa80feb2d2 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 2 Nov 2023 12:24:08 +0100 Subject: [PATCH 012/113] [TASK] Allow PHP8.1 as requirement and remove outdated branch-aliases --- composer.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/composer.json b/composer.json index dc44b7321..89a57a124 100755 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "type": "typo3-cms-extension", "license": "GPL-3.0-or-later", "require": { - "php": "^7.4 || ^8.0", + "php": "^7.4 || ^8.0 || ^8.1", "ext-json": "*", "ext-pdo": "*", "ext-zip": "*", @@ -80,10 +80,6 @@ ] }, "extra": { - "branch-alias": { - "dev-develop-v12": "12.3.x-dev", - "dev-master-v12": "12.3.x-dev" - }, "typo3/cms": { "cms-package-dir": "{$vendor-dir}/typo3/cms", "web-dir": ".Build/Web", From 15ac0946f8d0f9482a11158baa9d4780954ffb3b Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 2 Nov 2023 13:56:23 +0100 Subject: [PATCH 013/113] [TASK] Add new branch aliases for develop branch --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index 89a57a124..1ee3b929b 100755 --- a/composer.json +++ b/composer.json @@ -80,6 +80,10 @@ ] }, "extra": { + "branch-alias": { + "dev-develop": "12.3.x-dev", + "dev-master": "12.3.x-dev" + }, "typo3/cms": { "cms-package-dir": "{$vendor-dir}/typo3/cms", "web-dir": ".Build/Web", From 671216532807d41d99c907a99f114be981dcd6f1 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 2 Nov 2023 17:07:08 +0100 Subject: [PATCH 014/113] [TASK] Update composer requirements --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 1ee3b929b..cd6f36cdd 100755 --- a/composer.json +++ b/composer.json @@ -41,15 +41,15 @@ "ext-json": "*", "ext-pdo": "*", "ext-zip": "*", - "typo3/cms-core": "^11.5" + "typo3/cms-core": "^11.5 || ^12.4" }, "require-dev": { "symfony/polyfill-php80": "^1.24", "symfony/polyfill-php81": "^1.24", - "typo3/cms-extensionmanager": "^11.4", - "typo3/cms-filelist": "^11.5", - "typo3/cms-redirects": "^11.5", - "typo3/cms-reports": "^11.5", + "typo3/cms-extensionmanager": "^11.4 || ^12.4", + "typo3/cms-filelist": "^11.5 || ^12.4", + "typo3/cms-redirects": "^11.5 || ^12.4", + "typo3/cms-reports": "^11.5 || ^12.4", "typo3/testing-framework": "^6.12" }, "suggest": { From cb2d78d576335184f8f2dfa809790e848f15ee25 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 6 Nov 2023 13:38:25 +0100 Subject: [PATCH 015/113] [BUGFIX] Replace Spyc with symfony/yaml --- .project/qa/phpmd.xml | 1 - .project/qa/psalm.xml | 1 - .../ConfigContainer/Provider/FileProvider.php | 22 +- .../Provider/VersionedFileProvider.php | 9 +- .../Yaml/ForeignConfiguration.yaml.example | 2 - .../Yaml/LocalConfiguration.yaml.example | 2 - Resources/Private/Libraries/Spyc/Spyc.php | 1155 ----------------- composer.json | 3 +- 8 files changed, 16 insertions(+), 1179 deletions(-) delete mode 100755 Resources/Private/Libraries/Spyc/Spyc.php diff --git a/.project/qa/phpmd.xml b/.project/qa/phpmd.xml index 738586b89..f430a662f 100644 --- a/.project/qa/phpmd.xml +++ b/.project/qa/phpmd.xml @@ -58,7 +58,6 @@ \In2code\In2publishCore\Utility\LogUtility, \In2code\In2publishCore\Utility\StorageDriverExtractor, \In2code\In2publishCore\Utility\UriUtility, - \Spyc diff --git a/.project/qa/psalm.xml b/.project/qa/psalm.xml index 0099abe59..ee5956fec 100644 --- a/.project/qa/psalm.xml +++ b/.project/qa/psalm.xml @@ -26,7 +26,6 @@ - diff --git a/Classes/Component/ConfigContainer/Provider/FileProvider.php b/Classes/Component/ConfigContainer/Provider/FileProvider.php index 8a74feb39..195016235 100644 --- a/Classes/Component/ConfigContainer/Provider/FileProvider.php +++ b/Classes/Component/ConfigContainer/Provider/FileProvider.php @@ -34,15 +34,16 @@ use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use Spyc; +use Symfony\Component\Yaml\Parser; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use function class_exists; use function file_exists; +use function file_get_contents; use function hash_file; use function rtrim; +use function str_replace; use function strpos; use function substr; use function trigger_error; @@ -83,8 +84,10 @@ public function getConfig(): array $cacheKey = 'config_file_provider_' . hash_file('sha1', $file); if (!$this->earlyCache->has($cacheKey)) { - $this->loadSpycIfRequired(); - $config = Spyc::YAMLLoad($file); + $yamlContents = file_get_contents($file); + $yamlContents = str_replace(['groups: *', '---'], ['groups: "*"', ''], $yamlContents); + $yaml = new Parser(); + $config = $yaml->parse($yamlContents); $code = 'return ' . var_export($config, true) . ';'; $this->earlyCache->flushByTag('config_file_provider'); $this->earlyCache->set($cacheKey, $code, ['config_file_provider']); @@ -115,15 +118,4 @@ protected function getResolvedFilePath(): string } return rtrim($path, '/') . '/'; } - - protected function loadSpycIfRequired(): void - { - if (class_exists(Spyc::class)) { - return; - } - $file = ExtensionManagementUtility::extPath('in2publish_core', 'Resources/Private/Libraries/Spyc/Spyc.php'); - if (file_exists($file)) { - require_once($file); - } - } } diff --git a/Classes/Component/ConfigContainer/Provider/VersionedFileProvider.php b/Classes/Component/ConfigContainer/Provider/VersionedFileProvider.php index de5a0f8a2..cb493cdd4 100644 --- a/Classes/Component/ConfigContainer/Provider/VersionedFileProvider.php +++ b/Classes/Component/ConfigContainer/Provider/VersionedFileProvider.php @@ -32,11 +32,14 @@ use In2code\In2publishCore\Component\ConfigContainer\Cache\EarlyCacheInjection; use In2code\In2publishCore\Service\Extension\ExtensionServiceInjection; use Spyc; +use Symfony\Component\Yaml\Parser; use function explode; use function file_exists; +use function file_get_contents; use function hash_file; use function implode; +use function str_replace; use function var_export; class VersionedFileProvider extends FileProvider @@ -61,8 +64,10 @@ public function getConfig(): array if (file_exists($file)) { $cacheKey = 'config_versioned_file_provider_' . hash_file('sha1', $file); if (!$this->earlyCache->has($cacheKey)) { - $this->loadSpycIfRequired(); - $config = Spyc::YAMLLoad($file); + $yamlContents = file_get_contents($file); + $yamlContents = str_replace(['groups: *', '---'], ['groups: "*"', ''], $yamlContents); + $yaml = new Parser(); + $config = $yaml->parse($yamlContents); $code = 'return ' . var_export($config, true) . ';'; $this->earlyCache->flushByTag('config_versioned_file_provider'); $this->earlyCache->set($cacheKey, $code, ['config_versioned_file_provider']); diff --git a/Configuration/Yaml/ForeignConfiguration.yaml.example b/Configuration/Yaml/ForeignConfiguration.yaml.example index 4b9e1fbe6..e0f770c44 100755 --- a/Configuration/Yaml/ForeignConfiguration.yaml.example +++ b/Configuration/Yaml/ForeignConfiguration.yaml.example @@ -2,8 +2,6 @@ # Example Configuration for in2publish on foreign # ---- - # Backup configuration backup: diff --git a/Configuration/Yaml/LocalConfiguration.yaml.example b/Configuration/Yaml/LocalConfiguration.yaml.example index dc428e321..e3a5c2aa9 100755 --- a/Configuration/Yaml/LocalConfiguration.yaml.example +++ b/Configuration/Yaml/LocalConfiguration.yaml.example @@ -4,8 +4,6 @@ # Fields annotated with "@user" can be overridden using PageTS or UserTS # ---- - # PHP & Database settings on foreign server (for SSH access see "sshConnection") foreign: diff --git a/Resources/Private/Libraries/Spyc/Spyc.php b/Resources/Private/Libraries/Spyc/Spyc.php deleted file mode 100755 index c30a4dca5..000000000 --- a/Resources/Private/Libraries/Spyc/Spyc.php +++ /dev/null @@ -1,1155 +0,0 @@ - - * @author Chris Wanstrath - * @link https://github.com/mustangostang/spyc/ - * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * @package Spyc - */ - -if (!function_exists('spyc_load')) { - /** - * Parses YAML to array. - * @param string $string YAML string. - * @return array - */ - function spyc_load ($string) { - return Spyc::YAMLLoadString($string); - } -} - -if (!function_exists('spyc_load_file')) { - /** - * Parses YAML to array. - * @param string $file Path to YAML file. - * @return array - */ - function spyc_load_file ($file) { - return Spyc::YAMLLoad($file); - } -} - -if (!function_exists('spyc_dump')) { - /** - * Dumps array to YAML. - * @param array $data Array. - * @return string - */ - function spyc_dump ($data) { - return Spyc::YAMLDump($data, false, false, true); - } -} - -/** - * The Simple PHP YAML Class. - * - * This class can be used to read a YAML file and convert its contents - * into a PHP array. It currently supports a very limited subsection of - * the YAML spec. - * - * Usage: - * - * $Spyc = new Spyc; - * $array = $Spyc->load($file); - * - * or: - * - * $array = Spyc::YAMLLoad($file); - * - * or: - * - * $array = spyc_load_file($file); - * - * @package Spyc - */ -class Spyc { - - // SETTINGS - - const REMPTY = "\0\0\0\0\0"; - - /** - * Setting this to true will force YAMLDump to enclose any string value in - * quotes. False by default. - * - * @var bool - */ - public $setting_dump_force_quotes = false; - - /** - * Setting this to true will forse YAMLLoad to use syck_load function when - * possible. False by default. - * @var bool - */ - public $setting_use_syck_is_possible = false; - - - - /**#@+ - * @access private - * @var mixed - */ - private $_dumpIndent; - private $_dumpWordWrap; - private $_containsGroupAnchor = false; - private $_containsGroupAlias = false; - private $path; - private $result; - private $LiteralPlaceHolder = '___YAML_Literal_Block___'; - private $SavedGroups = array(); - private $indent; - /** - * Path modifier that should be applied after adding current element. - * @var array - */ - private $delayedPath = array(); - - /**#@+ - * @access public - * @var mixed - */ - public $_nodeId; - -/** - * Load a valid YAML string to Spyc. - * @param string $input - * @return array - */ - public function load ($input) { - return $this->__loadString($input); - } - - /** - * Load a valid YAML file to Spyc. - * @param string $file - * @return array - */ - public function loadFile ($file) { - return $this->__load($file); - } - - /** - * Load YAML into a PHP array statically - * - * The load method, when supplied with a YAML stream (string or file), - * will do its best to convert YAML in a file into a PHP array. Pretty - * simple. - * Usage: - * - * $array = Spyc::YAMLLoad('lucky.yaml'); - * print_r($array); - * - * @access public - * @return array - * @param string $input Path of YAML file or string containing YAML - */ - public static function YAMLLoad($input) { - $Spyc = new Spyc; - return $Spyc->__load($input); - } - - /** - * Load a string of YAML into a PHP array statically - * - * The load method, when supplied with a YAML string, will do its best - * to convert YAML in a string into a PHP array. Pretty simple. - * - * Note: use this function if you don't want files from the file system - * loaded and processed as YAML. This is of interest to people concerned - * about security whose input is from a string. - * - * Usage: - * - * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); - * print_r($array); - * - * @access public - * @return array - * @param string $input String containing YAML - */ - public static function YAMLLoadString($input) { - $Spyc = new Spyc; - return $Spyc->__loadString($input); - } - - /** - * Dump YAML from PHP array statically - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as nothing.yaml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @access public - * @return string - * @param array $array PHP array - * @param int $indent Pass in false to use the default, which is 2 - * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) - * @param int $no_opening_dashes Do not start YAML file with "---\n" - */ - public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) { - $spyc = new Spyc; - return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes); - } - - - /** - * Dump PHP array to YAML - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as tasteful.yaml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @access public - * @return string - * @param array $array PHP array - * @param int $indent Pass in false to use the default, which is 2 - * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) - */ - public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) { - // Dumps to some very clean YAML. We'll have to add some more features - // and options soon. And better support for folding. - - // New features and options. - if ($indent === false or !is_numeric($indent)) { - $this->_dumpIndent = 2; - } else { - $this->_dumpIndent = $indent; - } - - if ($wordwrap === false or !is_numeric($wordwrap)) { - $this->_dumpWordWrap = 40; - } else { - $this->_dumpWordWrap = $wordwrap; - } - - // New YAML document - $string = ""; - if (!$no_opening_dashes) $string = "---\n"; - - // Start at the base of the array and move through it. - if ($array) { - $array = (array)$array; - $previous_key = -1; - foreach ($array as $key => $value) { - if (!isset($first_key)) $first_key = $key; - $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array); - $previous_key = $key; - } - } - return $string; - } - - /** - * Attempts to convert a key / value array item to YAML - * @access private - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) { - if (is_array($value)) { - if (empty ($value)) - return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array); - // It has children. What to do? - // Make it the right kind of item - $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array); - // Add the indent - $indent += $this->_dumpIndent; - // Yamlize the array - $string .= $this->_yamlizeArray($value,$indent); - } elseif (!is_array($value)) { - // It doesn't have children. Yip. - $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); - } - return $string; - } - - /** - * Attempts to convert an array to YAML - * @access private - * @return string - * @param $array The array you want to convert - * @param $indent The indent of the current level - */ - private function _yamlizeArray($array,$indent) { - if (is_array($array)) { - $string = ''; - $previous_key = -1; - foreach ($array as $key => $value) { - if (!isset($first_key)) $first_key = $key; - $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array); - $previous_key = $key; - } - return $string; - } else { - return false; - } - } - - /** - * Returns YAML from a key and a value - * @access private - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) { - // do some folding here, for blocks - if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false || - strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false || - strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 || - substr ($value, -1, 1) == ':') - ) { - $value = $this->_doLiteralBlock($value,$indent); - } else { - $value = $this->_doFolding($value,$indent); - } - - if ($value === array()) $value = '[ ]'; - if ($value === "") $value = '""'; - if (self::isTranslationWord($value)) { - $value = $this->_doLiteralBlock($value, $indent); - } - if (trim ($value) != $value) - $value = $this->_doLiteralBlock($value,$indent); - - if (is_bool($value)) { - $value = $value ? "true" : "false"; - } - - if ($value === null) $value = 'null'; - if ($value === "'" . self::REMPTY . "'") $value = null; - - $spaces = str_repeat(' ',$indent); - - //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { - if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) { - // It's a sequence - $string = $spaces.'- '.$value."\n"; - } else { - // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); - // It's mapped - if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; } - $string = rtrim ($spaces.$key.': '.$value)."\n"; - } - return $string; - } - - /** - * Creates a literal block for dumping - * @access private - * @return string - * @param $value - * @param $indent int The value of the indent - */ - private function _doLiteralBlock($value,$indent) { - if ($value === "\n") return '\n'; - if (strpos($value, "\n") === false && strpos($value, "'") === false) { - return sprintf ("'%s'", $value); - } - if (strpos($value, "\n") === false && strpos($value, '"') === false) { - return sprintf ('"%s"', $value); - } - $exploded = explode("\n",$value); - $newValue = '|'; - $indent += $this->_dumpIndent; - $spaces = str_repeat(' ',$indent); - foreach ($exploded as $line) { - $newValue .= "\n" . $spaces . ($line); - } - return $newValue; - } - - /** - * Folds a string of text, if necessary - * @access private - * @return string - * @param $value The string you wish to fold - */ - private function _doFolding($value,$indent) { - // Don't do anything if wordwrap is set to 0 - - if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) { - $indent += $this->_dumpIndent; - $indent = str_repeat(' ',$indent); - $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); - $value = ">\n".$indent.$wrapped; - } else { - if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY) - $value = '"' . $value . '"'; - if (is_numeric($value) && is_string($value)) - $value = '"' . $value . '"'; - } - - - return $value; - } - - private function isTrueWord($value) { - $words = self::getTranslations(array('true', 'on', 'yes', 'y')); - return in_array($value, $words, true); - } - - private function isFalseWord($value) { - $words = self::getTranslations(array('false', 'off', 'no', 'n')); - return in_array($value, $words, true); - } - - private function isNullWord($value) { - $words = self::getTranslations(array('null', '~')); - return in_array($value, $words, true); - } - - private function isTranslationWord($value) { - return ( - self::isTrueWord($value) || - self::isFalseWord($value) || - self::isNullWord($value) - ); - } - - /** - * Coerce a string into a native type - * Reference: http://yaml.org/type/bool.html - * TODO: Use only words from the YAML spec. - * @access private - * @param $value The value to coerce - */ - private function coerceValue(&$value) { - if (self::isTrueWord($value)) { - $value = true; - } else if (self::isFalseWord($value)) { - $value = false; - } else if (self::isNullWord($value)) { - $value = null; - } - } - - /** - * Given a set of words, perform the appropriate translations on them to - * match the YAML 1.1 specification for type coercing. - * @param $words The words to translate - * @access private - */ - private static function getTranslations(array $words) { - $result = array(); - foreach ($words as $i) { - $result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i))); - } - return $result; - } - -// LOADING FUNCTIONS - - private function __load($input) { - $Source = $this->loadFromSource($input); - return $this->loadWithSource($Source); - } - - private function __loadString($input) { - $Source = $this->loadFromString($input); - return $this->loadWithSource($Source); - } - - private function loadWithSource($Source) { - if (empty ($Source)) return array(); - if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) { - $array = syck_load (implode ("\n", $Source)); - return is_array($array) ? $array : array(); - } - - $this->path = array(); - $this->result = array(); - - $cnt = count($Source); - for ($i = 0; $i < $cnt; $i++) { - $line = $Source[$i]; - - $this->indent = strlen($line) - strlen(ltrim($line)); - $tempPath = $this->getParentPathByIndent($this->indent); - $line = self::stripIndent($line, $this->indent); - if (self::isComment($line)) continue; - if (self::isEmpty($line)) continue; - $this->path = $tempPath; - - $literalBlockStyle = self::startsLiteralBlock($line); - if ($literalBlockStyle) { - $line = rtrim ($line, $literalBlockStyle . " \n"); - $literalBlock = ''; - $line .= ' '.$this->LiteralPlaceHolder; - $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1])); - while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { - $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent); - } - $i--; - } - - // Strip out comments - if (strpos ($line, '#')) { - $line = preg_replace('/\s*#([^"\']+)$/','',$line); - } - - while (++$i < $cnt && self::greedilyNeedNextLine($line)) { - $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t"); - } - $i--; - - $lineArray = $this->_parseLine($line); - - if ($literalBlockStyle) - $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock); - - $this->addArray($lineArray, $this->indent); - - foreach ($this->delayedPath as $indent => $delayedPath) - $this->path[$indent] = $delayedPath; - - $this->delayedPath = array(); - - } - return $this->result; - } - - private function loadFromSource ($input) { - if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) - $input = file_get_contents($input); - - return $this->loadFromString($input); - } - - private function loadFromString ($input) { - $lines = explode("\n",$input); - foreach ($lines as $k => $_) { - $lines[$k] = rtrim ($_, "\r"); - } - return $lines; - } - - /** - * Parses YAML code and returns an array for a node - * @access private - * @return array - * @param string $line A line from the YAML file - */ - private function _parseLine($line) { - if (!$line) return array(); - $line = trim($line); - if (!$line) return array(); - - $array = array(); - - $group = $this->nodeContainsGroup($line); - if ($group) { - $this->addGroup($line, $group); - $line = $this->stripGroup ($line, $group); - } - - if ($this->startsMappedSequence($line)) - return $this->returnMappedSequence($line); - - if ($this->startsMappedValue($line)) - return $this->returnMappedValue($line); - - if ($this->isArrayElement($line)) - return $this->returnArrayElement($line); - - if ($this->isPlainArray($line)) - return $this->returnPlainArray($line); - - - return $this->returnKeyValuePair($line); - - } - - /** - * Finds the type of the passed value, returns the value as the new type. - * @access private - * @param string $value - * @return mixed - */ - private function _toType($value) { - if ($value === '') return ""; - $first_character = $value[0]; - $last_character = substr($value, -1, 1); - - $is_quoted = false; - do { - if (!$value) break; - if ($first_character != '"' && $first_character != "'") break; - if ($last_character != '"' && $last_character != "'") break; - $is_quoted = true; - } while (0); - - if ($is_quoted) { - $value = str_replace('\n', "\n", $value); - return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\'')); - } else { - if ((string)(int)$value === (string)$value) { - return(int) $value; - } - } - - if (strpos($value, ' #') !== false && !$is_quoted) - $value = preg_replace('/\s+#(.+)$/','',$value); - - if ($first_character == '[' && $last_character == ']') { - // Take out strings sequences and mappings - $innerValue = trim(substr ($value, 1, -1)); - if ($innerValue === '') return array(); - $explode = $this->_inlineEscape($innerValue); - // Propagate value array - $value = array(); - foreach ($explode as $v) { - $value[] = $this->_toType($v); - } - return $value; - } - - if (strpos($value,': ')!==false && $first_character != '{') { - $array = explode(': ',$value); - $key = trim($array[0]); - array_shift($array); - $value = trim(implode(': ',$array)); - $value = $this->_toType($value); - return array($key => $value); - } - - if ($first_character == '{' && $last_character == '}') { - $innerValue = trim(substr ($value, 1, -1)); - if ($innerValue === '') return array(); - // Inline Mapping - // Take out strings sequences and mappings - $explode = $this->_inlineEscape($innerValue); - // Propagate value array - $array = array(); - foreach ($explode as $v) { - $SubArr = $this->_toType($v); - if (empty($SubArr)) continue; - if (is_array ($SubArr)) { - $array[key($SubArr)] = $SubArr[key($SubArr)]; continue; - } - $array[] = $SubArr; - } - return $array; - } - - if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { - return null; - } - - if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){ - $intvalue = (int)$value; - if ($intvalue != PHP_INT_MAX) - $value = $intvalue; - return $value; - } - - if (is_numeric($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) { - // Hexadecimal value. - return hexdec($value); - } - - $this->coerceValue($value); - - if (is_numeric($value)) { - if ($value === '0') return 0; - if (rtrim ($value, 0) === $value) - $value = (float)$value; - return $value; - } - - return $value; - } - - /** - * Used in inlines to check for more inlines or quoted strings - * @access private - * @return array - */ - private function _inlineEscape($inline) { - // There's gotta be a cleaner way to do this... - // While pure sequences seem to be nesting just fine, - // pure mappings and mappings with sequences inside can't go very - // deep. This needs to be fixed. - - $seqs = array(); - $maps = array(); - $saved_strings = array(); - $saved_empties = array(); - - // Check for empty strings - $regex = '/("")|(\'\')/'; - if (preg_match_all($regex,$inline,$strings)) { - $saved_empties = $strings[0]; - $inline = preg_replace($regex,'YAMLEmpty',$inline); - } - unset($regex); - - // Check for strings - $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; - if (preg_match_all($regex,$inline,$strings)) { - $saved_strings = $strings[0]; - $inline = preg_replace($regex,'YAMLString',$inline); - } - unset($regex); - - // echo $inline; - - $i = 0; - do { - - // Check for sequences - while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) { - $seqs[] = $matchseqs[0]; - $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); - } - - // Check for mappings - while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) { - $maps[] = $matchmaps[0]; - $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); - } - - if ($i++ >= 10) break; - - } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false); - - $explode = explode(',',$inline); - $explode = array_map('trim', $explode); - $stringi = 0; $i = 0; - - while (1) { - - // Re-add the sequences - if (!empty($seqs)) { - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLSeq') !== false) { - foreach ($seqs as $seqk => $seq) { - $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value); - $value = $explode[$key]; - } - } - } - } - - // Re-add the mappings - if (!empty($maps)) { - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLMap') !== false) { - foreach ($maps as $mapk => $map) { - $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); - $value = $explode[$key]; - } - } - } - } - - - // Re-add the strings - if (!empty($saved_strings)) { - foreach ($explode as $key => $value) { - while (strpos($value,'YAMLString') !== false) { - $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1); - unset($saved_strings[$stringi]); - ++$stringi; - $value = $explode[$key]; - } - } - } - - - // Re-add the empties - if (!empty($saved_empties)) { - foreach ($explode as $key => $value) { - while (strpos($value,'YAMLEmpty') !== false) { - $explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1); - $value = $explode[$key]; - } - } - } - - $finished = true; - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLSeq') !== false) { - $finished = false; break; - } - if (strpos($value,'YAMLMap') !== false) { - $finished = false; break; - } - if (strpos($value,'YAMLString') !== false) { - $finished = false; break; - } - if (strpos($value,'YAMLEmpty') !== false) { - $finished = false; break; - } - } - if ($finished) break; - - $i++; - if ($i > 10) - break; // Prevent infinite loops. - } - - - return $explode; - } - - private function literalBlockContinues ($line, $lineIndent) { - if (!trim($line)) return true; - if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true; - return false; - } - - private function referenceContentsByAlias ($alias) { - do { - if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; } - $groupPath = $this->SavedGroups[$alias]; - $value = $this->result; - foreach ($groupPath as $k) { - $value = $value[$k]; - } - } while (false); - return $value; - } - - private function addArrayInline ($array, $indent) { - $CommonGroupPath = $this->path; - if (empty ($array)) return false; - - foreach ($array as $k => $_) { - $this->addArray(array($k => $_), $indent); - $this->path = $CommonGroupPath; - } - return true; - } - - private function addArray ($incoming_data, $incoming_indent) { - - // print_r ($incoming_data); - - if (count ($incoming_data) > 1) - return $this->addArrayInline ($incoming_data, $incoming_indent); - - $key = key ($incoming_data); - $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; - if ($key === '__!YAMLZero') $key = '0'; - - if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. - if ($key || $key === '' || $key === '0') { - $this->result[$key] = $value; - } else { - $this->result[] = $value; end ($this->result); $key = key ($this->result); - } - $this->path[$incoming_indent] = $key; - return; - } - - - - $history = array(); - // Unfolding inner array tree. - $history[] = $_arr = $this->result; - foreach ($this->path as $k) { - $history[] = $_arr = $_arr[$k]; - } - - if ($this->_containsGroupAlias) { - $value = $this->referenceContentsByAlias($this->_containsGroupAlias); - $this->_containsGroupAlias = false; - } - - - // Adding string or numeric key to the innermost level or $this->arr. - if (is_string($key) && $key == '<<') { - if (!is_array ($_arr)) { $_arr = array (); } - - $_arr = array_merge ($_arr, $value); - } else if ($key || $key === '' || $key === '0') { - if (!is_array ($_arr)) - $_arr = array ($key=>$value); - else - $_arr[$key] = $value; - } else { - if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; } - else { $_arr[] = $value; end ($_arr); $key = key ($_arr); } - } - - $reverse_path = array_reverse($this->path); - $reverse_history = array_reverse ($history); - $reverse_history[0] = $_arr; - $cnt = count($reverse_history) - 1; - for ($i = 0; $i < $cnt; $i++) { - $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; - } - $this->result = $reverse_history[$cnt]; - - $this->path[$incoming_indent] = $key; - - if ($this->_containsGroupAnchor) { - $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; - if (is_array ($value)) { - $k = key ($value); - if (!is_int ($k)) { - $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; - } - } - $this->_containsGroupAnchor = false; - } - - } - - private static function startsLiteralBlock ($line) { - $lastChar = substr (trim($line), -1); - if ($lastChar != '>' && $lastChar != '|') return false; - if ($lastChar == '|') return $lastChar; - // HTML tags should not be counted as literal blocks. - if (preg_match ('#<.*?>$#', $line)) return false; - return $lastChar; - } - - private static function greedilyNeedNextLine($line) { - $line = trim ($line); - if (!strlen($line)) return false; - if (substr ($line, -1, 1) == ']') return false; - if ($line[0] == '[') return true; - if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true; - return false; - } - - private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) { - $line = self::stripIndent($line, $indent); - if ($literalBlockStyle !== '|') { - $line = self::stripIndent($line); - } - $line = rtrim ($line, "\r\n\t ") . "\n"; - if ($literalBlockStyle == '|') { - return $literalBlock . $line; - } - if (strlen($line) == 0) - return rtrim($literalBlock, ' ') . "\n"; - if ($line == "\n" && $literalBlockStyle == '>') { - return rtrim ($literalBlock, " \t") . "\n"; - } - if ($line != "\n") - $line = trim ($line, "\r\n ") . " "; - return $literalBlock . $line; - } - - function revertLiteralPlaceHolder ($lineArray, $literalBlock) { - foreach ($lineArray as $k => $_) { - if (is_array($_)) - $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock); - else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) - $lineArray[$k] = rtrim ($literalBlock, " \r\n"); - } - return $lineArray; - } - - private static function stripIndent ($line, $indent = -1) { - if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line)); - return substr ($line, $indent); - } - - private function getParentPathByIndent ($indent) { - if ($indent == 0) return array(); - $linePath = $this->path; - do { - end($linePath); $lastIndentInParentPath = key($linePath); - if ($indent <= $lastIndentInParentPath) array_pop ($linePath); - } while ($indent <= $lastIndentInParentPath); - return $linePath; - } - - - private function clearBiggerPathValues ($indent) { - - - if ($indent == 0) $this->path = array(); - if (empty ($this->path)) return true; - - foreach ($this->path as $k => $_) { - if ($k > $indent) unset ($this->path[$k]); - } - - return true; - } - - - private static function isComment ($line) { - if (!$line) return false; - if ($line[0] == '#') return true; - if (trim($line, " \r\n\t") == '---') return true; - return false; - } - - private static function isEmpty ($line) { - return (trim ($line) === ''); - } - - - private function isArrayElement ($line) { - if (!$line || !is_scalar($line)) return false; - if (substr($line, 0, 2) != '- ') return false; - if (strlen ($line) > 3) - if (substr($line,0,3) == '---') return false; - - return true; - } - - private function isHashElement ($line) { - return strpos($line, ':'); - } - - private function isLiteral ($line) { - if ($this->isArrayElement($line)) return false; - if ($this->isHashElement($line)) return false; - return true; - } - - - private static function unquote ($value) { - if (!$value) return $value; - if (!is_string($value)) return $value; - if ($value[0] == '\'') return trim ($value, '\''); - if ($value[0] == '"') return trim ($value, '"'); - return $value; - } - - private function startsMappedSequence ($line) { - return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':'); - } - - private function returnMappedSequence ($line) { - $array = array(); - $key = self::unquote(trim(substr($line,1,-1))); - $array[$key] = array(); - $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key); - return array($array); - } - - private function checkKeysInValue($value) { - if (strchr('[{"\'', $value[0]) === false) { - if (strchr($value, ': ') !== false) { - throw new Exception('Too many keys: '.$value); - } - } - } - - private function returnMappedValue ($line) { - $this->checkKeysInValue($line); - $array = array(); - $key = self::unquote (trim(substr($line,0,-1))); - $array[$key] = ''; - return $array; - } - - private function startsMappedValue ($line) { - return (substr ($line, -1, 1) == ':'); - } - - private function isPlainArray ($line) { - return ($line[0] == '[' && substr ($line, -1, 1) == ']'); - } - - private function returnPlainArray ($line) { - return $this->_toType($line); - } - - private function returnKeyValuePair ($line) { - $array = array(); - $key = ''; - if (strpos ($line, ': ')) { - // It's a key/value pair most likely - // If the key is in double quotes pull it out - if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { - $value = trim(str_replace($matches[1],'',$line)); - $key = $matches[2]; - } else { - // Do some guesswork as to the key and the value - $explode = explode(': ', $line); - $key = trim(array_shift($explode)); - $value = trim(implode(': ', $explode)); - $this->checkKeysInValue($value); - } - // Set the type of the value. Int, string, etc - $value = $this->_toType($value); - if ($key === '0') $key = '__!YAMLZero'; - $array[$key] = $value; - } else { - if ((string)(int)$line === (string)$line) { - $array = array((int)$line); - } else { - $array = array ($line); - } - } - return $array; - - } - - - private function returnArrayElement ($line) { - if (strlen($line) <= 1) return array(array()); // Weird %) - $array = array(); - $value = trim(substr($line,1)); - $value = $this->_toType($value); - if ($this->isArrayElement($value)) { - $value = $this->returnArrayElement($value); - } - $array[] = $value; - return $array; - } - - - private function nodeContainsGroup ($line) { - $symbolsForReference = 'A-z0-9_\-'; - if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-) - if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; - if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; - if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1]; - if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1]; - if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1]; - return false; - - } - - private function addGroup ($line, $group) { - if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1); - if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1); - //print_r ($this->path); - } - - private function stripGroup ($line, $group) { - $line = trim(str_replace($group, '', $line)); - return $line; - } -} - -// Enable use of Spyc from command line -// The syntax is the following: php Spyc.php spyc.yaml - -do { - if (PHP_SAPI != 'cli') break; - if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break; - if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break; - $file = $argv[1]; - echo json_encode (spyc_load_file ($file)); -} while (0); diff --git a/composer.json b/composer.json index cd6f36cdd..d10f0c37d 100755 --- a/composer.json +++ b/composer.json @@ -41,7 +41,8 @@ "ext-json": "*", "ext-pdo": "*", "ext-zip": "*", - "typo3/cms-core": "^11.5 || ^12.4" + "typo3/cms-core": "^11.5 || ^12.4", + "symfony/yaml": "^v5.4 || ^v6.3" }, "require-dev": { "symfony/polyfill-php80": "^1.24", From e0cca8abfd5ff70b7fab2009cec6f8708abed719 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 6 Nov 2023 14:28:54 +0100 Subject: [PATCH 016/113] [BUGFIX] Reduce resolver meta info to required keys class and args --- Classes/Component/Core/Resolver/AbstractResolver.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Classes/Component/Core/Resolver/AbstractResolver.php b/Classes/Component/Core/Resolver/AbstractResolver.php index 790ba5fe2..79f573328 100644 --- a/Classes/Component/Core/Resolver/AbstractResolver.php +++ b/Classes/Component/Core/Resolver/AbstractResolver.php @@ -23,7 +23,11 @@ public function __construct() && $frame['object'] instanceof AbstractProcessor && 'buildResolver' === $frame['function'] ) { - $this->metaInfo['builtBy'] = $frame; + $this->metaInfo['builtBy'] = [ + 'class' => $frame['class'], + 'args' => $frame['args'], + ]; + break; } } } From 68d933ff9127bc54b161ec4521bb32daa28cb8a1 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 6 Nov 2023 14:29:06 +0100 Subject: [PATCH 017/113] [CLEANUP] Remove unused import/empty line --- .../MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php | 1 - Classes/Service/ForeignSiteFinder.php | 1 - 2 files changed, 2 deletions(-) diff --git a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php index d1a800f75..d050f5162 100644 --- a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php +++ b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php @@ -19,7 +19,6 @@ use function array_column; use function array_sum; use function date; -use function sort; use function str_replace; use function str_starts_with; use function uniqid; diff --git a/Classes/Service/ForeignSiteFinder.php b/Classes/Service/ForeignSiteFinder.php index b2680bebf..ac381598c 100644 --- a/Classes/Service/ForeignSiteFinder.php +++ b/Classes/Service/ForeignSiteFinder.php @@ -29,7 +29,6 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use Closure; use In2code\In2publishCore\Cache\CachedRuntimeCacheInjection; use In2code\In2publishCore\Command\Foreign\Status\AllSitesCommand; use In2code\In2publishCore\Command\Foreign\Status\SiteConfigurationCommand; From 470682d4079484510699b2f8c8e58bc9448ecaa5 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 6 Nov 2023 15:59:41 +0100 Subject: [PATCH 018/113] [FEATURE] Cache the TcaPreProcessing result Caching the result is x40 times faster than rebuilding it every time. --- ...CachedTcaPreProcessingServiceInjection.php | 22 +++++++ .../CachedTcaPreprocessingService.php | 62 +++++++++++++++++++ .../PreProcessing/TcaPreProcessingService.php | 12 ++-- .../Core/Resolver/AbstractResolver.php | 2 +- .../Component/Core/Resolver/FlexResolver.php | 26 ++++++++ .../Core/Resolver/SelectMmResolver.php | 22 +++++++ .../Core/Resolver/SelectResolver.php | 19 ++++++ .../Component/Core/Resolver/TextResolver.php | 18 ++++++ .../Core/Service/ResolverService.php | 6 +- .../AdminTools/Controller/TcaController.php | 8 +-- .../Exporter/TcaExporter.php | 8 +-- Classes/Service/ReplaceMarkersService.php | 7 --- Configuration/Services.yaml | 4 +- 13 files changed, 190 insertions(+), 26 deletions(-) create mode 100644 Classes/Component/Core/PreProcessing/CachedTcaPreProcessingServiceInjection.php create mode 100644 Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php diff --git a/Classes/Component/Core/PreProcessing/CachedTcaPreProcessingServiceInjection.php b/Classes/Component/Core/PreProcessing/CachedTcaPreProcessingServiceInjection.php new file mode 100644 index 000000000..b555cb407 --- /dev/null +++ b/Classes/Component/Core/PreProcessing/CachedTcaPreProcessingServiceInjection.php @@ -0,0 +1,22 @@ +cachedTcaPreProcessingService = $cachedTcaPreprocessingService; + } +} diff --git a/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php b/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php new file mode 100644 index 000000000..97dbf96db --- /dev/null +++ b/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php @@ -0,0 +1,62 @@ + + */ + protected array $compatibleTca; + /** + * Stores the part of the TCA that can not be used for relation resolving including reasons + * + * @var array[] + */ + protected array $incompatibleTca; + + public function getIncompatibleTcaParts(): array + { + $this->initialize(); + return $this->incompatibleTca; + } + + public function getCompatibleTcaParts(): array + { + $this->initialize(); + return $this->compatibleTca; + } + + protected function initialize(): void + { + if (isset($this->compatibleTca, $this->incompatibleTca)) { + return; + } + + if ($this->cache->has('tca_preprocessing_results')) { + $cacheEntry = $this->cache->get('tca_preprocessing_results'); + $this->compatibleTca = $cacheEntry['compatibleTca']; + $this->incompatibleTca = $cacheEntry['incompatibleTca']; + return; + } + + $tcaPreProcessingService = GeneralUtility::makeInstance(TcaPreProcessingService::class); + $this->compatibleTca = $tcaPreProcessingService->getCompatibleTcaParts(); + $this->incompatibleTca = $tcaPreProcessingService->getIncompatibleTcaParts(); + + $cacheEntry = [ + 'compatibleTca' => $this->compatibleTca, + 'incompatibleTca' => $this->incompatibleTca, + ]; + $this->cache->set('tca_preprocessing_results', $cacheEntry); + } +} diff --git a/Classes/Component/Core/PreProcessing/TcaPreProcessingService.php b/Classes/Component/Core/PreProcessing/TcaPreProcessingService.php index 955aa1295..24225ecb2 100644 --- a/Classes/Component/Core/PreProcessing/TcaPreProcessingService.php +++ b/Classes/Component/Core/PreProcessing/TcaPreProcessingService.php @@ -49,23 +49,23 @@ protected function getProcessor(string $type, string $table, string $column): ?T public function getIncompatibleTcaParts(): array { - if (!$this->initialized) { - $this->initialize(); - } + $this->initialize(); return $this->incompatibleTca; } public function getCompatibleTcaParts(): array { - if (!$this->initialized) { - $this->initialize(); - } + $this->initialize(); return $this->compatibleTca; } public function initialize(): void { + if ($this->initialized) { + return; + } + $this->initialized = true; $tables = $this->excludedTablesService->getAllNonExcludedTcaTables(); diff --git a/Classes/Component/Core/Resolver/AbstractResolver.php b/Classes/Component/Core/Resolver/AbstractResolver.php index 79f573328..447203827 100644 --- a/Classes/Component/Core/Resolver/AbstractResolver.php +++ b/Classes/Component/Core/Resolver/AbstractResolver.php @@ -11,7 +11,7 @@ abstract class AbstractResolver implements Resolver { - private array $metaInfo = []; + protected array $metaInfo = []; public function __construct() { diff --git a/Classes/Component/Core/Resolver/FlexResolver.php b/Classes/Component/Core/Resolver/FlexResolver.php index ea22fd276..db1fa8db9 100644 --- a/Classes/Component/Core/Resolver/FlexResolver.php +++ b/Classes/Component/Core/Resolver/FlexResolver.php @@ -8,10 +8,15 @@ use In2code\In2publishCore\CommonInjection\FlexFormToolsInjection; use In2code\In2publishCore\Component\Core\Demand\Demands; use In2code\In2publishCore\Component\Core\Demand\ResolverServiceInjection; +use In2code\In2publishCore\Component\Core\PreProcessing\Service\FlexFormFlatteningService; use In2code\In2publishCore\Component\Core\PreProcessing\Service\FlexFormFlatteningServiceInjection; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseEntityRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Component\Core\Record\Model\VirtualFlexFormRecord; +use In2code\In2publishCore\Component\Core\Service\ResolverService; +use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools; +use TYPO3\CMS\Core\Service\FlexFormService; +use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_keys; use function array_merge; @@ -137,4 +142,25 @@ protected function convertAndFlattenFlexFormData($data, $record): array } return $data; } + + public function __serialize(): array + { + return [ + 'metaInfo' => $this->metaInfo, + 'table' => $this->table, + 'column' => $this->column, + 'processedTca' => $this->processedTca, + ]; + } + + public function __unserialize(array $data): void + { + $this->metaInfo = $data['metaInfo']; + unset($data['metaInfo']); + $this->configure(...$data); + $this->injectResolverService(GeneralUtility::makeInstance(ResolverService::class)); + $this->injectFlexFormFlatteningService(GeneralUtility::makeInstance(FlexFormFlatteningService::class)); + $this->injectFlexFormService(GeneralUtility::makeInstance(FlexFormService::class)); + $this->injectFlexFormTools(GeneralUtility::makeInstance(FlexFormTools::class)); + } } diff --git a/Classes/Component/Core/Resolver/SelectMmResolver.php b/Classes/Component/Core/Resolver/SelectMmResolver.php index e53648931..fa2ad20a8 100644 --- a/Classes/Component/Core/Resolver/SelectMmResolver.php +++ b/Classes/Component/Core/Resolver/SelectMmResolver.php @@ -8,7 +8,9 @@ use In2code\In2publishCore\Component\Core\Demand\Type\JoinDemand; use In2code\In2publishCore\Component\Core\PreProcessing\PreProcessor\AbstractProcessor; use In2code\In2publishCore\Component\Core\Record\Model\Record; +use In2code\In2publishCore\Service\ReplaceMarkersService; use In2code\In2publishCore\Service\ReplaceMarkersServiceInject; +use TYPO3\CMS\Core\Utility\GeneralUtility; use function preg_match; @@ -64,4 +66,24 @@ public function resolve(Demands $demands, Record $record): void ); $demands->addDemand($demand); } + + public function __serialize(): array + { + return [ + 'metaInfo' => $this->metaInfo, + 'foreignTableWhere' => $this->foreignTableWhere, + 'column' => $this->column, + 'mmTable' => $this->mmTable, + 'foreignTable' => $this->foreignTable, + 'selectField' => $this->selectField, + ]; + } + + public function __unserialize(array $data): void + { + $this->metaInfo = $data['metaInfo']; + unset($data['metaInfo']); + $this->configure(...$data); + $this->injectReplaceMarkersService(GeneralUtility::makeInstance(ReplaceMarkersService::class)); + } } diff --git a/Classes/Component/Core/Resolver/SelectResolver.php b/Classes/Component/Core/Resolver/SelectResolver.php index c2eb4a090..b503231b0 100644 --- a/Classes/Component/Core/Resolver/SelectResolver.php +++ b/Classes/Component/Core/Resolver/SelectResolver.php @@ -8,6 +8,7 @@ use In2code\In2publishCore\Component\Core\Demand\Type\SelectDemand; use In2code\In2publishCore\Component\Core\PreProcessing\PreProcessor\AbstractProcessor; use In2code\In2publishCore\Component\Core\Record\Model\Record; +use In2code\In2publishCore\Service\ReplaceMarkersService; use In2code\In2publishCore\Service\ReplaceMarkersServiceInject; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -60,4 +61,22 @@ public function resolve(Demands $demands, Record $record): void $demands->addDemand(new SelectDemand($this->foreignTable, $additionalWhere, 'uid', $splitValue, $record)); } } + + public function __serialize(): array + { + return [ + 'metaInfo' => $this->metaInfo, + 'column' => $this->column, + 'foreignTable' => $this->foreignTable, + 'foreignTableWhere' => $this->foreignTableWhere, + ]; + } + + public function __unserialize(array $data): void + { + $this->metaInfo = $data['metaInfo']; + unset($data['metaInfo']); + $this->configure(...$data); + $this->injectReplaceMarkersService(GeneralUtility::makeInstance(ReplaceMarkersService::class)); + } } diff --git a/Classes/Component/Core/Resolver/TextResolver.php b/Classes/Component/Core/Resolver/TextResolver.php index 944bd6b84..26e14ecf6 100644 --- a/Classes/Component/Core/Resolver/TextResolver.php +++ b/Classes/Component/Core/Resolver/TextResolver.php @@ -9,6 +9,8 @@ use In2code\In2publishCore\Component\Core\Demand\Type\SelectDemand; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Event\DemandsForTextWereCollected; +use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; +use TYPO3\CMS\Core\Utility\GeneralUtility; use function htmlspecialchars_decode; use function parse_str; @@ -69,4 +71,20 @@ protected function findRelationsInText(Demands $demands, string $text, Record $r $this->eventDispatcher->dispatch(new DemandsForTextWereCollected($demands, $record, $text)); } + + public function __serialize(): array + { + return [ + 'metaInfo' => $this->metaInfo, + 'column' => $this->column, + ]; + } + + public function __unserialize(array $data): void + { + $this->metaInfo = $data['metaInfo']; + unset($data['metaInfo']); + $this->configure(...$data); + $this->injectEventDispatcher(GeneralUtility::makeInstance(EventDispatcher::class)); + } } diff --git a/Classes/Component/Core/Service/ResolverService.php b/Classes/Component/Core/Service/ResolverService.php index cb9475031..5d4383e70 100644 --- a/Classes/Component/Core/Service/ResolverService.php +++ b/Classes/Component/Core/Service/ResolverService.php @@ -4,13 +4,13 @@ namespace In2code\In2publishCore\Component\Core\Service; -use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessingServiceInjection; +use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection; use In2code\In2publishCore\Component\Core\Resolver\Resolver; class ResolverService { use RelevantTablesServiceInjection; - use TcaPreProcessingServiceInjection; + use CachedTcaPreProcessingServiceInjection; /** * @var array> @@ -19,7 +19,7 @@ class ResolverService public function initializeObject(): void { - $compatibleTcaParts = $this->tcaPreProcessingService->getCompatibleTcaParts(); + $compatibleTcaParts = $this->cachedTcaPreProcessingService->getCompatibleTcaParts(); foreach ($compatibleTcaParts as $table => $properties) { foreach ($properties as $property => $array) { /** @var Resolver $resolver */ diff --git a/Classes/Features/AdminTools/Controller/TcaController.php b/Classes/Features/AdminTools/Controller/TcaController.php index 4aa8411f7..343c03073 100644 --- a/Classes/Features/AdminTools/Controller/TcaController.php +++ b/Classes/Features/AdminTools/Controller/TcaController.php @@ -29,7 +29,7 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessingServiceInjection; +use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection; use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; @@ -37,12 +37,12 @@ class TcaController extends ActionController { use AdminToolsModuleTemplate; - use TcaPreProcessingServiceInjection; + use CachedTcaPreProcessingServiceInjection; public function indexAction(): ResponseInterface { - $this->view->assign('incompatibleTca', $this->tcaPreProcessingService->getIncompatibleTcaParts()); - $this->view->assign('compatibleTca', $this->tcaPreProcessingService->getCompatibleTcaParts()); + $this->view->assign('incompatibleTca', $this->cachedTcaPreProcessingService->getIncompatibleTcaParts()); + $this->view->assign('compatibleTca', $this->cachedTcaPreProcessingService->getCompatibleTcaParts()); return $this->htmlResponse(); } diff --git a/Classes/Features/SystemInformationExport/Exporter/TcaExporter.php b/Classes/Features/SystemInformationExport/Exporter/TcaExporter.php index 5b72cc829..b71fe77ea 100644 --- a/Classes/Features/SystemInformationExport/Exporter/TcaExporter.php +++ b/Classes/Features/SystemInformationExport/Exporter/TcaExporter.php @@ -29,7 +29,7 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessingServiceInjection; +use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection; use ReflectionObject; use function get_class; @@ -38,7 +38,7 @@ class TcaExporter implements SystemInformationExporter { - use TcaPreProcessingServiceInjection; + use CachedTcaPreProcessingServiceInjection; public function getUniqueKey(): string { @@ -47,11 +47,11 @@ public function getUniqueKey(): string public function getInformation(): array { - $compatibleTcaParts = $this->tcaPreProcessingService->getCompatibleTcaParts(); + $compatibleTcaParts = $this->cachedTcaPreProcessingService->getCompatibleTcaParts(); return [ 'full' => $GLOBALS['TCA'], 'compatible' => $this->stripObjectsFromArray($compatibleTcaParts), - 'incompatible' => $this->tcaPreProcessingService->getIncompatibleTcaParts(), + 'incompatible' => $this->cachedTcaPreProcessingService->getIncompatibleTcaParts(), ]; } diff --git a/Classes/Service/ReplaceMarkersService.php b/Classes/Service/ReplaceMarkersService.php index db40ae78f..c55c3c283 100755 --- a/Classes/Service/ReplaceMarkersService.php +++ b/Classes/Service/ReplaceMarkersService.php @@ -33,7 +33,6 @@ use In2code\In2publishCore\CommonInjection\FlexFormToolsInjection; use In2code\In2publishCore\CommonInjection\LocalDatabaseInjection; use In2code\In2publishCore\CommonInjection\SiteFinderInjection; -use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessingService; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseEntityRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Component\Core\Record\Model\VirtualFlexFormRecord; @@ -71,12 +70,6 @@ class ReplaceMarkersService implements LoggerAwareInterface // Also replace optional quotes around the REC_FIELD_ because we will quote the actual value protected const REC_FIELD_REGEX = '~\'?###REC_FIELD_(.*?)###\'?~'; protected const SITE_FIELD_REGEX = '(###SITE:([^#]+)###)'; - protected TcaPreProcessingService $tcaPreProcessingService; - - public function injectTcaPreProcessingService(TcaPreProcessingService $tcaPreProcessingService): void - { - $this->tcaPreProcessingService = $tcaPreProcessingService; - } /** * replaces ###MARKER### where possible. It's missing diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index cf54abfc4..ee3c5781b 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -60,7 +60,6 @@ services: In2code\In2publishCore\Domain\Service\ForeignSiteFinder: arguments: [ '@cache.in2publish_core' ] - In2code\In2publishCore\Testing\Tests\SshConnection\SshFunctionAvailabilityTest: tags: - name: 'in2publish_core.adapter.ssh.remote_adapter_test' @@ -74,3 +73,6 @@ services: In2code\In2publishCore\Testing\Tests\SshConnection\SftpRequirementsTest: tags: - name: 'in2publish_core.adapter.ssh.transmission_adapter_test' + + In2code\In2publishCore\Service\ReplaceMarkersService: + public: true From 0680482a4f9f5efebb56901edb959158d55796c5 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 11:38:41 +0100 Subject: [PATCH 019/113] [BUGFIX] Handle constructor differences in PublishItemProvider between t3v11 and t3v12 --- .../ContextMenu/PublishItemProvider.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php index 036a9cb60..59b5bb7d0 100644 --- a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php +++ b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php @@ -35,8 +35,12 @@ use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; +use function func_get_args; +use function version_compare; + class PublishItemProvider extends AbstractProvider { protected $itemsConfiguration = [ @@ -48,9 +52,13 @@ class PublishItemProvider extends AbstractProvider ]; protected PermissionService $permissionService; - public function __construct(string $table, string $identifier, string $context = '') + public function __construct() { - parent::__construct($table, $identifier, $context); + $typo3Version = new Typo3Version(); + if (version_compare($typo3Version->getVersion(), '12', '<')) { + parent::__construct(...func_get_args()); + } + // Sorry, no DI available for Context Menu Item Provider $this->permissionService = GeneralUtility::makeInstance(PermissionService::class); } From f30ee7f06e36535c9c94c9a76d61c0470e48b5b0 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 11:41:54 +0100 Subject: [PATCH 020/113] [BUGFIX] Set correct narrowed return type hint for ConnectionFactory --- Classes/Factory/ConnectionFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Factory/ConnectionFactory.php b/Classes/Factory/ConnectionFactory.php index dc70dbdd9..7943e3a7e 100644 --- a/Classes/Factory/ConnectionFactory.php +++ b/Classes/Factory/ConnectionFactory.php @@ -29,7 +29,7 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use Doctrine\DBAL\Driver\Connection; +use TYPO3\CMS\Core\Database\Connection; use In2code\In2publishCore\Factory\Exception\ConnectionUnavailableException; use In2code\In2publishCore\Service\Context\ContextServiceInjection; use In2code\In2publishCore\Utility\DatabaseUtility; From 67cb4906a3046c4f25c61dca4235df5beb1cdd42 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Mon, 6 Nov 2023 08:32:37 +0100 Subject: [PATCH 021/113] [TASK] Remove deprecated TYPO3 constants see: https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.0/Deprecation-92947-DeprecateTYPO3_MODEAndTYPO3_REQUESTTYPEConstants.html --- ext_tables.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext_tables.php b/ext_tables.php index 918894a26..c8c8bb599 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -43,10 +43,6 @@ // Early return when installing per ZIP: autoload is not yet generated return; } - if (!(TYPO3_REQUESTTYPE & (TYPO3_REQUESTTYPE_BE | TYPO3_REQUESTTYPE_CLI))) { - // Do nothing when not in any of the desirable modes. - return; - } /**************************************************** Instances ***************************************************/ $configContainer = GeneralUtility::makeInstance(ConfigContainer::class); From f67aac4c38104f9bafd4518ab5aefb7aad82a032 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 12:17:36 +0100 Subject: [PATCH 022/113] [BUGFIX] Replace deprecated EventManager::getListeners with getAllListeners --- Classes/Utility/DatabaseUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Utility/DatabaseUtility.php b/Classes/Utility/DatabaseUtility.php index 2e5374ad4..be1aa0a5b 100755 --- a/Classes/Utility/DatabaseUtility.php +++ b/Classes/Utility/DatabaseUtility.php @@ -95,7 +95,7 @@ public static function buildForeignDatabaseConnection(): ?Connection try { $foreignConnection = $connectionPool->getConnectionByName('in2publish_foreign'); - foreach ($foreignConnection->getEventManager()->getListeners() as $event => $listeners) { + foreach ($foreignConnection->getEventManager()->getAllListeners() as $event => $listeners) { foreach ($listeners as $listener) { $foreignConnection->getEventManager()->removeEventListener($event, $listener); } From 60a74a69de94b10d354f81df1ebe5efbb0cd1186 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 12:19:47 +0100 Subject: [PATCH 023/113] [BUGFIX] Do not register the BackendRouteInitialization XCLASS in TYPO3 v12 --- ext_localconf.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ext_localconf.php b/ext_localconf.php index 9032cc3bf..d870e3d4d 100755 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -8,6 +8,7 @@ use In2code\In2publishCore\Service\Context\ContextService; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Log\LogLevel; use TYPO3\CMS\Core\Log\Writer\DatabaseWriter; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -27,9 +28,12 @@ /************************************************* Patching TYPO3 *************************************************/ // Issue: https://forge.typo3.org/issues/95962 // Patch: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72160 - $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Backend\Middleware\BackendRouteInitialization::class] = [ - 'className' => BackendRouteInitialization::class, - ]; + $typo3Version = new Typo3Version(); + if (version_compare($typo3Version->getVersion(), '12', '<')) { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Backend\Middleware\BackendRouteInitialization::class] = [ + 'className' => BackendRouteInitialization::class, + ]; + } /************************************************ Record Extension ************************************************/ $file = Environment::getVarPath() . '/cache/code/content_publisher/record_extension_trait.php'; From c97f20adfce33537aa1ed2cb9ac0c5dd0bc5236d Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 6 Nov 2023 13:00:41 +0100 Subject: [PATCH 024/113] [REFACTOR] Changes backend module registration for m1, m3, m5 The backend modules overview, file & redirects are now registered via Configuration/Backend/Modules.php For TYPO3 v11 they are registered via the old way (ext_tables.php) The Icons are provided via Icons.php and can be retrieved from the IconFactory now. Resolves: https://projekte.in2code.de/issues/60077 --- Configuration/Backend/Modules.php | 89 +++++++++++++++++++++++ Configuration/Icons.php | 45 ++++++++++++ ext_tables.php | 115 ++++++++++++++++-------------- 3 files changed, 197 insertions(+), 52 deletions(-) create mode 100644 Configuration/Backend/Modules.php create mode 100644 Configuration/Icons.php diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php new file mode 100644 index 000000000..0ae965dbe --- /dev/null +++ b/Configuration/Backend/Modules.php @@ -0,0 +1,89 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use In2code\In2publishCore\Component\ConfigContainer\ConfigContainer; +use In2code\In2publishCore\Controller\FileController; +use In2code\In2publishCore\Controller\RecordController; +use In2code\In2publishCore\Features\RedirectsSupport\Controller\RedirectController; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +$backendModulesToRegister = []; + +/** @var ConfigContainer $configContainer */ +$configContainer = GeneralUtility::makeInstance(ConfigContainer::class); + +if ($configContainer->get('module.m1')) { + $backendModulesToRegister['in2publish_core_m1'] = [ + 'parent' => 'web', + 'position' => [], + 'access' => 'user,group', + 'workspaces' => 'live', + 'path' => '/module/in2publish_core/m1', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod1.xlf', + 'extensionName' => 'in2publish_core', + 'iconIdentifier' => 'in2publish-core-overview-module', + 'controllerActions' => [ + RecordController::class => ['index', 'detail', 'publishRecord', 'toggleFilterStatus'], + ], + ]; +} + +if ($configContainer->get('module.m3')) { + $backendModulesToRegister['in2publish_core_m3'] = [ + 'parent' => 'file', + 'position' => [], + 'access' => 'user,group', + 'workspaces' => 'live', + 'path' => '/module/in2publish_core/m3', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod3.xlf', + 'extensionName' => 'in2publish_core', + 'iconIdentifier' => 'in2publish-core-file-module', + 'controllerActions' => [ + FileController::class => ['index', 'publishFolder', 'publishFile', 'toggleFilterStatus'], + ], + ]; +} + +if ($configContainer->get('features.redirectsSupport.enable')) { + $backendModulesToRegister['in2publish_core_m5'] = [ + 'parent' => 'site', + 'position' => ['after' => 'redirects/'], + 'access' => 'user,group', + 'workspaces' => 'live', + 'path' => '/module/in2publish_core/m5', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod5.xlf', + 'extensionName' => 'in2publish_core', + 'iconIdentifier' => 'in2publish-core-redirect-module', + 'controllerActions' => [ + RedirectController::class => ['list','publish','selectSite'], + ], + ]; +} + +return $backendModulesToRegister; diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 000000000..34eb24fe5 --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,45 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider; + +return [ + 'in2publish-core-overview-module' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:in2publish_core/Resources/Public/Icons/Overview.svg', + ], + 'in2publish-core-file-module' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:in2publish_core/Resources/Public/Icons/File.svg', + ], + 'in2publish-core-redirect-module' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:in2publish_core/Resources/Public/Icons/Redirect.svg', + ], +]; diff --git a/ext_tables.php b/ext_tables.php index c8c8bb599..56105e069 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -33,6 +33,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\ExtensionUtility; +use TYPO3\CMS\Core\Information\Typo3Version; (static function (): void { /***************************************************** Guards *****************************************************/ @@ -49,6 +50,8 @@ $contextService = GeneralUtility::makeInstance(ContextService::class); $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); $isForeign = $contextService->isForeign(); + /** @var Typo3Version $versionInformation */ + $versionInformation = GeneralUtility::makeInstance(Typo3Version::class); /******************************************* Colorize the BE on Foreign *******************************************/ if ($isForeign && $configContainer->get('features.warningOnForeign.colorizeHeader.enable')) { @@ -60,40 +63,67 @@ return; } - /******************************************** Register Backend Modules ********************************************/ - if ($configContainer->get('module.m1')) { - ExtensionUtility::registerModule( - 'in2publish_core', - 'web', - 'm1', - '', - [ - RecordController::class => 'index,detail,publishRecord,toggleFilterStatus', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:in2publish_core/Resources/Public/Icons/Overview.svg', - 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod1.xlf', - ], - ); - } - if ($configContainer->get('module.m3')) { - ExtensionUtility::registerModule( - 'in2publish_core', - 'file', - 'm3', - '', - [ - FileController::class => 'index,publishFolder,publishFile,toggleFilterStatus', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:in2publish_core/Resources/Public/Icons/File.svg', - 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod3.xlf', - ], - ); + if ($versionInformation->getMajorVersion() < 12) { + /** + * Deprecated registering of Backend Modules + * Register Backend Modules for TYPO3 v11 + * can be removed in TYPO3 v13 + */ + if ($configContainer->get('module.m1')) { + ExtensionUtility::registerModule( + 'in2publish_core', + 'web', + 'm1', + '', + [ + RecordController::class => 'index,detail,publishRecord,toggleFilterStatus', + ], + [ + 'access' => 'user,group', + 'iconIdentifier' => 'in2publish-core-overview-module', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod1.xlf', + ], + ); + } + if ($configContainer->get('module.m3')) { + ExtensionUtility::registerModule( + 'in2publish_core', + 'file', + 'm3', + '', + [ + FileController::class => 'index,publishFolder,publishFile,toggleFilterStatus', + ], + [ + 'access' => 'user,group', + 'iconIdentifier' => 'in2publish-core-file-module', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod3.xlf', + ], + ); + } + /************************************************ Redirect Support ************************************************/ + if ( + $configContainer->get('features.redirectsSupport.enable') + && ExtensionManagementUtility::isLoaded('redirects') + ) { + ExtensionUtility::registerModule( + 'in2publish_core', + 'site', + 'm5', + 'after:redirects', + [ + RedirectController::class => 'list,publish,selectSite', + ], + [ + 'access' => 'user,group', + 'iconIdentifier' => 'in2publish-core-redirect-module', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod5.xlf', + ], + ); + } } + /******************************************* Context Menu Publish Entry *******************************************/ if ($configContainer->get('features.contextMenuPublishEntry.enable')) { $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1595598780] = PublishItemProvider::class; @@ -127,24 +157,5 @@ $GLOBALS['in2publish_core']['tests'][] = SiteConfigurationTest::class; $GLOBALS['in2publish_core']['tests'][] = TableGarbageCollectorTest::class; - /************************************************ Redirect Support ************************************************/ - if ( - $configContainer->get('features.redirectsSupport.enable') - && ExtensionManagementUtility::isLoaded('redirects') - ) { - ExtensionUtility::registerModule( - 'in2publish_core', - 'site', - 'm5', - 'after:redirects', - [ - RedirectController::class => 'list,publish,selectSite', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:in2publish_core/Resources/Public/Icons/Redirect.svg', - 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod5.xlf', - ], - ); - } + })(); From f2698f84d3d6074fc5b232374074c13c553bbf12 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 6 Nov 2023 14:40:47 +0100 Subject: [PATCH 025/113] [BUGFIX] Removes trailing slash in Module Configuration --- Configuration/Backend/Modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 0ae965dbe..4ef178d8d 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -73,7 +73,7 @@ if ($configContainer->get('features.redirectsSupport.enable')) { $backendModulesToRegister['in2publish_core_m5'] = [ 'parent' => 'site', - 'position' => ['after' => 'redirects/'], + 'position' => ['after' => 'redirects'], 'access' => 'user,group', 'workspaces' => 'live', 'path' => '/module/in2publish_core/m5', From 42832769427edb308f17f6badb7301cfe8e76229 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 7 Nov 2023 13:48:51 +0100 Subject: [PATCH 026/113] [REFACTOR] Change compare of version --- ext_tables.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext_tables.php b/ext_tables.php index 56105e069..a70eeb414 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -51,7 +51,7 @@ $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); $isForeign = $contextService->isForeign(); /** @var Typo3Version $versionInformation */ - $versionInformation = GeneralUtility::makeInstance(Typo3Version::class); + $typo3Version = new Typo3Version(); /******************************************* Colorize the BE on Foreign *******************************************/ if ($isForeign && $configContainer->get('features.warningOnForeign.colorizeHeader.enable')) { @@ -63,7 +63,7 @@ return; } - if ($versionInformation->getMajorVersion() < 12) { + if (version_compare($typo3Version->getVersion(), '12', '<')) { /** * Deprecated registering of Backend Modules * Register Backend Modules for TYPO3 v11 From 5d9da251536eeb7053434e65e09086b0e58eadbf Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 6 Nov 2023 14:42:55 +0100 Subject: [PATCH 027/113] [REFACTOR] Changes Icon from Tools Module to IconFactory https://projekte.in2code.de/issues/60080 --- Classes/Features/AdminTools/Service/ToolsRegistry.php | 2 +- Configuration/Icons.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php index 43e298488..9c0133c3f 100644 --- a/Classes/Features/AdminTools/Service/ToolsRegistry.php +++ b/Classes/Features/AdminTools/Service/ToolsRegistry.php @@ -125,7 +125,7 @@ public function processData(): void $controllerActions, [ 'access' => 'admin', - 'icon' => 'EXT:in2publish_core/Resources/Public/Icons/Tools.svg', + 'iconIdentifier' => 'in2publish-core-tools-module', 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf', ], ); diff --git a/Configuration/Icons.php b/Configuration/Icons.php index 34eb24fe5..b9d6edcbe 100644 --- a/Configuration/Icons.php +++ b/Configuration/Icons.php @@ -42,4 +42,8 @@ 'provider' => SvgIconProvider::class, 'source' => 'EXT:in2publish_core/Resources/Public/Icons/Redirect.svg', ], + 'in2publish-core-tools-module' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:in2publish_core/Resources/Public/Icons/Tools.svg', + ], ]; From 1d951acff144e69886bb330ca20ed913cbb88976 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 12:52:04 +0100 Subject: [PATCH 028/113] [BUGFIX] Use the objects view property instead of initializeView arguments --- Classes/Controller/Traits/CommonViewVariables.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Classes/Controller/Traits/CommonViewVariables.php b/Classes/Controller/Traits/CommonViewVariables.php index 3f5a68105..cc13e5d47 100644 --- a/Classes/Controller/Traits/CommonViewVariables.php +++ b/Classes/Controller/Traits/CommonViewVariables.php @@ -7,7 +7,6 @@ use In2code\In2publishCore\Component\ConfigContainer\ConfigContainerInjection; use In2code\In2publishCore\Service\Environment\EnvironmentServiceInjection; use In2code\In2publishCore\Service\Extension\ExtensionServiceInjection; -use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; trait CommonViewVariables { @@ -15,10 +14,10 @@ trait CommonViewVariables use EnvironmentServiceInjection; use ExtensionServiceInjection; - protected function initializeView(ViewInterface $view): void + protected function initializeView(): void { - $view->assign('extensionVersion', $this->extensionService->getExtensionVersion('in2publish_core')); - $view->assign('config', $this->configContainer->get()); - $view->assign('testStatus', $this->environmentService->getTestStatus()); + $this->view->assign('extensionVersion', $this->extensionService->getExtensionVersion('in2publish_core')); + $this->view->assign('config', $this->configContainer->get()); + $this->view->assign('testStatus', $this->environmentService->getTestStatus()); } } From ac4959316c90d53efcd97b307aa368951089ba2b Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 12:53:05 +0100 Subject: [PATCH 029/113] [BUGFIX] Use withRequest to alter immutable request objects --- Classes/Controller/RecordController.php | 2 +- .../Features/RedirectsSupport/Controller/RedirectController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index fc428c13b..cd2905096 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -117,7 +117,7 @@ public function initializeIndexAction(): void $data['pageRecursionLimit'] = $pageRecursionLimit; $BE_USER->pushModuleData('tx_in2publishcore_m1', $data); } else { - $this->request->setArgument('pageRecursionLimit', $data['pageRecursionLimit'] ?? 1); + $this->request = $this->request->withArgument('pageRecursionLimit', $data['pageRecursionLimit'] ?? 1); } $menuRegistry = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry(); diff --git a/Classes/Features/RedirectsSupport/Controller/RedirectController.php b/Classes/Features/RedirectsSupport/Controller/RedirectController.php index 4c49fed6c..0156558b0 100644 --- a/Classes/Features/RedirectsSupport/Controller/RedirectController.php +++ b/Classes/Features/RedirectsSupport/Controller/RedirectController.php @@ -112,7 +112,7 @@ public function initializeListAction(): void } else { $filter = $GLOBALS['BE_USER']->getSessionData('tx_in2publishcore_redirects_filter'); if (null !== $filter) { - $this->request->setArgument('filter', $filter); + $this->request = $this->request->withArgument('filter', $filter); } $this->arguments->getArgument('filter')->getPropertyMappingConfiguration()->allowAllProperties(); } From 58267fd40ada2e1981e84983866e0c500d172fbe Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 13:27:41 +0100 Subject: [PATCH 030/113] [BUGFIX] Implement TYPO3 version specific code to translate the label of the Publish Overview Module shortcut button --- .../Backend/Button/ModuleShortcutButton.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Classes/Backend/Button/ModuleShortcutButton.php b/Classes/Backend/Button/ModuleShortcutButton.php index ee28ee610..8282313de 100644 --- a/Classes/Backend/Button/ModuleShortcutButton.php +++ b/Classes/Backend/Button/ModuleShortcutButton.php @@ -30,12 +30,15 @@ */ use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Backend\Module\ExtbaseModule; use TYPO3\CMS\Backend\Template\Components\Buttons\Action\ShortcutButton; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Routing\Route; use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use function ucfirst; +use function version_compare; class ModuleShortcutButton extends ShortcutButton { @@ -44,9 +47,20 @@ public function setRequest(ServerRequestInterface $request): void /** @var Route $route */ $route = $request->getAttribute('route'); $arguments = $request->getQueryParams(); - $modConf = $route->getOption('moduleConfiguration'); $pageId = $request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? null; - $displayName = LocalizationUtility::translate($modConf['labels'] . ':mlang_tabs_tab'); + + $typo3Version = new Typo3Version(); + if (version_compare($typo3Version->getVersion(), '12', '<')) { + $modConf = $route->getOption('moduleConfiguration'); + $displayName = LocalizationUtility::translate($modConf['labels'] . ':mlang_tabs_tab'); + } else { + /** + * @noinspection PhpUndefinedClassInspection + * @var ExtbaseModule $module + */ + $module = $route->getOption('module'); + $displayName = LocalizationUtility::translate($module->getTitle()); + } if (null !== $pageId) { if (0 === $pageId) { From 534d9b8df71398ac9f7e4d1f8ab968c071645e7b Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 14:01:34 +0100 Subject: [PATCH 031/113] [BUGFIX] Overwrite callActionMethod instead of initializeView to prevent version issues --- Classes/Controller/Traits/CommonViewVariables.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Classes/Controller/Traits/CommonViewVariables.php b/Classes/Controller/Traits/CommonViewVariables.php index cc13e5d47..81e95c1ce 100644 --- a/Classes/Controller/Traits/CommonViewVariables.php +++ b/Classes/Controller/Traits/CommonViewVariables.php @@ -7,6 +7,8 @@ use In2code\In2publishCore\Component\ConfigContainer\ConfigContainerInjection; use In2code\In2publishCore\Service\Environment\EnvironmentServiceInjection; use In2code\In2publishCore\Service\Extension\ExtensionServiceInjection; +use Psr\Http\Message\ResponseInterface; +use TYPO3\CMS\Extbase\Mvc\RequestInterface; trait CommonViewVariables { @@ -14,10 +16,11 @@ trait CommonViewVariables use EnvironmentServiceInjection; use ExtensionServiceInjection; - protected function initializeView(): void + protected function callActionMethod(RequestInterface $request): ResponseInterface { $this->view->assign('extensionVersion', $this->extensionService->getExtensionVersion('in2publish_core')); $this->view->assign('config', $this->configContainer->get()); $this->view->assign('testStatus', $this->environmentService->getTestStatus()); + return parent::callActionMethod($request); } } From b83850ba5d04b180d7e596c9002835efda141e00 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 14:06:03 +0100 Subject: [PATCH 032/113] [BUGFIX] Create a TYPO3 version aware service to replace TcaService::getTablesAllowedOnPage --- .../PageDoktypeRegistryInjection.php | 28 ++++++++ .../Core/RecordTree/RecordTreeBuilder.php | 6 +- .../Configuration/AbstractPageTypeService.php | 67 ++++++++++++++++++ .../Configuration/LegacyPageTypeService.php | 64 +++++++++++++++++ .../Configuration/PageTypeRegistryService.php | 60 ++++++++++++++++ .../Service/Configuration/PageTypeService.php | 36 ++++++++++ .../PageTypeServiceInjection.php | 21 ++++++ Classes/Service/Configuration/TcaService.php | 69 ------------------- Configuration/Services.php | 20 ++++++ .../Core/RecordTree/RecordTreeBuilderTest.php | 3 +- 10 files changed, 301 insertions(+), 73 deletions(-) create mode 100644 Classes/CommonInjection/PageDoktypeRegistryInjection.php create mode 100644 Classes/Service/Configuration/AbstractPageTypeService.php create mode 100644 Classes/Service/Configuration/LegacyPageTypeService.php create mode 100644 Classes/Service/Configuration/PageTypeRegistryService.php create mode 100644 Classes/Service/Configuration/PageTypeService.php create mode 100644 Classes/Service/Configuration/PageTypeServiceInjection.php diff --git a/Classes/CommonInjection/PageDoktypeRegistryInjection.php b/Classes/CommonInjection/PageDoktypeRegistryInjection.php new file mode 100644 index 000000000..bf6d208b8 --- /dev/null +++ b/Classes/CommonInjection/PageDoktypeRegistryInjection.php @@ -0,0 +1,28 @@ +pageDoktypeRegistry = $pageDoktypeRegistry; + } +} diff --git a/Classes/Component/Core/RecordTree/RecordTreeBuilder.php b/Classes/Component/Core/RecordTree/RecordTreeBuilder.php index 053b10c08..2ac5b6e83 100644 --- a/Classes/Component/Core/RecordTree/RecordTreeBuilder.php +++ b/Classes/Component/Core/RecordTree/RecordTreeBuilder.php @@ -16,7 +16,7 @@ use In2code\In2publishCore\Component\Core\RecordIndexInjection; use In2code\In2publishCore\Component\Core\Service\RelevantTablesServiceInjection; use In2code\In2publishCore\Event\RecordRelationsWereResolved; -use In2code\In2publishCore\Service\Configuration\TcaServiceInjection; +use In2code\In2publishCore\Service\Configuration\PageTypeServiceInjection; use In2code\In2publishCore\Service\Database\RawRecordServiceInjection; use function array_flip; @@ -33,7 +33,7 @@ class RecordTreeBuilder use DemandsFactoryInjection; use DemandResolverInjection; use DemandBuilderInjection; - use TcaServiceInjection; + use PageTypeServiceInjection; use RawRecordServiceInjection; public function buildRecordTree(RecordTreeBuildRequest $request): RecordTree @@ -155,7 +155,7 @@ public function findAllRecordsOnPages(): RecordCollection $tables = array_flip($tablesAsKeys); foreach ($pages as $page) { - $tablesAllowedOnPage = $this->tcaService->getTablesAllowedOnPage( + $tablesAllowedOnPage = $this->pageTypeService->getTablesAllowedOnPage( $page->getId(), $page->getProp('doktype'), ); diff --git a/Classes/Service/Configuration/AbstractPageTypeService.php b/Classes/Service/Configuration/AbstractPageTypeService.php new file mode 100644 index 000000000..f76ce3c04 --- /dev/null +++ b/Classes/Service/Configuration/AbstractPageTypeService.php @@ -0,0 +1,67 @@ + + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use function array_keys; + +abstract class AbstractPageTypeService implements PageTypeService +{ + protected array $rtc = []; + + /** + * Finds all tables which are allowed on either self::TYPE_ROOT or self::TYPE_PAGE according to the table's TCA + * 'rootLevel' setting. + * + * @return array + */ + protected function getAllAllowedTableNames(string $type): array + { + if (!isset($this->rtc['_types'])) { + $allowed = [ + self::TYPE_ROOT => [], + self::TYPE_PAGE => [], + ]; + foreach (array_keys($GLOBALS['TCA']) as $table) { + switch ('pages' === $table ? -1 : (int)($GLOBALS['TCA'][$table]['ctrl']['rootLevel'] ?? 0)) { + case -1: + $allowed[self::TYPE_ROOT][] = $table; + $allowed[self::TYPE_PAGE][] = $table; + break; + case 0: + $allowed[self::TYPE_PAGE][] = $table; + break; + case 1: + $allowed[self::TYPE_ROOT][] = $table; + break; + } + } + $this->rtc['_types'] = $allowed; + } + return $this->rtc['_types'][$type]; + } +} diff --git a/Classes/Service/Configuration/LegacyPageTypeService.php b/Classes/Service/Configuration/LegacyPageTypeService.php new file mode 100644 index 000000000..0b9fd231f --- /dev/null +++ b/Classes/Service/Configuration/LegacyPageTypeService.php @@ -0,0 +1,64 @@ + + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; + +use function strpos; + +class LegacyPageTypeService extends AbstractPageTypeService +{ + public function getTablesAllowedOnPage(int $pid, ?int $doktype): array + { + // The root page does not have a doktype. Just get all allowed tables. + if (0 === $pid) { + if (!isset($this->rtc[self::TYPE_ROOT])) { + $this->rtc[self::TYPE_ROOT] = $this->getAllAllowedTableNames(self::TYPE_ROOT); + } + return $this->rtc[self::TYPE_ROOT]; + } + + $type = isset($GLOBALS['PAGES_TYPES'][$doktype]['allowedTables']) ? $doktype : 'default'; + $key = self::TYPE_PAGE . '_' . $type; + + if (!isset($this->rtc[$key])) { + $allowedOnType = $this->getAllAllowedTableNames(self::TYPE_PAGE); + $allowedOnDoktype = $GLOBALS['PAGES_TYPES'][$type]['allowedTables']; + if (false === strpos($allowedOnDoktype, '*')) { + foreach ($allowedOnType as $index => $table) { + if (!GeneralUtility::inList($allowedOnDoktype, $table)) { + unset($allowedOnType[$index]); + } + } + } + + $this->rtc[$key] = $allowedOnType; + } + return $this->rtc[$key]; + } +} diff --git a/Classes/Service/Configuration/PageTypeRegistryService.php b/Classes/Service/Configuration/PageTypeRegistryService.php new file mode 100644 index 000000000..9a5164a21 --- /dev/null +++ b/Classes/Service/Configuration/PageTypeRegistryService.php @@ -0,0 +1,60 @@ + + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use In2code\In2publishCore\CommonInjection\PageDoktypeRegistryInjection; + +class PageTypeRegistryService extends AbstractPageTypeService +{ + use PageDoktypeRegistryInjection; + + public function getTablesAllowedOnPage(int $pid, ?int $doktype): array + { + // The root page does not have a doktype. Just get all allowed tables. + if (0 === $pid) { + if (!isset($this->rtc[self::TYPE_ROOT])) { + $this->rtc[self::TYPE_ROOT] = $this->getAllAllowedTableNames(self::TYPE_ROOT); + } + return $this->rtc[self::TYPE_ROOT]; + } + + $key = self::TYPE_PAGE . '_' . $doktype; + + if (!isset($this->rtc[$key])) { + $allowedOnType = $this->getAllAllowedTableNames(self::TYPE_PAGE); + foreach ($allowedOnType as $index => $table) { + if (!$this->pageDoktypeRegistry->isRecordTypeAllowedForDoktype($table, $doktype)) { + unset($allowedOnType[$index]); + } + } + + $this->rtc[$key] = $allowedOnType; + } + return $this->rtc[$key]; + } +} diff --git a/Classes/Service/Configuration/PageTypeService.php b/Classes/Service/Configuration/PageTypeService.php new file mode 100644 index 000000000..abf73b7ea --- /dev/null +++ b/Classes/Service/Configuration/PageTypeService.php @@ -0,0 +1,36 @@ + + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +interface PageTypeService +{ + public const TYPE_ROOT = 'root'; + public const TYPE_PAGE = 'page'; + + public function getTablesAllowedOnPage(int $pid, ?int $doktype): array; +} diff --git a/Classes/Service/Configuration/PageTypeServiceInjection.php b/Classes/Service/Configuration/PageTypeServiceInjection.php new file mode 100644 index 000000000..0bf343b1d --- /dev/null +++ b/Classes/Service/Configuration/PageTypeServiceInjection.php @@ -0,0 +1,21 @@ +pageTypeService = $pageTypeService; + } +} diff --git a/Classes/Service/Configuration/TcaService.php b/Classes/Service/Configuration/TcaService.php index d3d50fbb7..3d480711a 100644 --- a/Classes/Service/Configuration/TcaService.php +++ b/Classes/Service/Configuration/TcaService.php @@ -32,10 +32,8 @@ use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use function array_keys; use function implode; use function in_array; -use function strpos; use function ucfirst; use function user_error; @@ -43,11 +41,6 @@ class TcaService implements SingletonInterface { - protected const TYPE_ROOT = 'root'; - protected const TYPE_PAGE = 'page'; - /** @var array RunTime Cache */ - protected array $rtc = []; - public function getRecordLabel(array $row, string $table): string { $labelField = $GLOBALS['TCA'][$table]['ctrl']['label'] ?? null; @@ -98,68 +91,6 @@ public function isHiddenRootTable(string $tableName): bool && in_array($GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'], [1, -1], true); } - public function getTablesAllowedOnPage(int $pid, ?int $doktype): array - { - // The root page does not have a doktype. Just get all allowed tables. - if (0 === $pid) { - if (!isset($this->rtc[self::TYPE_ROOT])) { - $this->rtc[self::TYPE_ROOT] = $this->getAllAllowedTableNames(self::TYPE_ROOT); - } - return $this->rtc[self::TYPE_ROOT]; - } - - $type = isset($GLOBALS['PAGES_TYPES'][$doktype]['allowedTables']) ? $doktype : 'default'; - $key = self::TYPE_PAGE . '_' . $type; - - if (!isset($this->rtc[$key])) { - $allowedOnType = $this->getAllAllowedTableNames(self::TYPE_PAGE); - $allowedOnDoktype = $GLOBALS['PAGES_TYPES'][$type]['allowedTables']; - if (false === strpos($allowedOnDoktype, '*')) { - foreach ($allowedOnType as $index => $table) { - if (!GeneralUtility::inList($allowedOnDoktype, $table)) { - unset($allowedOnType[$index]); - } - } - } - - $this->rtc[$key] = $allowedOnType; - } - return $this->rtc[$key]; - } - - /** - * Finds all tables which are allowed on either self::TYPE_ROOT or self::TYPE_PAGE according to the table's TCA - * 'rootLevel' setting. - * - * @param string $type - * @return array - */ - protected function getAllAllowedTableNames(string $type): array - { - if (!isset($this->rtc['_types'])) { - $allowed = [ - self::TYPE_ROOT => [], - self::TYPE_PAGE => [], - ]; - foreach (array_keys($GLOBALS['TCA']) as $table) { - switch ('pages' === $table ? -1 : (int)($GLOBALS['TCA'][$table]['ctrl']['rootLevel'] ?? 0)) { - case -1: - $allowed[self::TYPE_ROOT][] = $table; - $allowed[self::TYPE_PAGE][] = $table; - break; - case 0: - $allowed[self::TYPE_PAGE][] = $table; - break; - case 1: - $allowed[self::TYPE_ROOT][] = $table; - break; - } - } - $this->rtc['_types'] = $allowed; - } - return $this->rtc['_types'][$type]; - } - /** * @deprecated Please access $GLOBALS['TCA'] directly. This Method will be removed in in2publish_core v13. */ diff --git a/Configuration/Services.php b/Configuration/Services.php index 9081a2f0f..08bfb1e39 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -3,11 +3,16 @@ declare(strict_types=1); use In2code\In2publishCore\Component\Core\Record\Factory\DatabaseRecordFactory; +use In2code\In2publishCore\Service\Configuration\LegacyPageTypeService; +use In2code\In2publishCore\Service\Configuration\PageTypeRegistryService; +use In2code\In2publishCore\Service\Configuration\PageTypeService; use In2code\In2publishCore\Service\Context\ContextService; use In2code\In2publishCore\Testing\Tests\TestCaseInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use TYPO3\CMS\Core\DependencyInjection\PublicServicePass; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; return static function (ContainerConfigurator $configurator, ContainerBuilder $builder): void { @@ -20,6 +25,21 @@ $configurator->import('ForeignServices.php'); } + if ($builder->hasDefinition(PageTypeService::class)) { + $pageTypeServiceDefinition = $builder->hasDefinition(PageTypeService::class); + } else { + $pageTypeServiceDefinition = new Definition(PageTypeService::class); + } + $pageTypeServiceDefinition->setShared(true); + $pageTypeServiceDefinition->setPublic(true); + $typo3version = new Typo3Version(); + if (version_compare($typo3version->getVersion(), '12', '<')) { + $pageTypeServiceDefinition->setClass(LegacyPageTypeService::class); + } else { + $pageTypeServiceDefinition->setClass(PageTypeRegistryService::class); + } + $builder->setDefinition(PageTypeService::class, $pageTypeServiceDefinition); + $builder->registerForAutoconfiguration(TestCaseInterface::class)->addTag('in2publish_core.testing.test'); $builder->registerForAutoconfiguration(DatabaseRecordFactory::class)->addTag( 'in2publish_core.factory.database_record', diff --git a/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php b/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php index fab4db378..03c0e1f64 100644 --- a/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php +++ b/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php @@ -17,6 +17,7 @@ use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuilder; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuildRequest; use In2code\In2publishCore\Component\Core\Service\RelevantTablesService; +use In2code\In2publishCore\Service\Configuration\PageTypeService; use In2code\In2publishCore\Service\Configuration\TcaService; use In2code\In2publishCore\Tests\UnitTestCase; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; @@ -83,7 +84,7 @@ function (Demands $demands, RecordCollection $recordCollection) use ($fooRecord) 1 => 'table_foo', ]); - $tcaService = $this->createMock(TcaService::class); + $tcaService = $this->createMock(PageTypeService::class); $tcaService->method('getTablesAllowedOnPage')->willReturn(['table_foo']); $recordTreeBuilder->injectDemandResolver($demandResolver); From faa6f629c87b0f2129cee60dec5fee991f8c0f28 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 14:18:12 +0100 Subject: [PATCH 033/113] [BUGFIX] Allow deserialization of TYPO3 v12 Site objects --- Classes/Service/ForeignSiteFinder.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Classes/Service/ForeignSiteFinder.php b/Classes/Service/ForeignSiteFinder.php index ac381598c..8785e7ff0 100644 --- a/Classes/Service/ForeignSiteFinder.php +++ b/Classes/Service/ForeignSiteFinder.php @@ -42,8 +42,10 @@ use TYPO3\CMS\Core\Exception\Page\PageNotFoundException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Http\Uri; +use TYPO3\CMS\Core\Localization\Locale; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; +use TYPO3\CMS\Core\Site\Entity\SiteSettings; use function array_key_exists; use function base64_decode; @@ -56,7 +58,13 @@ class ForeignSiteFinder implements LoggerAwareInterface use RemoteCommandDispatcherInjection; use CachedRuntimeCacheInjection; - private const UNSERIALIZE_ALLOWED_CLASS = [Site::class, Uri::class, SiteLanguage::class]; + private const UNSERIALIZE_ALLOWED_CLASS = [ + Site::class, + Uri::class, + SiteLanguage::class, + Locale::class, + SiteSettings::class, + ]; public function getSiteByPageId(int $pageId): Site { From 7c5ad31da3dcb436056decabf60e5b23cb6ae7ed Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 14:18:32 +0100 Subject: [PATCH 034/113] [BUGFIX] Enable autowiring of the dynamic PageTypeService --- Configuration/Services.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Configuration/Services.php b/Configuration/Services.php index 08bfb1e39..03e283e22 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -30,6 +30,8 @@ } else { $pageTypeServiceDefinition = new Definition(PageTypeService::class); } + $pageTypeServiceDefinition->setAutoconfigured(true); + $pageTypeServiceDefinition->setAutowired(true); $pageTypeServiceDefinition->setShared(true); $pageTypeServiceDefinition->setPublic(true); $typo3version = new Typo3Version(); @@ -40,10 +42,10 @@ } $builder->setDefinition(PageTypeService::class, $pageTypeServiceDefinition); - $builder->registerForAutoconfiguration(TestCaseInterface::class)->addTag('in2publish_core.testing.test'); - $builder->registerForAutoconfiguration(DatabaseRecordFactory::class)->addTag( - 'in2publish_core.factory.database_record', - ); + $builder->registerForAutoconfiguration(TestCaseInterface::class) + ->addTag('in2publish_core.testing.test'); + $builder->registerForAutoconfiguration(DatabaseRecordFactory::class) + ->addTag('in2publish_core.factory.database_record',); $builder->addCompilerPass(new PublicServicePass('in2publish_core.testing.test')); }; From 28e0a4742dfef1f442e6bbe6f9e5fdf5c6845068 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 14:58:42 +0100 Subject: [PATCH 035/113] [CLEANUP] Remove superfluous empty lines from ext_tables.php --- ext_tables.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext_tables.php b/ext_tables.php index a70eeb414..078c51a75 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -123,7 +123,6 @@ } } - /******************************************* Context Menu Publish Entry *******************************************/ if ($configContainer->get('features.contextMenuPublishEntry.enable')) { $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1595598780] = PublishItemProvider::class; @@ -156,6 +155,4 @@ $GLOBALS['in2publish_core']['tests'][] = ForeignConfigurationFormatTest::class; $GLOBALS['in2publish_core']['tests'][] = SiteConfigurationTest::class; $GLOBALS['in2publish_core']['tests'][] = TableGarbageCollectorTest::class; - - })(); From a3050ff5614552f547ab73d2617c7259952fcf04 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 15:05:41 +0100 Subject: [PATCH 036/113] [BUGFIX] Rename ext_typoscript_setup suffix to typoscript --- ext_typoscript_setup.txt => ext_typoscript_setup.typoscript | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ext_typoscript_setup.txt => ext_typoscript_setup.typoscript (100%) diff --git a/ext_typoscript_setup.txt b/ext_typoscript_setup.typoscript similarity index 100% rename from ext_typoscript_setup.txt rename to ext_typoscript_setup.typoscript From 7aa2834052e07b13a864460b1a49b2fcb7df23f2 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 15:21:12 +0100 Subject: [PATCH 037/113] [BUGFIX] Return the RedirectResponse in TYPO3 v12 No side effect in TYPO3 v11 since there'll be an exception thrown --- Classes/Controller/RecordController.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index cd2905096..8f9ea068c 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -179,20 +179,20 @@ public function initializePublishRecordAction(): void } } - public function publishRecordAction(int $id): void + public function publishRecordAction(int $id): ResponseInterface { $request = new RecordTreeBuildRequest('pages', $id, 0); $recordTree = $this->recordTreeBuilder->buildRecordTree($request); $actualRecord = $recordTree->getChild('pages', $id); if (null === $actualRecord) { - $this->addFlashMessagesAndRedirectToIndex(); + return $this->addFlashMessagesAndRedirectToIndex(); } $subRecordTree = new RecordTree([$actualRecord], $request); $publishingContext = new PublishingContext($subRecordTree); $this->publisherService->publish($publishingContext); - $this->addFlashMessagesAndRedirectToIndex(); + return $this->addFlashMessagesAndRedirectToIndex(); } /** @@ -209,10 +209,8 @@ public function toggleFilterStatusAction(string $filter): ResponseInterface /** * Add success message and redirect to indexAction - * - * @throws StopActionException */ - protected function addFlashMessagesAndRedirectToIndex(): void + protected function addFlashMessagesAndRedirectToIndex(): ResponseInterface { $failures = $this->failureCollector->getFailures(); @@ -233,6 +231,6 @@ protected function addFlashMessagesAndRedirectToIndex(): void } $this->addFlashMessage($message, $title, $severity); - $this->redirect('index', 'Record'); + return $this->redirect('index', 'Record'); } } From 3cdae1b50703ec703645f4ad06f6980e5aebf890 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 7 Nov 2023 15:43:36 +0100 Subject: [PATCH 038/113] [BUGFIX] Make the PageTsProvider a Singleton to unlock it globally Also, use an existing hook the unlock the provider instead of relying on a hacky solution to dispatch an event --- .../Component/ConfigContainer/Provider/PageTsProvider.php | 3 ++- Configuration/Component/ConfigContainer/Services.yaml | 7 ------- ext_localconf.php | 4 ++++ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Classes/Component/ConfigContainer/Provider/PageTsProvider.php b/Classes/Component/ConfigContainer/Provider/PageTsProvider.php index 305146cf9..f90726aae 100644 --- a/Classes/Component/ConfigContainer/Provider/PageTsProvider.php +++ b/Classes/Component/ConfigContainer/Provider/PageTsProvider.php @@ -34,9 +34,10 @@ use In2code\In2publishCore\Utility\DatabaseUtility; use TYPO3\CMS\Backend\Utility\BackendUtility as CoreBackendUtility; use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -class PageTsProvider implements ProviderServiceInterface, ContextualProvider +class PageTsProvider implements ProviderServiceInterface, ContextualProvider, SingletonInterface { protected bool $locked = true; diff --git a/Configuration/Component/ConfigContainer/Services.yaml b/Configuration/Component/ConfigContainer/Services.yaml index 41d6f7c9c..46af9de0a 100644 --- a/Configuration/Component/ConfigContainer/Services.yaml +++ b/Configuration/Component/ConfigContainer/Services.yaml @@ -9,13 +9,6 @@ services: In2code\In2publishCore\Component\ConfigContainer\: resource: '../../../Classes/Component/ConfigContainer/*' - In2code\In2publishCore\Component\ConfigContainer\Provider\PageTsProvider: - tags: - - name: event.listener - identifier: 'in2publishcore-PageTsProvider-bootCompleted' - method: 'processData' - event: In2code\In2publishCore\Event\ExtTablesPostProcessingEvent - In2code\In2publishCore\Component\ConfigContainer\ConfigContainer: shared: true public: true diff --git a/ext_localconf.php b/ext_localconf.php index d870e3d4d..fb11aab16 100755 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,5 +1,6 @@ 'timestamp_begin', 'expirePeriod' => 1, ]; + + /*********************************************** Enable PageTSProvider *******************************************/ + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['postUserLookUp'][1699367499] = PageTsProvider::class . '->processData'; })(); From 4d1b53228922c20f175d76615713b6b3d9134d66 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 6 Nov 2023 13:00:41 +0100 Subject: [PATCH 039/113] [REFACTOR] Changes backend module registration for m1, m3, m5 The backend modules overview, file & redirects are now registered via Configuration/Backend/Modules.php For TYPO3 v11 they are registered via the old way (ext_tables.php) The Icons are provided via Icons.php and can be retrieved from the IconFactory now. Resolves: https://projekte.in2code.de/issues/60077 --- ext_tables.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ext_tables.php b/ext_tables.php index 078c51a75..8d2a34aa8 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -123,6 +123,7 @@ } } + /******************************************* Context Menu Publish Entry *******************************************/ if ($configContainer->get('features.contextMenuPublishEntry.enable')) { $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1595598780] = PublishItemProvider::class; From 4cc767d5ede2c55e53907d022a00168881a9b5d3 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 7 Nov 2023 15:28:00 +0100 Subject: [PATCH 040/113] [REFACTOR] Module Registration for Publish Tools Module refactored https://projekte.in2code.de/issues/60080 --- .../AdminTools/Service/ToolsRegistry.php | 30 ++++++++----------- .../Features/AdminTools/Services.yaml | 7 ----- ext_tables.php | 21 +++++++++++++ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php index 9c0133c3f..e655a4e3c 100644 --- a/Classes/Features/AdminTools/Service/ToolsRegistry.php +++ b/Classes/Features/AdminTools/Service/ToolsRegistry.php @@ -91,12 +91,8 @@ public function getEntries(): array /** * @throws ClassNotFoundException */ - public function processData(): void + public function processData(): array { - if (!$this->configContainer->get('module.m4')) { - return; - } - $controllerActions = []; foreach ($this->entries as $entry) { if ($this->evaluateCondition($entry)) { @@ -113,22 +109,20 @@ public function processData(): void } } + return $controllerActions; + } + + /** + * @throws ClassNotFoundException + * @deprecated Will be removed in TYPO3 v13 + */ + public function processDataForTypo3V11(): array + { + $controllerActions = $this->processData(); foreach ($controllerActions as $controllerName => $actions) { $controllerActions[$controllerName] = implode(',', $actions); } - - ExtensionUtility::registerModule( - 'in2publish_core', - 'tools', - 'm4', - '', - $controllerActions, - [ - 'access' => 'admin', - 'iconIdentifier' => 'in2publish-core-tools-module', - 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf', - ], - ); + return $controllerActions; } protected function evaluateCondition(array $config): bool diff --git a/Configuration/Features/AdminTools/Services.yaml b/Configuration/Features/AdminTools/Services.yaml index 2ddee778a..ba446a91f 100644 --- a/Configuration/Features/AdminTools/Services.yaml +++ b/Configuration/Features/AdminTools/Services.yaml @@ -7,13 +7,6 @@ services: In2code\In2publishCore\Features\AdminTools\: resource: '../../../Classes/Features/AdminTools/*' - In2code\In2publishCore\Features\AdminTools\Service\ToolsRegistry: - tags: - - name: 'event.listener' - identifier: 'in2publish_core-ToolsRegistry-BootCompletedEvent' - event: 'In2code\In2publishCore\Event\ExtTablesPostProcessingEvent' - method: 'processData' - In2code\In2publishCore\Features\AdminTools\Controller\LetterboxController: tags: - name: 'in2publish_core.admin_tool' diff --git a/ext_tables.php b/ext_tables.php index 8d2a34aa8..48e52883f 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -3,6 +3,7 @@ use In2code\In2publishCore\Component\ConfigContainer\ConfigContainer; use In2code\In2publishCore\Controller\FileController; use In2code\In2publishCore\Controller\RecordController; +use In2code\In2publishCore\Features\AdminTools\Service\ToolsRegistry; use In2code\In2publishCore\Features\ContextMenuPublishEntry\ContextMenu\PublishItemProvider; use In2code\In2publishCore\Features\RedirectsSupport\Controller\RedirectController; use In2code\In2publishCore\Features\WarningOnForeign\Service\HeaderWarningColorRenderer; @@ -101,6 +102,26 @@ ], ); } + + if ($configContainer->get('module.m4')) { + $toolsRegistry = GeneralUtility::makeInstance(ToolsRegistry::class); + $controllerActions = $toolsRegistry->processDataForTypo3V11(); + if (!empty($controllerActions)) { + ExtensionUtility::registerModule( + 'in2publish_core', + 'tools', + 'm4', + '', + $controllerActions, + [ + 'access' => 'admin', + 'iconIdentifier' => 'in2publish-core-tools-module', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf', + ], + ); + } + } + /************************************************ Redirect Support ************************************************/ if ( $configContainer->get('features.redirectsSupport.enable') From 1a277aec293bcaf6156d343fe075e384884fa407 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 7 Nov 2023 15:41:56 +0100 Subject: [PATCH 041/113] [FEATURE] Register Publish Tools Menu in Modules.php Resolves: https://projekte.in2code.de/issues/60080 --- Configuration/Backend/Modules.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 4ef178d8d..514994868 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -30,6 +30,7 @@ use In2code\In2publishCore\Component\ConfigContainer\ConfigContainer; use In2code\In2publishCore\Controller\FileController; use In2code\In2publishCore\Controller\RecordController; +use In2code\In2publishCore\Features\AdminTools\Service\ToolsRegistry; use In2code\In2publishCore\Features\RedirectsSupport\Controller\RedirectController; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -70,6 +71,24 @@ ]; } +if ($configContainer->get('module.m4')) { + $toolsRegistry = GeneralUtility::makeInstance(ToolsRegistry::class); + $controllerActions = $toolsRegistry->processData(); + if (!empty($controllerActions)) { + $backendModulesToRegister['in2publish_core_m4'] = [ + 'parent' => 'tools', + 'position' => [], + 'access' => 'admin', + 'workspaces' => 'live', + 'path' => '/module/in2publish_core/m4', + 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf', + 'extensionName' => 'in2publish_core', + 'iconIdentifier' => 'in2publish-core-tools-module', + 'controllerActions' => $controllerActions, + ]; + } +} + if ($configContainer->get('features.redirectsSupport.enable')) { $backendModulesToRegister['in2publish_core_m5'] = [ 'parent' => 'site', From 61acab8b8a219d9125dd51f4f89f28777e096c9d Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 7 Nov 2023 16:45:55 +0100 Subject: [PATCH 042/113] [BUGFIX] Add correct hrefs to Buttons on Publish Tools https://projekte.in2code.de/issues/60080 --- Classes/Features/AdminTools/Service/ToolsRegistry.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php index e655a4e3c..a173cc9b7 100644 --- a/Classes/Features/AdminTools/Service/ToolsRegistry.php +++ b/Classes/Features/AdminTools/Service/ToolsRegistry.php @@ -81,6 +81,9 @@ public function getEntries(): array $processedTools[$key]['initialAction'] = $actions[0]; if (isset($controllerConfig[$controller]['alias'])) { $processedTools[$key]['alias'] = $controllerConfig[$controller]['alias']; + } else { + $controllerParts = explode('\\', $controller); + $processedTools[$key]['alias'] = str_replace('Controller', '', array_pop($controllerParts)); } } } From d19d1220cf40395a9bc15858a02daded8d51b048 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 7 Nov 2023 17:06:21 +0100 Subject: [PATCH 043/113] [REFACTOR] Removes unnecessary Event & Middleware Resolves: https://projekte.in2code.de/issues/60080 --- .../Event/ExtTablesPostProcessingEvent.php | 48 --------- .../Middleware/BackendRouteInitialization.php | 100 ------------------ Configuration/Services.yaml | 4 - .../Events/ExtTablesPostProcessingEvent.md | 16 --- ext_localconf.php | 12 --- 5 files changed, 180 deletions(-) delete mode 100644 Classes/Event/ExtTablesPostProcessingEvent.php delete mode 100644 Classes/Middleware/BackendRouteInitialization.php delete mode 100644 Documentation/Developers/Events/ExtTablesPostProcessingEvent.md diff --git a/Classes/Event/ExtTablesPostProcessingEvent.php b/Classes/Event/ExtTablesPostProcessingEvent.php deleted file mode 100644 index 4608401e7..000000000 --- a/Classes/Event/ExtTablesPostProcessingEvent.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - */ - -/** - * This class replaces the "ExtTablesPostProcessingHook" which was registered using - * $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'] The actual hook was removed - * and the suggested replacement is listening to the TYPO3\CMS\Core\Core\Event\BootCompletedEvent. The problem with - * that event is though, that IT IS DISPATCHED BEFORE ext_tables.php files are included, which ultimately defeats the - * purpose. So we here we go again and do it ourselves. - * - * Required until the patch got merged and released. - * - * Issue: https://forge.typo3.org/issues/95962 - * Patch: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72160 - * - * @codeCoverageIgnore - */ -final class ExtTablesPostProcessingEvent -{ -} diff --git a/Classes/Middleware/BackendRouteInitialization.php b/Classes/Middleware/BackendRouteInitialization.php deleted file mode 100644 index 066f3e5d3..000000000 --- a/Classes/Middleware/BackendRouteInitialization.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - */ - -use In2code\In2publishCore\CommonInjection\EventDispatcherInjection; -use In2code\In2publishCore\Event\ExtTablesPostProcessingEvent; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; -use TYPO3\CMS\Backend\Routing\Exception\MethodNotAllowedException; -use TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException; -use TYPO3\CMS\Backend\Routing\Router; -use TYPO3\CMS\Backend\Routing\UriBuilder; -use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Http\RedirectResponse; -use TYPO3\CMS\Core\Http\Response; -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * This XCLASS dispatches an event after Bootstrap::loadExtTables() to truly replace ExtTablesPostProcessingHooks. - * - * XCLASS original \TYPO3\CMS\Backend\Middleware\BackendRouteInitialization - * Required until the patch got merged and released. - * - * Issue: https://forge.typo3.org/issues/95962 - * Patch: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72160 - * - * Have a look at the event ExtTablesPostProcessingEvent for more information. - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Can't reduce. It is already as small as possible. And an XCLASS... - * @codeCoverageIgnore - */ -class BackendRouteInitialization implements MiddlewareInterface -{ - use EventDispatcherInjection; - - protected Router $router; - - public function __construct(Router $router) - { - $this->router = $router; - } - - /** - * Resolve the &route (or &M) GET/POST parameter, and also resolves a Route object - */ - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - // Backend Routes from Configuration/Backend/{,Ajax}Routes.php will be implicitly loaded thanks to DI. - // Load ext_tables.php files to add routes from ExtensionManagementUtility::addModule() calls. - Bootstrap::loadExtTables(); - $this->eventDispatcher->dispatch(new ExtTablesPostProcessingEvent()); - - try { - $route = $this->router->matchRequest($request); - $request = $request->withAttribute('route', $route); - $request = $request->withAttribute('target', $route->getOption('target')); - // add the GET parameter "route" for backwards-compatibility - $queryParams = $request->getQueryParams(); - $queryParams['route'] = $route->getPath(); - $request = $request->withQueryParams($queryParams); - } catch (MethodNotAllowedException $e) { - return new Response(null, 405); - } catch (ResourceNotFoundException $e) { - // Route not found in system - $uri = GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('login'); - return new RedirectResponse($uri); - } - - return $handler->handle($request); - } -} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index ee3c5781b..ff9202c33 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -21,10 +21,6 @@ services: - '../Classes/Component/*' - '../Classes/Features/*' - TYPO3\CMS\Backend\Middleware\BackendRouteInitialization: - alias: In2code\In2publishCore\Middleware\BackendRouteInitialization - public: true - # Services In2code.In2publishCore.Database.Local: diff --git a/Documentation/Developers/Events/ExtTablesPostProcessingEvent.md b/Documentation/Developers/Events/ExtTablesPostProcessingEvent.md deleted file mode 100644 index 66bc552a1..000000000 --- a/Documentation/Developers/Events/ExtTablesPostProcessingEvent.md +++ /dev/null @@ -1,16 +0,0 @@ -# ExtTablesPostProcessingEvent - -## When - -In the `BackendRouteInitialization` middleware - -## What - -nothing - -## Possibilities - -This event replaces the "ExtTablesPostProcessingHook" which was registered using -`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing']`. -Since TYPO3 does not provide an equivalent replacement, we XCLASS the `BackendRouteInitialization` to introduce this -event ourselves. Have a look at the event class for more information. diff --git a/ext_localconf.php b/ext_localconf.php index fb11aab16..235610bc6 100755 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -5,11 +5,9 @@ use In2code\In2publishCore\Controller\FrontendController; use In2code\In2publishCore\Log\Processor\BackendUserProcessor; use In2code\In2publishCore\Log\Processor\PublishingFailureCollector; -use In2code\In2publishCore\Middleware\BackendRouteInitialization; use In2code\In2publishCore\Service\Context\ContextService; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Log\LogLevel; use TYPO3\CMS\Core\Log\Writer\DatabaseWriter; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -26,16 +24,6 @@ return; } - /************************************************* Patching TYPO3 *************************************************/ - // Issue: https://forge.typo3.org/issues/95962 - // Patch: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72160 - $typo3Version = new Typo3Version(); - if (version_compare($typo3Version->getVersion(), '12', '<')) { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Backend\Middleware\BackendRouteInitialization::class] = [ - 'className' => BackendRouteInitialization::class, - ]; - } - /************************************************ Record Extension ************************************************/ $file = Environment::getVarPath() . '/cache/code/content_publisher/record_extension_trait.php'; if (file_exists($file)) { From b4ebac1d32034d41365f1ae7ed7a6ac71fa010bd Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Wed, 8 Nov 2023 09:47:44 +0100 Subject: [PATCH 044/113] [BUGFIX] Return ResponseInterface in publishFile and publishFolder action --- Classes/Controller/FileController.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Classes/Controller/FileController.php b/Classes/Controller/FileController.php index 1c2ea7cc2..e23dafc2c 100755 --- a/Classes/Controller/FileController.php +++ b/Classes/Controller/FileController.php @@ -140,7 +140,7 @@ public function indexAction(): ResponseInterface * @throws StopActionException * @SuppressWarnings(PHPMD.BooleanArgumentFlag) On purpose */ - public function publishFolderAction(string $combinedIdentifier, bool $skipNotification = false): void + public function publishFolderAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface { $recordTree = $this->tryToGetFolderInstance($combinedIdentifier, true); @@ -166,7 +166,7 @@ public function publishFolderAction(string $combinedIdentifier, bool $skipNotifi } } - $this->redirect('index'); + return $this->redirect('index'); } /** @@ -174,7 +174,7 @@ public function publishFolderAction(string $combinedIdentifier, bool $skipNotifi * @throws StopActionException * @SuppressWarnings(PHPMD.BooleanArgumentFlag) On purpose */ - public function publishFileAction(string $combinedIdentifier, bool $skipNotification = false): void + public function publishFileAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface { $recordTree = $this->defaultFalFinder->findFileRecord($combinedIdentifier); @@ -216,7 +216,7 @@ public function publishFileAction(string $combinedIdentifier, bool $skipNotifica } } - $this->redirect('index'); + return $this->redirect('index'); } /** From da8b69af64b21202968b82427128e0e6a2d2a4d3 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 10:55:25 +0100 Subject: [PATCH 045/113] [REFACTOR] Remove deprecated execute from GarbageCollectorTest https://projekte.in2code.de/issues/60123 --- Classes/Testing/Tests/Database/TableGarbageCollectorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Testing/Tests/Database/TableGarbageCollectorTest.php b/Classes/Testing/Tests/Database/TableGarbageCollectorTest.php index 4a77387d7..938d377e5 100644 --- a/Classes/Testing/Tests/Database/TableGarbageCollectorTest.php +++ b/Classes/Testing/Tests/Database/TableGarbageCollectorTest.php @@ -54,9 +54,9 @@ public function run(): TestResult $query->createNamedParameter('%tx_in2publishcore_running_request%'), ), ); - $statement = $query->execute(); + $statement = $query->executeQuery(); - if (0 === $statement->fetchColumn()) { + if (0 === $statement->fetchOne()) { return new TestResult( 'database.garbage_collector_task_missing', TestResult::ERROR, From 612ca965b66bc5827922bb637d238ba422ed69ce Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 10:55:55 +0100 Subject: [PATCH 046/113] [REFACTOR] Remove deprecations fomr LogsExporter https://projekte.in2code.de/issues/60123 --- .../SystemInformationExport/Exporter/LogsExporter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Classes/Features/SystemInformationExport/Exporter/LogsExporter.php b/Classes/Features/SystemInformationExport/Exporter/LogsExporter.php index 560419e1f..ced48e1cd 100644 --- a/Classes/Features/SystemInformationExport/Exporter/LogsExporter.php +++ b/Classes/Features/SystemInformationExport/Exporter/LogsExporter.php @@ -34,7 +34,7 @@ use function json_decode; use function sprintf; -use function strftime; +use function date; use function substr; use const JSON_THROW_ON_ERROR; @@ -56,7 +56,7 @@ public function getInformation(): array ->where($logQueryBuilder->expr()->lte('level', 4)) ->setMaxResults(500) ->orderBy('uid', 'DESC') - ->execute() + ->executeQuery() ->fetchAllAssociative(); $logsFormatted = []; @@ -65,7 +65,7 @@ public function getInformation(): array '[%s] [lvl:%d] @%s "%s"', $log['component'], $log['level'], - strftime('%F %T', (int)$log['time_micro']), + date('Y-m-d H:i:s', (int)$log['time_micro']), $log['message'], ); $logData = $log['data']; From b3228399495366ed9d25bc1c1326c99c69ee8957 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 12:04:08 +0100 Subject: [PATCH 047/113] [BUGFIX] Remove deprecations from LetterBox https://projekte.in2code.de/issues/60123 --- Classes/Component/RemoteProcedureCall/Letterbox.php | 6 +++--- .../Features/AdminTools/Controller/LetterboxController.php | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Classes/Component/RemoteProcedureCall/Letterbox.php b/Classes/Component/RemoteProcedureCall/Letterbox.php index 57b7d639f..911053e62 100644 --- a/Classes/Component/RemoteProcedureCall/Letterbox.php +++ b/Classes/Component/RemoteProcedureCall/Letterbox.php @@ -110,7 +110,7 @@ public function receiveEnvelope(int $uid, bool $burnEnvelope = true) ->where($query->expr()->eq('uid', $uid)) ->orderBy('data.sorting'); try { - $result = $query->execute(); + $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); } catch (Throwable $exception) { $this->logger->error( @@ -157,7 +157,7 @@ public function hasUnAnsweredEnvelopes(): bool ->from('tx_in2code_rpc_request', 'req') ->join('req', 'tx_in2code_rpc_data', 'data', 'req.uid = data.request') ->where($query->expr()->eq('data.data_type', $query->createNamedParameter('response'))); - return $query->execute()->fetchOne() > 0; + return $query->executeQuery()->fetchOne() > 0; } public function removeAnsweredEnvelopes(): void @@ -168,7 +168,7 @@ public function removeAnsweredEnvelopes(): void ->from('tx_in2code_rpc_request', 'req') ->join('req', 'tx_in2code_rpc_data', 'data', 'req.uid = data.request') ->where($query->expr()->eq('data.data_type', $query->createNamedParameter('response'))); - $uid = $query->execute()->fetchColumn(); + $uid = $query->executeQuery()->fetchOne(); $this->databaseOfForeign->delete('tx_in2code_rpc_request', ['uid' => $uid]); $this->databaseOfForeign->delete('tx_in2code_rpc_data', ['request' => $uid]); } diff --git a/Classes/Features/AdminTools/Controller/LetterboxController.php b/Classes/Features/AdminTools/Controller/LetterboxController.php index a08b0bc30..3e4022615 100644 --- a/Classes/Features/AdminTools/Controller/LetterboxController.php +++ b/Classes/Features/AdminTools/Controller/LetterboxController.php @@ -33,7 +33,6 @@ use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; class LetterboxController extends ActionController @@ -47,8 +46,7 @@ public function indexAction(): ResponseInterface return $this->htmlResponse(); } - /** @throws StopActionException */ - public function flushEnvelopesAction(): void + public function flushEnvelopesAction(): ResponseInterface { $this->letterbox->removeAnsweredEnvelopes(); $this->addFlashMessage( @@ -57,6 +55,6 @@ public function flushEnvelopesAction(): void 'in2publish_core', ), ); - $this->redirect('index'); + return $this->redirect('index'); } } From 67e7bdee652f26ab6bbd06c32b286a72300d34cd Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 12:16:15 +0100 Subject: [PATCH 048/113] [BUGFIX] Remove deprecations from RegistryController https://projekte.in2code.de/issues/60123 --- Classes/Features/AdminTools/Controller/RegistryController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Features/AdminTools/Controller/RegistryController.php b/Classes/Features/AdminTools/Controller/RegistryController.php index 1c5dcf108..5ecbad33f 100644 --- a/Classes/Features/AdminTools/Controller/RegistryController.php +++ b/Classes/Features/AdminTools/Controller/RegistryController.php @@ -47,10 +47,10 @@ public function indexAction(): ResponseInterface } /** @throws StopActionException */ - public function flushRegistryAction(): void + public function flushRegistryAction(): ResponseInterface { $this->registry->removeAllByNamespace('tx_in2publishcore'); $this->addFlashMessage(LocalizationUtility::translate('module.m4.registry_flushed', 'in2publish_core')); - $this->redirect('index'); + return $this->redirect('index'); } } From 8512ed110bdb0b58c9bcdc93b2856e28efb2553a Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 12:37:52 +0100 Subject: [PATCH 049/113] [FEATURE] Changes AdminButton to show primary styling correct https://projekte.in2code.de/issues/60123 --- .../Backend/Button/AdminToolButton.php | 20 ++++++++++++++++++- .../Traits/AdminToolsModuleTemplate.php | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Classes/Features/AdminTools/Backend/Button/AdminToolButton.php b/Classes/Features/AdminTools/Backend/Button/AdminToolButton.php index 8402ada88..23a265a11 100644 --- a/Classes/Features/AdminTools/Backend/Button/AdminToolButton.php +++ b/Classes/Features/AdminTools/Backend/Button/AdminToolButton.php @@ -38,6 +38,10 @@ class AdminToolButton extends LinkButton { protected $showLabelText = true; + protected $defaultClasses = [ + 'btn','btn-default' + ]; + public function isValid(): bool { return trim($this->getHref()) !== '' @@ -49,7 +53,7 @@ public function render(): string { $attributes = [ 'href' => $this->getHref(), - 'class' => 'btn btn-default ' . $this->getClasses(), + 'class' => $this->getDefaultClassesAsString() . ' ' . $this->getClasses(), 'title' => $this->getTitle(), ]; $labelText = ''; @@ -71,4 +75,18 @@ public function render(): string return '' . $labelText . ''; } + + protected function getDefaultClassesAsString(): string + { + return implode(' ', $this->defaultClasses); + } + + public function makeButtonPrimary(): void + { + $index = array_search('btn-default', $this->defaultClasses, true); + if (false !== $index) { + $this->defaultClasses[$index] = 'btn-primary'; + } + } + } diff --git a/Classes/Features/AdminTools/Controller/Traits/AdminToolsModuleTemplate.php b/Classes/Features/AdminTools/Controller/Traits/AdminToolsModuleTemplate.php index d777f0020..3b077dad5 100644 --- a/Classes/Features/AdminTools/Controller/Traits/AdminToolsModuleTemplate.php +++ b/Classes/Features/AdminTools/Controller/Traits/AdminToolsModuleTemplate.php @@ -80,7 +80,7 @@ protected function render(): string $this->request->getControllerObjectName() === $entry['controller'] && in_array($this->request->getControllerActionName(), explode(',', $entry['action'])) ) { - $button->setClasses('btn-primary'); + $button->makeButtonPrimary(); } $buttonBar->addButton($button); } From b0bd01e7c05389f8bf5c6ac0c05d8750c097d554 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 12:49:30 +0100 Subject: [PATCH 050/113] [REFACTOR] Simplifies the generation of an controller alias --- Classes/Features/AdminTools/Service/ToolsRegistry.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php index a173cc9b7..34662c4e3 100644 --- a/Classes/Features/AdminTools/Service/ToolsRegistry.php +++ b/Classes/Features/AdminTools/Service/ToolsRegistry.php @@ -79,12 +79,7 @@ public function getEntries(): array $processedTools[$key] = $config; $actions = GeneralUtility::trimExplode(',', $processedTools[$key]['action']); $processedTools[$key]['initialAction'] = $actions[0]; - if (isset($controllerConfig[$controller]['alias'])) { - $processedTools[$key]['alias'] = $controllerConfig[$controller]['alias']; - } else { - $controllerParts = explode('\\', $controller); - $processedTools[$key]['alias'] = str_replace('Controller', '', array_pop($controllerParts)); - } + $processedTools[$key]['alias'] = ExtensionUtility::resolveControllerAliasFromControllerClassName($controller); } } From b7e5904042fb7fe8b0ea70c76f75f66926d8e9ce Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 13:19:15 +0100 Subject: [PATCH 051/113] [REFACTOR] Use be.infobox viewhelper instead of own markup https://projekte.in2code.de/issues/60123 --- Classes/Testing/Tests/TestResult.php | 15 +++++++++++ Resources/Private/Templates/Test/Index.html | 30 +++------------------ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/Classes/Testing/Tests/TestResult.php b/Classes/Testing/Tests/TestResult.php index faaf45c35..966c2b340 100644 --- a/Classes/Testing/Tests/TestResult.php +++ b/Classes/Testing/Tests/TestResult.php @@ -90,6 +90,21 @@ public function getSeverityLabel(): string } } + public function getSeverityState(): int + { + switch ($this->severity) { + case self::OK: + return 0; + case self::WARNING: + return 1; + case self::SKIPPED: + return -2; + case self::ERROR: + default: + return 2; + } + } + public function getTranslatedLabel(): string { return TestLabelLocalizer::translate($this->label, $this->labelArguments); diff --git a/Resources/Private/Templates/Test/Index.html b/Resources/Private/Templates/Test/Index.html index 07415d1fc..932926273 100755 --- a/Resources/Private/Templates/Test/Index.html +++ b/Resources/Private/Templates/Test/Index.html @@ -10,33 +10,9 @@

-
-
-
- - - - - - - - - - - - - -
-
-
{testResult.translatedLabel}
-
-

- {testResult.translatedMessages} -

-
-
-
-
+ + {testResult.translatedMessages} +
From 52ef3f3b01fea006c844535ad15be94ab9cfb41c Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 13:23:38 +0100 Subject: [PATCH 052/113] =?UTF-8?q?[BUGFIX]=C2=A0Removes=20check=20for=20d?= =?UTF-8?q?irectory=20typo3conf=20in=20TYPO3v12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://projekte.in2code.de/issues/60123 --- Classes/Testing/Tests/SshConnection/SshConnectionTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php index bddd63ce5..b7a03e71d 100644 --- a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php +++ b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php @@ -35,6 +35,7 @@ use In2code\In2publishCore\Testing\Tests\TestCaseInterface; use In2code\In2publishCore\Testing\Tests\TestResult; use Throwable; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_diff; @@ -99,8 +100,12 @@ public function run(): TestResult $requiredNames = [ 'typo3', 'index.php', - 'typo3conf', ]; + /** @var Typo3Version $versionInformation */ + $typo3Version = new Typo3Version(); + if (version_compare($typo3Version->getVersion(), '12', '<')) { + $requiredNames[] = 'typo3conf'; + } if (!empty(array_diff($requiredNames, $documentRootFiles))) { return new TestResult('ssh_connection.foreign_document_root_wrong', TestResult::ERROR); From 910687de358417694cf7afb67914d0c2b176a465 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 14:29:27 +0100 Subject: [PATCH 053/113] [BUGFIX] Removes deprecated getSchemamanager call --- Classes/Testing/Tests/Application/LocalInstanceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Testing/Tests/Application/LocalInstanceTest.php b/Classes/Testing/Tests/Application/LocalInstanceTest.php index 6613e84bd..88f845a88 100644 --- a/Classes/Testing/Tests/Application/LocalInstanceTest.php +++ b/Classes/Testing/Tests/Application/LocalInstanceTest.php @@ -50,7 +50,7 @@ public function run(): TestResult } $excludedTables = $this->configContainer->get('excludeRelatedTables'); - $localTables = array_flip($this->localDatabase->getSchemaManager()->listTableNames()); + $localTables = array_flip($this->localDatabase->createSchemaManager()->listTableNames()); $missingTables = []; From 14a6fda86432d182ddcb4a31cbfdfd563b6ec2de Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 15:21:09 +0100 Subject: [PATCH 054/113] [REFACTOR] Removes deprecated QueryBuilder methods --- .../Foreign/Status/DbConfigTestCommand.php | 2 +- .../FileHandling/Service/FalDriverService.php | 4 +-- .../Publisher/Command/FalPublisherCommand.php | 2 +- .../Repository/SingleDatabaseRepository.php | 6 ++-- .../Domain/Repository/TaskRepository.php | 4 +-- .../CompareDatabaseToolController.php | 36 +++++++++---------- .../FileEdgeCacheInvalidationService.php | 18 +++++----- .../Service/TableBackupService.php | 2 +- .../Service/TableTransferService.php | 2 +- .../Repository/RunningRequestRepository.php | 8 ++--- .../Domain/Anomaly/SortingPublisher.php | 6 ++-- .../Controller/RedirectController.php | 10 ++---- .../Repository/SysRedirectRepository.php | 6 ++-- .../Domain/Anomaly/SysLogPublisher.php | 2 +- Classes/Service/Database/RawRecordService.php | 2 +- .../Data/FalStorageTestSubjectsProvider.php | 2 +- .../Tests/Application/AbstractDomainTest.php | 4 +-- .../Database/DatabaseDifferencesTest.php | 6 ++-- Classes/Utility/BackendUtility.php | 26 +++++--------- Classes/Utility/DatabaseUtility.php | 2 +- .../Service/RunningRequestServiceTest.php | 8 ++--- 21 files changed, 73 insertions(+), 85 deletions(-) diff --git a/Classes/Command/Foreign/Status/DbConfigTestCommand.php b/Classes/Command/Foreign/Status/DbConfigTestCommand.php index 3711d3d36..ea644481d 100644 --- a/Classes/Command/Foreign/Status/DbConfigTestCommand.php +++ b/Classes/Command/Foreign/Status/DbConfigTestCommand.php @@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $queryBuilder->createNamedParameter(ForeignDatabaseConfigTest::DB_CONFIG_TEST_TYPE), ); $queryBuilder->select('*')->from('tx_in2code_in2publish_task')->where($predicates); - $result = $queryBuilder->execute()->fetchAllAssociative(); + $result = $queryBuilder->executeQuery()->fetchAllAssociative(); $value = base64_encode(json_encode(array_column($result, 'configuration'), JSON_THROW_ON_ERROR)); $output->writeln('DB Config: ' . $value); return Command::SUCCESS; diff --git a/Classes/Component/Core/FileHandling/Service/FalDriverService.php b/Classes/Component/Core/FileHandling/Service/FalDriverService.php index 30b19953b..104b80bf2 100644 --- a/Classes/Component/Core/FileHandling/Service/FalDriverService.php +++ b/Classes/Component/Core/FileHandling/Service/FalDriverService.php @@ -42,7 +42,7 @@ public function getDriver(int $storage): DriverInterface $query->select('*') ->from('sys_file_storage') ->where($query->expr()->eq('uid', $query->createNamedParameter($storage))); - $result = $query->execute(); + $result = $query->executeQuery(); $storageRow = $result->fetchAssociative(); $driver = $this->createFalDriver($storageRow); } @@ -61,7 +61,7 @@ public function getDrivers(array $storagesUids): array $query->select('*') ->from('sys_file_storage') ->where($query->expr()->in('uid', $storagesUids)); - $result = $query->execute(); + $result = $query->executeQuery(); $storages = $result->fetchAllAssociative(); $drivers = []; diff --git a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php index d3f612043..c4c272cac 100644 --- a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php +++ b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php @@ -39,7 +39,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $query->select('*') ->from('tx_in2publishcore_filepublisher_instruction') ->where($query->expr()->eq('request_token', $query->createNamedParameter($requestToken))); - $result = $query->execute(); + $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); /** @var array $instructions */ diff --git a/Classes/Component/Core/Repository/SingleDatabaseRepository.php b/Classes/Component/Core/Repository/SingleDatabaseRepository.php index 8c6113304..a33f84691 100644 --- a/Classes/Component/Core/Repository/SingleDatabaseRepository.php +++ b/Classes/Component/Core/Repository/SingleDatabaseRepository.php @@ -73,7 +73,7 @@ public function findByProperty( $query->orderBy('uid'); } - $result = $query->execute(); + $result = $query->executeQuery(); return array_column($result->fetchAllAssociative(), null, 'uid'); } @@ -127,7 +127,7 @@ public function findByPropertyWithJoin( $query->orderBy('uid'); } - $result = $query->execute(); + $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); @@ -198,7 +198,7 @@ public function findByWhere($table, string $andWhere): array $query->orderBy('uid'); } - $result = $query->execute(); + $result = $query->executeQuery(); return array_column($result->fetchAllAssociative(), null, 'uid'); } } diff --git a/Classes/Component/PostPublishTaskExecution/Domain/Repository/TaskRepository.php b/Classes/Component/PostPublishTaskExecution/Domain/Repository/TaskRepository.php index bbc8bd04e..b09bd18ec 100755 --- a/Classes/Component/PostPublishTaskExecution/Domain/Repository/TaskRepository.php +++ b/Classes/Component/PostPublishTaskExecution/Domain/Repository/TaskRepository.php @@ -104,7 +104,7 @@ public function findByExecutionBegin(DateTime $executionBegin = null): array $tasksPropertiesArray = $query->select('*') ->from(self::TASK_TABLE_NAME) ->where($predicates) - ->execute() + ->executeQuery() ->fetchAllAssociative(); foreach ($tasksPropertiesArray as $taskProperties) { $taskObjects[] = $this->taskFactory->convertToObject($taskProperties); @@ -125,6 +125,6 @@ public function deleteObsolete(): void ->where( $query->expr()->lte('execution_end', $query->createNamedParameter($executionEnd)), ); - $query->execute(); + $query->executeStatement(); } } diff --git a/Classes/Features/CompareDatabaseTool/Controller/CompareDatabaseToolController.php b/Classes/Features/CompareDatabaseTool/Controller/CompareDatabaseToolController.php index 578bc0e45..0596f7b1f 100644 --- a/Classes/Features/CompareDatabaseTool/Controller/CompareDatabaseToolController.php +++ b/Classes/Features/CompareDatabaseTool/Controller/CompareDatabaseToolController.php @@ -37,7 +37,7 @@ use In2code\In2publishCore\Service\Configuration\IgnoredFieldsServiceInjection; use In2code\In2publishCore\Utility\ArrayUtility; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Core\Messaging\AbstractMessage; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; @@ -120,23 +120,23 @@ public function compareAction(ComparisonRequest $comparisonRequest = null): Resp $localResult = $localQuery->select('*') ->from($table) ->where( - $localQuery->expr()->andX( + $localQuery->expr()->and( $localQuery->expr()->gte('uid', $offset), $localQuery->expr()->lt('uid', $limit), ), ) - ->execute(); + ->executeQuery(); $localRows = array_column($localResult->fetchAllAssociative(), null, 'uid'); $foreignQuery = $this->foreignDatabase->createQueryBuilder(); $foreignResult = $foreignQuery->select('*') ->from($table) ->where( - $foreignQuery->expr()->andX( + $foreignQuery->expr()->and( $foreignQuery->expr()->gte('uid', $offset), $foreignQuery->expr()->lt('uid', $limit), ), ) - ->execute(); + ->executeQuery(); $foreignRows = array_column($foreignResult->fetchAllAssociative(), null, 'uid'); $uidList = array_unique(array_merge(array_keys($localRows), array_keys($foreignRows))); @@ -190,7 +190,7 @@ public function transferAction(string $table, int $uid, string $expected): void ->from($table) ->where($localQuery->expr()->eq('uid', $localQuery->createNamedParameter($uid))) ->setMaxResults(1); - $localResult = $localQuery->execute(); + $localResult = $localQuery->executeQuery(); $localRow = $localResult->fetchAssociative(); $foreignQuery = $this->foreignDatabase->createQueryBuilder(); @@ -199,14 +199,14 @@ public function transferAction(string $table, int $uid, string $expected): void ->from($table) ->where($foreignQuery->expr()->eq('uid', $foreignQuery->createNamedParameter($uid))) ->setMaxResults(1); - $foreignResult = $foreignQuery->execute(); + $foreignResult = $foreignQuery->executeQuery(); $foreignRow = $foreignResult->fetchAssociative(); if (empty($localRow) && empty($foreignRow)) { $this->addFlashMessage( LocalizationUtility::translate('compare_database.transfer.record_missing', 'in2publish_core'), LocalizationUtility::translate('compare_database.transfer.error', 'in2publish_core'), - AbstractMessage::ERROR, + ContextualFeedbackSeverity::ERROR, ); $this->redirect('index'); } @@ -216,14 +216,14 @@ public function transferAction(string $table, int $uid, string $expected): void $this->addFlashMessage( LocalizationUtility::translate('compare_database.transfer.exists_on_foreign', 'in2publish_core'), LocalizationUtility::translate('compare_database.transfer.error', 'in2publish_core'), - AbstractMessage::ERROR, + ContextualFeedbackSeverity::ERROR, ); $this->redirect('index'); } - $foreignQuery = $foreignDatabase->createQueryBuilder(); + $foreignQuery = $this->foreignDatabase->createQueryBuilder(); $foreignQuery->delete($table) ->where($localQuery->expr()->eq('uid', $foreignQuery->createNamedParameter($uid))); - $foreignResult = $foreignQuery->execute(); + $foreignResult = $foreignQuery->executeStatement(); if (1 === $foreignResult) { $this->addFlashMessage( LocalizationUtility::translate( @@ -241,14 +241,14 @@ public function transferAction(string $table, int $uid, string $expected): void $this->addFlashMessage( LocalizationUtility::translate('compare_database.transfer.exists_on_local', 'in2publish_core'), LocalizationUtility::translate('compare_database.transfer.error', 'in2publish_core'), - AbstractMessage::ERROR, + ContextualFeedbackSeverity::ERROR, ); $this->redirect('index'); } - $foreignQuery = $foreignDatabase->createQueryBuilder(); + $foreignQuery = $this->foreignDatabase->createQueryBuilder(); $foreignQuery->insert($table) ->values($localRow); - $foreignResult = $foreignQuery->execute(); + $foreignResult = $foreignQuery->executeStatement(); if (1 === $foreignResult) { $this->addFlashMessage( LocalizationUtility::translate( @@ -269,11 +269,11 @@ public function transferAction(string $table, int $uid, string $expected): void 'in2publish_core', ), LocalizationUtility::translate('compare_database.transfer.error', 'in2publish_core'), - AbstractMessage::ERROR, + ContextualFeedbackSeverity::ERROR, ); $this->redirect('index'); } - $foreignQuery = $foreignDatabase->createQueryBuilder(); + $foreignQuery = $this->foreignDatabase->createQueryBuilder(); $foreignQuery->update($table); foreach ($localRow as $field => $value) { if ($foreignRow[$field] !== $value) { @@ -281,7 +281,7 @@ public function transferAction(string $table, int $uid, string $expected): void } } $foreignQuery->where($foreignQuery->expr()->eq('uid', $foreignQuery->createNamedParameter($uid))); - $foreignResult = $foreignQuery->execute(); + $foreignResult = $foreignQuery->executeStatement(); if (1 === $foreignResult) { $this->addFlashMessage( LocalizationUtility::translate( @@ -299,7 +299,7 @@ public function transferAction(string $table, int $uid, string $expected): void protected function getAllNonExcludedTables(): array { - $tables = $this->localDatabase->getSchemaManager()->listTableNames(); + $tables = $this->localDatabase->createSchemaManager()->listTableNames(); $excludedTables = $this->configContainer->get('excludeRelatedTables'); return array_diff($tables, $excludedTables); } diff --git a/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php b/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php index 699fb6ada..49fd20c0d 100644 --- a/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php +++ b/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php @@ -77,12 +77,12 @@ protected function selectSysRefIndexRecords(array $uidList): Result $query = $this->localDatabase->createQueryBuilder(); $query->getRestrictions()->removeAll(); $query->select('tablename as table', 'recuid as uid')->from('sys_refindex')->where( - $query->expr()->andX( + $query->expr()->and( $query->expr()->eq('ref_table', '"sys_file"'), $query->expr()->in('ref_uid', $uidList), ), ); - return $query->execute(); + return $query->executeQuery(); } /** @@ -97,12 +97,12 @@ protected function selectSysFileReferenceRecords(array $uidList): Result $query->select('tablenames as table', 'uid_foreign as uid') ->from('sys_file_reference') ->where( - $query->expr()->andX( + $query->expr()->and( $query->expr()->eq('table_local', '"sys_file"'), $query->expr()->in('uid_local', $uidList), ), ); - return $query->execute(); + return $query->executeQuery(); } protected function addResultsToCollection(Result $statement, RecordCollection $recordCollection): void @@ -116,15 +116,15 @@ protected function addResultsToCollection(Result $statement, RecordCollection $r protected function resolveRecordsToPages(RecordCollection $recordCollection): void { - $schemaManager = $this->localDatabase->getSchemaManager(); + $schemaManager = $this->localDatabase->createSchemaManager(); $tableNames = $schemaManager->listTableNames(); foreach ($recordCollection->getRecords() as $table => $recordUidList) { if ( - !in_array($table, $tableNames, true) - || !array_key_exists('pid', $schemaManager->listTableColumns($table)) - || $table === '_file' + $table === '_file' || $table === '_folder' + || !in_array($table, $tableNames, true) + || !array_key_exists('pid', $schemaManager->listTableColumns($table)) ) { continue; } @@ -133,7 +133,7 @@ protected function resolveRecordsToPages(RecordCollection $recordCollection): vo $query->select('pid')->from($table); $query->where($query->expr()->in('uid', $recordUidList)); $query->groupBy('pid'); - $statement = $query->execute(); + $statement = $query->executeQuery(); while ($page = $statement->fetchOne()) { $recordCollection->addRecord('pages', $page); } diff --git a/Classes/Features/FullTablePublishing/Service/TableBackupService.php b/Classes/Features/FullTablePublishing/Service/TableBackupService.php index 52a3a985e..50338cd38 100644 --- a/Classes/Features/FullTablePublishing/Service/TableBackupService.php +++ b/Classes/Features/FullTablePublishing/Service/TableBackupService.php @@ -116,7 +116,7 @@ protected function dumpTableData(Connection $connection, string $table, $resourc { $query = $connection->createQueryBuilder(); $query->getRestrictions()->removeAll(); - $resultSet = $query->select('*')->from($table)->execute(); + $resultSet = $query->select('*')->from($table)->executeQuery(); $escapedTableName = $connection->quoteIdentifier($table); diff --git a/Classes/Features/FullTablePublishing/Service/TableTransferService.php b/Classes/Features/FullTablePublishing/Service/TableTransferService.php index b8bc6c8ed..fb2ea9889 100644 --- a/Classes/Features/FullTablePublishing/Service/TableTransferService.php +++ b/Classes/Features/FullTablePublishing/Service/TableTransferService.php @@ -14,7 +14,7 @@ public function copyTableContents(Connection $source, Connection $target, string $query = $source->createQueryBuilder(); $query->select('*')->from($table); - $result = $query->execute(); + $result = $query->executeQuery(); while ($row = $result->fetchAssociative()) { $target->insert($table, $row); } diff --git a/Classes/Features/PreventParallelPublishing/Domain/Repository/RunningRequestRepository.php b/Classes/Features/PreventParallelPublishing/Domain/Repository/RunningRequestRepository.php index 992167443..7dd32fe6e 100644 --- a/Classes/Features/PreventParallelPublishing/Domain/Repository/RunningRequestRepository.php +++ b/Classes/Features/PreventParallelPublishing/Domain/Repository/RunningRequestRepository.php @@ -58,7 +58,7 @@ public function flush(): void return; } foreach (array_chunk($this->inserts, 1000) as $chunk) { - $this->localDatabase->bulkInsert(self::RUNNING_REQUEST_TABLE_NAME, $this->inserts); + $this->localDatabase->bulkInsert(self::RUNNING_REQUEST_TABLE_NAME, $chunk); } $this->inserts = []; } @@ -73,8 +73,8 @@ public function isPublishingInDifferentRequest($identifier, string $tableName, s $query->select('*') ->from(self::RUNNING_REQUEST_TABLE_NAME) ->where($query->expr()->neq('request_token', $query->createNamedParameter($token))); - $result = $query->execute(); - foreach ($result->fetchAll() as $row) { + $result = $query->executeQuery(); + foreach ($result->fetchAllAssociative() as $row) { $this->rtc['content'][$row['table_name']][$row['record_id']] = true; } } @@ -86,6 +86,6 @@ public function deleteAllByToken(string $token): void $query = $this->localDatabase->createQueryBuilder(); $query->delete(self::RUNNING_REQUEST_TABLE_NAME) ->where($query->expr()->eq('request_token', $query->createNamedParameter($token))) - ->execute(); + ->executeStatement(); } } diff --git a/Classes/Features/PublishSorting/Domain/Anomaly/SortingPublisher.php b/Classes/Features/PublishSorting/Domain/Anomaly/SortingPublisher.php index 954bb131e..b184eb600 100644 --- a/Classes/Features/PublishSorting/Domain/Anomaly/SortingPublisher.php +++ b/Classes/Features/PublishSorting/Domain/Anomaly/SortingPublisher.php @@ -77,8 +77,8 @@ public function publishSortingRecursively(): void $query->select('uid', 'sorting') ->from($tableName) ->where($query->expr()->in('pid', $pidList)); - $statement = $query->execute(); - $localRows = $statement->fetchAllAssociative(); + $result = $query->executeQuery(); + $localRows = $result->fetchAllAssociative(); $updates = []; foreach ($localRows as $localRow) { @@ -93,7 +93,7 @@ public function publishSortingRecursively(): void $updateQuery->update($tableName) ->set($sortingField, $sorting) ->where($updateQuery->expr()->in('uid', $uidList)) - ->execute(); + ->executeStatement(); } } $this->sortingsToBePublished = []; diff --git a/Classes/Features/RedirectsSupport/Controller/RedirectController.php b/Classes/Features/RedirectsSupport/Controller/RedirectController.php index 0156558b0..8c2fa636f 100644 --- a/Classes/Features/RedirectsSupport/Controller/RedirectController.php +++ b/Classes/Features/RedirectsSupport/Controller/RedirectController.php @@ -47,10 +47,10 @@ use In2code\In2publishCore\Service\ForeignSiteFinderInjection; use Psr\Http\Message\ResponseInterface; use Throwable; -use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Pagination\ArrayPaginator; use TYPO3\CMS\Core\Pagination\SimplePagination; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; @@ -120,8 +120,6 @@ public function initializeListAction(): void /** * @param Filter|null $filter - * @param int $page - * @return ResponseInterface * @throws Throwable */ public function listAction(Filter $filter = null, int $page = 1): ResponseInterface @@ -129,7 +127,7 @@ public function listAction(Filter $filter = null, int $page = 1): ResponseInterf $query = $this->foreignDatabase->createQueryBuilder(); $query->getRestrictions()->removeAll(); $query->select('uid')->from('sys_redirect')->where($query->expr()->eq('deleted', 1)); - $foreignDeletedRedirects = $query->execute()->fetchAll(); + $foreignDeletedRedirects = $query->executeQuery()->fetchAllAssociative(); $additionalWhere = ''; if (!empty($foreignDeletedRedirects)) { $uidList = implode(',', array_column($foreignDeletedRedirects, 'uid')); @@ -170,7 +168,7 @@ public function publishAction(array $redirects): void $this->addFlashMessage( 'No redirect has been selected for publishing', 'Skipping publishing', - AbstractMessage::NOTICE, + ContextualFeedbackSeverity::NOTICE, ); $this->redirect('list'); } @@ -196,9 +194,7 @@ public function publishAction(array $redirects): void } /** - * @param int $redirect * @param array|null $properties - * @return ResponseInterface * @throws Throwable */ public function selectSiteAction(int $redirect, array $properties = null): ResponseInterface diff --git a/Classes/Features/RedirectsSupport/Domain/Repository/SysRedirectRepository.php b/Classes/Features/RedirectsSupport/Domain/Repository/SysRedirectRepository.php index ab2a1d243..f8b247f6e 100644 --- a/Classes/Features/RedirectsSupport/Domain/Repository/SysRedirectRepository.php +++ b/Classes/Features/RedirectsSupport/Domain/Repository/SysRedirectRepository.php @@ -44,7 +44,7 @@ public function findHostsOfRedirects(): array ->from('sys_redirect') ->orderBy('source_host') ->groupBy('source_host') - ->execute() + ->executeQuery() ->fetchAllAssociative(); } @@ -55,7 +55,7 @@ public function findStatusCodesOfRedirects(): array ->from('sys_redirect') ->orderBy('target_statuscode') ->groupBy('target_statuscode') - ->execute() + ->executeQuery() ->fetchAllAssociative(); } @@ -66,7 +66,7 @@ public function findLocalRawByUid(int $redirect): ?Redirect ->from('sys_redirect') ->where('uid = :redirect') ->setParameter('redirect', $redirect) - ->execute() + ->executeQuery() ->fetchAssociative(); if (false === $row) { return null; diff --git a/Classes/Features/SysLogPublisher/Domain/Anomaly/SysLogPublisher.php b/Classes/Features/SysLogPublisher/Domain/Anomaly/SysLogPublisher.php index 2c976b46e..3eadf7ed5 100644 --- a/Classes/Features/SysLogPublisher/Domain/Anomaly/SysLogPublisher.php +++ b/Classes/Features/SysLogPublisher/Domain/Anomaly/SysLogPublisher.php @@ -64,7 +64,7 @@ protected function findLatestSysLogForPage(int $identifier): ?array ->where($query->expr()->eq('event_pid', $query->createNamedParameter($identifier))) ->orderBy('uid', 'DESC') ->setMaxResults(1); - $result = $query->execute(); + $result = $query->executeQuery(); $row = $result->fetchAssociative(); if (!$row) { return null; diff --git a/Classes/Service/Database/RawRecordService.php b/Classes/Service/Database/RawRecordService.php index c5953976d..52e942ea9 100644 --- a/Classes/Service/Database/RawRecordService.php +++ b/Classes/Service/Database/RawRecordService.php @@ -89,7 +89,7 @@ protected function fetchRecord(string $table, int $uid, string $side): ?array ->from($table) ->where($query->expr()->eq('uid', $query->createNamedParameter($uid, PDO::PARAM_INT))) ->setMaxResults(1); - $statement = $query->execute(); + $statement = $query->executeQuery(); $result = $statement->fetchAssociative(); return is_array($result) ? $result : null; } diff --git a/Classes/Testing/Data/FalStorageTestSubjectsProvider.php b/Classes/Testing/Data/FalStorageTestSubjectsProvider.php index 1155ca57d..154047422 100644 --- a/Classes/Testing/Data/FalStorageTestSubjectsProvider.php +++ b/Classes/Testing/Data/FalStorageTestSubjectsProvider.php @@ -97,7 +97,7 @@ protected function fetchStorages(Connection $connection): array $rows = $query->select('*') ->from('sys_file_storage') ->where($query->expr()->eq('deleted', 0)) - ->execute() + ->executeQuery() ->fetchAllAssociative(); return array_combine(array_column($rows, 'uid'), $rows); } diff --git a/Classes/Testing/Tests/Application/AbstractDomainTest.php b/Classes/Testing/Tests/Application/AbstractDomainTest.php index 6cdd61d49..6c89ca44d 100644 --- a/Classes/Testing/Tests/Application/AbstractDomainTest.php +++ b/Classes/Testing/Tests/Application/AbstractDomainTest.php @@ -145,12 +145,12 @@ protected function findAllRootPages(): Result $query->select('uid') ->from('pages') ->where( - $query->expr()->andX( + $query->expr()->and( $query->expr()->eq('is_siteroot', $query->createNamedParameter(1)), $query->expr()->eq('sys_language_uid', $query->createNamedParameter(0)), ), ); - return $query->execute(); + return $query->executeQuery(); } protected function determineDomainTypes(array $pageIds): array diff --git a/Classes/Testing/Tests/Database/DatabaseDifferencesTest.php b/Classes/Testing/Tests/Database/DatabaseDifferencesTest.php index 56c62590d..622218954 100644 --- a/Classes/Testing/Tests/Database/DatabaseDifferencesTest.php +++ b/Classes/Testing/Tests/Database/DatabaseDifferencesTest.php @@ -217,7 +217,7 @@ protected function areDifferentDatabases(Connection $local, Connection $foreign) $statement = $query->select('*') ->from('tx_in2code_in2publish_task') ->where($query->expr()->eq('task_type', $query->createNamedParameter('Backend Test'))) - ->execute(); + ->executeQuery(); $identical = false; while ($result = $statement->fetchAssociative()) { if ($uid === (int)$result['uid'] && $random === (int)$result['configuration']) { @@ -234,7 +234,7 @@ protected function areDifferentDatabases(Connection $local, Connection $foreign) protected function readTableStructure(Connection $database): array { $tableStructure = []; - $tables = $database->getSchemaManager()->listTables(); + $tables = $database->createSchemaManager()->listTables(); foreach ($tables as $table) { $tableName = $table->getName(); @@ -244,7 +244,7 @@ protected function readTableStructure(Connection $database): array } $fieldStructure = []; - $fields = $database->getSchemaManager()->listTableColumns($tableName); + $fields = $database->createSchemaManager()->listTableColumns($tableName); foreach ($fields as $field) { $fieldName = $field->getName(); $fieldStructure[$fieldName] = [ diff --git a/Classes/Utility/BackendUtility.php b/Classes/Utility/BackendUtility.php index 814552f74..22ee1e44e 100755 --- a/Classes/Utility/BackendUtility.php +++ b/Classes/Utility/BackendUtility.php @@ -29,6 +29,7 @@ */ use Closure; +use Doctrine\DBAL\Exception; use In2code\In2publishCore\Service\Database\RawRecordService; use In2code\In2publishCore\Service\Environment\ForeignEnvironmentService; use In2code\In2publishCore\Service\Routing\SiteService; @@ -86,6 +87,7 @@ class BackendUtility * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.IfStatementAssignment) * @noinspection CallableParameterUseCaseInTypeContextInspection + * @throws Exception */ public static function getPageIdentifier($identifier = null, string $table = null) { @@ -133,7 +135,10 @@ public static function getPageIdentifier($identifier = null, string $table = nul } $localConnection = DatabaseUtility::buildLocalDatabaseConnection(); - $tableNames = $localConnection->getSchemaManager()->listTableNames(); + if (null === $localConnection) { + return 0; + } + $tableNames = $localConnection->createSchemaManager()->listTableNames(); // get id from record ?data[tt_content][13]=foo $data = GeneralUtility::_GP('data'); @@ -158,7 +163,7 @@ public static function getPageIdentifier($identifier = null, string $table = nul ->from($table) ->where($query->expr()->eq('uid', (int)key($data[$table]))) ->setMaxResults(1) - ->execute() + ->executeQuery() ->fetchAssociative(); if (false !== $result && isset($result['pid'])) { return (int)$result['pid']; @@ -180,7 +185,7 @@ public static function getPageIdentifier($identifier = null, string $table = nul ->from($rollbackData[0]) ->where($query->expr()->eq('uid', (int)$rollbackData[1])) ->setMaxResults(1) - ->execute() + ->executeQuery() ->fetchAssociative(); if (false !== $result && isset($result['pid'])) { return (int)$result['pid']; @@ -197,7 +202,7 @@ public static function getPageIdentifier($identifier = null, string $table = nul ->from($table) ->where($query->expr()->eq('uid', (int)$identifier)) ->setMaxResults(1) - ->execute() + ->executeQuery() ->fetchAssociative(); if (isset($row['pid'])) { return (int)$row['pid']; @@ -210,12 +215,6 @@ public static function getPageIdentifier($identifier = null, string $table = nul /** * Please don't blame me for this. * - * @param string $table - * @param int $identifier - * @param string $stagingLevel - * - * @return UriInterface|null - * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -338,8 +337,6 @@ protected static function parseAdditionalGetParameters(array &$parameters, array } /** - * @return VariableFrontend - * * @throws NoSuchCacheException */ protected static function getRuntimeCache(): VariableFrontend @@ -419,11 +416,6 @@ protected static function getLocalUriClosure(Site $site, int $pageUid, array $ad } /** - * @param Site $site - * @param int $language - * @param int $pageUid - * - * @return string * @throws AspectNotFoundException */ protected static function getPageRepositoryPageCacheIdentifier(Site $site, int $language, int $pageUid): string diff --git a/Classes/Utility/DatabaseUtility.php b/Classes/Utility/DatabaseUtility.php index be1aa0a5b..e775286a7 100755 --- a/Classes/Utility/DatabaseUtility.php +++ b/Classes/Utility/DatabaseUtility.php @@ -201,7 +201,7 @@ public static function getTreeList($id, $depth, $begin = 0, $permClause = ''): s if ($permClause !== '') { $queryBuilder->andWhere(self::stripLogicalOperatorPrefix($permClause)); } - $statement = $queryBuilder->execute(); + $statement = $queryBuilder->executeQuery(); while ($row = $statement->fetchAssociative()) { if ($begin <= 0) { $theList .= ',' . $row['uid']; diff --git a/Tests/Functional/Features/PreventParallelPublishing/Service/RunningRequestServiceTest.php b/Tests/Functional/Features/PreventParallelPublishing/Service/RunningRequestServiceTest.php index c9e3260c2..9561a3f65 100644 --- a/Tests/Functional/Features/PreventParallelPublishing/Service/RunningRequestServiceTest.php +++ b/Tests/Functional/Features/PreventParallelPublishing/Service/RunningRequestServiceTest.php @@ -52,18 +52,18 @@ public function testRecordWithMmRecordCanBeMarkedAsPublishing(): void $query->select('*') ->from('tx_in2publishcore_running_request') ->where( - $query->expr()->orX( - $query->expr()->andX( + $query->expr()->or( + $query->expr()->and( $query->expr()->eq('record_id', 1), $query->expr()->eq('table_name', $query->createNamedParameter('foo')), ), - $query->expr()->andX( + $query->expr()->and( $query->expr()->eq('record_id', $query->createNamedParameter($mmId)), $query->expr()->eq('table_name', $query->createNamedParameter('foo_bar_mm')), ), ), ); - $result = $query->execute(); + $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); $this->assertCount(2, $rows); } From 48025e24179d975449ab14595670fd1440410401 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 15:34:18 +0100 Subject: [PATCH 055/113] [BUGFIX] Show colors of badges in file module again --- Resources/Private/Sass/_ModulesGeneral.scss | 9 ++++++--- Resources/Public/Css/Modules.css | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index 79764e145..79a594130 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -705,10 +705,11 @@ div#typo3-docbody.stopScrolling { } } -.in2publish-badge { +.badge.in2publish-badge { &--unchanged { - color: #000!important; - background-color: $nobel!important; + color: #000; + background-color: $nobel; + color: white; } &--changed { @@ -721,10 +722,12 @@ div#typo3-docbody.stopScrolling { &--added { background-color: $apple; + color: white; } &--deleted { background-color: $appleblossom; + color: white; } &--moved { diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index b9757b534..a5d33774e 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.in2publish-badge--unchanged{color:#000 !important;background-color:#9C9C9C !important}.in2publish-badge--changed{background-color:#FFCA4B}.in2publish-badge--moved-and-changed{background-color:#FFCA4B}.in2publish-badge--added{background-color:#5D9A46}.in2publish-badge--deleted{background-color:#A94442}.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%} From d3d1079964833d6d03d310a9d64e9b57169d1af3 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 8 Nov 2023 15:38:57 +0100 Subject: [PATCH 056/113] [BUGFIX] Tighten Colors between v11 & v12 --- Resources/Private/Sass/_ModulesGeneral.scss | 2 ++ Resources/Public/Css/Modules.css | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index 79a594130..17c424203 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -714,10 +714,12 @@ div#typo3-docbody.stopScrolling { &--changed { background-color: $goldentainoi; + color: black; } &--moved-and-changed { background-color: $goldentainoi; + color: black; } &--added { diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index a5d33774e..f629dc933 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%} From 2b9702da1da3a3c864d868d9c76e12dc4f03189d Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 9 Nov 2023 11:00:22 +0100 Subject: [PATCH 057/113] [BUGFIX] Define (namespaced) constants for TYPO3 version for easier up/down-compatibility --- composer.json | 5 ++++- constants.php | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 constants.php diff --git a/composer.json b/composer.json index d10f0c37d..94e31febd 100755 --- a/composer.json +++ b/composer.json @@ -59,7 +59,10 @@ "autoload": { "psr-4": { "In2code\\In2publishCore\\": "Classes" - } + }, + "files": [ + "constants.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/constants.php b/constants.php new file mode 100644 index 000000000..c7c9326ed --- /dev/null +++ b/constants.php @@ -0,0 +1,22 @@ +getMajorVersion(); + + if (!defined('In2code\In2publishCore\TYPO3_V11')) { + define('In2code\In2publishCore\TYPO3_V11', 11 === $majorVersion); + } + if (!(defined('In2code\In2publishCore\TYPO3_V12'))) { + define('In2code\In2publishCore\TYPO3_V12', 12 === $majorVersion); + } +})(); From b9b63b1fe890295067252242d4996c75921a1495 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 11:16:44 +0100 Subject: [PATCH 058/113] [REFACTOR] Replace version_compare calls with TYPO3_V11 constant --- Classes/Backend/Button/ModuleShortcutButton.php | 7 +++---- .../ContextMenu/PublishItemProvider.php | 7 +++---- Classes/Testing/Tests/SshConnection/SshConnectionTest.php | 7 +++---- Configuration/Services.php | 7 ++++--- ext_tables.php | 7 +++---- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Classes/Backend/Button/ModuleShortcutButton.php b/Classes/Backend/Button/ModuleShortcutButton.php index 8282313de..d4a8d01ca 100644 --- a/Classes/Backend/Button/ModuleShortcutButton.php +++ b/Classes/Backend/Button/ModuleShortcutButton.php @@ -32,13 +32,13 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Module\ExtbaseModule; use TYPO3\CMS\Backend\Template\Components\Buttons\Action\ShortcutButton; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Routing\Route; use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use function ucfirst; -use function version_compare; + +use const In2code\In2publishCore\TYPO3_V11; class ModuleShortcutButton extends ShortcutButton { @@ -49,8 +49,7 @@ public function setRequest(ServerRequestInterface $request): void $arguments = $request->getQueryParams(); $pageId = $request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? null; - $typo3Version = new Typo3Version(); - if (version_compare($typo3Version->getVersion(), '12', '<')) { + if (TYPO3_V11) { $modConf = $route->getOption('moduleConfiguration'); $displayName = LocalizationUtility::translate($modConf['labels'] . ':mlang_tabs_tab'); } else { diff --git a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php index 59b5bb7d0..3e4c5efc1 100644 --- a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php +++ b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php @@ -35,11 +35,11 @@ use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use function func_get_args; -use function version_compare; + +use const In2code\In2publishCore\TYPO3_V11; class PublishItemProvider extends AbstractProvider { @@ -54,8 +54,7 @@ class PublishItemProvider extends AbstractProvider public function __construct() { - $typo3Version = new Typo3Version(); - if (version_compare($typo3Version->getVersion(), '12', '<')) { + if (TYPO3_V11) { parent::__construct(...func_get_args()); } diff --git a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php index b7a03e71d..e7262b419 100644 --- a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php +++ b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php @@ -35,12 +35,13 @@ use In2code\In2publishCore\Testing\Tests\TestCaseInterface; use In2code\In2publishCore\Testing\Tests\TestResult; use Throwable; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_diff; use function preg_match; +use const In2code\In2publishCore\TYPO3_V11; + class SshConnectionTest implements TestCaseInterface { use ConfigContainerInjection; @@ -101,9 +102,7 @@ public function run(): TestResult 'typo3', 'index.php', ]; - /** @var Typo3Version $versionInformation */ - $typo3Version = new Typo3Version(); - if (version_compare($typo3Version->getVersion(), '12', '<')) { + if (TYPO3_V11) { $requiredNames[] = 'typo3conf'; } diff --git a/Configuration/Services.php b/Configuration/Services.php index 03e283e22..796b9bba9 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -12,9 +12,10 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use TYPO3\CMS\Core\DependencyInjection\PublicServicePass; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; +use const In2code\In2publishCore\TYPO3_V11; + return static function (ContainerConfigurator $configurator, ContainerBuilder $builder): void { $configurator->import('Component/*/Services.php'); $configurator->import('Features/*/Services.php'); @@ -34,8 +35,8 @@ $pageTypeServiceDefinition->setAutowired(true); $pageTypeServiceDefinition->setShared(true); $pageTypeServiceDefinition->setPublic(true); - $typo3version = new Typo3Version(); - if (version_compare($typo3version->getVersion(), '12', '<')) { + + if (TYPO3_V11) { $pageTypeServiceDefinition->setClass(LegacyPageTypeService::class); } else { $pageTypeServiceDefinition->setClass(PageTypeRegistryService::class); diff --git a/ext_tables.php b/ext_tables.php index 48e52883f..641dc283e 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -34,7 +34,8 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\ExtensionUtility; -use TYPO3\CMS\Core\Information\Typo3Version; + +use const In2code\In2publishCore\TYPO3_V11; (static function (): void { /***************************************************** Guards *****************************************************/ @@ -51,8 +52,6 @@ $contextService = GeneralUtility::makeInstance(ContextService::class); $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); $isForeign = $contextService->isForeign(); - /** @var Typo3Version $versionInformation */ - $typo3Version = new Typo3Version(); /******************************************* Colorize the BE on Foreign *******************************************/ if ($isForeign && $configContainer->get('features.warningOnForeign.colorizeHeader.enable')) { @@ -64,7 +63,7 @@ return; } - if (version_compare($typo3Version->getVersion(), '12', '<')) { + if (TYPO3_V11) { /** * Deprecated registering of Backend Modules * Register Backend Modules for TYPO3 v11 From aa9fbae67227e70eb15d0587c569255744550ba4 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 12:06:59 +0100 Subject: [PATCH 059/113] [REFACTOR] Remove outdated overlay div --- Resources/Private/Layouts/File.html | 2 -- Resources/Private/Layouts/Record.html | 2 -- 2 files changed, 4 deletions(-) diff --git a/Resources/Private/Layouts/File.html b/Resources/Private/Layouts/File.html index 4ca88107b..e760a654c 100755 --- a/Resources/Private/Layouts/File.html +++ b/Resources/Private/Layouts/File.html @@ -1,6 +1,4 @@ -
- diff --git a/Resources/Private/Layouts/Record.html b/Resources/Private/Layouts/Record.html index 841376007..e33d7054a 100755 --- a/Resources/Private/Layouts/Record.html +++ b/Resources/Private/Layouts/Record.html @@ -1,6 +1,4 @@ -
-
From 0195f19726fdf570862a89fec30fdb1aa18f2cde Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 12:07:43 +0100 Subject: [PATCH 060/113] [BUGFIX] Change order of flashmessage container With this change the TYPO3 Core Styling is used --- Resources/Private/Layouts/Record.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Resources/Private/Layouts/Record.html b/Resources/Private/Layouts/Record.html index e33d7054a..e9ddbbb40 100755 --- a/Resources/Private/Layouts/Record.html +++ b/Resources/Private/Layouts/Record.html @@ -1,10 +1,12 @@
-
+
- - + +
+ +
From 3d7133571f427d6a22df04c9dbc47e03014d01f3 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 12:09:16 +0100 Subject: [PATCH 061/113] [BUGFIX] Jumpmenu Label is now rendered inline The height of the DocHeader is correct again --- Classes/Controller/RecordController.php | 2 ++ Resources/Private/Sass/_ModulesGeneral.scss | 11 +++++++++++ Resources/Public/Css/Modules.css | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index 8f9ea068c..ec957d042 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -120,6 +120,8 @@ public function initializeIndexAction(): void $this->request = $this->request->withArgument('pageRecursionLimit', $data['pageRecursionLimit'] ?? 1); } + $this->moduleTemplate->setModuleClass('in2publish_core_m1'); + $menuRegistry = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry(); $menu = $menuRegistry->makeMenu(); $menu->setIdentifier('depth'); diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index 17c424203..0a1657c29 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -773,3 +773,14 @@ div#typo3-docbody.stopScrolling { width: 50%; } } + +.in2publish_core_m1 { + .module-docheader-bar-column-left { + .form-group { + display: flex; + .form-select { + margin-left: 1em; + } + } + } +} diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index f629dc933..be9834e7c 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} From 3ca841ea12f7c695c03b2f02ad0f75e6ee9a6124 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 12:33:39 +0100 Subject: [PATCH 062/113] [BUGFIX] Add Padding at the Top of the module --- Resources/Private/Sass/_ModulesGeneral.scss | 1 + Resources/Public/Css/Modules.css | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index 0a1657c29..cef270d96 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -53,6 +53,7 @@ div.typo3-fullDoc { .in2publish-backend { font-size: 15px; color: $white; + padding-top: 1em; h1, h2, diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index be9834e7c..bd696fa2b 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff;padding-top:1em}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} From 1f1d231c46ed953eced733acc05e6191f018fa7c Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 13:18:14 +0100 Subject: [PATCH 063/113] [BUGFIX] Corrects styling of redirects module Resolves: https://projekte.in2code.de/issues/60145 --- .../Private/Partials/Redirect/Filter.html | 130 +++++++++--------- .../Private/Templates/Redirect/List.html | 30 ++-- 2 files changed, 82 insertions(+), 78 deletions(-) diff --git a/Resources/Private/Partials/Redirect/Filter.html b/Resources/Private/Partials/Redirect/Filter.html index 3c48c4ee9..d5f4231ea 100644 --- a/Resources/Private/Partials/Redirect/Filter.html +++ b/Resources/Private/Partials/Redirect/Filter.html @@ -3,73 +3,75 @@ data-namespace-typo3-fluid="true" > -
- - -
-
- - -
-
- - -
-
- - -
-
- - +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + -
-
- + class="form-select" + prependOptionLabel="{f:translate(key: 'LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.source_host.showAll')}" + prependOptionValue="" + /> +
+
+ +
diff --git a/Resources/Private/Templates/Redirect/List.html b/Resources/Private/Templates/Redirect/List.html index 4a0263164..5bee90836 100644 --- a/Resources/Private/Templates/Redirect/List.html +++ b/Resources/Private/Templates/Redirect/List.html @@ -1,23 +1,24 @@ -

TYPO3 Content Publisher - publish redirects

- - - +
+ +
- - +
+
+ @@ -26,8 +27,8 @@

- - + + @@ -91,9 +92,9 @@

- - - + + + @@ -102,9 +103,10 @@

- - -
{redirect.id}
+ + + +
From 7177e3848fbb357f44e0e5d6ec16d7c2d62413bc Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 9 Nov 2023 14:04:20 +0100 Subject: [PATCH 064/113] [DOC] Add documentation for changed ext_typoscript_template suffix --- ...king-ExtTyposcriptTemplateChangedSuffix.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md diff --git a/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md b/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md new file mode 100644 index 000000000..a855eac7b --- /dev/null +++ b/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md @@ -0,0 +1,19 @@ +# ext_typoscript_setup changed suffix + +Breaking Change TYPO3 https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/12.0/Breaking-96518-Ext_typoscript_txtFilesNotIncludedAnymore.html + +## Description + +The suffix of the `ext_typoscript_setup` has been changed from `.txt` to `.typoscript`. + +## Impact + + +## Affected Installations + +All installations that overwrite Content Publisher module templates and explicitly including the file +`EXT:in2publish_core/ext_typoscript_setup.txt` either via include statement of in the backend. + +## Migration + +* Include the file `EXT:in2publish_core/ext_typoscript_setup.typoscript` instead of `EXT:in2publish_core/ext_typoscript_setup.txt`. From 33a0e22a07c8c652f0e07d3a39e875c9a1919e2d Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 10 Nov 2023 21:50:01 +0100 Subject: [PATCH 065/113] [BUGFIX] Fetch folder records with demand/resolver structure --- .phpstorm.meta.php | 4 +- .../Core/Demand/Type/FilesInFolderDemand.php | 34 +++ .../Core/Demand/Type/FolderDemand.php | 34 +++ .../Demand/Type/FoldersInFolderDemand.php | 34 +++ .../Filesystem}/FileDemandResolver.php | 33 +-- .../FilesInFolderDemandResolver.php | 221 ++++++++++++++ .../Filesystem/FolderDemandResolver.php | 72 +++++ .../FoldersInFolderDemandResolver.php | 84 ++++++ .../Filesystem/Model/FileInfo.php | 109 +++++++ .../Filesystem/Model/FilesystemInfo.php | 14 + .../Model/FilesystemInformationCollection.php | 37 +++ .../Filesystem/Model/FolderInfo.php | 67 +++++ .../Filesystem/Model/MissingFileInfo.php | 32 ++ .../Filesystem/Model/MissingFolderInfo.php | 32 ++ .../Filesystem}/Service/FalDriverService.php | 36 +-- .../Service/FalDriverServiceInjection.php | 2 +- .../Filesystem/Service/FileInfoService.php | 39 +++ .../Service/FileInfoServiceInjection.php | 21 ++ .../Service/ForeignFileInfoService.php | 22 ++ .../ForeignFileInfoServiceInjection.php | 22 ++ .../Service/ForeignFolderInfoService.php | 33 +++ .../ForeignFolderInfoServiceInjection.php | 21 ++ .../Service/LocalFileInfoService.php | 27 ++ .../Service/LocalFileInfoServiceInjection.php | 21 ++ .../Service/LocalFolderInfoService.php | 68 +++++ .../LocalFolderInfoServiceInjection.php | 21 ++ .../Service/SharedFilesystemInfoCache.php | 44 +++ .../SharedFilesystemInfoCacheInjection.php | 21 ++ .../Core/FileHandling/DefaultFalFinder.php | 275 ++++-------------- .../Service/FileSystemInfoService.php | 64 ---- .../FileSystemInfoServiceInjection.php | 21 -- .../Service/ForeignFileSystemInfoService.php | 89 ------ .../ForeignFileSystemInfoServiceInjection.php | 21 -- .../Publisher/Command/FalPublisherCommand.php | 2 +- .../Core/Publisher/FileRecordPublisher.php | 2 +- .../Instruction/AddFileInstruction.php | 2 +- .../Instruction/AddFolderInstruction.php | 2 +- .../Instruction/DeleteFileInstruction.php | 2 +- .../Instruction/DeleteFolderInstruction.php | 2 +- .../Instruction/MoveFileInstruction.php | 2 +- .../Instruction/PublishInstruction.php | 2 +- .../ReplaceAndRenameFileInstruction.php | 2 +- .../Instruction/ReplaceFileInstruction.php | 2 +- .../Core/Record/Factory/RecordFactory.php | 9 +- .../Core/Record/Model/AbstractRecord.php | 28 +- .../Core/Record/Model/FolderRecord.php | 30 +- .../Component/Core/RecordTree/RecordTree.php | 7 +- .../EnvelopeDispatcher.php | 36 +-- .../EnvelopeSendingFailedException.php | 2 +- .../ExecuteCommandDispatcher.php | 57 ++++ .../ExecuteCommandDispatcherInjection.php | 21 ++ Classes/Controller/FileController.php | 20 +- .../EventListener}/FileRecordListener.php | 11 +- .../Testing/Tests/Fal/MissingStoragesTest.php | 4 +- .../Tests/Fal/UniqueStorageTargetTest.php | 12 +- Configuration/Component/Core/Services.yaml | 11 - .../ResolveFilesForIndices/Services.yaml | 19 ++ .../Private/Partials/File/FolderList.html | 2 +- .../Status/DbConfigTestCommandTest.php | 2 +- .../FileHandling/FileDemandResolverTest.php | 98 ++++--- .../FileHandling/FileRecordListenerTest.php | 6 +- .../Publisher/FolderRecordPublisherTest.php | 17 +- .../Core/Record/Factory/RecordFactoryTest.php | 1 - .../Core/Record/Model/FolderRecordTest.php | 18 +- .../Core/RecordTree/RecordTreeBuilderTest.php | 6 +- .../Service/ReplaceMarkersServiceTest.php | 6 - Tests/Unit/Utility/BackendUtilityTest.php | 18 +- 67 files changed, 1467 insertions(+), 669 deletions(-) create mode 100644 Classes/Component/Core/Demand/Type/FilesInFolderDemand.php create mode 100644 Classes/Component/Core/Demand/Type/FolderDemand.php create mode 100644 Classes/Component/Core/Demand/Type/FoldersInFolderDemand.php rename Classes/Component/Core/{FileHandling => DemandResolver/Filesystem}/FileDemandResolver.php (60%) create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/FilesInFolderDemandResolver.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/FolderDemandResolver.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/FoldersInFolderDemandResolver.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/FileInfo.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/FilesystemInfo.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/FilesystemInformationCollection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/FolderInfo.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFileInfo.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFolderInfo.php rename Classes/Component/Core/{FileHandling => DemandResolver/Filesystem}/Service/FalDriverService.php (75%) rename Classes/Component/Core/{FileHandling => DemandResolver/Filesystem}/Service/FalDriverServiceInjection.php (80%) create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoServiceInjection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoService.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoServiceInjection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoService.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoServiceInjection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoService.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoServiceInjection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoService.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoServiceInjection.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCache.php create mode 100644 Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCacheInjection.php delete mode 100644 Classes/Component/Core/FileHandling/Service/FileSystemInfoService.php delete mode 100644 Classes/Component/Core/FileHandling/Service/FileSystemInfoServiceInjection.php delete mode 100644 Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoService.php delete mode 100644 Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoServiceInjection.php rename Classes/Component/{Core/FileHandling/Service => RemoteProcedureCall}/Exception/EnvelopeSendingFailedException.php (85%) create mode 100644 Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcher.php create mode 100644 Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcherInjection.php rename Classes/{Component/Core/FileHandling => Features/ResolveFilesForIndices/EventListener}/FileRecordListener.php (92%) create mode 100644 Configuration/Features/ResolveFilesForIndices/Services.yaml diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 802b198bf..dca57dd18 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -42,9 +42,9 @@ expectedArguments( \In2code\In2publishCore\Component\RemoteProcedureCall\Envelope::__construct(), 0, - \In2code\In2publishCore\Component\RemoteProcedureCall\EnvelopeDispatcher::CMD_FOLDER_EXISTS, + \In2code\In2publishCore\Component\RemoteProcedureCall\EnvelopeDispatcher::CMD_GET_FOLDER_INFO, + \In2code\In2publishCore\Component\RemoteProcedureCall\EnvelopeDispatcher::CMD_GET_FILE_INFO, \In2code\In2publishCore\Component\RemoteProcedureCall\EnvelopeDispatcher::CMD_FILE_EXISTS, - \In2code\In2publishCore\Component\RemoteProcedureCall\EnvelopeDispatcher::CMD_LIST_FOLDER_CONTENTS, ); expectedArguments( \In2code\In2publishCore\Component\ConfigContainer\Builder::addNode(), diff --git a/Classes/Component/Core/Demand/Type/FilesInFolderDemand.php b/Classes/Component/Core/Demand/Type/FilesInFolderDemand.php new file mode 100644 index 000000000..c94875903 --- /dev/null +++ b/Classes/Component/Core/Demand/Type/FilesInFolderDemand.php @@ -0,0 +1,34 @@ +storage = $storage; + $this->parentFolderIdentifier = $parentFolderIdentifier; + $this->record = $record; + } + + public function addToDemandsArray(array &$demands): void + { + $uniqueRecordKey = $this->createUniqueRecordKey($this->record); + $demands[$this->storage][$this->parentFolderIdentifier][$uniqueRecordKey] = $this->record; + } + + public function addToMetaArray(array &$meta, array $frame): void + { + $meta[$this->storage][$this->parentFolderIdentifier][] = $frame; + } +} diff --git a/Classes/Component/Core/Demand/Type/FolderDemand.php b/Classes/Component/Core/Demand/Type/FolderDemand.php new file mode 100644 index 000000000..38c9a77bf --- /dev/null +++ b/Classes/Component/Core/Demand/Type/FolderDemand.php @@ -0,0 +1,34 @@ +storage = $storage; + $this->identifier = $identifier; + $this->record = $record; + } + + public function addToDemandsArray(array &$demands): void + { + $uniqueRecordKey = $this->createUniqueRecordKey($this->record); + $demands[$this->storage][$this->identifier][$uniqueRecordKey] = $this->record; + } + + public function addToMetaArray(array &$meta, array $frame): void + { + $meta[$this->storage][$this->identifier][] = $frame; + } +} diff --git a/Classes/Component/Core/Demand/Type/FoldersInFolderDemand.php b/Classes/Component/Core/Demand/Type/FoldersInFolderDemand.php new file mode 100644 index 000000000..e0359ad30 --- /dev/null +++ b/Classes/Component/Core/Demand/Type/FoldersInFolderDemand.php @@ -0,0 +1,34 @@ +storage = $storage; + $this->parentFolderIdentifier = $parentFolderIdentifier; + $this->record = $record; + } + + public function addToDemandsArray(array &$demands): void + { + $uniqueRecordKey = $this->createUniqueRecordKey($this->record); + $demands[$this->storage][$this->parentFolderIdentifier][$uniqueRecordKey] = $this->record; + } + + public function addToMetaArray(array &$meta, array $frame): void + { + $meta[$this->storage][$this->parentFolderIdentifier][] = $frame; + } +} diff --git a/Classes/Component/Core/FileHandling/FileDemandResolver.php b/Classes/Component/Core/DemandResolver/Filesystem/FileDemandResolver.php similarity index 60% rename from Classes/Component/Core/FileHandling/FileDemandResolver.php rename to Classes/Component/Core/DemandResolver/Filesystem/FileDemandResolver.php index 20e840cee..67fd2d336 100644 --- a/Classes/Component/Core/FileHandling/FileDemandResolver.php +++ b/Classes/Component/Core/DemandResolver/Filesystem/FileDemandResolver.php @@ -2,24 +2,24 @@ declare(strict_types=1); -namespace In2code\In2publishCore\Component\Core\FileHandling; +namespace In2code\In2publishCore\Component\Core\DemandResolver\Filesystem; use In2code\In2publishCore\Component\Core\Demand\Demands; use In2code\In2publishCore\Component\Core\Demand\Type\FileDemand; use In2code\In2publishCore\Component\Core\DemandResolver\DemandResolver; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FileSystemInfoServiceInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\ForeignFileSystemInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FilesystemInformationCollection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\ForeignFileInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\LocalFileInfoServiceInjection; use In2code\In2publishCore\Component\Core\Record\Factory\RecordFactoryInjection; use In2code\In2publishCore\Component\Core\RecordCollection; use function array_keys; -use function hash; class FileDemandResolver implements DemandResolver { use RecordFactoryInjection; - use ForeignFileSystemInfoServiceInjection; - use FileSystemInfoServiceInjection; + use LocalFileInfoServiceInjection; + use ForeignFileInfoServiceInjection; public function resolveDemand(Demands $demands, RecordCollection $recordCollection): void { @@ -35,9 +35,9 @@ public function resolveDemand(Demands $demands, RecordCollection $recordCollecti } } - $localDriverInfo = $this->fileSystemInfoService->getFileInfo($filesArray); + $localDriverInfo = $this->localFileInfoService->getFileInfo($filesArray); $localFileInfo = $this->addFileInfoToDriverInfo($files, $localDriverInfo); - $foreignDriverInfo = $this->foreignFileSystemInfoService->getFileInfo($filesArray); + $foreignDriverInfo = $this->foreignFileInfoService->getFileInfo($filesArray); $foreignFileInfo = $this->addFileInfoToDriverInfo($files, $foreignDriverInfo); foreach ($files as $storage => $identifiers) { @@ -57,24 +57,13 @@ public function resolveDemand(Demands $demands, RecordCollection $recordCollecti } } - protected function addFileInfoToDriverInfo(array $files, array $driverInfo): array + protected function addFileInfoToDriverInfo(array $files, FilesystemInformationCollection $driverInfo): array { $result = []; foreach ($files as $storage => $identifiers) { foreach ($identifiers as $identifier => $parentRecords) { - if (isset($driverInfo[$storage][$identifier])) { - $fileInfo = $driverInfo[$storage][$identifier]; - $result[$storage][$identifier] = [ - 'storage' => $storage, - 'identifier' => $identifier, - 'identifier_hash' => hash('sha1', $identifier), - 'size' => $fileInfo['size'], - 'mimetype' => $fileInfo['mimetype'], - 'name' => $fileInfo['name'], - 'extension' => $fileInfo['extension'], - 'folder_hash' => $fileInfo['folder_hash'], - ]; - } + $fileInfo = $driverInfo->getInfo($storage, $identifier); + $result[$storage][$identifier] = $fileInfo->toArray(); } } return $result; diff --git a/Classes/Component/Core/DemandResolver/Filesystem/FilesInFolderDemandResolver.php b/Classes/Component/Core/DemandResolver/Filesystem/FilesInFolderDemandResolver.php new file mode 100644 index 000000000..53869acfa --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/FilesInFolderDemandResolver.php @@ -0,0 +1,221 @@ +>> $filesInFolderDemands */ + $filesInFolderDemands = $demands->getDemandsByType(FilesInFolderDemand::class); + if (empty($filesInFolderDemands)) { + return; + } + + $fileDemands = $this->demandsFactory->createDemand(); + + $request = []; + foreach ($filesInFolderDemands as $storage => $parentFolderIdentifier) { + $request[$storage] = array_keys($parentFolderIdentifier); + } + + $localResponseCollection = $this->localFolderInfoService->getFolderInfo($request); + $foreignResponseCollection = $this->foreignFolderInfoService->getFolderInformation($request); + + foreach ($filesInFolderDemands as $storage => $parentIdentifiers) { + foreach ($parentIdentifiers as $parentIdentifier => $valueMap) { + $localInfo = $localResponseCollection->getInfo($storage, $parentIdentifier); + $foreignInfo = $foreignResponseCollection->getInfo($storage, $parentIdentifier); + + /** @var array $mergedFiles */ + $mergedFiles = []; + if ($localInfo instanceof FolderInfo) { + $localFiles = $localInfo->getFiles(); + foreach ($localFiles as $localFile) { + $identifier = $localFile->getIdentifier(); + $storage = $localFile->getStorage(); + $mergedFiles[$identifier]['local'] = $localFile; + $mergedFiles[$identifier]['foreign'] = new MissingFileInfo($storage, $identifier); + } + } + if ($foreignInfo instanceof FolderInfo) { + $foreignFiles = $foreignInfo->getFiles(); + foreach ($foreignFiles as $foreignFile) { + $identifier = $foreignFile->getIdentifier(); + $storage = $foreignFile->getStorage(); + $mergedFiles[$identifier]['local'] ??= new MissingFileInfo($storage, $identifier); + $mergedFiles[$identifier]['foreign'] = $foreignFile; + } + } + foreach ($mergedFiles as $mergedFile) { + $fileRecord = $this->recordFactory->createFileRecord( + $mergedFile['local']->toArray(), + $mergedFile['foreign']->toArray(), + ); + if (null !== $fileRecord) { + $recordCollection->addRecord($fileRecord); + foreach ($valueMap as $record) { + $record->addChild($fileRecord); + } + $fileDemands->addDemand( + new SelectDemand( + 'sys_file', + 'storage = ' . $fileRecord->getProp('storage'), + 'identifier_hash', + $fileRecord->getProp('identifier_hash'), + $fileRecord, + ), + ); + } + } + } + } + + $fileRecordCollection = new RecordCollection(); + $this->demandResolver->resolveDemand($fileDemands, $fileRecordCollection); + $this->recordTreeBuilder->findRecordsByTca($fileRecordCollection); + + foreach ($request as $storage => $parentFolderIdentifiers) { + foreach ($parentFolderIdentifiers as $parentFolderIdentifier) { + /** @var FolderRecord $folderRecord */ + $folderRecord = $this->recordIndex->getRecord( + FolderRecord::CLASSIFICATION, + $storage . ':' . $parentFolderIdentifier, + ); + $this->identifyMovedRecords($folderRecord); + } + } + } + + protected function identifyMovedRecords(FolderRecord $folderRecord): void + { + /** @var array $fileRecords */ + $fileRecords = []; + $sysFileRecordCollection = new RecordCollection(); + foreach ($folderRecord->getChildren()[FileRecord::CLASSIFICATION] ?? [] as $filesInFolder) { + $fileRecords[$filesInFolder->getProp('identifier')] = $filesInFolder; + $sysFileRecordCollection->addRecords($filesInFolder->getChildren()['sys_file'] ?? []); + } + + $filesMovedOutFromFolder = []; + $filesMovedIntoFolder = []; + + $sysFileRecords = $sysFileRecordCollection->getRecords('sys_file'); + foreach ($sysFileRecords as $sysFileRecord) { + if ($sysFileRecord->getState() === Record::S_CHANGED) { + $localProps = $sysFileRecord->getLocalProps(); + $foreignProps = $sysFileRecord->getForeignProps(); + $localIdentifier = $localProps['identifier']; + $foreignIdentifier = $foreignProps['identifier']; + if ($localIdentifier !== $foreignIdentifier) { + $fileRecord = $fileRecords[$localIdentifier] ?? null; + if (null === $fileRecord || empty($fileRecord->getLocalProps())) { + $filesMovedOutFromFolder[$localProps['storage']][] = $localIdentifier; + } + $fileRecord = $fileRecords[$foreignIdentifier] ?? null; + if (null === $fileRecord || empty($fileRecord->getForeignProps())) { + $filesMovedIntoFolder[$foreignProps['storage']][] = $foreignIdentifier; + } + } + } + } + + if (!empty($filesMovedOutFromFolder)) { + $foundMovedOutFiles = $this->localFileInfoService->getFileInfo($filesMovedOutFromFolder); + foreach ($foundMovedOutFiles as $localInfo) { + $identifier = $localInfo->getIdentifier(); + $fileRecords[$identifier] = $this->recordFactory->createFileRecord($localInfo->toArray(), []); + } + } + if (!empty($filesMovedIntoFolder)) { + $foundMovedIntoFiles = $this->foreignFileInfoService->getFileInfo($filesMovedIntoFolder); + foreach ($foundMovedIntoFiles as $foreignInfo) { + $identifier = $foreignInfo->getIdentifier(); + $fileRecords[$identifier] = $this->recordFactory->createFileRecord([], $foreignInfo->toArray()); + } + } + + foreach ($sysFileRecords as $sysFileRecord) { + if ($sysFileRecord->getState() === Record::S_CHANGED) { + $localIdentifier = $sysFileRecord->getLocalProps()['identifier']; + $foreignIdentifier = $sysFileRecord->getForeignProps()['identifier']; + if ($localIdentifier === $foreignIdentifier) { + continue; + } + + $localFileRecord = $fileRecords[$localIdentifier]; + $foreignFileRecord = $fileRecords[$foreignIdentifier]; + + $folderRecord->removeChild($localFileRecord); + $folderRecord->removeChild($foreignFileRecord); + $localFileRecord->removeChild($sysFileRecord); + $foreignFileRecord->removeChild($sysFileRecord); + + // Special case: A file was renamed and another file with the same name as the old one was uploaded + if (!empty($foreignFileRecord->getLocalProps())) { + $newFileOnForeign = $this->recordFactory->createFileRecord( + $foreignFileRecord->getLocalProps(), + [], + ); + if (null !== $newFileOnForeign) { + $newOnForeignSysFileRecords = $sysFileRecordCollection->getRecordsByProperties('sys_file', [ + 'storage' => $newFileOnForeign->getProp('storage'), + 'identifier' => $newFileOnForeign->getProp('identifier'), + ]); + foreach ($newOnForeignSysFileRecords as $newOnForeignSysFileRecord) { + if (empty($newOnForeignSysFileRecord->getForeignProps())) { + $localFileRecord->removeChild($newOnForeignSysFileRecord); + $foreignFileRecord->removeChild($newOnForeignSysFileRecord); + $newFileOnForeign->addChild($newOnForeignSysFileRecord); + } + } + $folderRecord->addChild($newFileOnForeign); + } + } + $recordToAdd = $this->recordFactory->createFileRecord( + $localFileRecord->getLocalProps(), + $foreignFileRecord->getForeignProps(), + ); + if (null !== $recordToAdd) { + $recordToAdd->addChild($sysFileRecord); + $folderRecord->addChild($recordToAdd); + } + } + } + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/FolderDemandResolver.php b/Classes/Component/Core/DemandResolver/Filesystem/FolderDemandResolver.php new file mode 100644 index 000000000..a23e7a45c --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/FolderDemandResolver.php @@ -0,0 +1,72 @@ +>> $folderDemands */ + $folderDemands = $demands->getDemandsByType(FolderDemand::class); + if (empty($folderDemands)) { + return; + } + + $request = []; + foreach ($folderDemands as $storage => $folderIdentifiers) { + $request[$storage] = array_keys($folderIdentifiers); + } + + $localResponseCollection = $this->localFolderInfoService->getFolderInfo($request); + $foreignResponseCollection = $this->foreignFolderInfoService->getFolderInformation($request); + + foreach ($folderDemands as $storage => $identifiers) { + foreach ($identifiers as $identifier => $valueMap) { + $localInfo = $localResponseCollection->getInfo($storage, $identifier); + $foreignInfo = $foreignResponseCollection->getInfo($storage, $identifier); + + $combinedIdentifier = $storage . ':' . $identifier; + + $folderRecord = $this->recordIndex->getRecord(FolderRecord::CLASSIFICATION, $combinedIdentifier); + if (null === $folderRecord) { + if ($localInfo instanceof MissingFolderInfo && $foreignInfo instanceof MissingFolderInfo) { + continue; + } + + $folderRecord = $this->recordFactory->createFolderRecord( + $localInfo->toArray(), + $foreignInfo->toArray(), + ); + if (null === $folderRecord) { + continue; + } + $recordCollection->addRecord($folderRecord); + } + foreach ($valueMap as $record) { + $record->addChild($folderRecord); + } + } + } + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/FoldersInFolderDemandResolver.php b/Classes/Component/Core/DemandResolver/Filesystem/FoldersInFolderDemandResolver.php new file mode 100644 index 000000000..a7776ee19 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/FoldersInFolderDemandResolver.php @@ -0,0 +1,84 @@ +>> $foldersInFolderDemand */ + $foldersInFolderDemand = $demands->getDemandsByType(FoldersInFolderDemand::class); + if (empty($foldersInFolderDemand)) { + return; + } + + $request = []; + foreach ($foldersInFolderDemand as $storage => $parentFolderIdentifier) { + $request[$storage] = array_keys($parentFolderIdentifier); + } + + $localResponseCollection = $this->localFolderInfoService->getFolderInfo($request); + $foreignResponseCollection = $this->foreignFolderInfoService->getFolderInformation($request); + + foreach ($foldersInFolderDemand as $storage => $parentIdentifiers) { + foreach ($parentIdentifiers as $parentIdentifier => $valueMap) { + $localInfo = $localResponseCollection->getInfo($storage, $parentIdentifier); + $foreignInfo = $foreignResponseCollection->getInfo($storage, $parentIdentifier); + + /** @var array $mergedFolders */ + $mergedFolders = []; + if ($localInfo instanceof FolderInfo) { + $localFolders = $localInfo->getFolders(); + foreach ($localFolders as $localFolder) { + $identifier = $localFolder->getIdentifier(); + $storage = $localFolder->getStorage(); + $mergedFolders[$identifier]['local'] = $localFolder; + $mergedFolders[$identifier]['foreign'] = new MissingFolderInfo($storage, $identifier); + } + } + if ($foreignInfo instanceof FolderInfo) { + $foreignFolders = $foreignInfo->getFolders(); + foreach ($foreignFolders as $foreignFolder) { + $identifier = $foreignFolder->getIdentifier(); + $storage = $foreignFolder->getStorage(); + $mergedFolders[$identifier]['local'] ??= new MissingFolderInfo($storage, $identifier); + $mergedFolders[$identifier]['foreign'] = $foreignFolder; + } + } + foreach ($mergedFolders as $mergedFolder) { + $folderRecord = $this->recordFactory->createFolderRecord( + $mergedFolder['local']->toArray(), + $mergedFolder['foreign']->toArray(), + ); + if (null !== $folderRecord) { + foreach ($valueMap as $record) { + $record->addChild($folderRecord); + } + } + } + } + } + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Model/FileInfo.php b/Classes/Component/Core/DemandResolver/Filesystem/Model/FileInfo.php new file mode 100644 index 000000000..1fd0d69e6 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Model/FileInfo.php @@ -0,0 +1,109 @@ +storage = $storage; + $this->identifier = $identifier; + $this->name = $name; + $this->sha1 = $sha1; + $this->publicUrl = $publicUrl; + $this->size = $size; + $this->mimetype = $mimetype; + $this->extension = $extension; + $this->folderHash = $folderHash; + $this->identifierHash = $identifierHash; + } + + public function getStorage(): int + { + return $this->storage; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function getName(): string + { + return $this->name; + } + + public function getSha1(): string + { + return $this->sha1; + } + + public function getPublicUrl(): string + { + return $this->publicUrl; + } + + public function getSize(): int + { + return $this->size; + } + + public function getMimetype(): string + { + return $this->mimetype; + } + + public function getExtension(): string + { + return $this->extension; + } + + public function getFolderHash(): string + { + return $this->folderHash; + } + + public function getIdentifierHash(): string + { + return $this->identifierHash; + } + + public function toArray(): array + { + return [ + 'storage' => $this->storage, + 'identifier' => $this->identifier, + 'name' => $this->name, + 'sha1' => $this->sha1, + 'publicUrl' => $this->publicUrl, + 'size' => $this->size, + 'mimetype' => $this->mimetype, + 'extension' => $this->extension, + 'folder_hash' => $this->folderHash, + 'identifier_hash' => $this->identifierHash, + ]; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Model/FilesystemInfo.php b/Classes/Component/Core/DemandResolver/Filesystem/Model/FilesystemInfo.php new file mode 100644 index 000000000..b48ab6470 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Model/FilesystemInfo.php @@ -0,0 +1,14 @@ +getStorage(); + $identifier = $filesystemInformation->getIdentifier(); + $this->information[$storage][$identifier] = $filesystemInformation; + } + + public function getInfo(int $storage, string $identifier): FilesystemInfo + { + return $this->information[$storage][$identifier]; + } + + /** + * @return Generator + */ + public function getIterator(): Generator + { + foreach ($this->information as $identifiers) { + foreach ($identifiers as $information) { + yield $information; + } + } + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Model/FolderInfo.php b/Classes/Component/Core/DemandResolver/Filesystem/Model/FolderInfo.php new file mode 100644 index 000000000..54c7f730e --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Model/FolderInfo.php @@ -0,0 +1,67 @@ + */ + protected array $files = []; + /** @var array */ + protected array $folders = []; + + public function __construct(int $storage, string $identifier, string $name) + { + $this->storage = $storage; + $this->identifier = $identifier; + $this->name = $name; + } + + public function getStorage(): int + { + return $this->storage; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function getName(): string + { + return $this->name; + } + + public function addFolder(FilesystemInfo $folderInformation): void + { + $this->folders[] = $folderInformation; + } + + public function getFolders(): array + { + return $this->folders; + } + + public function addFile(FilesystemInfo $fileInformation): void + { + $this->files[] = $fileInformation; + } + + public function getFiles(): array + { + return $this->files; + } + + public function toArray(): array + { + return [ + 'storage' => $this->storage, + 'identifier' => $this->identifier, + 'name' => $this->name, + ]; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFileInfo.php b/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFileInfo.php new file mode 100644 index 000000000..f4b2747bf --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFileInfo.php @@ -0,0 +1,32 @@ +storage = $storage; + $this->identifier = $identifier; + } + + public function getStorage(): int + { + return $this->storage; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function toArray(): array + { + return []; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFolderInfo.php b/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFolderInfo.php new file mode 100644 index 000000000..c08a6c640 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Model/MissingFolderInfo.php @@ -0,0 +1,32 @@ +storage = $storage; + $this->identifier = $identifier; + } + + public function getStorage(): int + { + return $this->storage; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function toArray(): array + { + return []; + } +} diff --git a/Classes/Component/Core/FileHandling/Service/FalDriverService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverService.php similarity index 75% rename from Classes/Component/Core/FileHandling/Service/FalDriverService.php rename to Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverService.php index 104b80bf2..b97cc91ee 100644 --- a/Classes/Component/Core/FileHandling/Service/FalDriverService.php +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverService.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace In2code\In2publishCore\Component\Core\FileHandling\Service; +namespace In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service; use In2code\In2publishCore\CommonInjection\FlexFormServiceInjection; use In2code\In2publishCore\CommonInjection\LocalDatabaseInjection; @@ -12,8 +12,6 @@ use TYPO3\CMS\Core\Resource\ResourceStorageInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use function in_array; - class FalDriverService { use LocalDatabaseInjection; @@ -51,38 +49,6 @@ public function getDriver(int $storage): DriverInterface return $this->rtc[$storage]; } - /** - * @return array - */ - public function getDrivers(array $storagesUids): array - { - $query = $this->localDatabase->createQueryBuilder(); - $query->getRestrictions()->removeAll(); - $query->select('*') - ->from('sys_file_storage') - ->where($query->expr()->in('uid', $storagesUids)); - $result = $query->executeQuery(); - $storages = $result->fetchAllAssociative(); - - $drivers = []; - foreach ($storages as $storage) { - $storageUid = $storage['uid']; - if (!isset($this->rtc[$storageUid])) { - $this->rtc[$storageUid] = $this->createFalDriver($storage); - } - $drivers[$storageUid] = $this->rtc[$storageUid]; - } - - if (in_array(0, $storagesUids)) { - if (!isset($this->rtc[0])) { - $this->rtc[0] = $this->createFallbackDriver(); - } - $drivers[0] = $this->rtc[0]; - } - - return $drivers; - } - protected function createFalDriver(array $storage): DriverInterface { $storageConfiguration = $this->convertFlexFormDataToConfigurationArray($storage['configuration'] ?? []); diff --git a/Classes/Component/Core/FileHandling/Service/FalDriverServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverServiceInjection.php similarity index 80% rename from Classes/Component/Core/FileHandling/Service/FalDriverServiceInjection.php rename to Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverServiceInjection.php index 62b51344c..56d2639de 100644 --- a/Classes/Component/Core/FileHandling/Service/FalDriverServiceInjection.php +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverServiceInjection.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace In2code\In2publishCore\Component\Core\FileHandling\Service; +namespace In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service; /** * @codeCoverageIgnore diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php new file mode 100644 index 000000000..c73077a58 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php @@ -0,0 +1,39 @@ +fileExists($fileIdentifier)) { + return new MissingFileInfo($storage, $fileIdentifier); + } + + $fileInfo = $driver->getFileInfoByIdentifier($fileIdentifier, self::PROPERTIES); + $fileInfo['folderHash'] = $fileInfo['folder_hash']; + $fileInfo['identifierHash'] = $fileInfo['identifier_hash']; + unset($fileInfo['folder_hash'], $fileInfo['identifier_hash']); + $fileInfo['sha1'] = $driver->hash($fileIdentifier, 'sha1'); + $fileInfo['publicUrl'] = $driver->getPublicUrl($fileInfo['identifier']); + return new FileInfo(...$fileInfo); + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoServiceInjection.php new file mode 100644 index 000000000..2a4b5a594 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoServiceInjection.php @@ -0,0 +1,21 @@ +fileInfoService = $fileInfoService; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoService.php new file mode 100644 index 000000000..6bd2d8646 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoService.php @@ -0,0 +1,22 @@ +executeCommandDispatcher->executeEnvelope($envelope); + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoServiceInjection.php new file mode 100644 index 000000000..077661b89 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFileInfoServiceInjection.php @@ -0,0 +1,22 @@ +foreignFileInfoService = $foreignFileInfoService; + } + +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoService.php new file mode 100644 index 000000000..699376348 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoService.php @@ -0,0 +1,33 @@ +sharedFilesystemInfoCache->getForeign($request); + if (null !== $collection) { + return $collection; + } + + /** @see EnvelopeDispatcher::getFolderInfo */ + $envelope = new Envelope(EnvelopeDispatcher::CMD_GET_FOLDER_INFO, $request); + + $response = $this->executeCommandDispatcher->executeEnvelope($envelope); + + $this->sharedFilesystemInfoCache->setForeign($response, $request); + + return $response; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoServiceInjection.php new file mode 100644 index 000000000..f7be7f9bc --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/ForeignFolderInfoServiceInjection.php @@ -0,0 +1,21 @@ +foreignFolderInfoService = $foreignFolderInfoService; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoService.php new file mode 100644 index 000000000..45e737d37 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoService.php @@ -0,0 +1,27 @@ + $fileIdentifiers) { + $driver = $this->falDriverService->getDriver($storage); + foreach ($fileIdentifiers as $identifier) { + $collection->addFilesystemInfo($this->fileInfoService->getFileInfo($driver, $storage, $identifier)); + } + } + + return $collection; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoServiceInjection.php new file mode 100644 index 000000000..911faf35f --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFileInfoServiceInjection.php @@ -0,0 +1,21 @@ +localFileInfoService = $localFileInfoService; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoService.php new file mode 100644 index 000000000..571f1ffe6 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoService.php @@ -0,0 +1,68 @@ +sharedFilesystemInfoCache->getLocal($request); + if (null !== $collection) { + return $collection; + } + $collection = new FilesystemInformationCollection(); + + foreach ($request as $storage => $identifiers) { + $driver = $this->falDriverService->getDriver($storage); + foreach ($identifiers as $identifier) { + if (!$driver->folderExists($identifier)) { + $collection->addFilesystemInfo(new MissingFolderInfo($storage, $identifier)); + continue; + } + + $name = $this->getFolderName($identifier, $storage); + $folderInformation = new FolderInfo($storage, $identifier, $name); + $collection->addFilesystemInfo($folderInformation); + + $folderIdentifiers = $driver->getFoldersInFolder($identifier); + foreach ($folderIdentifiers as $folderIdentifier) { + $name = $this->getFolderName($folderIdentifier, $storage); + $childFolderInformation = new FolderInfo($storage, $folderIdentifier, $name); + $folderInformation->addFolder($childFolderInformation); + } + + $fileIdentifiers = $driver->getFilesInFolder($identifier); + foreach ($fileIdentifiers as $fileIdentifier) { + $fileInfo = $this->fileInfoService->getFileInfo($driver, $storage, $fileIdentifier); + $folderInformation->addFile($fileInfo); + } + } + } + + $this->sharedFilesystemInfoCache->setLocal($collection, $request); + + return $collection; + } + + public function getFolderName(string $identifier, int $storage): string + { + $name = PathUtility::basename($identifier); + if (empty($name)) { + $name = $this->resourceFactory->getStorageObject($storage)->getName(); + } + return $name; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoServiceInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoServiceInjection.php new file mode 100644 index 000000000..274478624 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/LocalFolderInfoServiceInjection.php @@ -0,0 +1,21 @@ +localFolderInfoService = $localFolderInfoService; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCache.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCache.php new file mode 100644 index 000000000..c4936a56a --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCache.php @@ -0,0 +1,44 @@ + */ + protected array $local; + /** @var array */ + protected array $foreign; + + public function setLocal(FilesystemInformationCollection $response, array $request): void + { + ksort($request); + $this->local[sha1(json_encode($request, JSON_THROW_ON_ERROR))] = $response; + } + + public function setForeign(FilesystemInformationCollection $response, array $request): void + { + ksort($request); + $this->foreign[sha1(json_encode($request, JSON_THROW_ON_ERROR))] = $response; + } + + public function getLocal(array $request): ?FilesystemInformationCollection + { + ksort($request); + return $this->local[sha1(json_encode($request, JSON_THROW_ON_ERROR))] ?? null; + } + + public function getForeign(array $request): ?FilesystemInformationCollection + { + ksort($request); + return $this->foreign[sha1(json_encode($request, JSON_THROW_ON_ERROR))] ?? null; + } +} diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCacheInjection.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCacheInjection.php new file mode 100644 index 000000000..e212b4ac0 --- /dev/null +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/SharedFilesystemInfoCacheInjection.php @@ -0,0 +1,21 @@ +sharedFilesystemInfoCache = $sharedFilesystemInfoCache; + } +} diff --git a/Classes/Component/Core/FileHandling/DefaultFalFinder.php b/Classes/Component/Core/FileHandling/DefaultFalFinder.php index a145b4a15..408ceb14c 100644 --- a/Classes/Component/Core/FileHandling/DefaultFalFinder.php +++ b/Classes/Component/Core/FileHandling/DefaultFalFinder.php @@ -32,40 +32,39 @@ use In2code\In2publishCore\CommonInjection\EventDispatcherInjection; use In2code\In2publishCore\CommonInjection\ResourceFactoryInjection; use In2code\In2publishCore\Component\Core\Demand\DemandsFactoryInjection; +use In2code\In2publishCore\Component\Core\Demand\Type\FilesInFolderDemand; +use In2code\In2publishCore\Component\Core\Demand\Type\FolderDemand; +use In2code\In2publishCore\Component\Core\Demand\Type\FoldersInFolderDemand; use In2code\In2publishCore\Component\Core\Demand\Type\SelectDemand; use In2code\In2publishCore\Component\Core\DemandResolver\DemandResolverInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FileInfo; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\ForeignFileInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\LocalFileInfoServiceInjection; use In2code\In2publishCore\Component\Core\FileHandling\Exception\FolderDoesNotExistOnBothSidesException; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverServiceInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FileSystemInfoServiceInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\ForeignFileSystemInfoServiceInjection; use In2code\In2publishCore\Component\Core\Record\Factory\RecordFactoryInjection; -use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; +use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Component\Core\RecordCollection; -use In2code\In2publishCore\Component\Core\RecordIndexInjection; use In2code\In2publishCore\Component\Core\RecordTree\RecordTree; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuilderInjection; use In2code\In2publishCore\Event\RecordRelationsWereResolved; use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\PathUtility; use function explode; -use function ltrim; -use function sha1; +use function str_contains; +use function trim; class DefaultFalFinder { use RecordFactoryInjection; - use RecordIndexInjection; use DemandsFactoryInjection; use DemandResolverInjection; use ResourceFactoryInjection; - use ForeignFileSystemInfoServiceInjection; - use FalDriverServiceInjection; - use FileSystemInfoServiceInjection; use RecordTreeBuilderInjection; use EventDispatcherInjection; + use LocalFileInfoServiceInjection; + use ForeignFileInfoServiceInjection; /** * Creates a Record instance representing the current chosen folder in the @@ -97,221 +96,47 @@ public function findFolderRecord(?string $combinedIdentifier, bool $onlyRoot = f $folder = $this->resourceFactory->getDefaultStorage()->getRootLevelFolder(); // Update the combinedIdentifier to the actual folder we work with. $combinedIdentifier = $folder->getCombinedIdentifier(); - $storageUid = $folder->getStorage()->getUid(); + $storage = $folder->getStorage()->getUid(); $identifier = $folder->getIdentifier(); } else { + $combinedIdentifier = $this->normalizeCombinedIdentifier($combinedIdentifier); try { // This is the normal case. The local folder exists. $folder = $this->resourceFactory->getFolderObjectFromCombinedIdentifier($combinedIdentifier); - $storageUid = $folder->getStorage()->getUid(); + $storage = $folder->getStorage()->getUid(); } /** @noinspection PhpRedundantCatchClauseInspection */ catch (FolderDoesNotExistException $exception) { - $localFolderExists = false; - [$storageUid] = GeneralUtility::trimExplode(':', $combinedIdentifier); - $storageUid = (int)$storageUid; - $localStorage = $this->resourceFactory->getStorageObject($storageUid); + [$storage] = GeneralUtility::trimExplode(':', $combinedIdentifier); + $storage = (int)$storage; + $localStorage = $this->resourceFactory->getStorageObject($storage); $folder = $localStorage->getRootLevelFolder(); } $identifier = GeneralUtility::trimExplode(':', $combinedIdentifier)[1]; } - $storageName = $folder->getStorage()->getName(); - $foreignFolderExists = $this->foreignFileSystemInfoService->folderExists($storageUid, $identifier); - if (!$localFolderExists && !$foreignFolderExists) { - throw new FolderDoesNotExistOnBothSidesException($combinedIdentifier, $folder->getCombinedIdentifier()); - } - unset($folder); + $recordTree = new RecordTree(); - $folderName = PathUtility::basename($combinedIdentifier); - $folderIdentifier = explode(':', $combinedIdentifier)[1]; + $demands = $this->demandsFactory->createDemand(); + $demands->addDemand(new FolderDemand($storage, $identifier, $recordTree)); - $localProps = []; - if ($localFolderExists) { - $localProps = [ - 'combinedIdentifier' => $combinedIdentifier, - 'identifier' => $folderIdentifier, - 'name' => $folderName ?: $storageName, - 'storage' => $storageUid, - ]; - } + $recordCollection = new RecordCollection(); + $this->demandResolver->resolveDemand($demands, $recordCollection); - $foreignProps = []; - if ($foreignFolderExists) { - $foreignProps = [ - 'combinedIdentifier' => $combinedIdentifier, - 'identifier' => $folderIdentifier, - 'name' => $folderName ?: $storageName, - 'storage' => $storageUid, - ]; - } - $folderRecord = $this->recordFactory->createFolderRecord($combinedIdentifier, $localProps, $foreignProps); + $folderRecord = $recordTree->getChild(FolderRecord::CLASSIFICATION, $combinedIdentifier); if (null === $folderRecord) { - return new RecordTree(); + throw new FolderDoesNotExistOnBothSidesException($combinedIdentifier, $folder->getCombinedIdentifier()); } if ($onlyRoot) { - return new RecordTree([$folderRecord]); + $this->eventDispatcher->dispatch(new RecordRelationsWereResolved($recordTree)); + return $recordTree; } - $localFolderContents = $this->fileSystemInfoService->listFolderContents( - $storageUid, - $folderIdentifier, - ); - $foreignFolderContents = $this->foreignFileSystemInfoService->listFolderContents( - $storageUid, - $folderIdentifier, - ); - - $folders = []; - foreach ($localFolderContents['folders'] ?? [] as $folder) { - $combinedIdentifier = $storageUid . ':/' . ltrim($folder, '/'); - $folders[$combinedIdentifier]['local'] = [ - 'combinedIdentifier' => $combinedIdentifier, - 'identifier' => $folder, - 'name' => PathUtility::basename($folder), - 'storage' => $storageUid, - ]; - } - foreach ($foreignFolderContents['folders'] ?? [] as $folder) { - $combinedIdentifier = $storageUid . ':/' . ltrim($folder, '/'); - $folders[$combinedIdentifier]['foreign'] = [ - 'combinedIdentifier' => $combinedIdentifier, - 'identifier' => $folder, - 'name' => PathUtility::basename($folder), - 'storage' => $storageUid, - ]; - } - foreach ($folders as $subFolderIdentifier => $sides) { - $subFolderRecord = $this->recordFactory->createFolderRecord( - $subFolderIdentifier, - $sides['local'] ?? [], - $sides['foreign'] ?? [], - ); - if (null === $subFolderRecord) { - continue; - } - $folderRecord->addChild($subFolderRecord); - } - - $files = []; - foreach ($localFolderContents['files'] ?? [] as $localFiles) { - foreach ($localFiles as $file) { - $files[$file['identifier']]['local'] = $file; - } - } - foreach ($foreignFolderContents['files'] ?? [] as $foreignFiles) { - foreach ($foreignFiles as $file) { - $files[$file['identifier']]['foreign'] = $file; - } - } $demands = $this->demandsFactory->createDemand(); - foreach ($files as $sides) { - $fileRecord = $this->recordFactory->createFileRecord( - $sides['local'] ?? [], - $sides['foreign'] ?? [], - ); - if (null === $fileRecord) { - continue; - } - $demands->addDemand( - new SelectDemand( - 'sys_file', - 'storage = ' . $fileRecord->getProp('storage'), - 'identifier_hash', - sha1($fileRecord->getProp('identifier')), - $fileRecord, - ), - ); - $folderRecord->addChild($fileRecord); - } - $recordCollection = new RecordCollection(); + $demands->addDemand(new FoldersInFolderDemand($storage, $identifier, $folderRecord)); + $demands->addDemand(new FilesInFolderDemand($storage, $identifier, $folderRecord)); + $recordCollection = new RecordCollection(); $this->demandResolver->resolveDemand($demands, $recordCollection); - $this->recordTreeBuilder->findRecordsByTca($recordCollection); - - $filesMovedOutFromFolder = []; - $filesMovedIntoFolder = []; - - $sysFileRecords = $recordCollection->getRecords('sys_file'); - foreach ($sysFileRecords as $sysFileRecord) { - if ($sysFileRecord->getState() === Record::S_CHANGED) { - $localProps = $sysFileRecord->getLocalProps(); - $foreignProps = $sysFileRecord->getForeignProps(); - $localIdentifier = $localProps['identifier']; - $foreignIdentifier = $foreignProps['identifier']; - if ($localIdentifier !== $foreignIdentifier) { - if (!isset($files[$localIdentifier]['local'])) { - $filesMovedOutFromFolder[$localProps['storage']][] = $localIdentifier; - } - if (!isset($files[$foreignIdentifier]['foreign'])) { - $filesMovedIntoFolder[$foreignProps['storage']][] = $foreignIdentifier; - } - } - } - } - - if (!empty($filesMovedOutFromFolder)) { - $foundMovedOutFiles = $this->fileSystemInfoService->getFileInfo($filesMovedOutFromFolder); - foreach ($foundMovedOutFiles as $identifiers) { - foreach ($identifiers as $identifier => $fileInfo) { - $files[$identifier]['local'] = $fileInfo; - } - } - } - if (!empty($filesMovedIntoFolder)) { - $foundMovedIntoFiles = $this->foreignFileSystemInfoService->getFileInfo($filesMovedIntoFolder); - foreach ($foundMovedIntoFiles as $identifiers) { - foreach ($identifiers as $identifier => $fileInfo) { - $files[$identifier]['foreign'] = $fileInfo; - } - } - } - - foreach ($sysFileRecords as $sysFileRecord) { - if ($sysFileRecord->getState() === Record::S_CHANGED) { - $localProps = $sysFileRecord->getLocalProps(); - $foreignProps = $sysFileRecord->getForeignProps(); - $localIdentifier = $localProps['identifier']; - $foreignIdentifier = $foreignProps['identifier']; - if ($localIdentifier !== $foreignIdentifier) { - $localCombinedIdentifier = $localProps['storage'] . ':' . $localIdentifier; - $foreignCombinedIdentifier = $foreignProps['storage'] . ':' . $foreignIdentifier; - if (isset($files[$foreignIdentifier])) { - $files[$localIdentifier]['foreign'] = $files[$foreignIdentifier]['foreign']; - unset($files[$foreignIdentifier]); - $foreignRecordToRemove = $this->recordIndex->getRecord( - FileRecord::CLASSIFICATION, - $foreignCombinedIdentifier, - ); - if (null !== $foreignRecordToRemove) { - $folderRecord->removeChild($foreignRecordToRemove); - } - $localRecordToRemove = $this->recordIndex->getRecord( - FileRecord::CLASSIFICATION, - $localCombinedIdentifier, - ); - if (null !== $localRecordToRemove) { - $folderRecord->removeChild($localRecordToRemove); - } - $recordToAdd = $this->recordFactory->createFileRecord( - $files[$localIdentifier]['local'] ?? [], - $files[$localIdentifier]['foreign'] ?? [], - ); - if (null !== $recordToAdd) { - if (null !== $localRecordToRemove) { - $sysFileRecord->removeParent($localRecordToRemove); - } - if (null !== $foreignRecordToRemove) { - $sysFileRecord->removeParent($foreignRecordToRemove); - } - $recordToAdd->addChild($sysFileRecord); - $folderRecord->addChild($recordToAdd); - } - } - } - } - } - - $recordTree = new RecordTree([$folderRecord]); $this->eventDispatcher->dispatch(new RecordRelationsWereResolved($recordTree)); @@ -321,18 +146,17 @@ public function findFolderRecord(?string $combinedIdentifier, bool $onlyRoot = f public function findFileRecord(?string $combinedIdentifier): RecordTree { [$storage, $fileIdentifier] = explode(':', $combinedIdentifier); + $storage = (int)$storage; + $request = [$storage => [$fileIdentifier]]; - $localProps = []; - $localFileInfo = $this->fileSystemInfoService->getFileInfo([$storage => [$fileIdentifier]]); + $localFileInfo = $this->localFileInfoService->getFileInfo($request); + $fileInformation = $localFileInfo->getInfo($storage, $fileIdentifier); + $localProps = $fileInformation->toArray(); + + $foreignFileInfo = $this->foreignFileInfoService->getFileInfo($request); + $fileInformation = $foreignFileInfo->getInfo($storage, $fileIdentifier); + $foreignProps = $fileInformation->toArray(); - if (!empty($localFileInfo[$storage][$fileIdentifier])) { - $localProps = $localFileInfo[$storage][$fileIdentifier]; - } - $foreignProps = []; - $foreignFileInfo = $this->foreignFileSystemInfoService->getFileInfo([$storage => [$fileIdentifier]]); - if (!empty($foreignFileInfo[$storage][$fileIdentifier])) { - $foreignProps = $foreignFileInfo[$storage][$fileIdentifier]; - } $fileRecord = $this->recordFactory->createFileRecord($localProps, $foreignProps); if (null === $fileRecord) { return new RecordTree(); @@ -344,7 +168,7 @@ public function findFileRecord(?string $combinedIdentifier): RecordTree 'sys_file', 'storage = ' . $fileRecord->getProp('storage'), 'identifier_hash', - sha1($fileRecord->getProp('identifier')), + $fileRecord->getProp('identifier_hash'), $fileRecord, ), ); @@ -362,15 +186,13 @@ public function findFileRecord(?string $combinedIdentifier): RecordTree $foreignIdentifier = $foreignSysFileProps['identifier']; $foreignStorage = (int)$foreignSysFileProps['storage']; if ($localIdentifier !== $foreignIdentifier) { - $foreignFileInfo = $this->foreignFileSystemInfoService->getFileInfo( + $fileInfoCollection = $this->foreignFileInfoService->getFileInfo( [$foreignStorage => [$foreignIdentifier]], ); - if (!empty($foreignFileInfo[$foreignStorage][$foreignIdentifier])) { - $foreignProps = $foreignFileInfo[$foreignStorage][$foreignIdentifier]; - $fileRecord = $this->recordFactory->createFileRecord( - $localProps, - $foreignProps, - ); + $fileInfo = $fileInfoCollection->getInfo($foreignStorage, $foreignIdentifier); + if ($fileInfo instanceof FileInfo) { + $foreignProps = $fileInfo->toArray(); + $fileRecord = $this->recordFactory->createFileRecord($localProps, $foreignProps); if (null === $fileRecord) { return new RecordTree(); } @@ -387,4 +209,13 @@ public function findFileRecord(?string $combinedIdentifier): RecordTree return $recordTree; } + + protected function normalizeCombinedIdentifier(string $combinedIdentifier): string + { + if (str_contains($combinedIdentifier, ':')) { + [$storage, $name] = explode(':', $combinedIdentifier); + $combinedIdentifier = (int)$storage . ':/' . trim($name, '/'); + } + return $combinedIdentifier; + } } diff --git a/Classes/Component/Core/FileHandling/Service/FileSystemInfoService.php b/Classes/Component/Core/FileHandling/Service/FileSystemInfoService.php deleted file mode 100644 index ed16bc8b3..000000000 --- a/Classes/Component/Core/FileHandling/Service/FileSystemInfoService.php +++ /dev/null @@ -1,64 +0,0 @@ -falDriverService->getDriver($storageUid); - - try { - $folders = $driver->getFoldersInFolder($identifier); - $fileIdentifiers = $driver->getFilesInFolder($identifier); - } catch (InvalidArgumentException $exception) { - return []; - } - $files = $this->getFileInfo([$storageUid => $fileIdentifiers]); - return [ - 'folders' => $folders, - 'files' => $files, - ]; - } - - /** - * @param array> $files - */ - public function getFileInfo(array $files): array - { - $info = []; - - foreach ($files as $storage => $fileIdentifiers) { - $driver = $this->falDriverService->getDriver($storage); - foreach ($fileIdentifiers as $fileIdentifier) { - try { - $fileInfo = $driver->getFileInfoByIdentifier($fileIdentifier, self::PROPERTIES); - $fileInfo['sha1'] = $driver->hash($fileIdentifier, 'sha1'); - $fileInfo['publicUrl'] = $driver->getPublicUrl($fileInfo['identifier']); - $info[$storage][$fileIdentifier] = $fileInfo; - } catch (Throwable $exception) { - $info[$storage][$fileIdentifier] = null; - } - } - } - - return $info; - } -} diff --git a/Classes/Component/Core/FileHandling/Service/FileSystemInfoServiceInjection.php b/Classes/Component/Core/FileHandling/Service/FileSystemInfoServiceInjection.php deleted file mode 100644 index 2a5c366a1..000000000 --- a/Classes/Component/Core/FileHandling/Service/FileSystemInfoServiceInjection.php +++ /dev/null @@ -1,21 +0,0 @@ -fileSystemInfoService = $fileSystemInfoService; - } -} diff --git a/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoService.php b/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoService.php deleted file mode 100644 index e84c4569c..000000000 --- a/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoService.php +++ /dev/null @@ -1,89 +0,0 @@ - $storageUid, 'folderIdentifier' => $identifier], - ); - return $this->executeEnvelope($envelope); - } - - public function fileExists(int $storageUid, string $identifier): bool - { - $envelope = new Envelope( - EnvelopeDispatcher::CMD_FILE_EXISTS, - ['storage' => $storageUid, 'fileIdentifier' => $identifier], - ); - return $this->executeEnvelope($envelope); - } - - public function listFolderContents(int $storageUid, string $identifier): array - { - $envelope = new Envelope( - EnvelopeDispatcher::CMD_LIST_FOLDER_CONTENTS, - ['storageUid' => $storageUid, 'identifier' => $identifier], - ); - return $this->executeEnvelope($envelope); - } - - public function getFileInfo(array $files): array - { - $envelope = new Envelope( - EnvelopeDispatcher::CMD_GET_FILE_INFO, - ['files' => $files], - ); - return $this->executeEnvelope($envelope); - } - - protected function executeEnvelope(Envelope $envelope) - { - $uid = $this->letterbox->sendEnvelope($envelope); - if (!is_int($uid)) { - throw new EnvelopeSendingFailedException(); - } - $request = new RemoteCommandRequest(ExecuteCommand::IDENTIFIER, [], [$uid]); - $response = $this->remoteCommandDispatcher->dispatch($request); - - if (!$response->isSuccessful()) { - throw new RuntimeException( - sprintf( - 'Could not execute RPC [%d]. Errors and Output: %s %s', - $uid, - $response->getErrorsString(), - $response->getOutputString(), - ), - 1655988997, - ); - } - - $envelope = $this->letterbox->receiveEnvelope($uid); - - if (false === $envelope) { - throw new In2publishCoreException('Could not receive envelope [' . $uid . ']', 1655990891); - } - return $envelope->getResponse(); - } -} diff --git a/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoServiceInjection.php b/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoServiceInjection.php deleted file mode 100644 index e8bafce47..000000000 --- a/Classes/Component/Core/FileHandling/Service/ForeignFileSystemInfoServiceInjection.php +++ /dev/null @@ -1,21 +0,0 @@ -foreignFileSystemInfoService = $foreignFileSystemInfoService; - } -} diff --git a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php index c4c272cac..560a65e34 100644 --- a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php +++ b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php @@ -5,7 +5,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Command; use In2code\In2publishCore\CommonInjection\LocalDatabaseInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverServiceInjection; use In2code\In2publishCore\Component\Core\Publisher\Instruction\PublishInstruction; use In2code\In2publishCore\Service\Context\ContextServiceInjection; use Symfony\Component\Console\Command\Command; diff --git a/Classes/Component/Core/Publisher/FileRecordPublisher.php b/Classes/Component/Core/Publisher/FileRecordPublisher.php index d42ebc936..23bd68ad2 100644 --- a/Classes/Component/Core/Publisher/FileRecordPublisher.php +++ b/Classes/Component/Core/Publisher/FileRecordPublisher.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverServiceInjection; use In2code\In2publishCore\Component\Core\Publisher\Instruction\AddFileInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFileInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\MoveFileInstruction; diff --git a/Classes/Component/Core/Publisher/Instruction/AddFileInstruction.php b/Classes/Component/Core/Publisher/Instruction/AddFileInstruction.php index 8e512b7d6..140055efb 100644 --- a/Classes/Component/Core/Publisher/Instruction/AddFileInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/AddFileInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; use TYPO3\CMS\Core\Resource\Driver\DriverInterface; use TYPO3\CMS\Core\Utility\PathUtility; diff --git a/Classes/Component/Core/Publisher/Instruction/AddFolderInstruction.php b/Classes/Component/Core/Publisher/Instruction/AddFolderInstruction.php index b119473ad..7b28152da 100644 --- a/Classes/Component/Core/Publisher/Instruction/AddFolderInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/AddFolderInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; use TYPO3\CMS\Core\Utility\PathUtility; class AddFolderInstruction implements PublishInstruction diff --git a/Classes/Component/Core/Publisher/Instruction/DeleteFileInstruction.php b/Classes/Component/Core/Publisher/Instruction/DeleteFileInstruction.php index 797fa3ab9..cc27f4aa8 100644 --- a/Classes/Component/Core/Publisher/Instruction/DeleteFileInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/DeleteFileInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; class DeleteFileInstruction implements PublishInstruction { diff --git a/Classes/Component/Core/Publisher/Instruction/DeleteFolderInstruction.php b/Classes/Component/Core/Publisher/Instruction/DeleteFolderInstruction.php index 030937de6..627ce0561 100644 --- a/Classes/Component/Core/Publisher/Instruction/DeleteFolderInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/DeleteFolderInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; class DeleteFolderInstruction implements PublishInstruction { diff --git a/Classes/Component/Core/Publisher/Instruction/MoveFileInstruction.php b/Classes/Component/Core/Publisher/Instruction/MoveFileInstruction.php index bb6347dd8..edd976ab3 100644 --- a/Classes/Component/Core/Publisher/Instruction/MoveFileInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/MoveFileInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; use TYPO3\CMS\Core\Utility\PathUtility; class MoveFileInstruction implements PublishInstruction diff --git a/Classes/Component/Core/Publisher/Instruction/PublishInstruction.php b/Classes/Component/Core/Publisher/Instruction/PublishInstruction.php index 05e4b40b4..2b4870b9e 100644 --- a/Classes/Component/Core/Publisher/Instruction/PublishInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/PublishInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; interface PublishInstruction { diff --git a/Classes/Component/Core/Publisher/Instruction/ReplaceAndRenameFileInstruction.php b/Classes/Component/Core/Publisher/Instruction/ReplaceAndRenameFileInstruction.php index fb51bfce5..68081751a 100644 --- a/Classes/Component/Core/Publisher/Instruction/ReplaceAndRenameFileInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/ReplaceAndRenameFileInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; use TYPO3\CMS\Core\Utility\PathUtility; class ReplaceAndRenameFileInstruction implements PublishInstruction diff --git a/Classes/Component/Core/Publisher/Instruction/ReplaceFileInstruction.php b/Classes/Component/Core/Publisher/Instruction/ReplaceFileInstruction.php index fd73814b4..26d86f661 100644 --- a/Classes/Component/Core/Publisher/Instruction/ReplaceFileInstruction.php +++ b/Classes/Component/Core/Publisher/Instruction/ReplaceFileInstruction.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Instruction; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FalDriverService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverService; class ReplaceFileInstruction implements PublishInstruction { diff --git a/Classes/Component/Core/Record/Factory/RecordFactory.php b/Classes/Component/Core/Record/Factory/RecordFactory.php index 6e99513ec..9f2e5914c 100755 --- a/Classes/Component/Core/Record/Factory/RecordFactory.php +++ b/Classes/Component/Core/Record/Factory/RecordFactory.php @@ -105,12 +105,9 @@ public function createFileRecord(array $localProps, array $foreignProps): ?FileR return $record; } - public function createFolderRecord( - string $combinedIdentifier, - array $localProps, - array $foreignProps - ): ?FolderRecord { - $record = new FolderRecord($combinedIdentifier, $localProps, $foreignProps); + public function createFolderRecord(array $localProps, array $foreignProps): ?FolderRecord + { + $record = new FolderRecord($localProps, $foreignProps); if ($this->shouldIgnoreRecord($record)) { return null; } diff --git a/Classes/Component/Core/Record/Model/AbstractRecord.php b/Classes/Component/Core/Record/Model/AbstractRecord.php index 259de68fc..f36311729 100644 --- a/Classes/Component/Core/Record/Model/AbstractRecord.php +++ b/Classes/Component/Core/Record/Model/AbstractRecord.php @@ -6,6 +6,8 @@ use Generator; use In2code\In2publishCore\Component\Core\Reason\Reasons; +use In2code\In2publishCore\Component\Core\Record\Iterator\IterationControls\StopIteration; +use In2code\In2publishCore\Component\Core\Record\Iterator\RecordIterator; use In2code\In2publishCore\Component\Core\Record\Model\Extension\RecordExtensionTrait; use In2code\In2publishCore\Event\CollectReasonsWhyTheRecordIsNotPublishable; use LogicException; @@ -33,7 +35,6 @@ abstract class AbstractRecord implements Record * @var array */ protected array $dependencies = []; - protected bool $hasBeenAskedForRecursiveState = false; /** * @var array> */ @@ -220,24 +221,21 @@ public function getState(): string public function getStateRecursive(): string { $state = $this->getState(); - if ($state !== Record::S_UNCHANGED || $this->hasBeenAskedForRecursiveState) { + if ($state !== Record::S_UNCHANGED) { return $state; } - $this->hasBeenAskedForRecursiveState = true; - foreach ($this->children as $table => $records) { - if ('pages' === $table) { - continue; + $recordState = Record::S_UNCHANGED; + $recordIterator = new RecordIterator(); + $recordIterator->recurse($this, function (Record $record) use (&$recordState) { + if ($record->getClassification() === 'pages') { + return; } - foreach ($records as $record) { - $state = $record->getStateRecursive(); - if ($state !== Record::S_UNCHANGED) { - $this->hasBeenAskedForRecursiveState = false; - return Record::S_CHANGED; - } + if ($record->getState() !== Record::S_UNCHANGED) { + $recordState = Record::S_CHANGED; + throw new StopIteration(); } - } - $this->hasBeenAskedForRecursiveState = false; - return Record::S_UNCHANGED; + }); + return $recordState; } public function calculateDependencies(): array diff --git a/Classes/Component/Core/Record/Model/FolderRecord.php b/Classes/Component/Core/Record/Model/FolderRecord.php index b39737e74..d0432826a 100644 --- a/Classes/Component/Core/Record/Model/FolderRecord.php +++ b/Classes/Component/Core/Record/Model/FolderRecord.php @@ -4,16 +4,16 @@ namespace In2code\In2publishCore\Component\Core\Record\Model; +use In2code\In2publishCore\Component\Core\Record\Iterator\IterationControls\StopIteration; +use In2code\In2publishCore\Component\Core\Record\Iterator\RecordIterator; use LogicException; class FolderRecord extends AbstractRecord { public const CLASSIFICATION = '_folder'; - private string $combinedIdentifier; - public function __construct(string $combinedIdentifier, array $localProps, array $foreignProps) + public function __construct(array $localProps, array $foreignProps) { - $this->combinedIdentifier = $combinedIdentifier; $this->localProps = $localProps; $this->foreignProps = $foreignProps; @@ -25,9 +25,9 @@ public function getClassification(): string return self::CLASSIFICATION; } - public function getId() + public function getId(): string { - return $this->combinedIdentifier; + return $this->getProp('storage') . ':' . $this->getProp('identifier'); } public function getForeignIdentificationProps(): array @@ -35,4 +35,24 @@ public function getForeignIdentificationProps(): array throw new LogicException('NOT IMPLEMENTED'); return $this->getId(); } + + public function getStateRecursive(): string + { + $state = $this->getState(); + if ($state !== Record::S_UNCHANGED) { + return $state; + } + $stateRecursive = Record::S_UNCHANGED; + $recordIterator = new RecordIterator(); + $recordIterator->recurse($this, function (Record $record) use (&$stateRecursive) { + if ($record instanceof FolderRecord || $record instanceof FileRecord) { + return; + } + if ($record->getState() !== Record::S_UNCHANGED) { + $stateRecursive = Record::S_CHANGED; + throw new StopIteration(); + } + }); + return $stateRecursive; + } } diff --git a/Classes/Component/Core/RecordTree/RecordTree.php b/Classes/Component/Core/RecordTree/RecordTree.php index 9d7b3e0c7..f8b9dc776 100644 --- a/Classes/Component/Core/RecordTree/RecordTree.php +++ b/Classes/Component/Core/RecordTree/RecordTree.php @@ -58,9 +58,12 @@ public function getId(): int return -1; } - public function getChild(string $table, int $id): ?Record + /** + * @param int|string $id + */ + public function getChild(string $classification, $id): ?Record { - return $this->children[$table][$id] ?? null; + return $this->children[$classification][$id] ?? null; } public function getCurrentPage(): ?Record diff --git a/Classes/Component/RemoteProcedureCall/EnvelopeDispatcher.php b/Classes/Component/RemoteProcedureCall/EnvelopeDispatcher.php index cdffd9801..4dd936f57 100644 --- a/Classes/Component/RemoteProcedureCall/EnvelopeDispatcher.php +++ b/Classes/Component/RemoteProcedureCall/EnvelopeDispatcher.php @@ -30,9 +30,10 @@ */ use In2code\In2publishCore\CommonInjection\ResourceFactoryInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FileSystemInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FilesystemInformationCollection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\LocalFileInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\LocalFolderInfoServiceInjection; use In2code\In2publishCore\Component\RemoteProcedureCall\Exception\StorageIsOfflineException; -use InvalidArgumentException; use ReflectionProperty; use TYPO3\CMS\Core\Resource\Driver\DriverInterface; @@ -42,12 +43,12 @@ class EnvelopeDispatcher { use ResourceFactoryInjection; - use FileSystemInfoServiceInjection; + use LocalFolderInfoServiceInjection; + use LocalFileInfoServiceInjection; - public const CMD_FOLDER_EXISTS = 'folderExists'; - public const CMD_FILE_EXISTS = 'fileExists'; - public const CMD_LIST_FOLDER_CONTENTS = 'listFolderContents'; + public const CMD_GET_FOLDER_INFO = 'getFolderInfo'; public const CMD_GET_FILE_INFO = 'getFileInfo'; + public const CMD_FILE_EXISTS = 'fileExists'; public function dispatch(Envelope $envelope): bool { @@ -62,30 +63,19 @@ public function dispatch(Envelope $envelope): bool return false; } - protected function folderExists(array $request): bool - { - return $this->getStorageDriver($request)->folderExists($request['folderIdentifier']); - } - - protected function fileExists(array $request): bool + protected function getFolderInfo(array $request): FilesystemInformationCollection { - return $this->getStorageDriver($request)->fileExists($request['fileIdentifier']); + return $this->localFolderInfoService->getFolderInfo($request); } - public function listFolderContents(array $request): array + public function getFileInfo(array $request): FilesystemInformationCollection { - $storageUid = $request['storageUid']; - $identifier = $request['identifier']; - try { - return $this->fileSystemInfoService->listFolderContents($storageUid, $identifier); - } catch (InvalidArgumentException $e) { - return []; - } + return $this->localFileInfoService->getFileInfo($request); } - public function getFileInfo(array $request): array + protected function fileExists(array $request): bool { - return $this->fileSystemInfoService->getFileInfo($request['files']); + return $this->getStorageDriver($request)->fileExists($request['fileIdentifier']); } protected function getStorageDriver(array $request): DriverInterface diff --git a/Classes/Component/Core/FileHandling/Service/Exception/EnvelopeSendingFailedException.php b/Classes/Component/RemoteProcedureCall/Exception/EnvelopeSendingFailedException.php similarity index 85% rename from Classes/Component/Core/FileHandling/Service/Exception/EnvelopeSendingFailedException.php rename to Classes/Component/RemoteProcedureCall/Exception/EnvelopeSendingFailedException.php index 49960c6eb..64705ea04 100644 --- a/Classes/Component/Core/FileHandling/Service/Exception/EnvelopeSendingFailedException.php +++ b/Classes/Component/RemoteProcedureCall/Exception/EnvelopeSendingFailedException.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace In2code\In2publishCore\Component\Core\FileHandling\Service\Exception; +namespace In2code\In2publishCore\Component\RemoteProcedureCall\Exception; use In2code\In2publishCore\In2publishCoreException; use Throwable; diff --git a/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcher.php b/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcher.php new file mode 100644 index 000000000..affa7905d --- /dev/null +++ b/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcher.php @@ -0,0 +1,57 @@ +letterbox->sendEnvelope($envelope); + if (!is_int($uid)) { + throw new EnvelopeSendingFailedException(); + } + $request = new RemoteCommandRequest(ExecuteCommand::IDENTIFIER, [], [$uid]); + $response = $this->remoteCommandDispatcher->dispatch($request); + + if (!$response->isSuccessful()) { + throw new RuntimeException( + sprintf( + 'Could not execute RPC [%d]. Errors and Output: %s %s', + $uid, + $response->getErrorsString(), + $response->getOutputString(), + ), + 1699621336, + ); + } + + $envelope = $this->letterbox->receiveEnvelope($uid); + + if (false === $envelope) { + throw new In2publishCoreException('Could not receive envelope [' . $uid . ']', 1699641778); + } + return $envelope->getResponse(); + } +} diff --git a/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcherInjection.php b/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcherInjection.php new file mode 100644 index 000000000..244188613 --- /dev/null +++ b/Classes/Component/RemoteProcedureCall/ExecuteCommandDispatcherInjection.php @@ -0,0 +1,21 @@ +executeCommandDispatcher = $executeCommandDispatcher; + } +} diff --git a/Classes/Controller/FileController.php b/Classes/Controller/FileController.php index e23dafc2c..331f325f7 100755 --- a/Classes/Controller/FileController.php +++ b/Classes/Controller/FileController.php @@ -47,7 +47,6 @@ use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use function array_keys; @@ -101,14 +100,11 @@ public function injectPageRenderer(PageRenderer $pageRenderer): void ); } - /** - * @throws StopActionException - */ public function indexAction(): ResponseInterface { $pid = BackendUtility::getPageIdentifier(); try { - $recordTree = $this->tryToGetFolderInstance($pid === 0 ? null : $pid); + $recordTree = $this->defaultFalFinder->findFolderRecord($pid === 0 ? null : $pid); } catch (FolderDoesNotExistOnBothSidesException $e) { $uri = $this->request->getUri(); $queryParts = []; @@ -137,12 +133,12 @@ public function indexAction(): ResponseInterface /** * @param bool $skipNotification Used by the Enterprise Edition. Do not remove despite unused in the CE. * - * @throws StopActionException + * @throws FolderDoesNotExistOnBothSidesException * @SuppressWarnings(PHPMD.BooleanArgumentFlag) On purpose */ public function publishFolderAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface { - $recordTree = $this->tryToGetFolderInstance($combinedIdentifier, true); + $recordTree = $this->defaultFalFinder->findFolderRecord($combinedIdentifier, true); try { $this->publisherService->publishRecordTree($recordTree); @@ -171,7 +167,6 @@ public function publishFolderAction(string $combinedIdentifier, bool $skipNotifi /** * @param bool $skipNotification Used by the Enterprise Edition. Do not remove despite unused in the CE. - * @throws StopActionException * @SuppressWarnings(PHPMD.BooleanArgumentFlag) On purpose */ public function publishFileAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface @@ -235,15 +230,6 @@ public function toggleFilterStatusAction(string $filter): ResponseInterface */ protected function tryToGetFolderInstance(?string $combinedIdentifier, bool $onlyRoot = false): ?RecordTree { - if (is_string($combinedIdentifier) && strpos($combinedIdentifier, ':') < strlen($combinedIdentifier)) { - [$storage, $name] = explode(':', $combinedIdentifier); - $name = trim($name, '/'); - if (!empty($name)) { - $combinedIdentifier = $storage . ':/' . $name . '/'; - } else { - $combinedIdentifier = $storage . ':/'; - } - } return $this->defaultFalFinder->findFolderRecord($combinedIdentifier, $onlyRoot); } } diff --git a/Classes/Component/Core/FileHandling/FileRecordListener.php b/Classes/Features/ResolveFilesForIndices/EventListener/FileRecordListener.php similarity index 92% rename from Classes/Component/Core/FileHandling/FileRecordListener.php rename to Classes/Features/ResolveFilesForIndices/EventListener/FileRecordListener.php index 61cfc4e65..79a181660 100644 --- a/Classes/Component/Core/FileHandling/FileRecordListener.php +++ b/Classes/Features/ResolveFilesForIndices/EventListener/FileRecordListener.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace In2code\In2publishCore\Component\Core\FileHandling; +namespace In2code\In2publishCore\Features\ResolveFilesForIndices\EventListener; use In2code\In2publishCore\Component\Core\Demand\DemandsFactoryInjection; use In2code\In2publishCore\Component\Core\Demand\Type\FileDemand; @@ -17,18 +17,15 @@ class FileRecordListener use DemandsFactoryInjection; use DemandResolverInjection; - /** - * @var list - */ + /** @var array */ protected array $fileRecords = []; public function onRecordWasCreated(RecordWasCreated $event): void { $record = $event->getRecord(); - if ('sys_file' !== $record->getClassification()) { - return; + if ('sys_file' === $record->getClassification()) { + $this->fileRecords[] = $record; } - $this->fileRecords[] = $record; } public function onRecordRelationsWereResolved(): void diff --git a/Classes/Testing/Tests/Fal/MissingStoragesTest.php b/Classes/Testing/Tests/Fal/MissingStoragesTest.php index e5821beb8..d0af8f669 100644 --- a/Classes/Testing/Tests/Fal/MissingStoragesTest.php +++ b/Classes/Testing/Tests/Fal/MissingStoragesTest.php @@ -71,8 +71,8 @@ protected function getMissing(array $storages, array $messages, string $side): a if (!empty($missingOnSide)) { // fal.missing_on_local | fal.missing_on_foreign $messages[] = 'fal.missing_on_' . $side; - foreach ($missingOnSide as $storageUid) { - $messages[] = sprintf('[%d] %s', $storageUid, $storages[$opposite][$storageUid]['name']); + foreach ($missingOnSide as $storage) { + $messages[] = sprintf('[%d] %s', $storage, $storages[$opposite][$storage]['name']); } } return $messages; diff --git a/Classes/Testing/Tests/Fal/UniqueStorageTargetTest.php b/Classes/Testing/Tests/Fal/UniqueStorageTargetTest.php index 3a1a5d06c..3e6d33cb9 100644 --- a/Classes/Testing/Tests/Fal/UniqueStorageTargetTest.php +++ b/Classes/Testing/Tests/Fal/UniqueStorageTargetTest.php @@ -31,7 +31,8 @@ use Doctrine\DBAL\Driver\Exception as DriverException; use In2code\In2publishCore\CommonInjection\ResourceFactoryInjection; -use In2code\In2publishCore\Component\Core\FileHandling\Service\ForeignFileSystemInfoServiceInjection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FileInfo; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\ForeignFileInfoServiceInjection; use In2code\In2publishCore\Testing\Data\FalStorageTestSubjectsProviderInjection; use In2code\In2publishCore\Testing\Tests\Application\ForeignDatabaseConfigTest; use In2code\In2publishCore\Testing\Tests\Application\ForeignInstanceTest; @@ -57,7 +58,7 @@ class UniqueStorageTargetTest implements TestCaseInterface { use ResourceFactoryInjection; - use ForeignFileSystemInfoServiceInjection; + use ForeignFileInfoServiceInjection; use FalStorageTestSubjectsProviderInjection; /** @@ -91,12 +92,14 @@ public function run(): TestResult /** @var DriverInterface $localDriver */ $localDriver = $driverProperty->getValue($storageObject); + $storageUid = (int)$storages['foreign'][$key]['uid']; try { do { $uniqueFile = uniqid('tx_in2publish_testfile'); } while ( $localDriver->fileExists($uniqueFile) - || $this->foreignFileSystemInfoService->fileExists($storages['foreign'][$key]['uid'], $uniqueFile) + || $this->foreignFileInfoService->getFileInfo([$storageUid => [$uniqueFile]]) + ->getInfo($storageUid, $uniqueFile) instanceof FileInfo ); } catch (RuntimeException $e) { if (preg_match('/The storage \d+ is offline/', $e->getMessage())) { @@ -109,7 +112,8 @@ public function run(): TestResult $addedFile = $localDriver->addFile($sourceFile, $localDriver->getRootLevelFolder(), $uniqueFile); if ($uniqueFile === ltrim($addedFile, '/')) { - if ($this->foreignFileSystemInfoService->fileExists($storages['foreign'][$key]['uid'], $uniqueFile)) { + $fileInfoCollection = $this->foreignFileInfoService->getFileInfo([$storageUid => [$uniqueFile]]); + if ($fileInfoCollection->getInfo($storageUid, $uniqueFile) instanceof FileInfo) { $affectedStorages[] = '[' . $key . '] ' . $storages['local'][$key]['name']; } } else { diff --git a/Configuration/Component/Core/Services.yaml b/Configuration/Component/Core/Services.yaml index 6df2a5d27..9abcf137d 100644 --- a/Configuration/Component/Core/Services.yaml +++ b/Configuration/Component/Core/Services.yaml @@ -32,17 +32,6 @@ services: arguments: $connection: '@In2code.In2publishCore.Database.Foreign' - In2code\In2publishCore\Component\Core\FileHandling\FileRecordListener: - tags: - - name: event.listener - identifier: 'in2publishcore-FileRecordListener-RecordWasCreated' - method: 'onRecordWasCreated' - event: In2code\In2publishCore\Event\RecordWasCreated - - name: event.listener - identifier: 'in2publishcore-FileRecordListener-RecordRelationsWereResolved' - method: 'onRecordRelationsWereResolved' - event: In2code\In2publishCore\Event\RecordRelationsWereResolved - In2code\In2publishCore\Component\Core\Publisher\Command\FalPublisherCommand: tags: - name: 'console.command' diff --git a/Configuration/Features/ResolveFilesForIndices/Services.yaml b/Configuration/Features/ResolveFilesForIndices/Services.yaml new file mode 100644 index 000000000..a48794380 --- /dev/null +++ b/Configuration/Features/ResolveFilesForIndices/Services.yaml @@ -0,0 +1,19 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + In2code\In2publishCore\Features\ResolveFilesForIndices\: + resource: '../../../Classes/Features/ResolveFilesForIndices/*' + + In2code\In2publishCore\Features\ResolveFilesForIndices\EventListener\FileRecordListener: + tags: + - name: event.listener + identifier: 'in2publishcore-FileRecordListener-RecordWasCreated' + method: 'onRecordWasCreated' + event: In2code\In2publishCore\Event\RecordWasCreated + - name: event.listener + identifier: 'in2publishcore-FileRecordListener-RecordRelationsWereResolved' + method: 'onRecordRelationsWereResolved' + event: In2code\In2publishCore\Event\RecordRelationsWereResolved diff --git a/Resources/Private/Partials/File/FolderList.html b/Resources/Private/Partials/File/FolderList.html index f42f3c395..9be75ad0a 100755 --- a/Resources/Private/Partials/File/FolderList.html +++ b/Resources/Private/Partials/File/FolderList.html @@ -22,7 +22,7 @@ - + createMock(QueryBuilder::class); - $queryBuilder->method('execute')->willReturn($query); + $queryBuilder->method('executeQuery')->willReturn($query); $connection = $this->createMock(Connection::class); $connection->method('createQueryBuilder')->willReturn($queryBuilder); diff --git a/Tests/Unit/Component/Core/FileHandling/FileDemandResolverTest.php b/Tests/Unit/Component/Core/FileHandling/FileDemandResolverTest.php index 3293123d4..08bab061a 100644 --- a/Tests/Unit/Component/Core/FileHandling/FileDemandResolverTest.php +++ b/Tests/Unit/Component/Core/FileHandling/FileDemandResolverTest.php @@ -6,18 +6,23 @@ use In2code\In2publishCore\Component\Core\Demand\DemandsCollection; use In2code\In2publishCore\Component\Core\Demand\Type\FileDemand; -use In2code\In2publishCore\Component\Core\FileHandling\FileDemandResolver; -use In2code\In2publishCore\Component\Core\FileHandling\Service\FileSystemInfoService; -use In2code\In2publishCore\Component\Core\FileHandling\Service\ForeignFileSystemInfoService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\FileDemandResolver; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FileInfo; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FilesystemInformationCollection; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\ForeignFileInfoService; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\LocalFileInfoService; use In2code\In2publishCore\Component\Core\Record\Factory\RecordFactory; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Component\Core\RecordCollection; use In2code\In2publishCore\Tests\UnitTestCase; +use function bin2hex; use function hash; +use function random_bytes; +use function sha1; /** - * @coversDefaultClass \In2code\In2publishCore\Component\Core\FileHandling\FileDemandResolver + * @coversDefaultClass \In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\FileDemandResolver */ class FileDemandResolverTest extends UnitTestCase { @@ -27,67 +32,70 @@ class FileDemandResolverTest extends UnitTestCase public function testResolveDemand(): void { $fileDemandResolver = new FileDemandResolver(); - $file1 = new FileRecord(['identifier' => 'file1', 'storage' => 42], []); - $file2 = new FileRecord(['identifier' => 'file2', 'storage' => 42], []); - $filesArray = [ - 42 => [ - 'foo/bar' => [$file1], - '/file.txt' => [$file2], - ], - ]; - $fileInfoArray = $filesArray; - $fileInfoArray[42]['foo/bar'] = [ - 'size' => 123, - 'mimetype' => 'some_mimetype', - 'name' => 'some_name', - 'extension' => 'some_extension', - 'folder_hash' => 'some_folder_hash', - ]; - $fileInfoArray[42]['/file.txt'] = [ - 'size' => 123, - 'mimetype' => 'some_mimetype', - 'name' => 'some_name', - 'extension' => 'some_extension', - 'folder_hash' => 'some_folder_hash', - ]; + $childFile1Info = new FileInfo( + 42, + 'foo/bar', + 'some_name', + sha1(bin2hex(random_bytes(15))), + null, + 123, + 'some_mimetype', + 'some_extension', + 'some_folder_hash', + sha1('foo/bar') + ); + $childFile2Info = new FileInfo( + 42, + '/file.txt', + 'some_name', + sha1(bin2hex(random_bytes(15))), + null, + 123, + 'some_mimetype', + 'some_extension', + 'some_folder_hash', + sha1('foo/bar') + ); + $fileInfoArray = new FilesystemInformationCollection(); + $fileInfoArray->addFilesystemInfo($childFile1Info); + $fileInfoArray->addFilesystemInfo($childFile2Info); - $fileSystemInfoService = $this->createMock(FileSystemInfoService::class); + $fileSystemInfoService = $this->createMock(LocalFileInfoService::class); $fileSystemInfoService->expects($this->once())->method('getFileInfo')->willReturn($fileInfoArray); - $foreignFileSystemInfoService = $this->createMock(ForeignFileSystemInfoService::class); + $foreignFileInfoService = $this->createMock(ForeignFileInfoService::class); + $fileRecordChild1 = new FileRecord($childFile1Info->toArray(), []); + $fileRecordChild2 = new FileRecord($childFile2Info->toArray(), []); $recordFactory = $this->createMock(RecordFactory::class); - $localProps = $fileInfoArray[42]['foo/bar']; - $localProps['storage'] = 42; - $localProps['identifier'] = 'foo/bar'; - $localProps['identifier_hash'] = hash('sha1', 'foo/bar'); - $fileRecordChild1 = new FileRecord($localProps, []); - - $localProps = $fileInfoArray[42]['/file.txt']; - $localProps['storage'] = 42; - $localProps['identifier'] = '/file.txt'; - $localProps['identifier_hash'] = hash('sha1', '/file.txt'); - $fileRecordChild2 = new FileRecord($localProps, []); $recordFactory->method('createFileRecord')->willReturnOnConsecutiveCalls( $fileRecordChild1, $fileRecordChild2, ); - $fileDemandResolver->injectFileSystemInfoService($fileSystemInfoService); - $fileDemandResolver->injectForeignFileSystemInfoService($foreignFileSystemInfoService); + $fileDemandResolver->injectLocalFileInfoService($fileSystemInfoService); + $fileDemandResolver->injectForeignFileInfoService($foreignFileInfoService); $fileDemandResolver->injectRecordFactory($recordFactory); $demands = $this->createMock(DemandsCollection::class); - $demands->method('getDemandsByType')->with(FileDemand::class)->willReturn($filesArray); + $parentFile1 = new FileRecord(['identifier' => 'file1', 'storage' => 42], []); + $parentFile2 = new FileRecord(['identifier' => 'file2', 'storage' => 42], []); + $fileDemand = [ + 42 => [ + 'foo/bar' => [$parentFile1], + '/file.txt' => [$parentFile2], + ], + ]; + $demands->method('getDemandsByType')->with(FileDemand::class)->willReturn($fileDemand); $recordCollection = new RecordCollection(); $fileDemandResolver->resolveDemand($demands, $recordCollection); - $file1Children = $file1->getChildren(); + $file1Children = $parentFile1->getChildren(); $this->assertSame($fileRecordChild1, $file1Children['_file']['42:foo/bar']); - $file2Children = $file2->getChildren(); + $file2Children = $parentFile2->getChildren(); $this->assertSame($fileRecordChild2, $file2Children['_file']['42:/file.txt']); } } diff --git a/Tests/Unit/Component/Core/FileHandling/FileRecordListenerTest.php b/Tests/Unit/Component/Core/FileHandling/FileRecordListenerTest.php index 1140056c2..3f243eefd 100644 --- a/Tests/Unit/Component/Core/FileHandling/FileRecordListenerTest.php +++ b/Tests/Unit/Component/Core/FileHandling/FileRecordListenerTest.php @@ -6,16 +6,16 @@ use In2code\In2publishCore\Component\Core\Demand\DemandsCollection; use In2code\In2publishCore\Component\Core\Demand\DemandsFactory; -use In2code\In2publishCore\Component\Core\FileHandling\FileDemandResolver; -use In2code\In2publishCore\Component\Core\FileHandling\FileRecordListener; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\FileDemandResolver; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseRecord; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Event\RecordWasCreated; +use In2code\In2publishCore\Features\ResolveFilesForIndices\EventListener\FileRecordListener; use In2code\In2publishCore\Tests\UnitTestCase; use ReflectionProperty; /** - * @coversDefaultClass \In2code\In2publishCore\Component\Core\FileHandling\FileRecordListener + * @coversDefaultClass \In2code\In2publishCore\Features\ResolveFilesForIndices\EventListener\FileRecordListener */ class FileRecordListenerTest extends UnitTestCase { diff --git a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php index 63ee602cc..848796e2d 100644 --- a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php +++ b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php @@ -4,6 +4,7 @@ namespace In2code\In2publishCore\Tests\Unit\Component\Core\Publisher; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FolderInfo; use In2code\In2publishCore\Component\Core\Publisher\FolderRecordPublisher; use In2code\In2publishCore\Component\Core\Publisher\Instruction\AddFolderInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFolderInstruction; @@ -47,14 +48,8 @@ public function testPublishRemovesDeletedFolder() $folderRecordPublisher = $this->createFolderRecordPublisher(); $deletedFolder = new FolderRecord( - '1:/foo/bar', [], - [ - 'combinedIdentifier' => '1:/foo/bar', - 'identifier' => '/foo/bar', - 'name' => 'bar', - 'storage' => 1, - ], + (new FolderInfo(1, '/foo/bar', 'bar'))->toArray(), ); $foreignDatabase = $this->createMock(Connection::class); @@ -87,13 +82,7 @@ public function testPublishAddsAddedFolder() $folderRecordPublisher = $this->createFolderRecordPublisher(); $addedFolder = new FolderRecord( - '1:/foo/bar', - [ - 'combinedIdentifier' => '1:/foo/bar', - 'identifier' => '/foo/bar', - 'name' => 'bar', - 'storage' => 1, - ], + (new FolderInfo(1, '/foo/bar', 'bar'))->toArray(), [], ); diff --git a/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php b/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php index f251f06fc..615496913 100644 --- a/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php +++ b/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php @@ -195,7 +195,6 @@ public function testFolderRecordIsCreatedAndAddedToRecordIndex(): void $recordFactory->injectRecordIndex($recordIndex); $record = $recordFactory->createFolderRecord( - 'combined_identifier', ['field_foo' => 'value_foo'], [], ); diff --git a/Tests/Unit/Component/Core/Record/Model/FolderRecordTest.php b/Tests/Unit/Component/Core/Record/Model/FolderRecordTest.php index beaaefaad..0b4a33375 100644 --- a/Tests/Unit/Component/Core/Record/Model/FolderRecordTest.php +++ b/Tests/Unit/Component/Core/Record/Model/FolderRecordTest.php @@ -4,6 +4,7 @@ namespace In2code\In2publishCore\Tests\Unit\Component\Core\Record\Model; +use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FolderInfo; use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Tests\UnitTestCase; @@ -24,10 +25,13 @@ class FolderRecordTest extends UnitTestCase */ public function testConstructor(): void { - $folderRecord = new FolderRecord('42:folder_name', ['prop_1' => 'value_1'], []); + $folderRecord = new FolderRecord((new FolderInfo(42, 'folder_name', 'blala'))->toArray(), []); $this->assertInstanceOf(FolderRecord::class, $folderRecord); $this->assertSame('42:folder_name', $folderRecord->getId()); - $this->assertSame(['prop_1' => 'value_1'], $folderRecord->getLocalProps()); + $this->assertSame( + ['storage' => 42, 'identifier' => 'folder_name', 'name' => 'blala'], + $folderRecord->getLocalProps() + ); $this->assertSame([], $folderRecord->getForeignProps()); $this->assertSame(FolderRecord::CLASSIFICATION, $folderRecord->getClassification()); @@ -41,16 +45,18 @@ public function testConstructor(): void */ public function testCalculateState(): void { - $folderRecord = new FolderRecord('42:folder_name', ['prop_1' => 'value_1'], []); + $props = (new FolderInfo(42, 'folder_name', 'blala'))->toArray(); + $folderRecord = new FolderRecord($props, []); $this->assertSame(Record::S_ADDED, $folderRecord->getState()); - $folderRecord = new FolderRecord('42:folder_name', ['prop_1' => 'value_1'], ['prop_1' => 'value_1']); + $folderRecord = new FolderRecord($props, $props); $this->assertSame(Record::S_UNCHANGED, $folderRecord->getState()); - $folderRecord = new FolderRecord('42:folder_name', ['prop_1' => 'value_1'], ['prop_1' => 'value_2']); + $props2 = (new FolderInfo(42, 'other_folder_name', 'foooo'))->toArray(); + $folderRecord = new FolderRecord($props, $props2); $this->assertSame(Record::S_CHANGED, $folderRecord->getState()); - $folderRecord = new FolderRecord('42:folder_name', [], ['prop_1' => 'value_2']); + $folderRecord = new FolderRecord([], $props); $this->assertSame(Record::S_DELETED, $folderRecord->getState()); } } diff --git a/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php b/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php index 03c0e1f64..d09081f36 100644 --- a/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php +++ b/Tests/Unit/Component/Core/RecordTree/RecordTreeBuilderTest.php @@ -84,14 +84,14 @@ function (Demands $demands, RecordCollection $recordCollection) use ($fooRecord) 1 => 'table_foo', ]); - $tcaService = $this->createMock(PageTypeService::class); - $tcaService->method('getTablesAllowedOnPage')->willReturn(['table_foo']); + $pageTypeService = $this->createMock(PageTypeService::class); + $pageTypeService->method('getTablesAllowedOnPage')->willReturn(['table_foo']); $recordTreeBuilder->injectDemandResolver($demandResolver); $recordTreeBuilder->injectRecordIndex($recordIndex); $recordTreeBuilder->injectDemandsFactory($demandsFactory); $recordTreeBuilder->injectRelevantTablesService($relevantTablesService); - $recordTreeBuilder->injectTcaService($tcaService); + $recordTreeBuilder->injectPageTypeService($pageTypeService); // act $recordsInCollection = $recordTreeBuilder->findAllRecordsOnPages(); diff --git a/Tests/Unit/Service/ReplaceMarkersServiceTest.php b/Tests/Unit/Service/ReplaceMarkersServiceTest.php index 8d6d0878b..ac75d26d4 100644 --- a/Tests/Unit/Service/ReplaceMarkersServiceTest.php +++ b/Tests/Unit/Service/ReplaceMarkersServiceTest.php @@ -54,7 +54,6 @@ public function testReplaceMarkerServiceSupportsPageTsConfigId(): void $record = $this->getRecordStub('tx_unit_test_table'); $flexFormTools = $this->createMock(FlexFormTools::class); - $tcaPreProcessingService = $this->createMock(TcaPreProcessingService::class); $siteFinder = $this->createMock(SiteFinder::class); $connection = $this->createMock(Connection::class); @@ -74,7 +73,6 @@ protected function getPagesTsConfig(int $pageIdentifier): array }; $replaceMarkerService->injectLocalDatabase($connection); $replaceMarkerService->injectFlexFormTools($flexFormTools); - $replaceMarkerService->injectTcaPreProcessingService($tcaPreProcessingService); $replaceMarkerService->injectSiteFinder($siteFinder); $replacement = $replaceMarkerService->replaceMarkers( @@ -95,7 +93,6 @@ public function testReplaceMarkerServiceSupportsPageTsConfigIdList(): void $record = $this->getRecordStub('tx_unit_test_table'); $flexFormTools = $this->createMock(FlexFormTools::class); - $tcaPreProcessingService = $this->createMock(TcaPreProcessingService::class); $siteFinder = $this->createMock(SiteFinder::class); $connection = $this->createMock(Connection::class); @@ -115,7 +112,6 @@ protected function getPagesTsConfig(int $pageIdentifier): array }; $replaceMarkerService->injectLocalDatabase($connection); $replaceMarkerService->injectFlexFormTools($flexFormTools); - $replaceMarkerService->injectTcaPreProcessingService($tcaPreProcessingService); $replaceMarkerService->injectSiteFinder($siteFinder); $replacement = $replaceMarkerService->replaceMarkers( @@ -135,7 +131,6 @@ public function testReplaceSiteMarker(): void $record = $this->getRecordStub('tx_unit_test_table'); $flexFormTools = $this->createMock(FlexFormTools::class); - $tcaProcessingService = $this->createMock(TcaPreProcessingService::class); $siteFinder = $this->createMock(SiteFinder::class); $siteFinder->method('getSiteByPageId')->willReturn( new Site('test', 1, [ @@ -161,7 +156,6 @@ public function testReplaceSiteMarker(): void $replaceMarkerService->injectLocalDatabase($connection); $replaceMarkerService->injectFlexFormTools($flexFormTools); $replaceMarkerService->injectSiteFinder($siteFinder); - $replaceMarkerService->injectTcaPreProcessingService($tcaProcessingService); $replacement = $replaceMarkerService->replaceMarkers( $record, diff --git a/Tests/Unit/Utility/BackendUtilityTest.php b/Tests/Unit/Utility/BackendUtilityTest.php index f2cc0d525..5b64a4508 100644 --- a/Tests/Unit/Utility/BackendUtilityTest.php +++ b/Tests/Unit/Utility/BackendUtilityTest.php @@ -29,8 +29,8 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use Doctrine\DBAL\Driver\Mysqli\MysqliStatement; -use Doctrine\DBAL\Schema\MySqlSchemaManager; +use Doctrine\DBAL\Result; +use Doctrine\DBAL\Schema\AbstractSchemaManager; use In2code\In2publishCore\Tests\UnitTestCase; use In2code\In2publishCore\Utility\BackendUtility; use ReflectionProperty; @@ -50,30 +50,30 @@ class BackendUtilityTest extends UnitTestCase protected function setUp(): void { parent::setUp(); - $connection = $this->createMock(Connection::class); - $schemaManager = $this->createMock(MySqlSchemaManager::class); + $schemaManager = $this->createMock(AbstractSchemaManager::class); $schemaManager->method('listTableNames')->willReturn( [ 'tt_content', ], ); - $connection->method('getSchemaManager')->willReturn($schemaManager); - $result = $this->createMock(MysqliStatement::class); + $result = $this->createMock(Result::class); $result->method('fetchAssociative')->willReturnCallback( function () { return $this->rows; }, ); - $restrictionContainer = $this->createMock(DefaultRestrictionContainer::class); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('select')->willReturn($queryBuilder); $queryBuilder->method('from')->willReturn($queryBuilder); $queryBuilder->method('where')->willReturn($queryBuilder); $queryBuilder->method('setMaxResults')->willReturn($queryBuilder); - $queryBuilder->method('execute')->willReturn($result); - $queryBuilder->method('getRestrictions')->willReturn($restrictionContainer); + $queryBuilder->method('executeQuery')->willReturn($result); + $queryBuilder->method('getRestrictions')->willReturn($this->createMock(DefaultRestrictionContainer::class)); + + $connection = $this->createMock(Connection::class); + $connection->method('createSchemaManager')->willReturn($schemaManager); $connection->method('createQueryBuilder')->willReturn($queryBuilder); $reflection = new ReflectionProperty(ConnectionPool::class, 'connections'); From e3cf710307def057665589041d6d9f3abc334102 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 10 Nov 2023 21:50:33 +0100 Subject: [PATCH 066/113] Revert "[DOC] Add documentation for changed ext_typoscript_template suffix" This reverts commit 7177e3848fbb357f44e0e5d6ec16d7c2d62413bc. --- ...king-ExtTyposcriptTemplateChangedSuffix.md | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md diff --git a/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md b/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md deleted file mode 100644 index a855eac7b..000000000 --- a/Documentation/Developers/Changelog/96518-Breaking-ExtTyposcriptTemplateChangedSuffix.md +++ /dev/null @@ -1,19 +0,0 @@ -# ext_typoscript_setup changed suffix - -Breaking Change TYPO3 https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/12.0/Breaking-96518-Ext_typoscript_txtFilesNotIncludedAnymore.html - -## Description - -The suffix of the `ext_typoscript_setup` has been changed from `.txt` to `.typoscript`. - -## Impact - - -## Affected Installations - -All installations that overwrite Content Publisher module templates and explicitly including the file -`EXT:in2publish_core/ext_typoscript_setup.txt` either via include statement of in the backend. - -## Migration - -* Include the file `EXT:in2publish_core/ext_typoscript_setup.typoscript` instead of `EXT:in2publish_core/ext_typoscript_setup.txt`. From 2de8da932c64ee58f47adfb444c6104b080beefb Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 9 Nov 2023 17:09:34 +0100 Subject: [PATCH 067/113] [WIP] Changed all Templates of Publish Tools Module --- .../AbstractAdminToolsController.php | 59 ++++++++++ .../Controller/LetterboxController.php | 5 +- .../Controller/RegistryController.php | 5 +- .../ShowConfigurationController.php | 5 +- .../AdminTools/Controller/TcaController.php | 5 +- .../AdminTools/Controller/TestController.php | 5 +- .../AdminTools/Controller/ToolsController.php | 5 +- .../Controller/RecordInspectorController.php | 6 +- .../SystemInformationExportController.php | 6 +- Resources/Private/Language/locallang.xlf | 42 +++++++- Resources/Private/Layouts/Submodule.html | 6 ++ Resources/Private/Partials/Footer.html | 26 +++-- Resources/Private/Partials/Header.html | 8 ++ .../CompareDatabaseTool/TableDetails.html | 16 +-- .../CompareDatabaseTool/TransferNotice.html | 21 +--- Resources/Private/Partials/Tools/GetHelp.html | 20 ++++ .../Partials/Tools/IntroductionMenu.html | 31 ++++-- .../Private/Partials/Tools/SysInfoDecode.html | 9 -- Resources/Private/Sass/_ModulesGeneral.scss | 20 +++- .../CompareDatabaseTool/Compare.html | 6 +- .../Templates/CompareDatabaseTool/Index.html | 44 +++++--- .../Private/Templates/Letterbox/Index.html | 39 +++++-- .../Templates/RecordInspector/Index.html | 50 +++++---- .../Templates/RecordInspector/Inspect.html | 20 +++- .../Private/Templates/Registry/Index.html | 27 +++-- .../Templates/ShowConfiguration/Index.html | 101 +++++++++++++++--- .../SysInfoDecode.html | 32 +++++- .../SystemInformationExport/SysInfoIndex.html | 70 ++++++++---- .../SystemInformationExport/SysInfoShow.html | 26 ++++- Resources/Private/Templates/Tca/Index.html | 67 +++++++----- Resources/Private/Templates/Test/Index.html | 28 ++--- Resources/Private/Templates/Tools/Index.html | 36 ++----- Resources/Public/Css/Modules.css | 2 +- 33 files changed, 585 insertions(+), 263 deletions(-) create mode 100644 Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php create mode 100644 Resources/Private/Layouts/Submodule.html create mode 100644 Resources/Private/Partials/Header.html create mode 100644 Resources/Private/Partials/Tools/GetHelp.html delete mode 100644 Resources/Private/Partials/Tools/SysInfoDecode.html diff --git a/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php new file mode 100644 index 000000000..174c249b3 --- /dev/null +++ b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php @@ -0,0 +1,59 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use In2code\In2publishCore\CommonInjection\PageRendererInjection; +use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; +use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; + +abstract class AbstractAdminToolsController extends ActionController +{ + use AdminToolsModuleTemplate; + use PageRendererInjection { + injectPageRenderer as actualInjectPageRenderer; + } + + /** + * @codeCoverageIgnore + * @noinspection PhpUnused + */ + public function injectPageRenderer(PageRenderer $pageRenderer): void + { + $this->actualInjectPageRenderer($pageRenderer); + $this->pageRenderer->addCssFile( + 'EXT:in2publish_core/Resources/Public/Css/Modules.css', + 'stylesheet', + 'all', + '', + false, + ); + } +} diff --git a/Classes/Features/AdminTools/Controller/LetterboxController.php b/Classes/Features/AdminTools/Controller/LetterboxController.php index 3e4022615..8ad2d904f 100644 --- a/Classes/Features/AdminTools/Controller/LetterboxController.php +++ b/Classes/Features/AdminTools/Controller/LetterboxController.php @@ -30,14 +30,11 @@ */ use In2code\In2publishCore\Component\RemoteProcedureCall\LetterboxInjection; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -class LetterboxController extends ActionController +class LetterboxController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use LetterboxInjection; public function indexAction(): ResponseInterface diff --git a/Classes/Features/AdminTools/Controller/RegistryController.php b/Classes/Features/AdminTools/Controller/RegistryController.php index 5ecbad33f..841e715c0 100644 --- a/Classes/Features/AdminTools/Controller/RegistryController.php +++ b/Classes/Features/AdminTools/Controller/RegistryController.php @@ -30,15 +30,12 @@ */ use In2code\In2publishCore\CommonInjection\RegistryInjection; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -class RegistryController extends ActionController +class RegistryController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use RegistryInjection; public function indexAction(): ResponseInterface diff --git a/Classes/Features/AdminTools/Controller/ShowConfigurationController.php b/Classes/Features/AdminTools/Controller/ShowConfigurationController.php index ae39e91f9..77824159d 100644 --- a/Classes/Features/AdminTools/Controller/ShowConfigurationController.php +++ b/Classes/Features/AdminTools/Controller/ShowConfigurationController.php @@ -31,13 +31,10 @@ use In2code\In2publishCore\Component\ConfigContainer\ConfigContainerInjection; use In2code\In2publishCore\Component\ConfigContainer\Dumper\ConfigContainerDumper; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -class ShowConfigurationController extends ActionController +class ShowConfigurationController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use ConfigContainerInjection; private ConfigContainerDumper $configContainerDumper; diff --git a/Classes/Features/AdminTools/Controller/TcaController.php b/Classes/Features/AdminTools/Controller/TcaController.php index 343c03073..9bf2d8d14 100644 --- a/Classes/Features/AdminTools/Controller/TcaController.php +++ b/Classes/Features/AdminTools/Controller/TcaController.php @@ -30,13 +30,10 @@ */ use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -class TcaController extends ActionController +class TcaController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use CachedTcaPreProcessingServiceInjection; public function indexAction(): ResponseInterface diff --git a/Classes/Features/AdminTools/Controller/TestController.php b/Classes/Features/AdminTools/Controller/TestController.php index d045e1aad..00509e3eb 100644 --- a/Classes/Features/AdminTools/Controller/TestController.php +++ b/Classes/Features/AdminTools/Controller/TestController.php @@ -29,17 +29,14 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use In2code\In2publishCore\In2publishCoreException; use In2code\In2publishCore\Service\Environment\EnvironmentServiceInjection; use In2code\In2publishCore\Testing\Service\TestingServiceInjection; use In2code\In2publishCore\Testing\Tests\TestResult; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -class TestController extends ActionController +class TestController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use EnvironmentServiceInjection; use TestingServiceInjection; diff --git a/Classes/Features/AdminTools/Controller/ToolsController.php b/Classes/Features/AdminTools/Controller/ToolsController.php index 2370bf731..69a5ad763 100644 --- a/Classes/Features/AdminTools/Controller/ToolsController.php +++ b/Classes/Features/AdminTools/Controller/ToolsController.php @@ -30,20 +30,17 @@ */ use In2code\In2publishCore\Event\CreatedDefaultHelpLabels; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; use In2code\In2publishCore\Service\Environment\EnvironmentServiceInjection; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Messaging\AbstractMessage; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use function implode; use const PHP_EOL; -class ToolsController extends ActionController +class ToolsController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use EnvironmentServiceInjection; public function indexAction(): ResponseInterface diff --git a/Classes/Features/RecordInspector/Controller/RecordInspectorController.php b/Classes/Features/RecordInspector/Controller/RecordInspectorController.php index 19509ff7e..297a70713 100644 --- a/Classes/Features/RecordInspector/Controller/RecordInspectorController.php +++ b/Classes/Features/RecordInspector/Controller/RecordInspectorController.php @@ -9,17 +9,15 @@ use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuilderInjection; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuildRequest; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; +use In2code\In2publishCore\Features\AdminTools\Controller\AbstractAdminToolsController; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use function array_combine; use function array_keys; use function array_merge; -class RecordInspectorController extends ActionController +class RecordInspectorController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; use RecordTreeBuilderInjection; use DefaultFalFinderInjection; diff --git a/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php b/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php index 51a68681a..db00d3508 100644 --- a/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php +++ b/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php @@ -29,12 +29,11 @@ * This copyright notice MUST APPEAR in all copies of the script! */ -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; +use In2code\In2publishCore\Features\AdminTools\Controller\AbstractAdminToolsController; use In2code\In2publishCore\Features\SystemInformationExport\Service\SystemInformationExportService; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Extbase\Http\ForwardResponse; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; @@ -55,9 +54,8 @@ use const JSON_THROW_ON_ERROR; -class SystemInformationExportController extends ActionController +class SystemInformationExportController extends AbstractAdminToolsController { - use AdminToolsModuleTemplate; protected SystemInformationExportService $sysInfoExportService; diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index d107911cf..b03b045ee 100755 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -16,8 +16,23 @@ Publish files - - administration tools + + Administration Tools + + + Getting Help + + + Tests + + + Compare Database + + + Record Inspector + + + Select Classification and Identifier for inspection Publish redirects @@ -269,11 +284,20 @@ Configuration + + Navigate to Global Configuration + + + Navigate to Personal Configuration + + + Navigate to Config Container Dump + Global Configuration - Personal Config + Personal Configuration Config Container Dump @@ -308,15 +332,27 @@ Navigate to controls + + Registry entries + + + System Information + Flushed all related registry entries. + + Superfluous Envelopes + Flushed all superfluous envelopes. Flush superfluous envelopes. + + There are superfluous envelopes in the foreign database. + There are no envelopes to flush. diff --git a/Resources/Private/Layouts/Submodule.html b/Resources/Private/Layouts/Submodule.html new file mode 100644 index 000000000..e0d5bfcd5 --- /dev/null +++ b/Resources/Private/Layouts/Submodule.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/Resources/Private/Partials/Footer.html b/Resources/Private/Partials/Footer.html index 22d43d957..278a7ba9a 100755 --- a/Resources/Private/Partials/Footer.html +++ b/Resources/Private/Partials/Footer.html @@ -1,6 +1,9 @@ - + diff --git a/Resources/Private/Partials/Header.html b/Resources/Private/Partials/Header.html new file mode 100644 index 000000000..0a848d631 --- /dev/null +++ b/Resources/Private/Partials/Header.html @@ -0,0 +1,8 @@ + +

+ + - {moduleName} +

+ diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html index b84df19be..04d1f1c0b 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html @@ -3,8 +3,9 @@ xmlns:publish="http://typo3.org/ns/In2code/In2publishCore/ViewHelpers" data-namespace-typo3-fluid="true" > - - +
+
+ @@ -20,8 +21,8 @@ - - + + @@ -33,7 +34,7 @@ row="{value.local}" /> +
UID PID
- +
@@ -75,6 +76,7 @@ - -
{field}
+
+
diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html index 7327ecb53..ded570814 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html @@ -1,20 +1,5 @@ -
-
-
- - - - -
-
-

- -

-
- -
-
-
-
+ + + diff --git a/Resources/Private/Partials/Tools/GetHelp.html b/Resources/Private/Partials/Tools/GetHelp.html new file mode 100644 index 000000000..1095e94b7 --- /dev/null +++ b/Resources/Private/Partials/Tools/GetHelp.html @@ -0,0 +1,20 @@ + +
+
+
+

+ +

+
+
+
+
    + +
  • + {support} +
  • +
    +
+
+
+ diff --git a/Resources/Private/Partials/Tools/IntroductionMenu.html b/Resources/Private/Partials/Tools/IntroductionMenu.html index 5a25a0f41..ad18d4bf4 100644 --- a/Resources/Private/Partials/Tools/IntroductionMenu.html +++ b/Resources/Private/Partials/Tools/IntroductionMenu.html @@ -1,12 +1,23 @@ -
    - -
  • - - {entry.name} - :{entry.description} - -
  • -
    -
+
+
+
+

+ Introduction +

+
+
+
+
    + +
  • + + {entry.name} + :{entry.description} + +
  • +
    +
+
+
diff --git a/Resources/Private/Partials/Tools/SysInfoDecode.html b/Resources/Private/Partials/Tools/SysInfoDecode.html deleted file mode 100644 index 47bd47f15..000000000 --- a/Resources/Private/Partials/Tools/SysInfoDecode.html +++ /dev/null @@ -1,9 +0,0 @@ - - -
- - -
- -
- diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index cef270d96..9fc7cb065 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -662,13 +662,25 @@ div#typo3-docbody.stopScrolling { border-bottom-right-radius: 2px } -// Fix buttons in admin tools module - -.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group { - flex-wrap: wrap; +.tx_in2publishcore_admintools { + .card-body { + .extbase-debugger { + margin: 0; + } + } + // Fix buttons in admin tools module + .module-docheader-bar-buttons { + .btn-toolbar { + .btn-group { + flex-wrap: wrap; + } + } + } } + + .in2publish-state-icon { &:before { font-size: 6px; diff --git a/Resources/Private/Templates/CompareDatabaseTool/Compare.html b/Resources/Private/Templates/CompareDatabaseTool/Compare.html index 83b9e7a60..56b56153b 100644 --- a/Resources/Private/Templates/CompareDatabaseTool/Compare.html +++ b/Resources/Private/Templates/CompareDatabaseTool/Compare.html @@ -1,5 +1,9 @@ - + + + + + diff --git a/Resources/Private/Templates/CompareDatabaseTool/Index.html b/Resources/Private/Templates/CompareDatabaseTool/Index.html index 4e68901b6..711ca1f4d 100644 --- a/Resources/Private/Templates/CompareDatabaseTool/Index.html +++ b/Resources/Private/Templates/CompareDatabaseTool/Index.html @@ -1,27 +1,41 @@ - + + + + + - -
-

-
-
-
- - -
+ + +
+
+
+

+ +

-
-
-
+
+
+
+ + +
+
-
+
diff --git a/Resources/Private/Templates/Letterbox/Index.html b/Resources/Private/Templates/Letterbox/Index.html index ae72c17bf..ad365b1a8 100644 --- a/Resources/Private/Templates/Letterbox/Index.html +++ b/Resources/Private/Templates/Letterbox/Index.html @@ -1,16 +1,33 @@ - + + + + + - - - - - - - -

-
-
+
+
+
+ + +

+ +

+
+ +

+
+
+
+ +
+
diff --git a/Resources/Private/Templates/RecordInspector/Index.html b/Resources/Private/Templates/RecordInspector/Index.html index 3a1c9d903..67ac701ef 100644 --- a/Resources/Private/Templates/RecordInspector/Index.html +++ b/Resources/Private/Templates/RecordInspector/Index.html @@ -1,33 +1,45 @@ - + + + + + - -
-
-
-
- - -
+
+
+
+

+ +

-
-
- +
+
+
+
+ + +
+
+
-
-
-
-
-
+
-
+
diff --git a/Resources/Private/Templates/RecordInspector/Inspect.html b/Resources/Private/Templates/RecordInspector/Inspect.html index 2b5143fed..f7e4306b4 100644 --- a/Resources/Private/Templates/RecordInspector/Inspect.html +++ b/Resources/Private/Templates/RecordInspector/Inspect.html @@ -1,11 +1,25 @@ - + + + + + - - {recordTree} +
+

+
+ {recordTree} +
+
+ + diff --git a/Resources/Private/Templates/Registry/Index.html b/Resources/Private/Templates/Registry/Index.html index 724320d47..7e9878303 100644 --- a/Resources/Private/Templates/Registry/Index.html +++ b/Resources/Private/Templates/Registry/Index.html @@ -1,13 +1,24 @@ - + - -

- -

+ + + - - - + +
+
+
+

+ +

+
+ +
+
diff --git a/Resources/Private/Templates/ShowConfiguration/Index.html b/Resources/Private/Templates/ShowConfiguration/Index.html index e315c576a..9c3415446 100755 --- a/Resources/Private/Templates/ShowConfiguration/Index.html +++ b/Resources/Private/Templates/ShowConfiguration/Index.html @@ -1,26 +1,93 @@ - + - -

Publish Content

- -

global config

- - {globalConfig} - -

personal config

+ + + - {fullConfig} + + + +
+
+
+

+ global config +

+
+
+
+ {globalConfig} +
+
-

module.m4.container_dump

+ + +
+
+
+

+ personal config +

+
+
+
+ {fullConfig} +
+
- -
- - + + +
+
+
+

+ module.m4.container_dump +

+
+
+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+
+ {containerDump} +
+
- +
+ - {containerDump} + + diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html b/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html index f0f936717..069ccbf20 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html @@ -1,10 +1,32 @@ - + + + + + - - - {info} - +
+
+ +
+
+ + +
+
+
+
+ +
+
+
+ + {info} + +
+
diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html b/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html index 61cb9f130..e9b0a0945 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html @@ -1,25 +1,55 @@ - - + + + + + + - - system_info.show - - - system_info.download - - - system_info.decode - - -
- - +
+
+
+

+ + + system_info.show + +

+

+ + + system_info.download + +

+

+ + + system_info.decode + +

+
+
+
+
+ +
+
+ + +
+
+ +
+
+
+
- - +
diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html b/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html index 56ad7a286..3db5ecd8d 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html @@ -1,11 +1,27 @@ - + + + + + -
- - +
+
+
+

+ JSON +

+
+
+
+ +
+
+
+
+ {info} +
- {info} diff --git a/Resources/Private/Templates/Tca/Index.html b/Resources/Private/Templates/Tca/Index.html index 049c984ae..5d4806455 100755 --- a/Resources/Private/Templates/Tca/Index.html +++ b/Resources/Private/Templates/Tca/Index.html @@ -1,39 +1,54 @@ - + - -

- Publish Content - - - TCA -

+ + + + -

- Compatible TCA -

- - {compatibleTca} +
+
+
+

+ Compatible TCA +

+
+
+
+ {compatibleTca} +
+
-

- Inompatible TCA -

- {incompatibleTca} +
+
+
+

+ Inompatible TCA +

+
+
+
+ {incompatibleTca} +
+
- - + diff --git a/Resources/Private/Templates/Test/Index.html b/Resources/Private/Templates/Test/Index.html index 932926273..320b0aab2 100755 --- a/Resources/Private/Templates/Test/Index.html +++ b/Resources/Private/Templates/Test/Index.html @@ -1,19 +1,21 @@ - + - -

- Publish Content - - - Tools -

+ + + -
- - - {testResult.translatedMessages} - - + +
+
+
+ + + {testResult.translatedMessages} + + +
+
diff --git a/Resources/Private/Templates/Tools/Index.html b/Resources/Private/Templates/Tools/Index.html index f487c4fc5..defc2fa46 100755 --- a/Resources/Private/Templates/Tools/Index.html +++ b/Resources/Private/Templates/Tools/Index.html @@ -1,30 +1,16 @@ - + - - -

Getting Help

- -
    - -
  • - {support} -
  • -
    -
-
- - -

- Publish Content - - - Tools -

- -

- admin tools -

+ + + - + +
+ + + + +
diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index bd696fa2b..bea1fd08f 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff;padding-top:1em}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff;padding-top:1em}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .card-body .extbase-debugger{margin:0}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} From a0931c98ebd83069d048c3ebcc118c511f49c51a Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 13 Nov 2023 14:10:50 +0100 Subject: [PATCH 068/113] [FEATURE] Moved all Labels from Publish Tools Module to locallang_mod4.xlf Resolves: https://projekte.in2code.de/issues/60157 --- .../AbstractAdminToolsController.php | 3 + .../Controller/LetterboxController.php | 3 +- .../Controller/RegistryController.php | 6 +- .../AdminTools/Controller/ToolsController.php | 8 +- .../SystemInformationExportController.php | 10 +- .../Features/AdminTools/Services.yaml | 24 +- .../CompareDatabaseTool/Services.yaml | 4 +- .../Features/RecordInspector/Services.yaml | 4 +- .../SystemInformationExport/Services.yaml | 4 +- Resources/Private/Language/de.locallang.xlf | 828 ++++++------------ .../Private/Language/de.locallang_mod4.xlf | 324 ++++++- Resources/Private/Language/locallang.xlf | 558 +++--------- Resources/Private/Language/locallang_mod4.xlf | 242 ++++- .../Tools/CompareDatabaseTool/Details.html | 4 +- .../CompareDatabaseTool/TableDetails.html | 10 +- .../CompareDatabaseTool/TransferNotice.html | 9 +- Resources/Private/Partials/Tools/GetHelp.html | 4 +- .../Partials/Tools/IntroductionMenu.html | 6 +- .../CompareDatabaseTool/Compare.html | 4 +- .../Templates/CompareDatabaseTool/Index.html | 8 +- .../Private/Templates/Letterbox/Index.html | 8 +- .../Templates/RecordInspector/Index.html | 4 +- .../Templates/RecordInspector/Inspect.html | 4 +- .../Private/Templates/Registry/Index.html | 6 +- .../Templates/ShowConfiguration/Index.html | 22 +- .../SysInfoDecode.html | 6 +- .../SystemInformationExport/SysInfoIndex.html | 12 +- .../SystemInformationExport/SysInfoShow.html | 2 +- Resources/Private/Templates/Tca/Index.html | 14 +- Resources/Private/Templates/Test/Index.html | 2 +- Resources/Private/Templates/Tools/Index.html | 2 +- 31 files changed, 1035 insertions(+), 1110 deletions(-) diff --git a/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php index 174c249b3..7fbfd9b10 100644 --- a/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php +++ b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php @@ -48,6 +48,9 @@ abstract class AbstractAdminToolsController extends ActionController public function injectPageRenderer(PageRenderer $pageRenderer): void { $this->actualInjectPageRenderer($pageRenderer); + $this->pageRenderer->addInlineLanguageLabelFile( + 'EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf', + ); $this->pageRenderer->addCssFile( 'EXT:in2publish_core/Resources/Public/Css/Modules.css', 'stylesheet', diff --git a/Classes/Features/AdminTools/Controller/LetterboxController.php b/Classes/Features/AdminTools/Controller/LetterboxController.php index 8ad2d904f..8a6e3b264 100644 --- a/Classes/Features/AdminTools/Controller/LetterboxController.php +++ b/Classes/Features/AdminTools/Controller/LetterboxController.php @@ -48,8 +48,7 @@ public function flushEnvelopesAction(): ResponseInterface $this->letterbox->removeAnsweredEnvelopes(); $this->addFlashMessage( LocalizationUtility::translate( - 'module.m4.superfluous_envelopes_flushed', - 'in2publish_core', + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:flush_envelopes.flushed', ), ); return $this->redirect('index'); diff --git a/Classes/Features/AdminTools/Controller/RegistryController.php b/Classes/Features/AdminTools/Controller/RegistryController.php index 841e715c0..a1bb7604e 100644 --- a/Classes/Features/AdminTools/Controller/RegistryController.php +++ b/Classes/Features/AdminTools/Controller/RegistryController.php @@ -47,7 +47,11 @@ public function indexAction(): ResponseInterface public function flushRegistryAction(): ResponseInterface { $this->registry->removeAllByNamespace('tx_in2publishcore'); - $this->addFlashMessage(LocalizationUtility::translate('module.m4.registry_flushed', 'in2publish_core')); + $this->addFlashMessage( + LocalizationUtility::translate( + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:flush_registry.registry_flushed' + ) + ); return $this->redirect('index'); } } diff --git a/Classes/Features/AdminTools/Controller/ToolsController.php b/Classes/Features/AdminTools/Controller/ToolsController.php index 69a5ad763..06b4256dd 100644 --- a/Classes/Features/AdminTools/Controller/ToolsController.php +++ b/Classes/Features/AdminTools/Controller/ToolsController.php @@ -60,8 +60,12 @@ public function indexAction(): ResponseInterface } $supports = [ - LocalizationUtility::translate('help.github_issues', 'in2publish_core'), - LocalizationUtility::translate('help.slack_channel', 'in2publish_core'), + LocalizationUtility::translate( + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:help.github_issues' + ), + LocalizationUtility::translate( + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:help.slack_channel' + ), ]; $event = new CreatedDefaultHelpLabels($supports); diff --git a/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php b/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php index db00d3508..32ceb8bb4 100644 --- a/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php +++ b/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php @@ -90,8 +90,14 @@ public function sysInfoDecodeAction(string $json = ''): ResponseInterface } else { $args = [json_last_error(), json_last_error_msg()]; $this->addFlashMessage( - LocalizationUtility::translate('system_info.decode.json_error.details', 'in2publish_core', $args), - LocalizationUtility::translate('system_info.decode.json_error', 'in2publish_core'), + LocalizationUtility::translate( + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:system_info.decode.json_error.details', + null, + $args + ), + LocalizationUtility::translate( + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:system_info.decode.json_error', + ), AbstractMessage::ERROR, ); } diff --git a/Configuration/Features/AdminTools/Services.yaml b/Configuration/Features/AdminTools/Services.yaml index ba446a91f..fa1387745 100644 --- a/Configuration/Features/AdminTools/Services.yaml +++ b/Configuration/Features/AdminTools/Services.yaml @@ -10,42 +10,42 @@ services: In2code\In2publishCore\Features\AdminTools\Controller\LetterboxController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.flush_envelopes' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.flush_envelopes.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.flush_envelopes' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.flush_envelopes.description' actions: 'index,flushEnvelopes' In2code\In2publishCore\Features\AdminTools\Controller\RegistryController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.flush_registry' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.flush_registry.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.flush_registry' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.flush_registry.description' actions: 'index,flushRegistry' In2code\In2publishCore\Features\AdminTools\Controller\TcaController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.tca' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.tca.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.tca' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.tca.description' actions: 'index' In2code\In2publishCore\Features\AdminTools\Controller\ShowConfigurationController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.configuration' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.configuration.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.configuration' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.configuration.description' actions: 'index' In2code\In2publishCore\Features\AdminTools\Controller\TestController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.test' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.test.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.test' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.test.description' actions: 'index' In2code\In2publishCore\Features\AdminTools\Controller\ToolsController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.index' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.index.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.index' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.index.description' actions: 'index' before: '*' diff --git a/Configuration/Features/CompareDatabaseTool/Services.yaml b/Configuration/Features/CompareDatabaseTool/Services.yaml index 3d5835e65..fdc030cec 100644 --- a/Configuration/Features/CompareDatabaseTool/Services.yaml +++ b/Configuration/Features/CompareDatabaseTool/Services.yaml @@ -13,6 +13,6 @@ services: In2code\In2publishCore\Features\CompareDatabaseTool\Controller\CompareDatabaseToolController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.compare' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.compare.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.compare' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.compare.description' actions: 'index,compare,transfer' diff --git a/Configuration/Features/RecordInspector/Services.yaml b/Configuration/Features/RecordInspector/Services.yaml index 22851e0a7..26e47844b 100644 --- a/Configuration/Features/RecordInspector/Services.yaml +++ b/Configuration/Features/RecordInspector/Services.yaml @@ -10,6 +10,6 @@ services: In2code\In2publishCore\Features\RecordInspector\Controller\RecordInspectorController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.record_inspector' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.record_inspector.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.record_inspector' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.record_inspector.description' actions: 'index,inspect' diff --git a/Configuration/Features/SystemInformationExport/Services.yaml b/Configuration/Features/SystemInformationExport/Services.yaml index bf3f6664d..30bb3d8db 100644 --- a/Configuration/Features/SystemInformationExport/Services.yaml +++ b/Configuration/Features/SystemInformationExport/Services.yaml @@ -13,6 +13,6 @@ services: In2code\In2publishCore\Features\SystemInformationExport\Controller\SystemInformationExportController: tags: - name: 'in2publish_core.admin_tool' - title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.system_info' - description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.system_info.description' + title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.system_info' + description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.system_info.description' actions: 'sysInfoIndex,sysInfoShow,sysInfoDecode,sysInfoDownload,sysInfoUpload' diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 9667a0c67..0f6b7d37f 100755 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -1,812 +1,476 @@ - - - + + +
- + Publish Overview - Publisher Übersicht + Publisher Übersicht - - + TYPO3 Content Publisher - TYPO3 Content Publisher + TYPO3 Content Publisher - + publish pages and records overview - Übersicht Seiten und Datensätze veröffentlichen + Übersicht Seiten und Datensätze veröffentlichen - + Publish files - Dateien veröffentlichen - - - administration tools - Tools für Administratoren + Dateien veröffentlichen - + Publish redirects - Redirects veröffentlichen + Redirects veröffentlichen - - + Depth - Tiefe + Tiefe - + %d level - %d Ebene + %d Ebene - + %d levels - %d Ebenen + %d Ebenen - - + Stage System - Redaktionssystem + Redaktionssystem - + Production System - Produktivsystem + Produktivsystem - + The selected record has been published successfully. (Duration: %s) - Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. (Dauer: %s) + Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. (Dauer: %s) - + One or more errors occurred during publishing. Please check the logs. (Duration: %s) - Ein oder mehrere Fehler traten während des Publizierungsvorgangs auf. Bitte prüfen Sie die Fehlerlogs. (Dauer: %s) + Ein oder mehrere Fehler traten während des Publizierungsvorgangs auf. Bitte prüfen Sie die Fehlerlogs. (Dauer: %s) - + One or more errors occurred during relation resolving. Please check the logs. - Ein oder mehrere Fehler traten auf während die Verknüpfungen aufgelöst wurden. Bitte prüfen Sie die Fehlerlogs. + Ein oder mehrere Fehler traten auf während die Verknüpfungen aufgelöst wurden. Bitte prüfen Sie die Fehlerlogs. - + The selected record has been published successfully. - Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. + Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. - + The selected folder has been created successfully. - Der ausgewählte Ordner wurde erfolgreich angelegt. + Der ausgewählte Ordner wurde erfolgreich angelegt. - + The selected folder could not be created. - Der ausgewählte Ordner konnte nicht angelegt werden. + Der ausgewählte Ordner konnte nicht angelegt werden. - + The selected folder has been removed successfully. - Der ausgewählte Ordner wurde erfolgreich gelöscht. + Der ausgewählte Ordner wurde erfolgreich gelöscht. - + The selected folder could not be removed. - Der ausgewählte Ordner konnte nicht gelöscht werden. + Der ausgewählte Ordner konnte nicht gelöscht werden. - - in2publish failed to retrieve information about the folder %s or any of it's sub folders. Please verify that is in2publish is working properly by running the tests. - in2publish konnte keine Informationen über den Ordner %s oder einen seiner Unterordner auslesen. Bitte überprüfen Sie ob in2publish korrekt eingerichtet ist, indem Sie die Tests durchführen. + + in2publish failed to retrieve information about the folder %s or any of it's sub folders. Please verify that is in2publish is working properly by running the tests. + in2publish konnte keine Informationen über den Ordner %s oder einen seiner Unterordner auslesen. Bitte überprüfen Sie ob in2publish korrekt eingerichtet ist, indem Sie die Tests durchführen. - - Publish page "%s" and its subpages. - Veröffentlichen der Seite "%s" und ihrer Unterseiten + + Publish page "%s" and its subpages. + Veröffentlichen der Seite "%s" und ihrer Unterseiten - + Do you really want to publish all pages? - Möchten Sie wirklich alle Seiten veröffentlichen? + Möchten Sie wirklich alle Seiten veröffentlichen? - + Do you really want to publish this page? - Möchten Sie diese Seite wirklich veröffentlichen? + Möchten Sie diese Seite wirklich veröffentlichen? - + Publish Publizieren - + Publish this page - Diese Seite publizieren + Diese Seite publizieren - + This page is currently being published - Diese Seite wird gerade veröffentlicht + Diese Seite wird gerade veröffentlicht - + This file is currently being published - Diese Datei wird gerade veröffentlicht + Diese Datei wird gerade veröffentlicht - - Publish all files within folder "%s". - Veröffentlichen aller Dateien innerhalb von "%s" + + Publish all files within folder "%s". + Veröffentlichen aller Dateien innerhalb von "%s" - + Do you really want to publish all files? - Möchten Sie wirklich alle Dateien veröffentlichen? + Möchten Sie wirklich alle Dateien veröffentlichen? - + Do you really want to publish this file? - Möchten Sie diese Datei wirklich veröffentlichen? + Möchten Sie diese Datei wirklich veröffentlichen? - + Preview - Vorschau + Vorschau - + Compare - Vergleichsansicht + Vergleichsansicht - + History - Historie + Historie - + File preview - Dateivorschau + Dateivorschau - + Edit - Bearbeiten + Bearbeiten - + %s properties - Eigenschaften von %s + Eigenschaften von %s - + Page properties - Seiteneigenschaften + Seiteneigenschaften - + Record history - Datensatz Historie + Datensatz Historie - + Edit record - Datensatz bearbeiten + Datensatz bearbeiten - + Related Records - Verknüpfte Datensätze + Verknüpfte Datensätze - + Record State - Datensatz Status - - - - Introduction - Übersicht - - - This tool just lists all other tools. - Dieses Tool listet nur alle anderen Tools auf - - - Show configuration - Konfigurationsübersicht - - - Display the local configuration of in2publish from LocalConfiguration.yaml - Zeige die aktuelle Konfiguration von in2publish von der LocalConfiguration.yaml Datei - - - Show logs - Logs anzeigen - - - Show all logs of the Content Publisher with plenty filter options - Zeigt die Logeinträge des Content Publishers mit vielen Filteroptionen an - - - Tests - Tests - - - Run some function test of in2publish - Teste in2publish auf Funktionsfähigkeit - - - Inspect TCA - TCA inspection - - - See which parts of the TCA are processed, and the reason why others are not. - Zeige die Teile des TCA die verwendet werden und alle anderen mit der Begründung warum sie nicht verwendet werden. - - - Remove superfluous envelopes - Überflüssige Envelopes löschen - - - Deletes all envelopes (remote procedure call database entries) which were already used (envelopes are one-way records). - Löscht alle Envelopes ("Remote Procedure Call"-Datenbankeinträge) die bereits genutzt wurden (Diese sind Einweg-Einträge) - - - Remove all Registry entries - Registereinträge löschen - - - Removes all registry entries which store information about the local and foreign environment. You must run the test after flushing these. - Löscht alle Registereinträge, welche Informationen über das lokale und entfernte System vorhalten. Danach müssen die Tests erneut ausgeführt werden. - - - System information - Systeminformationen - - - Use this module to collect information which will be required or useful to solve a bug or problem. - Anzeige von Informationen welche erforderlich oder nützlich sind Probleme zu identifizieren und sie zu beheben. - - - Compare Databases - Datenbankvergleich - - - The compare tool scans the whole database for differences. This tool is ought to help administrators clean up UID conflicts. - Zeigt unterschiede zwischen den Datenbanken an. Dieses Tools soll Administratoren dabei helfen UID-Konflikte zu lösen. - - - Inspect a record tree - RecordTree Untersuchen - - - You can query for a record tree by classification and identifier and inspect it with all of its properties and children. - Hier kann ein RecordTree mittels Klassifikation und Identifikation aufgebaut und untersucht werden.. - - - - Show the system info - Systeminformationen anzeigen - - - Download the system info - Systeminformationen herunterladen + Datensatz Status - - Decode the system info JSON - JSON dekodieren - - - JSON string - JSON Text - - - Decode! - Dekodieren - - - Error during json decoding - Fehler während des dekodierens - - - JSON decode error #%d: %s - JSON dekodierfehler #%d: %s - - - SysInfo JSON file - Systeminformationen JSON Datei - - - Upload! - Hochladen! - - - + Filter by: Filtern nach: - - + Filename Dateiname - - + Status Status - - + Record unchanged - Unverändert + Unverändert - + Record changed - Datensatz geändert + Datensatz geändert - + New record - Neuer Datensatz + Neuer Datensatz - + Record deleted - Gelöschter Datensatz + Gelöschter Datensatz - + Record moved - Datensatz verschoben + Datensatz verschoben - - - + Unchanged - Unverändert + Unverändert - + Changed - Verändert + Verändert - + New - Neu + Neu - + Deleted - Gelöscht + Gelöscht - + Moved - Verschoben + Verschoben - + Moved/Changed - Verschoben/Verändert + Verschoben/Verändert - - Configuration - Konfiguration - - - Global Configuration - Globale Konfiguration - - - Personal Config - Persönliche Konfiguration - - - Config Container Dump - Config Container Konfiguration - - - Enter Page ID for page specific configuration - Seiten-ID für Seitenspezifische konfiguration angeben - - - Overview - Übersicht - - - Filter - Filter - - - TCA inspection - TCA Inspizieren - - - Compatible TCA - Kompatibles TCA - - - Incompatible TCA - Inkompatibles TCA - - - Controls - Controls - - - Navigate to incompatible TCA - Zu inkompatiblem TCA springen - - - Navigate to compatible TCA - Zu kompatiblem TCA springen - - - Navigate to controls - Zu controls springen - - - Flushed all related registry entries. - Alle zugehörigen Registereinträge wurden gelöscht. - - - Flushed all superfluous envelopes. - Alle überflüssigen Envelopes wurden gelöscht. - - - Flush superfluous envelopes. - Überflüssigen Envelopes löschen. - - - There are no envelopes to flush. - Es gibt keine Envelopes zum löschen. - - - Clear registry entries. - Registry-Einträge löschen. - - - The Content Publisher stores various information in the registry, like the outcome of the last test run. You can force the removal of these entries here. - Der Content Publisher speichert Informationen wie das Ergebnis des letzten Testlaufs in der Registry. Sie können die Löschung dieser Einträge hier erzwingen. - - - + In2publish might not work as expected. - In2publish könnte vom erwarteten Verhalten abweichen. + In2publish könnte vom erwarteten Verhalten abweichen. - + Unknown test state. Please execute the tests in the Publish Tools Module. - Unbekannter Teststatus. Bitte führen sie die Tests im Publish Tools Modul aus. + Unbekannter Teststatus. Bitte führen sie die Tests im Publish Tools Modul aus. - + Some In2publish tests are failing. - Einige Tests von in2publish schlagen fehl. + Einige Tests von in2publish schlagen fehl. - + Your TYPO3 installation changed. - Ihre TYPO3 Installation hat sich verändert. + Ihre TYPO3 Installation hat sich verändert. - + The In2publish configuration has changed. - Die In2publish Konfiguration wurde verändert. + Die In2publish Konfiguration wurde verändert. - - + Vertical - Vertikal + Vertikal - + Horizontal - Horizontal + Horizontal - - - Successful published. - Erfolgreich publiziert. + + Successfully published. + Erfolgreich publiziert. - + Something went wrong. - Ein Fehler ist aufgetreten. + Ein Fehler ist aufgetreten. - + The selected folder %s has been published to the foreign system. - Das Verzeichnis %s wurde erfolgreich publiziert. + Das Verzeichnis %s wurde erfolgreich publiziert. - + The selected folder %s could not be published. - Das Verzeichnis %s konnte nicht publiziert werden. + Das Verzeichnis %s konnte nicht publiziert werden. - + The selected file %s has been published to the foreign system. - Die Datei %s wurde erfolgreich publiziert. + Die Datei %s wurde erfolgreich publiziert. - + The selected file %s could not be fully published. - Die Datei %s konnte nicht vollständig publiziert werden. + Die Datei %s konnte nicht vollständig publiziert werden. - - + One or more additional tasks which run after the successful publishing process failed. Caches and other non critical aspects might not behave as expected. The logs might contain more information. - Eine oder mehrere Aufgaben, die nach dem erfolgreichen publizieren ausgeführt werden sind fehlgeschlagen. Caches und andere nicht kritische Aspekte könnten sich nicht wie erwartet verhalten. Die Logs können weitere Informationen enthalten. + Eine oder mehrere Aufgaben, die nach dem erfolgreichen publizieren ausgeführt werden sind fehlgeschlagen. Caches und andere nicht kritische Aspekte könnten sich nicht wie erwartet verhalten. Die Logs können weitere Informationen enthalten. - - + Secure, authenticated and encrypted command execution - Sichere, authentifizierte und verschlüsselte Befehlsausführung + Sichere, authentifizierte und verschlüsselte Befehlsausführung - + Secure, reliable and encrypted asset transmission - Sichere, zuverlässige und Verschlüsselte Dateiübertragung - - - - https://typo3.slack.com/archives/C2ULY79MZ]]> - https://typo3.slack.com/archives/C2ULY79MZ]]> - - - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> + Sichere, zuverlässige und Verschlüsselte Dateiübertragung - - + You are not allowed to publish this page. - Sie dürfen diese Seite nicht veröffentlichen. + Sie dürfen diese Seite nicht veröffentlichen. - + No page parameter was transferred. - Es wurde keine Seiten-ID zum veröffentlichen übertragen. + Es wurde keine Seiten-ID zum veröffentlichen übertragen. - - The page "%s" has been published. - Die Seite "%s" wurde veröffentlicht. + + The page "%s" has been published. + Die Seite "%s" wurde veröffentlicht. - - Error during publishing of page "%s". Please check your logs. - Beim veröffentlichen der Seite "%s" ist ein Fehler aufgetreten. Weitere Informationen finden Sie in den Logs. + + Error during publishing of page "%s". Please check your logs. + Beim veröffentlichen der Seite "%s" ist ein Fehler aufgetreten. Weitere Informationen finden Sie in den Logs. - + This record is not yet publishable. - Diese Seite ist noch nicht veröffentlichbar. + Diese Seite ist noch nicht veröffentlichbar. - - + Associated page - Verknüpfte Seite + Verknüpfte Seite - + Associated foreign Site - Verknüpfte Site des entfernten Systems + Verknüpfte Site des entfernten Systems - + Use site from associated page - Site der verknüpften Seite benutzen + Site der verknüpften Seite benutzen - + Page/Site association - Seite/Site Verknüpfung + Seite/Site Verknüpfung - - + Save and publish - Speichern und veröffentlichen + Speichern und veröffentlichen - + Publish all selected - Gewählte veröffentlichen + Gewählte veröffentlichen - + Status icons explained - Status Legende + Status Legende - + The redirect requires an associated page or site to be published - Dieser Redirect benötigt eine verknüpfte Seite oder Site um veröffentlicht werden zu können + Dieser Redirect benötigt eine verknüpfte Seite oder Site um veröffentlicht werden zu können - + The associated page is not published - Die verknüpfte Seite ist nicht publiziert. + Die verknüpfte Seite ist nicht publiziert. - + This redirect has unpublished changes. Hover over the icon to get more information - Der Redirect hat unveröffentlichte Änderungen. Den Mauszeiger auf das Icon bewegen um mehr zu erfahren + Der Redirect hat unveröffentlichte Änderungen. Den Mauszeiger auf das Icon bewegen um mehr zu erfahren - + This redirect is published - Dieser Redirect ist publiziert + Dieser Redirect ist publiziert - + Action icons explained - Aktionen Legende + Aktionen Legende - + This redirect can be published. Click to publish. - Dieser Redorect kann publiziert werden. Klicken um zu publizieren. + Dieser Redorect kann publiziert werden. Klicken um zu publizieren. - + This redirect can be published with a manual site association. Click to assign a Site and publish. - Dieser Redirect kann mit einer manuellen Site-Verknüpfung veröffentlicht werden. Klicken um eine Site zu verknüpfen und zu publizieren. + Dieser Redirect kann mit einer manuellen Site-Verknüpfung veröffentlicht werden. Klicken um eine Site zu verknüpfen und zu publizieren. - - + Property - Eigenschaft + Eigenschaft - + Old value - Alt + Alt - + New value - Neu + Neu - + ID - ID + ID - + Domain - Domain + Domain - + Source - Quelle + Quelle - + Target - Ziel + Ziel - + Status - Status + Status - + Actions - Aktionen + Aktionen - - + Missing associated page or site - Fehlende Seite oder Seitenkonfiguration + Fehlende Seite oder Seitenkonfiguration - - The associated page [%d] "%s" is not published - Die verknüpfte Seite [%d] "%s" ist nicht publiziert + + The associated page [%d] "%s" is not published + Die verknüpfte Seite [%d] "%s" ist nicht publiziert - + This redirect is published - Dieser Redirect ist publiziert + Dieser Redirect ist publiziert - - + Ready for publishing - Bereit zur Veröffentlichung + Bereit zur Veröffentlichung - + Missing page or site - Fehlende Seite oder Seitenkonfiguration + Fehlende Seite oder Seitenkonfiguration - + Requires page publishing - Fehlende Veröffentlichung der Seite + Fehlende Veröffentlichung der Seite - + Published - Veröffentlicht + Veröffentlicht - - + Filter - Filtern + Filtern - + Association - Verknüpfung + Verknüpfung - + Association present - Verknüpft + Verknüpft - + Association missing - Verknüpfung fehlend + Verknüpfung fehlend - - + Refresh page - Seite neu laden - - - - New - Neu - - - Deleted - Gelöscht + Seite neu laden - - Differences - Unterschiede - - - Generally - Generell - - - The table is empty on Local - Die Tabelle is auf Local leer. - - - The table is empty on Foreign - Die Tabelle is auf Foreign leer. - - - Transfer these changes to the foreign system - Übertrage diese Änderungen auf das entfernte System - - - No differences were found in the data of the selected tables. - Es wurden keine Unterschiede in den Daten der gewählten Tabellen entdeckt. - - - Select the tables to compare - Tabellen für den Vergleich auswählen - - - Tables - Tabellen - - - Compare - Vergleichen - - - This is not publishing - Dies ist kein Publishing - - - A transfer is not a publishing. Only the exact record that is selected is transferred. No relations to other records are resolved and no MM-records are displayed nor transferred. You should always prefer normal publishing to this feature. Use this feature only in an emergency and only if you are aware of all the consequences. - Ein Transfer ist kein Publishing. Es wird dabei nur exakt der Datensatz übertragen, der ausgewählt wird. Es werden keine Verknüpfungen zu anderen Datensätzen aufgelöst und es werden auch keine MM-Datensätze angezeigt oder übertragen. Sie sollten ein normales Publishing immer diesem Feature vorziehen. Nutzen Sie dieses Feature nur im Notfall und nur, wenn Sie sich aller Konsequenzen bewusst sind. - - - Record label - Datensatztitle - - - Actions - Aktionen - - - Differences - Unterschiede - - - Error - Fehler - - - Success - Erfolg - - - The record which should be transferred does not exist anymore. - Der Datensatz der übertragen werden sollte existiert nicht mehr. - - - The record which should be transferred should not exists on Foreign but it does. It was probably published in the meantime. - Der Datensatz der übertragen werden sollte sollte nicht auf Foreign existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit veröffentlicht. - - - The record which should be transferred should not exists on Local but it does. It was probably created in the meantime. - Der Datensatz der übertragen werden sollte sollte nicht auf Local existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit erstellt. - - - The record which should be transferred should exists on both Local and Foreign but it does not. Please reload the comparison view and try again. - Der Datensatz der übertragen werden sollte sollte auf Local und Foreign existieren, er fehlt jedoch auf mindestens einem System. Bitte versuchen Sie es noch einmal, nachdem Sie die Vergleichsansicht neu geladen haben. - - - The record %s[%d] was deleted from foreign. - Der Datensatz %s[%d] wurde auf Foreign gelöscht. - - - The record %s[%d] was created on foreign. - Der Datensatz %s[%d] wurde auf Foreign erstellt. - - - The record %s[%d] was updated on foreign. - Der Datensatz %s[%d] wurde auf Foreign aktualisiert. - - - + Admin tools - Administrationswerkzeuge + Administrationswerkzeuge - - - "%s" requires that the record "%s" (which is the default language version) is published first. - "%s" erfordert, dass der Datensatz "%s" (das ist die Standardsprachversion) zuerst veröffentlicht wird. + + "%s" requires that the record "%s" (which is the default language version) is published first. + "%s" erfordert, dass der Datensatz "%s" (das ist die Standardsprachversion) zuerst veröffentlicht wird. - - The record "%s" cannot be published until all visibility settings (%s) of the default language "%s" have been published. - Der Datensatz "%s" kann nicht veröffentlicht werden, bevor nicht alle Sichtbarkeitseinstellung (%s) der Standardsprache "%s" veröffentlicht wurden. + + The record "%s" cannot be published until all visibility settings (%s) of the default language "%s" have been published. + Der Datensatz "%s" kann nicht veröffentlicht werden, bevor nicht alle Sichtbarkeitseinstellung (%s) der Standardsprache "%s" veröffentlicht wurden. - - "%s" requires that the page "%s" is published first. - "%s" erfordert, dass die Seite "%s" zuerst veröffentlicht wird. + + "%s" requires that the page "%s" is published first. + "%s" erfordert, dass die Seite "%s" zuerst veröffentlicht wird. - - "%s" requires that the page "%s" has all of its properties published (%s) which determine if the record is visible. - "%s" setzt voraus, dass die Seite "%s" alle seine Eigenschaften veröffentlicht hat (%s), die bestimmen, ob der Datensatz sichtbar ist. + + "%s" requires that the page "%s" has all of its properties published (%s) which determine if the record is visible. + "%s" setzt voraus, dass die Seite "%s" alle seine Eigenschaften veröffentlicht hat (%s), die bestimmen, ob der Datensatz sichtbar ist. - - The record with classification "%s" and properties "%s" does not exist. - Der Datensatz mit der klassifizierung "%s" und Eigenschaften "%s" existiert nicht. + + The record with classification "%s" and properties "%s" does not exist. + Der Datensatz mit der klassifizierung "%s" und Eigenschaften "%s" existiert nicht. - - The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. - Der Datensatz "%s" ist ein Ziel des Verknüpfungsdatensatzes "%s". Das Ziel muss veröffentlicht werden, bevor der Verknüpfungsdatensatz veröffentlicht werden kann. + + The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. + Der Datensatz "%s" ist ein Ziel des Verknüpfungsdatensatzes "%s". Das Ziel muss veröffentlicht werden, bevor der Verknüpfungsdatensatz veröffentlicht werden kann. diff --git a/Resources/Private/Language/de.locallang_mod4.xlf b/Resources/Private/Language/de.locallang_mod4.xlf index f63133db9..5687865f6 100755 --- a/Resources/Private/Language/de.locallang_mod4.xlf +++ b/Resources/Private/Language/de.locallang_mod4.xlf @@ -1,19 +1,323 @@ - - - + + +
- - Publish Tools - Publisher Tools + + Publisher Tools + Publisher Tools - + This Module offers some admin tools to the TYPO3 Content Publisher. - Dieses Modul bietet Administratoren einige Zusatzfunktionen zum TYPO3 Content Publisher. + Dieses Modul bietet Administratoren einige Zusatzfunktionen zum TYPO3 Content Publisher. - + TYPO3 Content Publisher - TYPO3 Content Publisher + TYPO3 Content Publisher + + + Show the system info + Systeminformationen anzeigen + + + Download the system info + Systeminformationen herunterladen + + + Decode the system info JSON + JSON dekodieren + + + JSON string + JSON Text + + + Decode! + Dekodieren + + + JSON decode error #%d: %s + JSON dekodierfehler #%d: %s + + + SysInfo JSON file + Systeminformationen JSON Datei + + + Upload! + Hochladen! + + + Select Classification and Identifier for inspection + Bitte Klassifizierung und Identität auswählen + + + Toggle all relations + Alle Relationen umschalten + + + New + Neu + + + Deleted + Gelöscht + + + Differences + Unterschiede + + + Generally + Generell + + + The table is empty on Local + Die Tabelle is auf Local leer. + + + The table is empty on Foreign + Die Tabelle is auf Foreign leer. + + + Transfer these changes to the foreign system + Übertrage diese Änderungen auf das entfernte System + + + No differences were found in the data of the selected tables. + Es wurden keine Unterschiede in den Daten der gewählten Tabellen entdeckt. + + + Select the tables to compare + Tabellen für den Vergleich auswählen + + + Tables + Tabellen + + + Compare + Vergleichen + + + This is not publishing + Dies ist kein Publishing + + + A transfer is not a publishing. Only the exact record that is selected is transferred. No relations to other records are resolved and no MM-records are displayed nor transferred. You should always prefer normal publishing to this feature. Use this feature only in an emergency and only if you are aware of all the consequences. + Ein Transfer ist kein Publishing. Es wird dabei nur exakt der Datensatz übertragen, der ausgewählt wird. Es werden keine Verknüpfungen zu anderen Datensätzen aufgelöst und es werden auch keine MM-Datensätze angezeigt oder übertragen. Sie sollten ein normales Publishing immer diesem Feature vorziehen. Nutzen Sie dieses Feature nur im Notfall und nur, wenn Sie sich aller Konsequenzen bewusst sind. + + + Record label + Datensatztitle + + + Actions + Aktionen + + + Error + Fehler + + + Success + Erfolg + + + The record which should be transferred does not exist anymore. + Der Datensatz der übertragen werden sollte existiert nicht mehr. + + + The record which should be transferred should not exists on Foreign but it does. It was probably published in the meantime. + Der Datensatz der übertragen werden sollte sollte nicht auf Foreign existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit veröffentlicht. + + + The record which should be transferred should not exists on Local but it does. It was probably created in the meantime. + Der Datensatz der übertragen werden sollte sollte nicht auf Local existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit erstellt. + + + The record which should be transferred should exists on both Local and Foreign but it does not. Please reload the comparison view and try again. + Der Datensatz der übertragen werden sollte sollte auf Local und Foreign existieren, er fehlt jedoch auf mindestens einem System. Bitte versuchen Sie es noch einmal, nachdem Sie die Vergleichsansicht neu geladen haben. + + + The record %s[%d] was deleted from foreign. + Der Datensatz %s[%d] wurde auf Foreign gelöscht. + + + The record %s[%d] was created on foreign. + Der Datensatz %s[%d] wurde auf Foreign erstellt. + + + The record %s[%d] was updated on foreign. + Der Datensatz %s[%d] wurde auf Foreign aktualisiert. + + + Overview + Übersicht + + + Getting Help + Hilfe + + + Navigate to incompatible TCA + Zu inkompatiblem TCA springen + + + Navigate to compatible TCA + Zu kompatiblem TCA springen + + + Incompatible TCA + Inkompatibles TCA + + + Compatible TCA + Kompatibles TCA + + + Navigate to Personal Configuration + zur persönlichen Konfiguration springen + + + Navigate to Global Configuration + zur globalen Konfiguration springen + + + Navigate to Config Container Dump + zum Dump des Config Containers springen + + + Enter Page ID for page specific configuration + Seiten-ID für Seitenspezifische konfiguration angeben + + + Config Container Dump + Config Container Konfiguration + + + Global Configuration + Globale Konfiguration + + + Personal Configuration + Persönliche Konfiguration + + + Flushed all related registry entries. + Alle zugehörigen Registereinträge wurden gelöscht. + + + The Content Publisher stores various information in the registry, like the outcome of the last test run. You can force the removal of these entries here. + Der Content Publisher speichert Informationen wie das Ergebnis des letzten Testlaufs in der Registry. Sie können die Löschung dieser Einträge hier erzwingen. + + + Remove registry entries + Entferne Registrierungseinträge + + + Flushed all superfluous envelopes. + Alle überflüssigen Envelopes wurden gelöscht. + + + There are superfluous envelopes in the foreign database. + In der Foreign Datenbank sind überflüssige Envelopes vorhanden. + + + There are no envelopes to flush. + Es gibt keine Envelopes zum löschen. + + + Remove superfluous envelopes + Entferne überflüssige Envelopes + + + Introduction + Übersicht + + + This tool just lists all other tools. + Dieses Tool listet nur alle anderen Tools auf + + + Show configuration + Konfigurationsübersicht + + + Display the local configuration of in2publish from LocalConfiguration.yaml + Zeige die aktuelle Konfiguration von in2publish von der LocalConfiguration.yaml Datei + + + Show logs + Logs anzeigen + + + Show all logs of the Content Publisher with plenty filter options + Zeigt die Logeinträge des Content Publishers mit vielen Filteroptionen an + + + Tests + Tests + + + Run some function test of in2publish + Teste in2publish auf Funktionsfähigkeit + + + Inspect TCA + TCA inspection + + + See which parts of the TCA are processed, and the reason why others are not. + Zeige die Teile des TCA die verwendet werden und alle anderen mit der Begründung warum sie nicht verwendet werden. + + + Remove superfluous envelopes + Überflüssige Envelopes löschen + + + Deletes all envelopes (remote procedure call database entries) which were already used (envelopes are one-way records). + Löscht alle Envelopes ("Remote Procedure Call"-Datenbankeinträge) die bereits genutzt wurden (Diese sind Einweg-Einträge) + + + Remove all Registry entries + Registereinträge löschen + + + Removes all registry entries which store information about the local and foreign environment. You must run the test after flushing these. + Löscht alle Registereinträge, welche Informationen über das lokale und entfernte System vorhalten. Danach müssen die Tests erneut ausgeführt werden. + + + System information + Systeminformationen + + + Use this module to collect information which will be required or useful to solve a bug or problem. + Anzeige von Informationen welche erforderlich oder nützlich sind Probleme zu identifizieren und sie zu beheben. + + + Compare Databases + Datenbankvergleich + + + The compare tool scans the whole database for differences. This tool is ought to help administrators clean up UID conflicts. + Zeigt unterschiede zwischen den Datenbanken an. Dieses Tools soll Administratoren dabei helfen UID-Konflikte zu lösen. + + + Inspect a record tree + RecordTree Untersuchen + + + You can query for a record tree by classification and identifier and inspect it with all of its properties and children. + Hier kann ein RecordTree mittels Klassifikation und Identifikation aufgebaut und untersucht werden.. + + + https://typo3.slack.com/archives/C2ULY79MZ]]> + https://typo3.slack.com/archives/C2ULY79MZ]]> + + + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index b03b045ee..b4e55c761 100755 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -1,653 +1,359 @@ - - - + + +
- + Publish Overview - - + TYPO3 Content Publisher - + publish pages and records overview - + Publish files - - Administration Tools - - - Getting Help - - - Tests - - - Compare Database - - - Record Inspector - - - Select Classification and Identifier for inspection - - + Publish redirects - - + Depth - + %d level - + %d levels - - + Stage System - + Production System - + The selected record has been published successfully. (Duration: %s) - + One or more errors occurred during publishing. Please check the logs. (Duration: %s) - + One or more errors occurred during relation resolving. Please check the logs. - + The selected record has been published successfully. - + The selected folder has been created successfully. - + The selected folder could not be created. - + The selected folder has been removed successfully. - + The selected folder could not be removed. - - in2publish failed to retrieve information about the folder %s or any of it's sub folders. Please verify that is in2publish is working properly by running the tests. + + in2publish failed to retrieve information about the folder %s or any of it's sub folders. Please verify that is in2publish is working properly by running the tests. - - Publish page "%s" and its subpages. + + Publish page "%s" and its subpages. - + Do you really want to publish all pages? - + Do you really want to publish this page? - + Publish - + Publish this page - + This page is currently being published - + This file is currently being published - - Publish all files within folder "%s". + + Publish all files within folder "%s". - + Do you really want to publish all files? - + Do you really want to publish this file? - + Preview - + Compare - + History - + File preview - + Edit - + %s properties - + Page properties - + Record history - + Edit record - + Related Records - + Record State - - - Introduction - - - This tool just lists all other tools. - - - Show configuration - - - Display the local configuration of in2publish from LocalConfiguration.yaml - - - Show logs - - - Show all logs of the Content Publisher with plenty filter options - - - Tests - - - Run some function test of in2publish - - - Inspect TCA - - - See which parts of the TCA are processed, and the reason why others are not. - - - Remove superfluous envelopes - - - Deletes all envelopes (remote procedure call database entries) which were already used (envelopes are one-way records). - - - Remove all Registry entries - - - Removes all registry entries which store information about the local and foreign environment. You must run the test after flushing these. - - - System information - - - Use this module to collect information which will be required or useful to solve a bug or problem. - - - Compare Databases - - - The compare tool scans the whole database for differences. This tool is ought to help administrators clean up UID conflicts. - - - Inspect a record tree - - - You can query for a record tree by classification and identifier and inspect it with all of its properties and children. - - - - Show the system info - - - Download the system info - - - Decode the system info JSON - - - JSON string - - - Decode! - - - Error during json decoding - - - JSON decode error #%d: %s - - - SysInfo JSON file - - - Upload! - - - + Filter by: - - + Filename - - + Status - - + Record unchanged - + Record changed - + New record - + Record deleted - + Record moved - - + Unchanged - + Changed - + New - + Deleted - + Moved - + Moved/Changed - - Configuration - - - Navigate to Global Configuration - - - Navigate to Personal Configuration - - - Navigate to Config Container Dump - - - Global Configuration - - - Personal Configuration - - - Config Container Dump - - - Enter Page ID for page specific configuration - - - Overview - - - Filter - - - TCA inspection - - - Compatible TCA - - - Incompatible TCA - - - Controls - - - Navigate to incompatible TCA - - - Navigate to compatible TCA - - - Navigate to controls - - - Registry entries - - - System Information - - - Flushed all related registry entries. - - - Superfluous Envelopes - - - Flushed all superfluous envelopes. - - - Flush superfluous envelopes. - - - There are superfluous envelopes in the foreign database. - - - There are no envelopes to flush. - - - Clear registry entries. - - - The Content Publisher stores various information in the registry, like the outcome of the last test run. You can force the removal of these entries here. - - - + In2publish might not work as expected. - + Unknown test state. Please execute the tests in the Publish Tools Module. - + Some In2publish tests are failing. - + Your TYPO3 installation changed. - + The In2publish configuration has changed. - - + Vertical - + Horizontal - - + Successfully published. - + Something went wrong. - + The selected folder %s has been published to the foreign system. - + The selected folder %s could not be published. - + The selected file %s has been published to the foreign system. - + The selected file %s could not be fully published. - - + One or more additional tasks which run after the successful publishing process failed. Caches and other non critical aspects might not behave as expected. The logs might contain more information. - - + Secure, authenticated and encrypted command execution - + Secure, reliable and encrypted asset transmission - - - https://typo3.slack.com/archives/C2ULY79MZ]]> - - - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> - - - + You are not allowed to publish this page. - + No page parameter was transferred. - - The page "%s" has been published. + + The page "%s" has been published. - - Error during publishing of page "%s". Please check your logs. + + Error during publishing of page "%s". Please check your logs. - + This record is not yet publishable. - - + Associated page - + Associated foreign Site - + Use site from associated page - + Page/Site association - - + Save and publish - + Publish all selected - + Status icons explained - + The redirect requires an associated page or site to be published - + The associated page is not published - + This redirect has unpublished changes. Hover over the icon to get more information - + This redirect is published - + Action icons explained - + This redirect can be published. Click to publish. - + This redirect can be published with a manual site association. Click to assign a Site and publish. - - + Property - + Old value - + New value - + ID - + Domain - + Source - + Target - + Status - + Actions - - + Missing associated page or site - - The associated page [%d] "%s" is not published + + The associated page [%d] "%s" is not published - + This redirect is published - - + Ready for publishing - + Missing page or site - + Requires page publishing - + Published - - + Filter - + Association - + Association present - + Association missing - - + Refresh page - - - New - - - Deleted - - - Differences - - - Generally - - - The table is empty on Local - - - The table is empty on Foreign - - - Transfer these changes to the foreign system - - - No differences were found in the data of the selected tables. - - - Select the tables to compare - - - Tables - - - Compare - - - This is not publishing - - - A transfer is not a publishing. Only the exact record that is selected is transferred. No relations to other records are resolved and no MM-records are displayed nor transferred. You should always prefer normal publishing to this feature. Use this feature only in an emergency and only if you are aware of all the consequences. - - - Record label - - - Actions - - - Differences - - - Error - - - Success - - - The record which should be transferred does not exist anymore. - - - The record which should be transferred should not exists on Foreign but it does. It was probably published in the meantime. - - - The record which should be transferred should not exists on Local but it does. It was probably created in the meantime. - - - The record which should be transferred should exists on both Local and Foreign but it does not. Please reload the comparison view and try again. - - - The record %s[%d] was deleted from foreign. - - - The record %s[%d] was created on foreign. - - - The record %s[%d] was updated on foreign. - - - + Admin tools - - - "%s" requires that the record "%s" (which is the default language version) is published first. + + "%s" requires that the record "%s" (which is the default language version) is published first. - - The record "%s" cannot be published until all visibility settings (%s) of the default language "%s" have been published. + + The record "%s" cannot be published until all visibility settings (%s) of the default language "%s" have been published. - - "%s" requires that the page "%s" is published first. + + "%s" requires that the page "%s" is published first. - - "%s" requires that the page "%s" has all of its properties published (%s) which determine if the record is visible. + + "%s" requires that the page "%s" has all of its properties published (%s) which determine if the record is visible. - - The record with classification "%s" and properties "%s" does not exist. + + The record with classification "%s" and properties "%s" does not exist. - - The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. + + The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. diff --git a/Resources/Private/Language/locallang_mod4.xlf b/Resources/Private/Language/locallang_mod4.xlf index c7f2c1156..3992198d3 100755 --- a/Resources/Private/Language/locallang_mod4.xlf +++ b/Resources/Private/Language/locallang_mod4.xlf @@ -1,17 +1,245 @@ - - - + + +
- - Publish Tools + + Publisher Tools - + This Module offers some admin tools to the TYPO3 Content Publisher. - + TYPO3 Content Publisher + + Show the system info + + + Download the system info + + + Decode the system info JSON + + + JSON string + + + Decode! + + + JSON decode error #%d: %s + + + SysInfo JSON file + + + Upload! + + + Select Classification and Identifier for inspection + + + Toggle all relations + + + New + + + Deleted + + + Differences + + + Generally + + + The table is empty on Local + + + The table is empty on Foreign + + + Transfer these changes to the foreign system + + + No differences were found in the data of the selected tables. + + + Select the tables to compare + + + Tables + + + Compare + + + This is not publishing + + + A transfer is not a publishing. Only the exact record that is selected is transferred. No relations to other records are resolved and no MM-records are displayed nor transferred. You should always prefer normal publishing to this feature. Use this feature only in an emergency and only if you are aware of all the consequences. + + + Record label + + + Actions + + + Error + + + Success + + + The record which should be transferred does not exist anymore. + + + The record which should be transferred should not exists on Foreign but it does. It was probably published in the meantime. + + + The record which should be transferred should not exists on Local but it does. It was probably created in the meantime. + + + The record which should be transferred should exists on both Local and Foreign but it does not. Please reload the comparison view and try again. + + + The record %s[%d] was deleted from foreign. + + + The record %s[%d] was created on foreign. + + + The record %s[%d] was updated on foreign. + + + Overview + + + Getting Help + + + Navigate to incompatible TCA + + + Navigate to compatible TCA + + + Incompatible TCA + + + Compatible TCA + + + Navigate to Personal Configuration + + + Navigate to Global Configuration + + + Navigate to Config Container Dump + + + Enter Page ID for page specific configuration + + + Config Container Dump + + + Global Configuration + + + Personal Configuration + + + Flushed all related registry entries. + + + The Content Publisher stores various information in the registry, like the outcome of the last test run. You can force the removal of these entries here. + + + Remove registry entries + + + Flushed all superfluous envelopes. + + + There are superfluous envelopes in the foreign database. + + + There are no envelopes to flush. + + + Remove superfluous envelopes + + + Introduction + + + This tool just lists all other tools. + + + Show configuration + + + Display the local configuration of in2publish from LocalConfiguration.yaml + + + Show logs + + + Show all logs of the Content Publisher with plenty filter options + + + Tests + + + Run some function test of in2publish + + + Inspect TCA + + + See which parts of the TCA are processed, and the reason why others are not. + + + Remove superfluous envelopes + + + Deletes all envelopes (remote procedure call database entries) which were already used (envelopes are one-way records). + + + Remove all Registry entries + + + Removes all registry entries which store information about the local and foreign environment. You must run the test after flushing these. + + + System information + + + Use this module to collect information which will be required or useful to solve a bug or problem. + + + Compare Databases + + + The compare tool scans the whole database for differences. This tool is ought to help administrators clean up UID conflicts. + + + Inspect a record tree + + + You can query for a record tree by classification and identifier and inspect it with all of its properties and children. + + + https://typo3.slack.com/archives/C2ULY79MZ]]> + + + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> + diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/Details.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/Details.html index ecc999e2a..f25a1cb2b 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/Details.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/Details.html @@ -13,12 +13,12 @@

- +

- +

diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html index 04d1f1c0b..4a859c53a 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html @@ -10,15 +10,15 @@ UID PID - + - + - + @@ -49,7 +49,7 @@ @@ -66,7 +66,7 @@ diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html index ded570814..ee71ebe42 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/TransferNotice.html @@ -1,5 +1,10 @@ - - + + diff --git a/Resources/Private/Partials/Tools/GetHelp.html b/Resources/Private/Partials/Tools/GetHelp.html index 1095e94b7..5b1036a00 100644 --- a/Resources/Private/Partials/Tools/GetHelp.html +++ b/Resources/Private/Partials/Tools/GetHelp.html @@ -3,7 +3,9 @@

- +

diff --git a/Resources/Private/Partials/Tools/IntroductionMenu.html b/Resources/Private/Partials/Tools/IntroductionMenu.html index ad18d4bf4..3b6772485 100644 --- a/Resources/Private/Partials/Tools/IntroductionMenu.html +++ b/Resources/Private/Partials/Tools/IntroductionMenu.html @@ -3,7 +3,7 @@

- Introduction +

@@ -12,8 +12,8 @@

  • - {entry.name} - :{entry.description} + + :
  • diff --git a/Resources/Private/Templates/CompareDatabaseTool/Compare.html b/Resources/Private/Templates/CompareDatabaseTool/Compare.html index 56b56153b..a44197f6b 100644 --- a/Resources/Private/Templates/CompareDatabaseTool/Compare.html +++ b/Resources/Private/Templates/CompareDatabaseTool/Compare.html @@ -2,7 +2,7 @@ - + @@ -12,7 +12,7 @@ -

    +

    diff --git a/Resources/Private/Templates/CompareDatabaseTool/Index.html b/Resources/Private/Templates/CompareDatabaseTool/Index.html index 711ca1f4d..f16fedc08 100644 --- a/Resources/Private/Templates/CompareDatabaseTool/Index.html +++ b/Resources/Private/Templates/CompareDatabaseTool/Index.html @@ -2,7 +2,7 @@ - + @@ -12,7 +12,7 @@

    - +

    @@ -20,7 +20,7 @@

    />
    - +

    diff --git a/Resources/Private/Templates/Letterbox/Index.html b/Resources/Private/Templates/Letterbox/Index.html index ad365b1a8..7a2844a23 100644 --- a/Resources/Private/Templates/Letterbox/Index.html +++ b/Resources/Private/Templates/Letterbox/Index.html @@ -2,7 +2,7 @@ - + @@ -12,18 +12,18 @@

    - +

    -

    +

    diff --git a/Resources/Private/Templates/RecordInspector/Index.html b/Resources/Private/Templates/RecordInspector/Index.html index 67ac701ef..c4afa0aa7 100644 --- a/Resources/Private/Templates/RecordInspector/Index.html +++ b/Resources/Private/Templates/RecordInspector/Index.html @@ -2,7 +2,7 @@ - + @@ -11,7 +11,7 @@

    - +

    diff --git a/Resources/Private/Templates/RecordInspector/Inspect.html b/Resources/Private/Templates/RecordInspector/Inspect.html index f7e4306b4..d1461824d 100644 --- a/Resources/Private/Templates/RecordInspector/Inspect.html +++ b/Resources/Private/Templates/RecordInspector/Inspect.html @@ -2,7 +2,7 @@ - + @@ -12,7 +12,7 @@ + });">
    diff --git a/Resources/Private/Templates/Registry/Index.html b/Resources/Private/Templates/Registry/Index.html index 7e9878303..424eae0f6 100644 --- a/Resources/Private/Templates/Registry/Index.html +++ b/Resources/Private/Templates/Registry/Index.html @@ -2,7 +2,7 @@ - + @@ -10,12 +10,12 @@

    - +

    diff --git a/Resources/Private/Templates/ShowConfiguration/Index.html b/Resources/Private/Templates/ShowConfiguration/Index.html index 9c3415446..786543a18 100755 --- a/Resources/Private/Templates/ShowConfiguration/Index.html +++ b/Resources/Private/Templates/ShowConfiguration/Index.html @@ -2,7 +2,7 @@ - + @@ -12,12 +12,12 @@

    - global config +

    - {globalConfig} + {globalConfig}
    @@ -27,12 +27,12 @@

    - personal config +

    - {fullConfig} + {fullConfig}

    @@ -42,7 +42,7 @@

    - module.m4.container_dump +

    @@ -53,7 +53,7 @@

    @@ -64,7 +64,7 @@

    - {containerDump} + {containerDump}
    @@ -75,17 +75,17 @@

    diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html b/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html index 069ccbf20..aec0174e4 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoDecode.html @@ -2,7 +2,7 @@ - + @@ -12,14 +12,14 @@
    - +
    diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html b/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html index e9b0a0945..e85ebd171 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoIndex.html @@ -5,7 +5,7 @@ - + @@ -15,19 +15,19 @@

    - system_info.show +

    - system_info.download +

    - system_info.decode +

    @@ -38,13 +38,13 @@
    + value="{f:translate(id:'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:system_info.upload.upload')}" />
    diff --git a/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html b/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html index 3db5ecd8d..bcb253b77 100644 --- a/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html +++ b/Resources/Private/Templates/SystemInformationExport/SysInfoShow.html @@ -2,7 +2,7 @@ - + diff --git a/Resources/Private/Templates/Tca/Index.html b/Resources/Private/Templates/Tca/Index.html index 5d4806455..e0eb66bc5 100755 --- a/Resources/Private/Templates/Tca/Index.html +++ b/Resources/Private/Templates/Tca/Index.html @@ -2,7 +2,7 @@ - + @@ -12,12 +12,12 @@

    - Compatible TCA +

    - {compatibleTca} + {compatibleTca}
    @@ -27,12 +27,12 @@

    - Inompatible TCA +

    - {incompatibleTca} + {incompatibleTca}
    @@ -41,12 +41,12 @@

    diff --git a/Resources/Private/Templates/Test/Index.html b/Resources/Private/Templates/Test/Index.html index 320b0aab2..cb76218a5 100755 --- a/Resources/Private/Templates/Test/Index.html +++ b/Resources/Private/Templates/Test/Index.html @@ -2,7 +2,7 @@ - + diff --git a/Resources/Private/Templates/Tools/Index.html b/Resources/Private/Templates/Tools/Index.html index defc2fa46..cc55fa5ce 100755 --- a/Resources/Private/Templates/Tools/Index.html +++ b/Resources/Private/Templates/Tools/Index.html @@ -2,7 +2,7 @@ - + From d45dd1857468dab2f8b6fbc1dbffd8606845f98b Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 13 Nov 2023 14:18:15 +0100 Subject: [PATCH 069/113] [BUGFIX] Correct Caption of english Labels --- .../AdminTools/Controller/ToolsController.php | 4 +- .../Private/Language/de.locallang_mod4.xlf | 46 +++++++++---------- Resources/Private/Language/locallang_mod4.xlf | 42 ++++++++--------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/Classes/Features/AdminTools/Controller/ToolsController.php b/Classes/Features/AdminTools/Controller/ToolsController.php index 06b4256dd..247912ac0 100644 --- a/Classes/Features/AdminTools/Controller/ToolsController.php +++ b/Classes/Features/AdminTools/Controller/ToolsController.php @@ -61,10 +61,10 @@ public function indexAction(): ResponseInterface $supports = [ LocalizationUtility::translate( - 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:help.github_issues' + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:introduction.help.github_issues' ), LocalizationUtility::translate( - 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:help.slack_channel' + 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:introduction.help.slack_channel' ), ]; diff --git a/Resources/Private/Language/de.locallang_mod4.xlf b/Resources/Private/Language/de.locallang_mod4.xlf index 5687865f6..6420fd702 100755 --- a/Resources/Private/Language/de.locallang_mod4.xlf +++ b/Resources/Private/Language/de.locallang_mod4.xlf @@ -1,6 +1,6 @@ - +
    @@ -40,7 +40,7 @@ JSON dekodierfehler #%d: %s - SysInfo JSON file + Systeminformation JSON file Systeminformationen JSON Datei @@ -48,7 +48,7 @@ Hochladen! - Select Classification and Identifier for inspection + Select classification and identifier for inspection Bitte Klassifizierung und Identität auswählen @@ -76,7 +76,7 @@ Die Tabelle is auf Local leer. - The table is empty on Foreign + The table is empty on foreign Die Tabelle is auf Foreign leer. @@ -156,9 +156,17 @@ Übersicht - Getting Help + Getting help Hilfe + + https://typo3.slack.com/archives/C2ULY79MZ]]> + https://typo3.slack.com/archives/C2ULY79MZ]]> + + + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> + Navigate to incompatible TCA Zu inkompatiblem TCA springen @@ -176,31 +184,31 @@ Kompatibles TCA - Navigate to Personal Configuration + Navigate to personal configuration zur persönlichen Konfiguration springen - Navigate to Global Configuration + Navigate to global configuration zur globalen Konfiguration springen - Navigate to Config Container Dump + Navigate to config container dump zum Dump des Config Containers springen - Enter Page ID for page specific configuration + Enter page ID for page specific configuration Seiten-ID für Seitenspezifische konfiguration angeben - Config Container Dump + Config container dump Config Container Konfiguration - Global Configuration + Global configuration Globale Konfiguration - Personal Configuration + Personal configuration Persönliche Konfiguration @@ -280,7 +288,7 @@ Löscht alle Envelopes ("Remote Procedure Call"-Datenbankeinträge) die bereits genutzt wurden (Diese sind Einweg-Einträge) - Remove all Registry entries + Remove all registry entries Registereinträge löschen @@ -288,7 +296,7 @@ Löscht alle Registereinträge, welche Informationen über das lokale und entfernte System vorhalten. Danach müssen die Tests erneut ausgeführt werden. - System information + Systeminformation Systeminformationen @@ -296,7 +304,7 @@ Anzeige von Informationen welche erforderlich oder nützlich sind Probleme zu identifizieren und sie zu beheben. - Compare Databases + Compare databases Datenbankvergleich @@ -311,14 +319,6 @@ You can query for a record tree by classification and identifier and inspect it with all of its properties and children. Hier kann ein RecordTree mittels Klassifikation und Identifikation aufgebaut und untersucht werden.. - - https://typo3.slack.com/archives/C2ULY79MZ]]> - https://typo3.slack.com/archives/C2ULY79MZ]]> - - - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> - diff --git a/Resources/Private/Language/locallang_mod4.xlf b/Resources/Private/Language/locallang_mod4.xlf index 3992198d3..ec78793fa 100755 --- a/Resources/Private/Language/locallang_mod4.xlf +++ b/Resources/Private/Language/locallang_mod4.xlf @@ -1,6 +1,6 @@ - +
    @@ -31,13 +31,13 @@ JSON decode error #%d: %s - SysInfo JSON file + Systeminformation JSON file Upload! - Select Classification and Identifier for inspection + Select classification and identifier for inspection Toggle all relations @@ -58,7 +58,7 @@ The table is empty on Local - The table is empty on Foreign + The table is empty on foreign Transfer these changes to the foreign system @@ -118,7 +118,13 @@ Overview - Getting Help + Getting help + + + https://typo3.slack.com/archives/C2ULY79MZ]]> + + + https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> Navigate to incompatible TCA @@ -133,25 +139,25 @@ Compatible TCA - Navigate to Personal Configuration + Navigate to personal configuration - Navigate to Global Configuration + Navigate to global configuration - Navigate to Config Container Dump + Navigate to config container dump - Enter Page ID for page specific configuration + Enter page ID for page specific configuration - Config Container Dump + Config container dump - Global Configuration + Global configuration - Personal Configuration + Personal configuration Flushed all related registry entries. @@ -211,19 +217,19 @@ Deletes all envelopes (remote procedure call database entries) which were already used (envelopes are one-way records). - Remove all Registry entries + Remove all registry entries Removes all registry entries which store information about the local and foreign environment. You must run the test after flushing these. - System information + Systeminformation Use this module to collect information which will be required or useful to solve a bug or problem. - Compare Databases + Compare databases The compare tool scans the whole database for differences. This tool is ought to help administrators clean up UID conflicts. @@ -234,12 +240,6 @@ You can query for a record tree by classification and identifier and inspect it with all of its properties and children. - - https://typo3.slack.com/archives/C2ULY79MZ]]> - - - https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]> - From 74b0fd0ffe368cc9a2de6b4ccc005863a1f9d933 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Mon, 13 Nov 2023 14:41:53 +0100 Subject: [PATCH 070/113] [CLEANUP] Remove Logs Integration --- .../Controller/LogController.php | 67 ------------------- .../Features/LogsIntegration/Services.php | 32 --------- .../Private/Language/de.locallang_mod4.xlf | 10 +-- Resources/Private/Language/locallang_mod4.xlf | 8 +-- Resources/Private/Templates/Log/Filter.html | 13 ---- 5 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 Classes/Features/LogsIntegration/Controller/LogController.php delete mode 100644 Configuration/Features/LogsIntegration/Services.php delete mode 100644 Resources/Private/Templates/Log/Filter.html diff --git a/Classes/Features/LogsIntegration/Controller/LogController.php b/Classes/Features/LogsIntegration/Controller/LogController.php deleted file mode 100644 index 9e6af444f..000000000 --- a/Classes/Features/LogsIntegration/Controller/LogController.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - */ - -use CoStack\Logs\Controller\LogController as LogsController; -use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate; -use TYPO3\CMS\Fluid\View\TemplateView; -use TYPO3Fluid\Fluid\View\ViewInterface; - -class LogController extends LogsController -{ - use AdminToolsModuleTemplate; - - protected function initializeAction(): void - { - parent::initializeAction(); - $this->logConfiguration = $GLOBALS['TYPO3_CONF_VARS']['LOG']['In2code']['In2publishCore']; - } - - protected function resolveView(): ViewInterface - { - $view = parent::resolveView(); - if ($view instanceof TemplateView) { - $templatePaths = $view->getTemplatePaths(); - $templatePaths->setTemplateRootPaths([ - 0 => 'EXT:logs/Resources/Private/Templates/', - 10 => 'EXT:in2publish_core/Resources/Private/Templates/', - ]); - $templatePaths->setLayoutRootPaths([ - 0 => 'EXT:logs/Resources/Private/Layouts/', - 10 => 'EXT:in2publish_core/Resources/Private/Layouts/', - ]); - $templatePaths->setPartialRootPaths([ - 0 => 'EXT:logs/Resources/Private/Partials/', - 10 => 'EXT:in2publish_core/Resources/Private/Partials/', - ]); - } - return $view; - } -} diff --git a/Configuration/Features/LogsIntegration/Services.php b/Configuration/Features/LogsIntegration/Services.php deleted file mode 100644 index 004f924d6..000000000 --- a/Configuration/Features/LogsIntegration/Services.php +++ /dev/null @@ -1,32 +0,0 @@ -services(); - $defaults = $services->defaults(); - $defaults->autowire(true); - $defaults->autoconfigure(true); - $defaults->private(); - - $services->load( - 'In2code\\In2publishCore\\Features\\LogsIntegration\\', - __DIR__ . '/../../../Classes/Features/LogsIntegration/*', - ); - - $services->set(LogController::class) - ->tag( - 'in2publish_core.admin_tool', - [ - 'title' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.logs', - 'description' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang.xlf:moduleselector.logs.description', - 'actions' => 'filter,delete,deleteAlike', - ], - ); - } -}; diff --git a/Resources/Private/Language/de.locallang_mod4.xlf b/Resources/Private/Language/de.locallang_mod4.xlf index 6420fd702..839a9fef2 100755 --- a/Resources/Private/Language/de.locallang_mod4.xlf +++ b/Resources/Private/Language/de.locallang_mod4.xlf @@ -1,6 +1,6 @@ - +
    @@ -255,14 +255,6 @@ Display the local configuration of in2publish from LocalConfiguration.yaml Zeige die aktuelle Konfiguration von in2publish von der LocalConfiguration.yaml Datei - - Show logs - Logs anzeigen - - - Show all logs of the Content Publisher with plenty filter options - Zeigt die Logeinträge des Content Publishers mit vielen Filteroptionen an - Tests Tests diff --git a/Resources/Private/Language/locallang_mod4.xlf b/Resources/Private/Language/locallang_mod4.xlf index ec78793fa..9fa701713 100755 --- a/Resources/Private/Language/locallang_mod4.xlf +++ b/Resources/Private/Language/locallang_mod4.xlf @@ -1,6 +1,6 @@ - +
    @@ -192,12 +192,6 @@ Display the local configuration of in2publish from LocalConfiguration.yaml - - Show logs - - - Show all logs of the Content Publisher with plenty filter options - Tests diff --git a/Resources/Private/Templates/Log/Filter.html b/Resources/Private/Templates/Log/Filter.html deleted file mode 100644 index 9d901fa49..000000000 --- a/Resources/Private/Templates/Log/Filter.html +++ /dev/null @@ -1,13 +0,0 @@ - - - Changes: - * Render our Layout "Default" - - - - - - - - - From 2eb986999be0c8b2a46308ff20952afaef66743d Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Tue, 14 Nov 2023 16:10:29 +0100 Subject: [PATCH 071/113] [BUGFIX] Fix Database Compare Table View --- .../CompareDatabaseTool/TableDetails.html | 147 +++++++++--------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html index 4a859c53a..558b7b23c 100644 --- a/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html +++ b/Resources/Private/Partials/Tools/CompareDatabaseTool/TableDetails.html @@ -4,79 +4,82 @@ data-namespace-typo3-fluid="true" >
    - - - - - - - + +
    UIDPID - -
    + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    UIDPID - + - -
    {value.local.uid}{value.local.pid} - - - - - - - - - -
    {field} - -
    -
    - - - -
    {value.uid}{value.pid} - - - - - -
    + + + + + + + + + + + + + + + + {value.local.uid} + {value.local.pid} + + + + + + + + + + + +
    {field}
    + + + + + + + +
    + + + {value.uid} + {value.pid} + + + + + + + + + + +
    +
    + + +
    From 44414778d6d8c5eed562696f2fe1cd9022569505 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 15 Nov 2023 09:11:19 +0100 Subject: [PATCH 072/113] [CODESTYLE] Add Annotations for Exceptions --- .../AdminTools/Service/ToolsRegistry.php | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php index 34662c4e3..15d0e2ac5 100644 --- a/Classes/Features/AdminTools/Service/ToolsRegistry.php +++ b/Classes/Features/AdminTools/Service/ToolsRegistry.php @@ -32,9 +32,10 @@ use In2code\In2publishCore\CommonInjection\ExtensionConfigurationInjection; use In2code\In2publishCore\Component\ConfigContainer\ConfigContainerInjection; use In2code\In2publishCore\Features\AdminTools\Service\Exception\ClassNotFoundException; +use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; +use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Utility\ExtensionUtility; use function class_exists; @@ -63,16 +64,14 @@ public function addTool( ]; } + /** + * @throws ExtensionConfigurationPathDoesNotExistException + * @throws ExtensionConfigurationExtensionNotConfiguredException + */ public function getEntries(): array { - // Do not inject the ConfigurationManager, because it will not contain the configured tools. - $configurationManager = GeneralUtility::makeInstance(ConfigurationManagerInterface::class); - $configuration = $configurationManager->getConfiguration( - ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, - ); $processedTools = []; - $controllerConfig = $configuration['controllerConfiguration']; foreach ($this->entries as $key => $config) { if ($this->evaluateCondition($config)) { $controller = $config['controller']; @@ -88,6 +87,8 @@ public function getEntries(): array /** * @throws ClassNotFoundException + * @throws ExtensionConfigurationExtensionNotConfiguredException + * @throws ExtensionConfigurationPathDoesNotExistException */ public function processData(): array { @@ -112,6 +113,8 @@ public function processData(): array /** * @throws ClassNotFoundException + * @throws ExtensionConfigurationExtensionNotConfiguredException + * @throws ExtensionConfigurationPathDoesNotExistException * @deprecated Will be removed in TYPO3 v13 */ public function processDataForTypo3V11(): array @@ -123,6 +126,10 @@ public function processDataForTypo3V11(): array return $controllerActions; } + /** + * @throws ExtensionConfigurationPathDoesNotExistException + * @throws ExtensionConfigurationExtensionNotConfiguredException + */ protected function evaluateCondition(array $config): bool { if (null === $config['condition']) { From f70c6f7d40a38e4bc149c662d815ddaee94fc2f4 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 15 Nov 2023 09:11:46 +0100 Subject: [PATCH 073/113] [FEATURE] Change Order of Modules in Publish Tools Moves Tests on 2nd position --- Configuration/Features/AdminTools/Services.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Configuration/Features/AdminTools/Services.yaml b/Configuration/Features/AdminTools/Services.yaml index fa1387745..612a523ed 100644 --- a/Configuration/Features/AdminTools/Services.yaml +++ b/Configuration/Features/AdminTools/Services.yaml @@ -41,6 +41,7 @@ services: title: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.test' description: 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:moduleselector.test.description' actions: 'index' + after: 'In2code\In2publishCore\Features\AdminTools\Controller\ToolsController' In2code\In2publishCore\Features\AdminTools\Controller\ToolsController: tags: From 84a1c8bf5b007f563f510fb858bf64de2d098051 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 15 Nov 2023 12:20:09 +0100 Subject: [PATCH 074/113] [BUGFIX] Fix multiple errors that occur when calling publishRecordTree more than once --- .../Publisher/AbstractFilesystemPublisher.php | 76 +++++++++++++------ .../Publisher/Command/FalPublisherCommand.php | 14 +++- .../Publisher/DatabaseRecordPublisher.php | 7 +- .../Core/Publisher/FileRecordPublisher.php | 35 ++++++++- .../Core/Publisher/PublisherService.php | 37 ++++----- .../Service/TaskExecutionServiceInjection.php | 21 +++++ Configuration/Component/Core/Services.yaml | 4 + 7 files changed, 141 insertions(+), 53 deletions(-) create mode 100644 Classes/Component/PostPublishTaskExecution/Service/TaskExecutionServiceInjection.php diff --git a/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php index e2a781fd4..efec941dc 100644 --- a/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php +++ b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php @@ -11,47 +11,75 @@ use function bin2hex; use function get_class; +use function implode; use function json_encode; use function random_bytes; -abstract class AbstractFilesystemPublisher implements Publisher, FinishablePublisher +use const JSON_THROW_ON_ERROR; + +abstract class AbstractFilesystemPublisher implements Publisher, TransactionalPublisher, ReversiblePublisher { use ForeignDatabaseReconnectedInjection; use RemoteCommandDispatcherInjection; - protected string $requestToken; protected array $instructions = []; - public function __construct() + public function start(): void + { + if (!$this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->beginTransaction(); + } + } + + public function cancel(): void { - $this->requestToken = bin2hex(random_bytes(16)); + if ($this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->rollBack(); + } + } + + public function reverse(): void + { + if ($this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->rollBack(); + } } public function finish(): void { - if (!empty($this->instructions)) { - $instructions = $this->instructions; - $this->instructions = []; - $data = []; - foreach ($instructions as $instruction) { - $class = get_class($instruction); - $configuration = json_encode($instruction->getConfiguration(), JSON_THROW_ON_ERROR); - $data[] = [ - 'request_token' => $this->requestToken, - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'instruction' => $class, - 'configuration' => $configuration, - ]; + if (empty($this->instructions)) { + if ($this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->commit(); } + return; + } - $this->foreignDatabase->bulkInsert('tx_in2publishcore_filepublisher_instruction', $data); + $requestTokens = []; + $instructions = $this->instructions; + $this->instructions = []; + $data = []; + foreach ($instructions as $instruction) { + $requestTokens[] = $requestToken = bin2hex(random_bytes(16)); + $class = get_class($instruction); + $configuration = json_encode($instruction->getConfiguration(), JSON_THROW_ON_ERROR); + $data[] = [ + 'request_token' => $requestToken, + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'instruction' => $class, + 'configuration' => $configuration, + ]; + } - $request = new RemoteCommandRequest('in2publish_core:core:falpublisher', [], [$this->requestToken]); - $response = $this->remoteCommandDispatcher->dispatch($request); - if (!$response->isSuccessful()) { - throw new FalPublisherExecutionFailedException($response); - } + $this->foreignDatabase->bulkInsert('tx_in2publishcore_filepublisher_instruction', $data); + if ($this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->commit(); + } + + $request = new RemoteCommandRequest('in2publish_core:core:falpublisher', [], [implode(',', $requestTokens)]); + $response = $this->remoteCommandDispatcher->dispatch($request); + if (!$response->isSuccessful()) { + throw new FalPublisherExecutionFailedException($response); } } } diff --git a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php index 560a65e34..a3a2dbcd1 100644 --- a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php +++ b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php @@ -4,6 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Command; +use Doctrine\DBAL\ArrayParameterType; use In2code\In2publishCore\CommonInjection\LocalDatabaseInjection; use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverServiceInjection; use In2code\In2publishCore\Component\Core\Publisher\Instruction\PublishInstruction; @@ -13,6 +14,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use function explode; use function json_decode; class FalPublisherCommand extends Command @@ -28,17 +30,23 @@ public function isEnabled(): bool protected function configure(): void { - $this->addArgument('requestToken', InputArgument::REQUIRED); + $this->addArgument('requestTokens', InputArgument::REQUIRED); } protected function execute(InputInterface $input, OutputInterface $output): int { - $requestToken = $input->getArgument('requestToken'); + $requestTokens = $input->getArgument('requestTokens'); + $requestTokens = explode(',', $requestTokens); $query = $this->localDatabase->createQueryBuilder(); $query->select('*') ->from('tx_in2publishcore_filepublisher_instruction') - ->where($query->expr()->eq('request_token', $query->createNamedParameter($requestToken))); + ->where( + $query->expr()->in( + 'request_token', + $query->createNamedParameter($requestTokens, ArrayParameterType::STRING) + ) + ); $result = $query->executeQuery(); $rows = $result->fetchAllAssociative(); diff --git a/Classes/Component/Core/Publisher/DatabaseRecordPublisher.php b/Classes/Component/Core/Publisher/DatabaseRecordPublisher.php index 731c1c5d7..ea7494308 100644 --- a/Classes/Component/Core/Publisher/DatabaseRecordPublisher.php +++ b/Classes/Component/Core/Publisher/DatabaseRecordPublisher.php @@ -5,6 +5,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher; use In2code\In2publishCore\CommonInjection\ForeignDatabaseInjection; +use In2code\In2publishCore\CommonInjection\ForeignDatabaseReconnectedInjection; use In2code\In2publishCore\Component\Core\Record\Model\AbstractDatabaseRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; @@ -12,7 +13,7 @@ class DatabaseRecordPublisher implements Publisher, TransactionalPublisher { - use ForeignDatabaseInjection; + use ForeignDatabaseReconnectedInjection; public function canPublish(Record $record): bool { @@ -43,7 +44,9 @@ public function publish(Record $record) public function start(): void { - $this->foreignDatabase->beginTransaction(); + if (!$this->foreignDatabase->isTransactionActive()) { + $this->foreignDatabase->beginTransaction(); + } } public function cancel(): void diff --git a/Classes/Component/Core/Publisher/FileRecordPublisher.php b/Classes/Component/Core/Publisher/FileRecordPublisher.php index 23bd68ad2..ae4d99aec 100644 --- a/Classes/Component/Core/Publisher/FileRecordPublisher.php +++ b/Classes/Component/Core/Publisher/FileRecordPublisher.php @@ -12,12 +12,23 @@ use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceFileInstruction; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcherInjection; +use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandRequest; use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitterInjection; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use TYPO3\CMS\Core\Utility\GeneralUtility; -class FileRecordPublisher extends AbstractFilesystemPublisher +class FileRecordPublisher extends AbstractFilesystemPublisher implements LoggerAwareInterface { use AssetTransmitterInjection; use FalDriverServiceInjection; + use RemoteCommandDispatcherInjection; + use LoggerAwareTrait; + + /** @var array */ + protected array $transmittedFiles = []; public function canPublish(Record $record): bool { @@ -72,6 +83,7 @@ public function publish(Record $record): void ); } else { $transmitTemporaryFile = $this->transmitTemporaryFile($record); + $this->transmittedFiles[] = $transmitTemporaryFile; $instruction = new ReplaceAndRenameFileInstruction( $storage, $foreignFileIdentifier, @@ -81,6 +93,7 @@ public function publish(Record $record): void } } else { $transmitTemporaryFile = $this->transmitTemporaryFile($record); + $this->transmittedFiles[] = $transmitTemporaryFile; $instruction = new ReplaceFileInstruction( $storage, $localFileIdentifier, @@ -102,4 +115,24 @@ protected function transmitTemporaryFile(Record $record): string $localFile = $driver->getFileForLocalProcessing($identifier); return $this->assetTransmitter->transmitTemporaryFile($localFile); } + + /** + * Only a partial reverse. Will not un-publish files that have already been processed on foreign. + */ + public function reverse(): void + { + $options = []; + $options[] = '-f'; + foreach ($this->transmittedFiles as $transmittedFile) { + $options[] = $transmittedFile; + } + $request = new RemoteCommandRequest('rm', [], $options); + $response = $this->remoteCommandDispatcher->dispatch($request); + if ($response->isSuccessful()) { + $this->logger->alert( + 'Removing temporary files during rollback failed', + ['output' => $response->getOutput(), 'error' => $response->getErrors()], + ); + } + } } diff --git a/Classes/Component/Core/Publisher/PublisherService.php b/Classes/Component/Core/Publisher/PublisherService.php index 4c7b1c1f2..e09305c37 100644 --- a/Classes/Component/Core/Publisher/PublisherService.php +++ b/Classes/Component/Core/Publisher/PublisherService.php @@ -8,6 +8,7 @@ use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Component\Core\RecordTree\RecordTree; use In2code\In2publishCore\Component\PostPublishTaskExecution\Service\TaskExecutionService; +use In2code\In2publishCore\Component\PostPublishTaskExecution\Service\TaskExecutionServiceInjection; use In2code\In2publishCore\Event\PublishingOfOneRecordBegan; use In2code\In2publishCore\Event\PublishingOfOneRecordEnded; use In2code\In2publishCore\Event\RecordWasPublished; @@ -19,9 +20,11 @@ class PublisherService { use EventDispatcherInjection; + use TaskExecutionServiceInjection; protected PublisherCollection $publisherCollection; - protected TaskExecutionService $taskExecutionService; + /** @var array> */ + protected array $visitedRecords = []; public function __construct() { @@ -29,14 +32,8 @@ public function __construct() } /** - * @codeCoverageIgnore - * @noinspection PhpUnused + * Called by the DI container when constructing this service */ - public function injectTaskExecutionService(TaskExecutionService $taskExecutionService): void - { - $this->taskExecutionService = $taskExecutionService; - } - public function addPublisher(Publisher $publisher): void { $this->publisherCollection->addPublisher($publisher); @@ -55,10 +52,9 @@ public function publishRecordTree(RecordTree $recordTree, bool $includeChildPage $this->publisherCollection->start(); try { - $visitedRecords = []; foreach ($recordTree->getChildren() as $records) { foreach ($records as $record) { - $this->publishRecord($record, $visitedRecords, $includeChildPages); + $this->publishRecord($record, $includeChildPages); } } } catch (Throwable $exception) { @@ -79,15 +75,15 @@ public function publishRecordTree(RecordTree $recordTree, bool $includeChildPage $this->taskExecutionService->runTasks(); } - protected function publishRecord(Record $record, array &$visitedRecords = [], bool $includeChildPages = false): void + protected function publishRecord(Record $record, bool $includeChildPages = false): void { $classification = $record->getClassification(); $id = $record->getId(); - if (isset($visitedRecords[$classification][$id])) { + if (isset($this->visitedRecords[$classification][$id])) { return; } - $visitedRecords[$classification][$id] = true; + $this->visitedRecords[$classification][$id] = true; $this->eventDispatcher->dispatch(new RecordWasSelectedForPublishing($record)); @@ -106,16 +102,11 @@ protected function publishRecord(Record $record, array &$visitedRecords = [], bo } foreach ($record->getChildren() as $table => $children) { - if ('pages' !== $table) { - foreach ($children as $child) { - $this->publishRecord($child, $visitedRecords, true); - } - } else { - if ($includeChildPages === true) { - foreach ($children as $child) { - $this->publishRecord($child, $visitedRecords, true); - } - } + if ('pages' === $table && !$includeChildPages) { + continue; + } + foreach ($children as $child) { + $this->publishRecord($child, true); } } } diff --git a/Classes/Component/PostPublishTaskExecution/Service/TaskExecutionServiceInjection.php b/Classes/Component/PostPublishTaskExecution/Service/TaskExecutionServiceInjection.php new file mode 100644 index 000000000..71d918919 --- /dev/null +++ b/Classes/Component/PostPublishTaskExecution/Service/TaskExecutionServiceInjection.php @@ -0,0 +1,21 @@ +taskExecutionService = $taskExecutionService; + } +} diff --git a/Configuration/Component/Core/Services.yaml b/Configuration/Component/Core/Services.yaml index 9abcf137d..260126f97 100644 --- a/Configuration/Component/Core/Services.yaml +++ b/Configuration/Component/Core/Services.yaml @@ -41,3 +41,7 @@ services: In2code\In2publishCore\Component\Core\DemandResolver\DemandResolver: factory: [ '@In2code\In2publishCore\Component\Core\DemandResolver\DemandResolverFactory', 'createDemandResolver' ] + + In2code\In2publishCore\Component\Core\Publisher\PublisherService: + public: true + shared: true From 7b1f3d643e35c5d94ec1dec46d189df9c8241e44 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 12:04:26 +0100 Subject: [PATCH 075/113] [CLEANUP] Remove unused imports from FileController --- Classes/Controller/FileController.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Classes/Controller/FileController.php b/Classes/Controller/FileController.php index 331f325f7..4617d85e3 100755 --- a/Classes/Controller/FileController.php +++ b/Classes/Controller/FileController.php @@ -50,15 +50,10 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use function array_keys; -use function explode; use function http_build_query; use function implode; -use function is_string; use function json_encode; use function parse_str; -use function strlen; -use function strpos; -use function trim; use const JSON_THROW_ON_ERROR; @@ -127,6 +122,7 @@ public function indexAction(): ResponseInterface $moduleTemplate = $this->moduleTemplateFactory->create($this->request); $moduleTemplate->setFlashMessageQueue($this->getFlashMessageQueue()); $moduleTemplate->setContent($this->view->render()); + /** @see packages/in2publish_core/Resources/Private/Templates/File/Index.html */ return $this->htmlResponse($moduleTemplate->renderContent()); } From 258c7355a55f54615a475dcfc5dfa2bb9b22dc0c Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 12:05:09 +0100 Subject: [PATCH 076/113] [BUGFIX] Close modals in TYPO3 v12 via new API --- Resources/Public/JavaScript/BackendModule.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Resources/Public/JavaScript/BackendModule.js b/Resources/Public/JavaScript/BackendModule.js index 05756c655..b8ddf352c 100644 --- a/Resources/Public/JavaScript/BackendModule.js +++ b/Resources/Public/JavaScript/BackendModule.js @@ -348,7 +348,11 @@ define([ name: 'abort', active: true, trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); + if (typeof Modal.currentModal.hideModal === "function") { + Modal.currentModal.hideModal(); + } else { + Modal.currentModal.trigger('modal-dismiss'); + } In2publishCoreModule.hidePreLoader(); } }, @@ -357,7 +361,11 @@ define([ btnClass: 'btn ' + actionButtonClass, name: 'publish', trigger: () => { - Modal.currentModal.trigger('modal-dismiss'); + if (typeof Modal.currentModal.hideModal === "function") { + Modal.currentModal.hideModal(); + } else { + Modal.currentModal.trigger('modal-dismiss'); + } if (target.classList.contains('js-publish-overlay')) { In2publishCoreModule.showPreloader(); } From e462d04cf2561749f97dca37c05dd4638d5ba8f2 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 16 Nov 2023 13:40:02 +0100 Subject: [PATCH 077/113] [FEATURE] Add some Injection Traits --- .../BackendUserAuthenticationInjection.php | 45 +++++++++++++++++++ ...nslationConfigurationProviderInjection.php | 45 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 Classes/CommonInjection/BackendUserAuthenticationInjection.php create mode 100644 Classes/CommonInjection/TranslationConfigurationProviderInjection.php diff --git a/Classes/CommonInjection/BackendUserAuthenticationInjection.php b/Classes/CommonInjection/BackendUserAuthenticationInjection.php new file mode 100644 index 000000000..6eab967cd --- /dev/null +++ b/Classes/CommonInjection/BackendUserAuthenticationInjection.php @@ -0,0 +1,45 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; + +trait BackendUserAuthenticationInjection +{ + protected BackendUserAuthentication $backendUserAuthentication; + + /** + * @noinspection PhpUnused + */ + public function injectBackendUserAuthentication(BackendUserAuthentication $backendUserAuthentication): void + { + $this->backendUserAuthentication = $backendUserAuthentication; + } +} diff --git a/Classes/CommonInjection/TranslationConfigurationProviderInjection.php b/Classes/CommonInjection/TranslationConfigurationProviderInjection.php new file mode 100644 index 000000000..5baeb70c0 --- /dev/null +++ b/Classes/CommonInjection/TranslationConfigurationProviderInjection.php @@ -0,0 +1,45 @@ + + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + */ + +use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; + +trait TranslationConfigurationProviderInjection +{ + protected TranslationConfigurationProvider $translationConfigurationProvider; + + /** + * @noinspection PhpUnused + */ + public function injectTranslationConfigurationProvider(TranslationConfigurationProvider $translationConfigurationProvider): void + { + $this->translationConfigurationProvider = $translationConfigurationProvider; + } +} From cc03bdad99c6260f10a6fec097c3f28a843daabe Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 13:34:23 +0100 Subject: [PATCH 078/113] [BUGFIX] Introduce a special class for folders which are file storage roots and display the correct icon --- Classes/Component/Core/Record/Factory/RecordFactory.php | 7 ++++++- .../Core/Record/Model/StorageRootFolderRecord.php | 9 +++++++++ Classes/ViewHelpers/File/IconViewHelper.php | 8 ++++++++ Resources/Private/Partials/File/FolderList.html | 4 ++-- 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 Classes/Component/Core/Record/Model/StorageRootFolderRecord.php diff --git a/Classes/Component/Core/Record/Factory/RecordFactory.php b/Classes/Component/Core/Record/Factory/RecordFactory.php index 9f2e5914c..031a55d1c 100755 --- a/Classes/Component/Core/Record/Factory/RecordFactory.php +++ b/Classes/Component/Core/Record/Factory/RecordFactory.php @@ -36,6 +36,7 @@ use In2code\In2publishCore\Component\Core\Record\Model\MmDatabaseRecord; use In2code\In2publishCore\Component\Core\Record\Model\PageTreeRootRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; +use In2code\In2publishCore\Component\Core\Record\Model\StorageRootFolderRecord; use In2code\In2publishCore\Component\Core\RecordIndexInjection; use In2code\In2publishCore\Event\DecideIfRecordShouldBeIgnored; use In2code\In2publishCore\Event\RecordWasCreated; @@ -107,7 +108,11 @@ public function createFileRecord(array $localProps, array $foreignProps): ?FileR public function createFolderRecord(array $localProps, array $foreignProps): ?FolderRecord { - $record = new FolderRecord($localProps, $foreignProps); + if ('/' === ($localProps['identifier'] ?? null) || '/' === ($foreignProps['identifier'] ?? null)) { + $record = new StorageRootFolderRecord($localProps, $foreignProps); + } else { + $record = new FolderRecord($localProps, $foreignProps); + } if ($this->shouldIgnoreRecord($record)) { return null; } diff --git a/Classes/Component/Core/Record/Model/StorageRootFolderRecord.php b/Classes/Component/Core/Record/Model/StorageRootFolderRecord.php new file mode 100644 index 000000000..643ea370c --- /dev/null +++ b/Classes/Component/Core/Record/Model/StorageRootFolderRecord.php @@ -0,0 +1,9 @@ +getProp('mime_type'); if ($mimeType === null) { return $this->getIconIdentifierForFileExtension($record); diff --git a/Resources/Private/Partials/File/FolderList.html b/Resources/Private/Partials/File/FolderList.html index 9be75ad0a..66f3f02fe 100755 --- a/Resources/Private/Partials/File/FolderList.html +++ b/Resources/Private/Partials/File/FolderList.html @@ -16,7 +16,7 @@ Left - + @@ -37,7 +37,7 @@ Right - + From e13da1dc97c1e574442ec9158d00b179ad5a4897 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 13:35:35 +0100 Subject: [PATCH 079/113] [REFACTOR] Rename ResolverService::getResolversForTable to getResolversForClassification --- Classes/Component/Core/Demand/DemandBuilder.php | 2 +- Classes/Component/Core/Resolver/FlexResolver.php | 2 +- Classes/Component/Core/Service/ResolverService.php | 8 ++++---- Tests/Unit/Component/Core/Demand/DemandServiceTest.php | 4 ++-- Tests/Unit/Component/Core/Resolver/FlexResolverTest.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Classes/Component/Core/Demand/DemandBuilder.php b/Classes/Component/Core/Demand/DemandBuilder.php index 9a4107d96..0821864e6 100644 --- a/Classes/Component/Core/Demand/DemandBuilder.php +++ b/Classes/Component/Core/Demand/DemandBuilder.php @@ -16,7 +16,7 @@ public function buildDemandForRecords(RecordCollection $records): Demands $demand = $this->demandsFactory->createDemand(); foreach ($records->getRecordsFlat() as $record) { $classification = $record->getClassification(); - $resolvers = $this->resolverService->getResolversForTable($classification); + $resolvers = $this->resolverService->getResolversForClassification($classification); foreach ($resolvers as $resolver) { $resolver->resolve($demand, $record); } diff --git a/Classes/Component/Core/Resolver/FlexResolver.php b/Classes/Component/Core/Resolver/FlexResolver.php index db1fa8db9..e7ec8ac5a 100644 --- a/Classes/Component/Core/Resolver/FlexResolver.php +++ b/Classes/Component/Core/Resolver/FlexResolver.php @@ -92,7 +92,7 @@ public function resolve(Demands $demands, Record $record): void $flexFormTableName = $this->table . '/' . $this->column . '/' . $dataStructureKey; $virtualRecord = new VirtualFlexFormRecord($record, $flexFormTableName, $localValues, $foreignValues); - $resolvers = $this->resolverService->getResolversForTable($flexFormTableName); + $resolvers = $this->resolverService->getResolversForClassification($flexFormTableName); $expressions = []; foreach ($resolvers as $field => $resolver) { diff --git a/Classes/Component/Core/Service/ResolverService.php b/Classes/Component/Core/Service/ResolverService.php index 5d4383e70..e4ee3abf2 100644 --- a/Classes/Component/Core/Service/ResolverService.php +++ b/Classes/Component/Core/Service/ResolverService.php @@ -20,14 +20,14 @@ class ResolverService public function initializeObject(): void { $compatibleTcaParts = $this->cachedTcaPreProcessingService->getCompatibleTcaParts(); - foreach ($compatibleTcaParts as $table => $properties) { + foreach ($compatibleTcaParts as $classification => $properties) { foreach ($properties as $property => $array) { /** @var Resolver $resolver */ $resolver = $array['resolver']; $targetTables = $resolver->getTargetTables(); $relevantTables = $this->relevantTablesService->removeExcludedAndEmptyTables($targetTables); if (!empty($relevantTables)) { - $this->resolvers[$table][$property] = $resolver; + $this->resolvers[$classification][$property] = $resolver; } } } @@ -36,8 +36,8 @@ public function initializeObject(): void /** * @return array */ - public function getResolversForTable(string $table): array + public function getResolversForClassification(string $classification): array { - return $this->resolvers[$table] ?? []; + return $this->resolvers[$classification] ?? []; } } diff --git a/Tests/Unit/Component/Core/Demand/DemandServiceTest.php b/Tests/Unit/Component/Core/Demand/DemandServiceTest.php index abe732535..afdd95157 100644 --- a/Tests/Unit/Component/Core/Demand/DemandServiceTest.php +++ b/Tests/Unit/Component/Core/Demand/DemandServiceTest.php @@ -47,7 +47,7 @@ public function resolve(Demands $demands, Record $record): void ]; $resolverService = $this->createMock(ResolverService::class); - $resolverService->method('getResolversForTable')->willReturn($resolversForTable); + $resolverService->method('getResolversForClassification')->willReturn($resolversForTable); $demandBuilder->injectResolverService($resolverService); $demand = $demandBuilder->buildDemandForRecords(new RecordCollection([$record])); @@ -97,7 +97,7 @@ public function resolve(Demands $demands, Record $record): void ]; $resolverService = $this->createMock(ResolverService::class); - $resolverService->method('getResolversForTable')->willReturnOnConsecutiveCalls( + $resolverService->method('getResolversForClassification')->willReturnOnConsecutiveCalls( $resolversForTableFoo, $resolversForTableBar, ); diff --git a/Tests/Unit/Component/Core/Resolver/FlexResolverTest.php b/Tests/Unit/Component/Core/Resolver/FlexResolverTest.php index ba9a57339..b75449a88 100644 --- a/Tests/Unit/Component/Core/Resolver/FlexResolverTest.php +++ b/Tests/Unit/Component/Core/Resolver/FlexResolverTest.php @@ -93,7 +93,7 @@ public function testResolveDoesNotGetResolverOnEmptyDatabaseRecord(): void $flexFormTools->method('getDataStructureIdentifier')->willReturn($dataStructure); $flexFormService = $this->createMock(FlexFormService::class); $flexFormService->method('convertFlexFormContentToArray')->willReturn([]); - $resolversService->expects($this->never())->method('getResolversForTable'); + $resolversService->expects($this->never())->method('getResolversForClassification'); $flexResolver->injectFlexFormTools($flexFormTools); $flexResolver->injectFlexFormService($flexFormService); @@ -132,7 +132,7 @@ public function testResolveDelegatesResolveToItsResolvers(): void $selectResolver = $this->createMock(SelectResolver::class); $selectResolver->expects($this->once())->method('resolve'); $resolvers = ['column_foo' => $selectResolver,]; - $resolversService->expects($this->once())->method('getResolversForTable')->willReturn($resolvers); + $resolversService->expects($this->once())->method('getResolversForClassification')->willReturn($resolvers); $flexResolver->injectFlexFormTools($flexFormTools); $flexResolver->injectFlexFormService($flexFormService); From 10dba84e536bef2c782fb9128ae01b7072536b48 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 13:37:45 +0100 Subject: [PATCH 080/113] [BUGFIX] Access correct property to set the name attribute of folders --- Resources/Private/Partials/File/FolderList.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Private/Partials/File/FolderList.html b/Resources/Private/Partials/File/FolderList.html index 66f3f02fe..0a9f1dcdf 100755 --- a/Resources/Private/Partials/File/FolderList.html +++ b/Resources/Private/Partials/File/FolderList.html @@ -27,7 +27,7 @@ class="js-publish-trigger js-publish-overlay btn btn-default" action="publishFolder" arguments="{combinedIdentifier: record.id}" - data="{type: 'folder', name: '{publish:record.getMergedProperty(record: record, propertyName: \'id\')}'}" + data="{type: 'folder', name: '{publish:record.getMergedProperty(record: record, propertyName: \'identifier\')}'}" > From 1c89b3f0247a0764802d0c76d914fabe86b8cf56 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 13:38:22 +0100 Subject: [PATCH 081/113] [BUGFIX] Resolve storage for StorageRootFolderRecords --- .../StaticResolverPass.php | 31 +++++++++++++++++++ .../Core/FileHandling/DefaultFalFinder.php | 6 ++++ .../Core/Resolver/StaticResolver.php | 17 ++++++++++ .../Core/Resolver/StorageRootResolver.php | 31 +++++++++++++++++++ .../Core/Service/ResolverService.php | 16 +++++++++- Configuration/Component/Core/Services.php | 4 +++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 Classes/Component/Core/DependencyInjection/StaticResolverPass.php create mode 100644 Classes/Component/Core/Resolver/StaticResolver.php create mode 100644 Classes/Component/Core/Resolver/StorageRootResolver.php diff --git a/Classes/Component/Core/DependencyInjection/StaticResolverPass.php b/Classes/Component/Core/DependencyInjection/StaticResolverPass.php new file mode 100644 index 000000000..a446fd575 --- /dev/null +++ b/Classes/Component/Core/DependencyInjection/StaticResolverPass.php @@ -0,0 +1,31 @@ +tagName = $tagName; + } + + public function process(ContainerBuilder $container) + { + $resolverServiceDefinition = $container->findDefinition(ResolverService::class); + $staticResolvers = $container->findTaggedServiceIds($this->tagName); + foreach (array_keys($staticResolvers) as $staticResolver) { + $resolverServiceDefinition->addMethodCall('addStaticResolver', [new Reference($staticResolver)]); + } + } +} diff --git a/Classes/Component/Core/FileHandling/DefaultFalFinder.php b/Classes/Component/Core/FileHandling/DefaultFalFinder.php index 408ceb14c..d485b07a8 100644 --- a/Classes/Component/Core/FileHandling/DefaultFalFinder.php +++ b/Classes/Component/Core/FileHandling/DefaultFalFinder.php @@ -31,6 +31,7 @@ use In2code\In2publishCore\CommonInjection\EventDispatcherInjection; use In2code\In2publishCore\CommonInjection\ResourceFactoryInjection; +use In2code\In2publishCore\Component\Core\Demand\DemandBuilderInjection; use In2code\In2publishCore\Component\Core\Demand\DemandsFactoryInjection; use In2code\In2publishCore\Component\Core\Demand\Type\FilesInFolderDemand; use In2code\In2publishCore\Component\Core\Demand\Type\FolderDemand; @@ -65,6 +66,7 @@ class DefaultFalFinder use EventDispatcherInjection; use LocalFileInfoServiceInjection; use ForeignFileInfoServiceInjection; + use DemandBuilderInjection; /** * Creates a Record instance representing the current chosen folder in the @@ -121,6 +123,10 @@ public function findFolderRecord(?string $combinedIdentifier, bool $onlyRoot = f $recordCollection = new RecordCollection(); $this->demandResolver->resolveDemand($demands, $recordCollection); + $demands = $this->demandBuilder->buildDemandForRecords($recordCollection); + $recordCollection = new RecordCollection(); + $this->demandResolver->resolveDemand($demands, $recordCollection); + $folderRecord = $recordTree->getChild(FolderRecord::CLASSIFICATION, $combinedIdentifier); if (null === $folderRecord) { throw new FolderDoesNotExistOnBothSidesException($combinedIdentifier, $folder->getCombinedIdentifier()); diff --git a/Classes/Component/Core/Resolver/StaticResolver.php b/Classes/Component/Core/Resolver/StaticResolver.php new file mode 100644 index 000000000..74d95f253 --- /dev/null +++ b/Classes/Component/Core/Resolver/StaticResolver.php @@ -0,0 +1,17 @@ +addDemand(new SelectDemand('sys_file_storage', '', 'uid', $record->getProp('storage'), $record)); + } + } +} diff --git a/Classes/Component/Core/Service/ResolverService.php b/Classes/Component/Core/Service/ResolverService.php index e4ee3abf2..848542097 100644 --- a/Classes/Component/Core/Service/ResolverService.php +++ b/Classes/Component/Core/Service/ResolverService.php @@ -6,6 +6,7 @@ use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection; use In2code\In2publishCore\Component\Core\Resolver\Resolver; +use In2code\In2publishCore\Component\Core\Resolver\StaticResolver; class ResolverService { @@ -15,7 +16,20 @@ class ResolverService /** * @var array> */ - protected array $resolvers; + protected array $resolvers = []; + + /** + * @noinspection PhpUnused Called via DI + * @see \In2code\In2publishCore\Component\Core\DependencyInjection\StaticResolverPass + */ + public function addStaticResolver(StaticResolver $staticResolver): void + { + foreach ($staticResolver->getTargetClassification() as $classification) { + foreach ($staticResolver->getTargetProperties() as $property) { + $this->resolvers[$classification][$property] = $staticResolver; + } + } + } public function initializeObject(): void { diff --git a/Configuration/Component/Core/Services.php b/Configuration/Component/Core/Services.php index 060cefa27..21cc8f1eb 100644 --- a/Configuration/Component/Core/Services.php +++ b/Configuration/Component/Core/Services.php @@ -8,16 +8,19 @@ use In2code\In2publishCore\Component\Core\DependencyInjection\PublisherPass; use In2code\In2publishCore\Component\Core\DependencyInjection\RecordExtensionProvider\RecordExtensionsProvider; use In2code\In2publishCore\Component\Core\DependencyInjection\RecordExtensionTraitCompilerPass; +use In2code\In2publishCore\Component\Core\DependencyInjection\StaticResolverPass; use In2code\In2publishCore\Component\Core\DependencyInjection\TcaPreProcessorPass; use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessor; use In2code\In2publishCore\Component\Core\Publisher\Publisher; use In2code\In2publishCore\Component\Core\Resolver\Resolver; +use In2code\In2publishCore\Component\Core\Resolver\StaticResolver; use Symfony\Component\DependencyInjection\ContainerBuilder; use TYPO3\CMS\Core\DependencyInjection\PublicServicePass; return static function (ContainerBuilder $builder): void { $builder->registerForAutoconfiguration(TcaPreProcessor::class)->addTag('in2publish_core.tca.preprocessor'); $builder->registerForAutoconfiguration(Resolver::class)->addTag('in2publish_core.tca.resolver'); + $builder->registerForAutoconfiguration(StaticResolver::class)->addTag('in2publish_core.static_resolver'); $builder->registerForAutoconfiguration(Publisher::class)->addTag('in2publish_core.publisher'); $builder->registerForAutoconfiguration(DemandResolver::class)->addTag('in2publish_core.tca.demand_resolver'); $builder->registerForAutoconfiguration(RecordExtensionsProvider::class) @@ -25,6 +28,7 @@ $builder->addCompilerPass(new TcaPreProcessorPass('in2publish_core.tca.preprocessor')); $builder->addCompilerPass(new PublicServicePass('in2publish_core.tca.resolver', true)); + $builder->addCompilerPass(new StaticResolverPass('in2publish_core.static_resolver')); $builder->addCompilerPass(new PublisherPass('in2publish_core.publisher')); $builder->addCompilerPass(new DemandResolverPass('in2publish_core.tca.demand_resolver')); $builder->addCompilerPass(new DatabaseRecordFactoryFactoryCompilerPass('in2publish_core.factory.database_record')); From 4d73de75335cf6f8f456f94a9d217b7a5497fff6 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 16 Nov 2023 13:38:46 +0100 Subject: [PATCH 082/113] [BUGFIX] Correctly exclude folders and files for the recursiveState of Folder Records --- .../Core/Record/Model/FolderRecord.php | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Classes/Component/Core/Record/Model/FolderRecord.php b/Classes/Component/Core/Record/Model/FolderRecord.php index d0432826a..afe3ca872 100644 --- a/Classes/Component/Core/Record/Model/FolderRecord.php +++ b/Classes/Component/Core/Record/Model/FolderRecord.php @@ -4,6 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Record\Model; +use In2code\In2publishCore\Component\Core\Record\Iterator\IterationControls\SkipChildren; use In2code\In2publishCore\Component\Core\Record\Iterator\IterationControls\StopIteration; use In2code\In2publishCore\Component\Core\Record\Iterator\RecordIterator; use LogicException; @@ -42,17 +43,24 @@ public function getStateRecursive(): string if ($state !== Record::S_UNCHANGED) { return $state; } + $children = $this->getChildren(); + unset($children[FolderRecord::CLASSIFICATION], $children[FileRecord::CLASSIFICATION]); + $stateRecursive = Record::S_UNCHANGED; $recordIterator = new RecordIterator(); - $recordIterator->recurse($this, function (Record $record) use (&$stateRecursive) { - if ($record instanceof FolderRecord || $record instanceof FileRecord) { - return; - } - if ($record->getState() !== Record::S_UNCHANGED) { - $stateRecursive = Record::S_CHANGED; - throw new StopIteration(); + foreach ($children as $childRecords) { + foreach ($childRecords as $childRecord) { + $recordIterator->recurse($childRecord, function (Record $record) use (&$stateRecursive) { + if ($record instanceof FolderRecord || $record instanceof FileRecord) { + throw new SkipChildren(); + } + if ($record->getState() !== Record::S_UNCHANGED) { + $stateRecursive = Record::S_CHANGED; + throw new StopIteration(); + } + }); } - }); + } return $stateRecursive; } } From dff16d4dbda8d057bfc691807f85ad79f527fb24 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 10:06:34 +0100 Subject: [PATCH 083/113] [BUGFIX] Make PublisherService::publishRecordTree internal to force everyone to use the PublishingContext --- .../Core/Publisher/PublisherService.php | 27 +++++++++++++++++-- .../Core/Publisher/PublishingContext.php | 10 +++++-- Classes/Controller/FileController.php | 7 +++-- .../Controller/PublishPageAjaxController.php | 4 ++- .../Controller/RedirectController.php | 5 +++- .../Core/Publisher/PublisherServiceTest.php | 18 ++++++++++--- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Classes/Component/Core/Publisher/PublisherService.php b/Classes/Component/Core/Publisher/PublisherService.php index e09305c37..68494e6ea 100644 --- a/Classes/Component/Core/Publisher/PublisherService.php +++ b/Classes/Component/Core/Publisher/PublisherService.php @@ -7,7 +7,6 @@ use In2code\In2publishCore\CommonInjection\EventDispatcherInjection; use In2code\In2publishCore\Component\Core\Record\Model\Record; use In2code\In2publishCore\Component\Core\RecordTree\RecordTree; -use In2code\In2publishCore\Component\PostPublishTaskExecution\Service\TaskExecutionService; use In2code\In2publishCore\Component\PostPublishTaskExecution\Service\TaskExecutionServiceInjection; use In2code\In2publishCore\Event\PublishingOfOneRecordBegan; use In2code\In2publishCore\Event\PublishingOfOneRecordEnded; @@ -17,11 +16,18 @@ use In2code\In2publishCore\Event\RecursiveRecordPublishingEnded; use Throwable; +use function debug_backtrace; +use function user_error; + +use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const E_USER_DEPRECATED; + class PublisherService { use EventDispatcherInjection; use TaskExecutionServiceInjection; + protected const DEPRECATION_DIRECTLY_INVOKED = '%s%s%s directly invoked \In2code\In2publishCore\Component\Core\Publisher\PublisherService::publishRecordTree. This will not work in in2publish_core v13 anymore. Please use \In2code\In2publishCore\Component\Core\Publisher\PublisherService::publish instead.'; protected PublisherCollection $publisherCollection; /** @var array> */ protected array $visitedRecords = []; @@ -39,14 +45,31 @@ public function addPublisher(Publisher $publisher): void $this->publisherCollection->addPublisher($publisher); } + /** + * @throws Throwable + */ public function publish(PublishingContext $publishingContext): void { $recordTree = $publishingContext->getRecordTree(); - $this->publishRecordTree($recordTree); + $this->publishRecordTree($recordTree, $publishingContext->publishChildPages); } + /** + * @throws Throwable + * @internal This method will be made non-public in in2publish_core v13. Use publish() with PublishingContext + * instead. + */ public function publishRecordTree(RecordTree $recordTree, bool $includeChildPages = false): void { + // Check if method was called by something else than self::publish and trigger a deprecation. + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + $frame = $backtrace[1]; + if ($frame['function'] !== 'publish' || $frame['class'] !== self::class) { + $message = sprintf(self::DEPRECATION_DIRECTLY_INVOKED, $frame['class'], $frame['type'], $frame['function']); + user_error($message, E_USER_DEPRECATED); + } + unset($backtrace, $frame, $message); + $this->eventDispatcher->dispatch(new RecursiveRecordPublishingBegan($recordTree)); $this->publisherCollection->start(); diff --git a/Classes/Component/Core/Publisher/PublishingContext.php b/Classes/Component/Core/Publisher/PublishingContext.php index 5acb66b9d..99fb605fd 100644 --- a/Classes/Component/Core/Publisher/PublishingContext.php +++ b/Classes/Component/Core/Publisher/PublishingContext.php @@ -9,10 +9,16 @@ class PublishingContext { protected RecordTree $recordTree; + public bool $publishChildPages = false; - public function __construct(RecordTree $recordTree) - { + public function __construct( + RecordTree $recordTree, + bool $publishChildPages = null + ) { $this->recordTree = $recordTree; + if (null !== $publishChildPages) { + $this->publishChildPages = $publishChildPages; + } } public function getRecordTree(): RecordTree diff --git a/Classes/Controller/FileController.php b/Classes/Controller/FileController.php index 4617d85e3..b5f341436 100755 --- a/Classes/Controller/FileController.php +++ b/Classes/Controller/FileController.php @@ -35,6 +35,7 @@ use In2code\In2publishCore\Component\Core\FileHandling\DefaultFalFinderInjection; use In2code\In2publishCore\Component\Core\FileHandling\Exception\FolderDoesNotExistOnBothSidesException; use In2code\In2publishCore\Component\Core\Publisher\PublisherServiceInjection; +use In2code\In2publishCore\Component\Core\Publisher\PublishingContext; use In2code\In2publishCore\Component\Core\RecordTree\RecordTree; use In2code\In2publishCore\Controller\Traits\CommonViewVariables; use In2code\In2publishCore\Controller\Traits\ControllerFilterStatus; @@ -135,9 +136,10 @@ public function indexAction(): ResponseInterface public function publishFolderAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface { $recordTree = $this->defaultFalFinder->findFolderRecord($combinedIdentifier, true); + $publishingContext = new PublishingContext($recordTree); try { - $this->publisherService->publishRecordTree($recordTree); + $this->publisherService->publish($publishingContext); if (!$skipNotification) { $this->addFlashMessage( LocalizationUtility::translate('file_publishing.folder', 'in2publish_core', [$combinedIdentifier]), @@ -168,9 +170,10 @@ public function publishFolderAction(string $combinedIdentifier, bool $skipNotifi public function publishFileAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface { $recordTree = $this->defaultFalFinder->findFileRecord($combinedIdentifier); + $publishingContext = new PublishingContext($recordTree); try { - $this->publisherService->publishRecordTree($recordTree); + $this->publisherService->publish($publishingContext); if (!$skipNotification) { $this->addFlashMessage( LocalizationUtility::translate( diff --git a/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php b/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php index bc7e872a3..5dd38cb24 100644 --- a/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php +++ b/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php @@ -30,6 +30,7 @@ */ use In2code\In2publishCore\Component\Core\Publisher\PublisherServiceInjection; +use In2code\In2publishCore\Component\Core\Publisher\PublishingContext; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuilderInjection; use In2code\In2publishCore\Component\Core\RecordTree\RecordTreeBuildRequest; use In2code\In2publishCore\Component\PostPublishTaskExecution\Service\Exception\TaskExecutionFailedException; @@ -77,9 +78,10 @@ public function publishPage(ServerRequestInterface $request): ResponseInterface $recordTreeBuildRequest = new RecordTreeBuildRequest('pages', (int)$page, 0); $recordTree = $this->recordTreeBuilder->buildRecordTree($recordTreeBuildRequest); $record = $recordTree->getChild('pages', (int)$page, 0); + $publishingContext = new PublishingContext($recordTree); if (null !== $record && $record->isPublishable()) { try { - $this->publisherService->publishRecordTree($recordTree); + $this->publisherService->publish($publishingContext); $content['success'] = true; $content['error'] = false; $content['label'] = 'context_menu_publish_entry.page_published'; diff --git a/Classes/Features/RedirectsSupport/Controller/RedirectController.php b/Classes/Features/RedirectsSupport/Controller/RedirectController.php index 8c2fa636f..4c8902d8e 100644 --- a/Classes/Features/RedirectsSupport/Controller/RedirectController.php +++ b/Classes/Features/RedirectsSupport/Controller/RedirectController.php @@ -37,6 +37,7 @@ use In2code\In2publishCore\Component\Core\Demand\Type\SysRedirectDemand; use In2code\In2publishCore\Component\Core\DemandResolver\DemandResolverInjection; use In2code\In2publishCore\Component\Core\Publisher\PublisherServiceInjection; +use In2code\In2publishCore\Component\Core\Publisher\PublishingContext; use In2code\In2publishCore\Component\Core\RecordCollection; use In2code\In2publishCore\Component\Core\RecordTree\RecordTree; use In2code\In2publishCore\Controller\Traits\ControllerModuleTemplate; @@ -183,7 +184,9 @@ public function publishAction(array $redirects): void $recordCollection = new RecordCollection(); $this->demandResolver->resolveDemand($demands, $recordCollection); - $this->publisherService->publishRecordTree($recordTree); + $publishingContext = new PublishingContext($recordTree); + + $this->publisherService->publish($publishingContext); if (count($redirects) === 1) { $this->addFlashMessage(sprintf('Redirect %s published', reset($redirects))); diff --git a/Tests/Unit/Component/Core/Publisher/PublisherServiceTest.php b/Tests/Unit/Component/Core/Publisher/PublisherServiceTest.php index 2b8211b11..052024091 100644 --- a/Tests/Unit/Component/Core/Publisher/PublisherServiceTest.php +++ b/Tests/Unit/Component/Core/Publisher/PublisherServiceTest.php @@ -9,6 +9,7 @@ use In2code\In2publishCore\Component\Core\Publisher\FileRecordPublisher; use In2code\In2publishCore\Component\Core\Publisher\Publisher; use In2code\In2publishCore\Component\Core\Publisher\PublisherService; +use In2code\In2publishCore\Component\Core\Publisher\PublishingContext; use In2code\In2publishCore\Component\Core\Publisher\ReversiblePublisher; use In2code\In2publishCore\Component\Core\Publisher\TransactionalPublisher; use In2code\In2publishCore\Component\Core\Record\Model\DatabaseRecord; @@ -25,6 +26,7 @@ class PublisherServiceTest extends UnitTestCase { /** + * @covers ::publish * @covers ::publishRecordTree * @covers ::publishRecord */ @@ -41,11 +43,13 @@ public function testPublishRecordTreePublishesAllUnchangedRecordsInTree(): void $publisherService->addPublisher($databaseRecordPublisher); $recordTree = $this->getRecordTree1(); + $publishingContext = new PublishingContext($recordTree); - $publisherService->publishRecordTree($recordTree); + $publisherService->publish($publishingContext); } /** + * @covers ::publish * @covers ::publishRecordTree * @covers ::publishRecord */ @@ -62,11 +66,13 @@ public function testPublishRecordTreePublishesChildRecordsWithoutPages(): void $publisherService->addPublisher($databaseRecordPublisher); $recordTree = $this->getRecordTree2(); + $publishingContext = new PublishingContext($recordTree); - $publisherService->publishRecordTree($recordTree); + $publisherService->publish($publishingContext); } /** + * @covers ::publish * @covers ::publishRecordTree */ public function testCancelIsCalledWhenExceptionIsThrownDuringPublishing(): void @@ -81,12 +87,14 @@ public function testCancelIsCalledWhenExceptionIsThrownDuringPublishing(): void $publisherService->addPublisher($databaseRecordPublisher); $recordTree = $this->getRecordTree1(); + $publishingContext = new PublishingContext($recordTree); $this->expectException(Exception::class); - $publisherService->publishRecordTree($recordTree); + $publisherService->publish($publishingContext); } /** + * @covers ::publish * @covers ::addPublisher * @covers ::publishRecordTree */ @@ -107,11 +115,13 @@ public function testCancelAndReverseAreCalledWhenExceptionIsThrownDuringFinish() $reversibleTransactionalPublisher = $this->getReversibleTransactionalPublisher(); $publisherService->addPublisher($reversibleTransactionalPublisher); + $publishingContext = new PublishingContext($recordTree); + $GLOBALS['number_of_calls_reverse'] = 0; $GLOBALS['number_of_calls_cancel'] = 0; try { $this->expectException(Exception::class); - $publisherService->publishRecordTree($recordTree); + $publisherService->publish($publishingContext); } finally { $this->assertEquals(1, $GLOBALS['number_of_calls_reverse']); $this->assertEquals(1, $GLOBALS['number_of_calls_cancel']); From 672df38b7096f77f94802b8a5a4193805ea4c269 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 10:07:00 +0100 Subject: [PATCH 084/113] [BUGFIX] Overwrite toString for PageTreeRootRecord to return the "sitename" --- Classes/Component/Core/Record/Model/PageTreeRootRecord.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Classes/Component/Core/Record/Model/PageTreeRootRecord.php b/Classes/Component/Core/Record/Model/PageTreeRootRecord.php index 6417d5602..31ded5ec7 100644 --- a/Classes/Component/Core/Record/Model/PageTreeRootRecord.php +++ b/Classes/Component/Core/Record/Model/PageTreeRootRecord.php @@ -18,4 +18,9 @@ public function getPageId(): int { return 0; } + + public function __toString(): string + { + return $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']; + } } From 309bd7eb178397ed8050a89d2188c9fb3f20d27d Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 10:07:27 +0100 Subject: [PATCH 085/113] [REFACTOR] Extract $GLOBALS access to method --- Classes/Controller/RecordController.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index ec957d042..816a23fe8 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -109,13 +109,12 @@ public function injectPageRenderer(PageRenderer $pageRenderer): void public function initializeIndexAction(): void { - /** @var BackendUserAuthentication $BE_USER */ - $BE_USER = $GLOBALS['BE_USER']; - $data = $BE_USER->getModuleData('tx_in2publishcore_m1') ?? ['pageRecursionLimit' => 1]; + $backendUser = $this->getBackendUser(); + $data = $backendUser->getModuleData('tx_in2publishcore_m1') ?? ['pageRecursionLimit' => 1]; if ($this->request->hasArgument('pageRecursionLimit')) { $pageRecursionLimit = (int)$this->request->getArgument('pageRecursionLimit'); $data['pageRecursionLimit'] = $pageRecursionLimit; - $BE_USER->pushModuleData('tx_in2publishcore_m1', $data); + $backendUser->pushModuleData('tx_in2publishcore_m1', $data); } else { $this->request = $this->request->withArgument('pageRecursionLimit', $data['pageRecursionLimit'] ?? 1); } @@ -235,4 +234,9 @@ protected function addFlashMessagesAndRedirectToIndex(): ResponseInterface return $this->redirect('index', 'Record'); } + + public function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } } From 02973bf9de14df81a58f6c6b8b87e2ffd094614f Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 11:08:55 +0100 Subject: [PATCH 086/113] [BUGFIX] Use Connection::PARAM_STR_ARRAY instead of ArrayParameterType ArrayParameterType does not exist in TYPO3 v11 --- .../Component/Core/Publisher/Command/FalPublisherCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php index a3a2dbcd1..f4880efa9 100644 --- a/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php +++ b/Classes/Component/Core/Publisher/Command/FalPublisherCommand.php @@ -4,7 +4,6 @@ namespace In2code\In2publishCore\Component\Core\Publisher\Command; -use Doctrine\DBAL\ArrayParameterType; use In2code\In2publishCore\CommonInjection\LocalDatabaseInjection; use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service\FalDriverServiceInjection; use In2code\In2publishCore\Component\Core\Publisher\Instruction\PublishInstruction; @@ -14,6 +13,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use TYPO3\CMS\Core\Database\Connection; + use function explode; use function json_decode; @@ -44,7 +45,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ->where( $query->expr()->in( 'request_token', - $query->createNamedParameter($requestTokens, ArrayParameterType::STRING) + $query->createNamedParameter($requestTokens, Connection::PARAM_STR_ARRAY) ) ); $result = $query->executeQuery(); From 020c11e42376d1d2a0a2348ff704257ecdd5a6d8 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 12:15:35 +0100 Subject: [PATCH 087/113] [BUGFIX] Allow passing nodes directly to JS overlay and modal functions --- Resources/Public/JavaScript/BackendModule.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Resources/Public/JavaScript/BackendModule.js b/Resources/Public/JavaScript/BackendModule.js index b8ddf352c..28240722c 100644 --- a/Resources/Public/JavaScript/BackendModule.js +++ b/Resources/Public/JavaScript/BackendModule.js @@ -147,8 +147,11 @@ define([ }); }; - In2publishCoreModule.overlayListener = function () { - document.querySelectorAll('[data-in2publish-confirm]').forEach(element => { + In2publishCoreModule.overlayListener = function (nodes = null) { + if (nodes === null) { + nodes = document.querySelectorAll('[data-in2publish-confirm]'); + } + nodes.forEach(element => { element.addEventListener('click', In2publishCoreModule.overlayHandler, true) }) }; @@ -284,8 +287,11 @@ define([ } } - In2publishCoreModule.setupPublishListeners = function () { - document.querySelectorAll('.js-publish-trigger').forEach( + In2publishCoreModule.setupPublishListeners = function (nodes = null) { + if (nodes === null) { + nodes = document.querySelectorAll('.js-publish-trigger'); + } + nodes.forEach( element => element.addEventListener( 'click', In2publishCoreModule.publishFileEventListener, From 0dcee195c850f56cea0c012481d9119bdb99af7b Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Fri, 17 Nov 2023 17:45:45 +0100 Subject: [PATCH 088/113] [BUGFIX] Use middleware to inject the loading overlay, split JS into specific modules --- .../InjectLoadingOverlayMiddleware.php | 89 ++++++++ Configuration/Backend/Modules.php | 6 +- Configuration/RequestMiddlewares.php | 7 +- Resources/Private/Language/de.locallang.xlf | 22 +- .../Private/Language/de.locallang_js.xlf | 6 - Resources/Private/Language/locallang.xlf | 16 +- Resources/Private/Language/locallang_js.xlf | 4 - Resources/Private/Layouts/File.html | 2 - Resources/Private/Layouts/Record.html | 1 - .../Private/Partials/LoadingOverlay.html | 9 - .../Record/Publishing/PublishButton.html | 2 +- .../Publishing/PublishButtonWithWarning.html | 7 +- Resources/Private/Sass/LoadingOverlay.scss | 64 ++++++ Resources/Private/Sass/_ModulesGeneral.scss | 57 ----- Resources/Public/Css/LoadingOverlay.css | 1 + Resources/Public/Css/Modules.css | 2 +- Resources/Public/JavaScript/BackendModule.js | 207 +----------------- .../Public/JavaScript/ConfirmationModal.js | 149 +++++++++++++ Resources/Public/JavaScript/LoadingOverlay.js | 62 ++++++ 19 files changed, 419 insertions(+), 294 deletions(-) create mode 100644 Classes/Middleware/InjectLoadingOverlayMiddleware.php delete mode 100755 Resources/Private/Partials/LoadingOverlay.html create mode 100644 Resources/Private/Sass/LoadingOverlay.scss create mode 100644 Resources/Public/Css/LoadingOverlay.css create mode 100644 Resources/Public/JavaScript/ConfirmationModal.js create mode 100644 Resources/Public/JavaScript/LoadingOverlay.js diff --git a/Classes/Middleware/InjectLoadingOverlayMiddleware.php b/Classes/Middleware/InjectLoadingOverlayMiddleware.php new file mode 100644 index 000000000..70aff8fbd --- /dev/null +++ b/Classes/Middleware/InjectLoadingOverlayMiddleware.php @@ -0,0 +1,89 @@ + +
    +
    +
    +
    +
    +
    +
    + +HTML; + protected const SUPPORTED_PATHS = [ + '/typo3/module/web/', + '/typo3/module/file/in2publish', + '/typo3/module/site/in2publish', + '/typo3/module/tools/in2publish', + '/typo3/module/in2publish', + ]; + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if (!$this->isInSupportedPath($request)) { + return $handler->handle($request); + } + + /** @var PageRenderer $pageRenderer */ + $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); + $pageRenderer->addCssFile( + 'EXT:in2publish_core/Resources/Public/Css/LoadingOverlay.css', + 'stylesheet', + 'all', + '', + false, + ); + $pageRenderer->loadRequireJsModule('TYPO3/CMS/In2publishCore/LoadingOverlay'); + $pageRenderer->addInlineLanguageLabelFile('EXT:in2publish_core/Resources/Private/Language/locallang_js.xlf'); + + $response = $handler->handle($request); + + if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) { + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + $contents = $body->getContents(); + + $offset = strpos($contents, '') + 6; + $contents = substr($contents, 0, $offset) . self::CODE . substr($contents, $offset); + + $streamFactory = GeneralUtility::makeInstance(StreamFactory::class); + $newBody = $streamFactory->createStream($contents); + $response = $response->withBody($newBody); + } + + return $response; + } + + protected function isInSupportedPath(ServerRequestInterface $request): bool + { + $requestPath = strtolower($request->getUri()->getPath()); + foreach (self::SUPPORTED_PATHS as $path) { + if (str_starts_with($requestPath, $path)) { + return true; + } + } + return false; + } +} diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 514994868..b5e9dfe83 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -43,7 +43,7 @@ $backendModulesToRegister['in2publish_core_m1'] = [ 'parent' => 'web', 'position' => [], - 'access' => 'user,group', + 'access' => 'user', 'workspaces' => 'live', 'path' => '/module/in2publish_core/m1', 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod1.xlf', @@ -59,7 +59,7 @@ $backendModulesToRegister['in2publish_core_m3'] = [ 'parent' => 'file', 'position' => [], - 'access' => 'user,group', + 'access' => 'user', 'workspaces' => 'live', 'path' => '/module/in2publish_core/m3', 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod3.xlf', @@ -93,7 +93,7 @@ $backendModulesToRegister['in2publish_core_m5'] = [ 'parent' => 'site', 'position' => ['after' => 'redirects'], - 'access' => 'user,group', + 'access' => 'user', 'workspaces' => 'live', 'path' => '/module/in2publish_core/m5', 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod5.xlf', diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index f339213df..61af39eec 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -3,12 +3,17 @@ declare(strict_types=1); use In2code\In2publishCore\Features\MetricsAndDebug\Middleware\MetricsAndDebugMiddleware; +use In2code\In2publishCore\Middleware\InjectLoadingOverlayMiddleware; return [ 'backend' => [ - 'in2code/in2publish/debugging' => [ + 'in2code/in2publish_core/debugging' => [ 'target' => MetricsAndDebugMiddleware::class, 'after' => 'typo3/cms-core/response-propagation', ], + 'in2code/in2publish_core/inject-loading-overlay' => [ + 'target' => InjectLoadingOverlayMiddleware::class, + 'after' => 'typo3/cms-core/response-propagation', + ], ], ]; diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 0f6b7d37f..c5a10a4bd 100755 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -83,10 +83,6 @@ Publish page "%s" and its subpages. Veröffentlichen der Seite "%s" und ihrer Unterseiten
    - - Do you really want to publish all pages? - Möchten Sie wirklich alle Seiten veröffentlichen? - Do you really want to publish this page? Möchten Sie diese Seite wirklich veröffentlichen? @@ -472,6 +468,24 @@ The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. Der Datensatz "%s" ist ein Ziel des Verknüpfungsdatensatzes "%s". Das Ziel muss veröffentlicht werden, bevor der Verknüpfungsdatensatz veröffentlicht werden kann. + + This page has unmet dependencies. Since you cannot access the dependencies, it is possible to publish this page anyway. However, there is no guarantee that the page will look exactly the same as on Local. + You can see the dependencies in the details of the page. + Diese Seite hat unerfüllte Abhängigkeiten. Da Sie auf die Abhängigkeiten nicht zugreifen können ist es möglich, diese Seite trotzdem zu veröffentlichen. Allerdings ohne Garantie, dass die Seite exakt so aussieht wie auf Local. + Sie können die Abhängigkeiten in den Details der Seite einsehen. + + + Publish + Veröffentlichen + + + Abort + Abbrechen + + + Confirm publish + Veröffentlichung bestätigen + diff --git a/Resources/Private/Language/de.locallang_js.xlf b/Resources/Private/Language/de.locallang_js.xlf index 6a846ba8f..a84daf5bd 100755 --- a/Resources/Private/Language/de.locallang_js.xlf +++ b/Resources/Private/Language/de.locallang_js.xlf @@ -23,12 +23,6 @@ Are you sure you want to publish the folder $name$? This cannot be reversed. Möchten Sie den Ordner $name$ wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden. - - This page has unmet dependencies. Since you cannot access the dependencies, it is possible to publish this page anyway. However, there is no guarantee that the page will look exactly the same as on Local. - You can see the dependencies in the details of the page. - Diese Seite hat unerfüllte Abhängigkeiten. Da Sie auf die Abhängigkeiten nicht zugreifen können ist es möglich, diese Seite trotzdem zu veröffentlichen. Allerdings ohne Garantie, dass die Seite exakt so aussieht wie auf Local. - Sie können die Abhängigkeiten in den Details der Seite einsehen. - diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index b4e55c761..a3617b200 100755 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -63,9 +63,6 @@ Publish page "%s" and its subpages. - - Do you really want to publish all pages? - Do you really want to publish this page? @@ -355,6 +352,19 @@ The record "%s" is a target of the shortcut record "%s". The target must be published before the shortcut record can be published. + + This page has unmet dependencies. Since you cannot access the dependencies, it is possible to publish this page anyway. However, there is no guarantee that the page will look exactly the same as on Local. + You can see the dependencies in the details of the page. + + + Publish + + + Abort + + + Confirm publish + diff --git a/Resources/Private/Language/locallang_js.xlf b/Resources/Private/Language/locallang_js.xlf index 2a3d884e5..f1de53505 100755 --- a/Resources/Private/Language/locallang_js.xlf +++ b/Resources/Private/Language/locallang_js.xlf @@ -18,10 +18,6 @@ Are you sure you want to publish the folder $name$? This cannot be reversed. - - This page has unmet dependencies. Since you cannot access the dependencies, it is possible to publish this page anyway. However, there is no guarantee that the page will look exactly the same as on Local. - You can see the dependencies in the details of the page. - diff --git a/Resources/Private/Layouts/File.html b/Resources/Private/Layouts/File.html index e760a654c..2e3e15cbf 100755 --- a/Resources/Private/Layouts/File.html +++ b/Resources/Private/Layouts/File.html @@ -1,6 +1,4 @@ - - diff --git a/Resources/Private/Layouts/Record.html b/Resources/Private/Layouts/Record.html index e9ddbbb40..5a9b9c9aa 100755 --- a/Resources/Private/Layouts/Record.html +++ b/Resources/Private/Layouts/Record.html @@ -2,7 +2,6 @@
    -
    diff --git a/Resources/Private/Partials/LoadingOverlay.html b/Resources/Private/Partials/LoadingOverlay.html deleted file mode 100755 index d36e0eef2..000000000 --- a/Resources/Private/Partials/LoadingOverlay.html +++ /dev/null @@ -1,9 +0,0 @@ -
    -
    -
    -
    -
    -
    -
    -
    -
    diff --git a/Resources/Private/Partials/Record/Publishing/PublishButton.html b/Resources/Private/Partials/Record/Publishing/PublishButton.html index 68dcdd520..1968e0590 100644 --- a/Resources/Private/Partials/Record/Publishing/PublishButton.html +++ b/Resources/Private/Partials/Record/Publishing/PublishButton.html @@ -1,7 +1,7 @@ diff --git a/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html b/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html index bda50d2f7..b017fe280 100644 --- a/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html +++ b/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html @@ -1,10 +1,13 @@ + + + diff --git a/Resources/Private/Sass/LoadingOverlay.scss b/Resources/Private/Sass/LoadingOverlay.scss new file mode 100644 index 000000000..f83ffa7b4 --- /dev/null +++ b/Resources/Private/Sass/LoadingOverlay.scss @@ -0,0 +1,64 @@ +@import "compass"; +@import "Settings"; + +.in2publish-loading-overlay { + background-color: $scorpion; + height: 100%; + position: fixed; + z-index: 100000; + text-align: center; + opacity: 0.3; + top: 0; + left: 0; + right: 0; + bottom: 0; + filter: blur(0); +} + +.in2publish-loading-overlay--hidden { + display: none; +} + +.in2publish-loading-overlay--spinner { + position: relative; + top: 30%; + margin: 100px auto; + width: 50px; + height: 30px; + text-align: center; + font-size: 10px; + + > div { + background-color: $white; + height: 100%; + width: 6px; + display: inline-block; + + -webkit-animation: stretchdelay 1.2s infinite ease-in-out; + animation: stretchdelay 1.2s infinite ease-in-out; + } + + .rect2 { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; + } + + .rect3 { + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; + } + + .rect4 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; + } + + .rect5 { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; + } +} + +body:has(.in2publish-loading-overlay--active) > *:not(.in2publish-loading-overlay) { + filter: blur(3px); +} diff --git a/Resources/Private/Sass/_ModulesGeneral.scss b/Resources/Private/Sass/_ModulesGeneral.scss index 9fc7cb065..b7a416435 100644 --- a/Resources/Private/Sass/_ModulesGeneral.scss +++ b/Resources/Private/Sass/_ModulesGeneral.scss @@ -466,63 +466,6 @@ a.in2publish-notextdecoration { } } -.in2publish-preloader { - background-color: $scorpion; - height: 100%; - position: fixed; - z-index: 100000; - text-align: center; - opacity: 0.9; - top: 0; - left: 0; - right: 0; - bottom: 0; -} - -.in2publish-preloader--hidden { - display: none; -} - -.in2publish-preloader--spinner { - position: relative; - top: 30%; - margin: 100px auto; - width: 50px; - height: 30px; - text-align: center; - font-size: 10px; - - > div { - background-color: $white; - height: 100%; - width: 6px; - display: inline-block; - - -webkit-animation: stretchdelay 1.2s infinite ease-in-out; - animation: stretchdelay 1.2s infinite ease-in-out; - } - - .rect2 { - -webkit-animation-delay: -1.1s; - animation-delay: -1.1s; - } - - .rect3 { - -webkit-animation-delay: -1.0s; - animation-delay: -1.0s; - } - - .rect4 { - -webkit-animation-delay: -0.9s; - animation-delay: -0.9s; - } - - .rect5 { - -webkit-animation-delay: -0.8s; - animation-delay: -0.8s; - } -} - div#typo3-docbody.stopScrolling { transform: none; } diff --git a/Resources/Public/Css/LoadingOverlay.css b/Resources/Public/Css/LoadingOverlay.css new file mode 100644 index 000000000..e79366992 --- /dev/null +++ b/Resources/Public/Css/LoadingOverlay.css @@ -0,0 +1 @@ +.in2publish-loading-overlay{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.3;top:0;left:0;right:0;bottom:0;filter:blur(0)}.in2publish-loading-overlay--hidden{display:none}.in2publish-loading-overlay--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-loading-overlay--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-loading-overlay--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-loading-overlay--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-loading-overlay--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-loading-overlay--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}body:has(.in2publish-loading-overlay--active)>*:not(.in2publish-loading-overlay){filter:blur(3px)} diff --git a/Resources/Public/Css/Modules.css b/Resources/Public/Css/Modules.css index bea1fd08f..f873f1f07 100644 --- a/Resources/Public/Css/Modules.css +++ b/Resources/Public/Css/Modules.css @@ -1 +1 @@ -.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff;padding-top:1em}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}.in2publish-preloader{background-color:#585858;height:100%;position:fixed;z-index:100000;text-align:center;opacity:0.9;top:0;left:0;right:0;bottom:0}.in2publish-preloader--hidden{display:none}.in2publish-preloader--spinner{position:relative;top:30%;margin:100px auto;width:50px;height:30px;text-align:center;font-size:10px}.in2publish-preloader--spinner>div{background-color:#fff;height:100%;width:6px;display:inline-block;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.in2publish-preloader--spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.in2publish-preloader--spinner .rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}.in2publish-preloader--spinner .rect4{-webkit-animation-delay:-0.9s;animation-delay:-0.9s}.in2publish-preloader--spinner .rect5{-webkit-animation-delay:-0.8s;animation-delay:-0.8s}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .card-body .extbase-debugger{margin:0}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} +.in2publish-icon-info{position:absolute;top:1px;right:25px}.in2publish-icon-loop-alt4:before{font-size:90px !important;color:#5D9A46;position:absolute;top:25px;left:-45px}.in2publish-icon-loop-alt4.in2publish-warning:before{color:#FFCA4B}.in2publish-icon-loop-alt4.in2publish-connection-error:before{color:#A94442}.in2publish-icon-folder{margin:0 15px !important;position:relative;top:3px}.in2publish-icon-file{margin:0 15px;position:relative;top:3px}.in2publish-link-publish{position:absolute;right:0;top:1px}.in2publish-link-publish:hover{text-decoration:none}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish{right:1px;cursor:not-allowed}.in2publish-stagelisting__item__publish--blocked .in2publish-link-publish .in2publish-icon-publish:before{content:"\e60a"}.in2publish-stagelisting__item--removed .in2publish-link-publish .in2publish-icon-publish:hover{color:#5D9A46}@font-face{font-family:'in2publish';src:url("../Fonts/in2publish.eot?abcdef");src:url("../Fonts/in2publish.eot?#iefixabcdef") format("embedded-opentype"),url("../Fonts/in2publish.woff?abcdef") format("woff"),url("../Fonts/in2publish.ttf?abcdef") format("truetype"),url("../Fonts/in2publish.svg?abcdef#in2publish") format("svg");font-weight:normal;font-style:normal}[class^="in2publish-icon-"]:before,[class*=" in2publish-icon-"]:before,.in2publish-messages--removeable>.typo3-message:before{font-family:'in2publish';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;font-size:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-circle-o:before,.in2publish-icon-circle-o:before{content:"\f10c"}.icon-circle:before,.in2publish-icon-circle:before{content:"\f111"}.icon-blocked:before,.in2publish-icon-blocked:before{content:"\e60a"}.icon-x-altx-alt:before,.in2publish-icon-x-altx-alt:before{content:"\e609"}.icon-folder-download:before,.in2publish-icon-folder-download:before,.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e608"}.icon-history:before,.in2publish-icon-history:before{content:"\e603"}.icon-info:before,.in2publish-icon-info:before{content:"\e601"}.icon-loop-alt4:before,.in2publish-icon-loop-alt4:before{content:"\e600"}.icon-folder:before,.in2publish-icon-folder:before{content:"\e92f"}.icon-folder-open:before,.in2publish-icon-folder-open:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e930"}.icon-folder-plus:before,.in2publish-icon-folder-plus:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e931"}.icon-folder-minus:before,.in2publish-icon-folder-minus:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-folder:before{content:"\e932"}.icon-eye:before,.in2publish-icon-eye:before{content:"\e9ce"}.icon-arrow-right:before,.in2publish-link-publish .in2publish-icon-publish:before{content:"\ea34"}.icon-file-broken:before,.in2publish-icon-file-delete:before,.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-folder:before,.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e604"}.icon-file-add:before,.in2publish-icon-file-add:before,.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e605"}.icon-file-settings:before,.in2publish-icon-file-changed:before,.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column .in2publish-icon-file:before,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column .in2publish-icon-file:before{content:"\e606"}.icon-align-justify:before,.in2publish-icon-file:before{content:"\e607"}.icon-clock2:before{content:"\e60b"}.icon-edit:before,.in2publish-icon-edit:before{content:"\e602"}.nav-pills-container{background:white;padding:10px}div.typo3-fullDoc{height:auto}.in2publish-hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.in2publish-clearfix{zoom:1}.in2publish-clearfix:after{clear:both}.in2publish-clearfix:before,.in2publish-clearfix:after{content:"";display:table}.in2publish-icon-small:before,.in2publish-icon-history:before,.in2publish-icon-info:before,.in2publish-icon-eye:before,.in2publish-icon-edit:before,.in2publish-link-publish .in2publish-icon-publish:before{font-size:16px}.in2publish-unstyledlist{margin:0;padding:0;list-style-type:none}[data-action]{cursor:pointer}.in2publish-inline-block{display:inline-block}.in2publish-backend{font-size:15px;color:#fff;padding-top:1em}.in2publish-backend h1,.in2publish-backend h2,.in2publish-backend h3,.in2publish-backend h4,.in2publish-backend legend{color:#fff}.in2publish-backend select{color:#444}#typo3-docheader .in2publish-backend-select.module-docheader-bar{overflow:initial}.in2publish-backend *,.in2publish-backend *:before,.in2publish-backend *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.in2publish-backend ul{margin:0;padding:0}.in2publish-module>section{margin:15px 0}.in2publish-module>section>h3{margin-bottom:10px}.in2publish-module{background:#585858;margin:-48px -24px;padding-top:24px;min-height:calc(100vh - 41px)}legend{display:block;width:100%;padding:0;margin-bottom:18px;font-size:inherit;line-height:inherit;color:currentColor;border-style:none}label{font-weight:normal}a.in2publish-notextdecoration{text-decoration:none}.in2publish-main{margin-top:40px;overflow:hidden}.in2publish-container{overflow:hidden;margin:0 0 30px}.in2publish-container-50{position:relative;width:50%;float:left;text-align:center}.in2publish-container-50 img{width:90px;height:auto}.in2publish-stagelisting__item__column{background-color:#666;width:50%;float:left;height:30px;line-height:30px;position:relative;top:0;left:0}.in2publish-stagelisting__item__column a{color:#fff}.in2publish-stagelisting__item--added .in2publish-stagelisting__item__column{background-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item__column{background-color:#A94442}.in2publish-stagelisting__item--removed .in2publish-stagelisting__item__column{background-color:#000}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column{background-color:#FFCA4B;color:#585858}.in2publish-stagelisting__item--moved-and-changed .in2publish-stagelisting__item__column a,.in2publish-stagelisting__item--changed .in2publish-stagelisting__item__column a{color:#585858}.in2publish-stagelisting__item--moved .in2publish-stagelisting__item__column{background-color:#425ea1}.in2publish-list-level--1 .in2publish-icon-info{right:37px}.in2publish-list-level--1 .in2publish-link-publish{right:12px}.in2publish-list-level--1 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:27px}.in2publish-list-level--2 .in2publish-icon-info{right:49px}.in2publish-list-level--2 .in2publish-link-publish{right:24px}.in2publish-list-level--2 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:39px}.in2publish-list-level--3 .in2publish-icon-info{right:61px}.in2publish-list-level--3 .in2publish-link-publish{right:36px}.in2publish-list-level--3 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:51px}.in2publish-list-level--4 .in2publish-icon-info{right:73px}.in2publish-list-level--4 .in2publish-link-publish{right:48px}.in2publish-list-level--4 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:63px}.in2publish-list-level--5 .in2publish-icon-info{right:85px}.in2publish-list-level--5 .in2publish-link-publish{right:60px}.in2publish-list-level--5 .in2publish-stagelisting__item__column--right .in2publish-icon-folder{margin-left:75px}.in2publish-backend .in2publish-list-level{margin:0 0 0 25px}.in2publish-backend .in2publish-list-level>li{border-top:1px solid #585858}.in2publish-stagelisting__dropdown{overflow:hidden;background-color:#DBDBDB;color:#585858;border:10px solid #666}.in2publish-stagelisting__dropdown--open{margin-bottom:10px}.in2publish-stagelisting__dropdown--close{display:none}.in2publish-stagelisting__dropdown__item{width:50%;float:left;line-height:30px;padding:0}.in2publish-stagelisting__dropdown__item--full{width:100%}.in2publish-stagelisting__dropdown__item h3{line-height:30px}.in2publish-stagelisting__dropdown a{color:currentColor}.in2publish-stagelisting__dropdown h3{background-color:#585858;font-weight:normal;font-size:1em;padding:0 15px;margin-top:0}.in2publish-stagelisting__dropdown h4{background-color:#666;font-style:italic;padding:3px 15px}.in2publish-stagelisting__dropdown li{list-style-type:none;padding:0 0 0 15px;word-break:break-all}.in2publish-stagelisting__dropdown span.in2publish-link-publish,.in2publish-stagelisting__dropdown [class^="in2publish-icon-"],.in2publish-stagelisting__dropdown [class*=" in2publish-icon-"]{padding:0 10px 0 0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown{border-color:#3B7826}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown{border-color:#A94442}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown{border-color:#FFCA4B}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown{border-color:#425ea1}.in2publish-backend .in2publish-stagelisting__dropdown__item__list>li{border-style:none;position:relative}.in2publish-stagelisting__dropdown__actions{padding:0 15px;background-color:#A0A0A0;color:#fff}.in2publish-stagelisting__dropdown__actions>a{margin-right:20px}.in2publish-stagelisting__dropdown__actions>a:last-child{margin-right:0}.in2publish-stagelisting__item--added .in2publish-stagelisting__dropdown__actions{background-color:#5D9A46}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__dropdown__actions{background-color:#C15955}.in2publish-stagelisting__item--changed .in2publish-stagelisting__dropdown__actions{background-color:#FFDB88;color:currentColor}.in2publish-stagelisting__item--moved .in2publish-stagelisting__dropdown__actions{background-color:#557AD1;color:#fff}.in2publish-stagelisting__dropdown__page{background-color:#fff}.in2publish-backend .in2publish-related__title{font-style:normal;line-height:30px;padding:0 15px;margin:0;background-color:#FFDB88;color:#444}.in2publish-backend .in2publish-related__list{margin:12px 0 15px}.in2publish-backend .in2publish-related__list li{font-size:14px}.in2publish-backend .in2publish-stagelisting__dropdown__item__list{margin-bottom:12px}.in2publish-footer{margin:20px 0;color:#A0A0A0;font-size:80%}.in2publish-footer .in2publish-logo{float:right;width:160px;height:48px}.in2publish-functions-bar{background-color:#666;margin:20px 0;text-align:center;position:relative;padding:15px;min-height:73px}.in2publish-functions-bar__filter{position:absolute;right:20px;top:22px}.in2publish-functions-bar__filter i:before{font-size:30px}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link{display:inline-block;margin:0 0 0 10px;color:#fff}.in2publish-functions-bar__filter .in2publish-functions-bar__filter__link:hover{text-decoration:none}.in2publish-functions-bar__filter .in2publish-functions-bar--active{border-bottom:2px solid #fff}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-changed{border-color:#FFCA4B}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-added{border-color:#5D9A46}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-deleted{border-color:#A94442}.in2publish-functions-bar__filter .in2publish-functions-bar--active.in2publish-icon-status-moved{border-color:#557AD1}div#typo3-docbody.stopScrolling{transform:none}@-webkit-keyframes stretchdelay{0%, 40%, 100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%, 40%, 100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.in2publish-removevalue:before{right:4px;bottom:4px}.pagination .t3-icon{margin:0}.pagination .paginator-input{display:inline-block;width:auto;margin:-6px 0;height:26px;padding:4px 4px;font-size:11px;line-height:1.5;border-radius:2px}.pagination-block{display:block}.pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:2px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 6px;margin-left:-1px;line-height:1.5;color:#212424;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#000;background-color:#f5f5f5;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0078e6;border-color:#0078e6}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#d7d7d7;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:12px 12px;font-size:15px;line-height:1.33333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 4px;font-size:11px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.tx_in2publishcore_admintools .card-body .extbase-debugger{margin:0}.tx_in2publishcore_admintools .module-docheader-bar-buttons .btn-toolbar .btn-group{flex-wrap:wrap}.in2publish-state-icon:before{font-size:6px;margin-bottom:2px;display:inline-block;vertical-align:middle;height:12px;line-height:12px}.in2publish-state--unchanged{color:#9C9C9C}.in2publish-state--changed{color:#FFCA4B}.in2publish-state--moved-and-changed{color:#FFCA4B}.in2publish-state--added{color:#5D9A46}.in2publish-state--deleted{color:#A94442}.in2publish-state--moved{color:#557AD1}.badge.in2publish-badge--unchanged{color:#000;background-color:#9C9C9C;color:white}.badge.in2publish-badge--changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--moved-and-changed{background-color:#FFCA4B;color:black}.badge.in2publish-badge--added{background-color:#5D9A46;color:white}.badge.in2publish-badge--deleted{background-color:#A94442;color:white}.badge.in2publish-badge--moved{background-color:#557AD1}.in2publish-stagelisting__item--deleted .in2publish-stagelisting__item-filename{color:#A94442}.in2publish-icon-toggle__on{display:none}.in2publish-icon-toggle__off{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__on{display:initial}.in2publish-icon-toggle--active .in2publish-icon-toggle__off{display:none}.in2publish-table .col-filename{width:50%}.in2publish_core_m1 .module-docheader-bar-column-left .form-group{display:flex}.in2publish_core_m1 .module-docheader-bar-column-left .form-group .form-select{margin-left:1em} diff --git a/Resources/Public/JavaScript/BackendModule.js b/Resources/Public/JavaScript/BackendModule.js index 28240722c..778cf45b8 100644 --- a/Resources/Public/JavaScript/BackendModule.js +++ b/Resources/Public/JavaScript/BackendModule.js @@ -1,8 +1,13 @@ 'use strict'; define([ - 'jquery', 'TYPO3/CMS/Core/Event/DebounceEvent', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Input/Clearable' -], function ($, DebounceEvent, Modal) { + 'jquery', + 'TYPO3/CMS/Core/Event/DebounceEvent', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Input/Clearable', + 'TYPO3/CMS/In2publishCore/LoadingOverlay', + 'TYPO3/CMS/In2publishCore/ConfirmationModal', +], function ($, DebounceEvent, Modal, LoadingOverlay, ConfirmationModal) { var In2publishCoreModule = { isPublishFilesModule: (document.querySelector('.module[data-module-name="file_In2publishCoreM3"]') !== null), unchangedFilter: false, @@ -10,12 +15,6 @@ define([ addedFilter: false, deletedFilter: false, movedFilter: false, - publisherBag: [], - objects: { - body: undefined, - preLoader: undefined, - typo3DocBody: undefined - }, }; In2publishCoreModule.initialize = function () { @@ -24,14 +23,10 @@ define([ In2publishCoreModule.filterItemsByStatus(); In2publishCoreModule.setupFilterListeners(); In2publishCoreModule.setupClearableInputs(); - In2publishCoreModule.setupPublishListeners(); } else { In2publishCoreModule.setFilterForPageView(); In2publishCoreModule.filterButtonsListener(); - In2publishCoreModule.setupPublishListeners(); } - In2publishCoreModule.overlayListener(); - In2publishCoreModule.ajaxUriListener(); }; In2publishCoreModule.filterItemsByStatus = function () { @@ -147,89 +142,6 @@ define([ }); }; - In2publishCoreModule.overlayListener = function (nodes = null) { - if (nodes === null) { - nodes = document.querySelectorAll('[data-in2publish-confirm]'); - } - nodes.forEach(element => { - element.addEventListener('click', In2publishCoreModule.overlayHandler, true) - }) - }; - - /** - * @param {Event} event - */ - In2publishCoreModule.overlayHandler = function (event) { - /** - * @type {HTMLAnchorElement} - */ - const target = event.currentTarget - if ( - target.dataset['in2publishConfirm'] - && ( - target.classList.contains('in2publish-stagelisting__item__publish--blocked') - || !confirm(target.dataset['in2publishConfirm']) - ) - ) { - event.preventDefault(); - event.stopPropagation(); - event.stopImmediatePropagation(); - return; - } - if ('TRUE' === target.dataset['in2publishOverlay']) { - In2publishCoreModule.showPreloader(); - } - } - - In2publishCoreModule.showPreloader = function () { - In2publishCoreModule.objects.preLoader.removeClass('in2publish-preloader--hidden'); - In2publishCoreModule.objects.typo3DocBody.addClass('stopScrolling'); - }; - - In2publishCoreModule.ajaxUriListener = function () { - $('*[data-action-ajax-uri]').click(function (e) { - var $this = $(this); - var uri = $this.data('action-ajax-uri'); - if ('href' === uri) { - uri = $this.prop('href'); - e.preventDefault(); - } - var once = true === $this.data('action-ajax-once'); - var container = $this.data('action-ajax-result'); - var filled = false; - if (undefined !== container) { - var $container = $(container); - filled = true === $container.data('container-filled'); - } - - if (!once || !filled) { - $.ajax({ - url: uri, - beforeSend: function () { - In2publishCoreModule.showPreloader(); - }, - complete: function () { - In2publishCoreModule.hidePreLoader(); - }, - success: function (data) { - if (data && undefined !== container) { - $container.html(data); - $container.data('container-filled', true); - } - In2publishCoreModule.openOrCloseStageListingDropdownContainer( - $container.find('.in2publish-stagelisting__dropdown') - ); - } - }); - } - }); - }; - - In2publishCoreModule.hidePreLoader = function () { - In2publishCoreModule.objects.preLoader.addClass('in2publish-preloader--hidden'); - In2publishCoreModule.objects.typo3DocBody.removeClass('stopScrolling'); - }; - In2publishCoreModule.setupFilterListeners = function () { const filters = document.querySelectorAll('.js-in2publish-filter'); @@ -287,108 +199,6 @@ define([ } } - In2publishCoreModule.setupPublishListeners = function (nodes = null) { - if (nodes === null) { - nodes = document.querySelectorAll('.js-publish-trigger'); - } - nodes.forEach( - element => element.addEventListener( - 'click', - In2publishCoreModule.publishFileEventListener, - {capture: true} - ) - ) - }; - - In2publishCoreModule.publishFileEventListener = function (event) { - event.preventDefault(); - const target = event.currentTarget; - const type = target.dataset.type; - const severity = parseInt(target.dataset.severity || '0'); - let actionButtonClass = 'btn-default'; - let modalTitle = ''; - let modalContent = ''; - let modalButtonAbort = ''; - let modalButtonPublish = ''; - switch(severity) { - /* - * TYPO3.Severity.error = 2 - * TYPO3.Severity.warning = 1 - * TYPO3.Severity.ok = 0 - * TYPO3.Severity.info = -1 - * TYPO3.Severity.notice = -2 - */ - case -2: - case -1: - actionButtonClass = 'btn-info'; - break; - case 0: - actionButtonClass = 'btn-success'; - break; - case 1: - actionButtonClass = 'btn-warning'; - break; - case 2: - actionButtonClass = 'btn-danger'; - break; - } - if (TYPO3.lang['tx_in2publishcore.modal.publish.' + type + '.text'] !== undefined) { - modalTitle = TYPO3.lang['tx_in2publishcore.modal.publish.title']; - modalContent = TYPO3.lang['tx_in2publishcore.modal.publish.' + type + '.text'].replace('$name$', target.dataset.name); - modalButtonAbort = TYPO3.lang['tx_in2publishcore.action.abort']; - modalButtonPublish = TYPO3.lang['tx_in2publishcore.actions.publish']; - } else { - modalTitle = target.dataset.modalTitle; - modalContent = target.dataset.modalText + '\n' + target.dataset.modalReasons; - modalButtonAbort = target.dataset.modalButtonAbortCaption; - modalButtonPublish = target.dataset.modalButtonPublishCaption; - } - const configuration = { - title: modalTitle, - content: modalContent, - severity: severity, - buttons: [ - { - text: modalButtonAbort, - btnClass: 'btn btn-default', - name: 'abort', - active: true, - trigger: function () { - if (typeof Modal.currentModal.hideModal === "function") { - Modal.currentModal.hideModal(); - } else { - Modal.currentModal.trigger('modal-dismiss'); - } - In2publishCoreModule.hidePreLoader(); - } - }, - { - text: modalButtonPublish, - btnClass: 'btn ' + actionButtonClass, - name: 'publish', - trigger: () => { - if (typeof Modal.currentModal.hideModal === "function") { - Modal.currentModal.hideModal(); - } else { - Modal.currentModal.trigger('modal-dismiss'); - } - if (target.classList.contains('js-publish-overlay')) { - In2publishCoreModule.showPreloader(); - } - target.removeEventListener( - 'click', - In2publishCoreModule.publishFileEventListener, - {capture: true} - ); - target.dispatchEvent(event); - window.location = target.href; - } - } - ] - }; - Modal.advanced(configuration); - } - In2publishCoreModule.setupClearableInputs = function () { (Array.from(document.querySelectorAll('.t3js-clearable'))).forEach(function (input) { input.clearable(); @@ -396,9 +206,6 @@ define([ }; $(function () { - In2publishCoreModule.objects.body = $('body'); - In2publishCoreModule.objects.preLoader = $('.in2publish-preloader'); - In2publishCoreModule.objects.typo3DocBody = $('#typo3-docbody'); In2publishCoreModule.initialize(); }); diff --git a/Resources/Public/JavaScript/ConfirmationModal.js b/Resources/Public/JavaScript/ConfirmationModal.js new file mode 100644 index 000000000..458768370 --- /dev/null +++ b/Resources/Public/JavaScript/ConfirmationModal.js @@ -0,0 +1,149 @@ +'use strict' + +define(['TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/In2publishCore/LoadingOverlay'], function (Modal, LoadingOverlay) { + 'use strict' + + class ConfirmationModal { + + easyModalMethod = this.handleClickEasyModal.bind(this) + advancedModalMethod = this.handleClickAdvancedModal.bind(this) + + constructor() { + document.querySelectorAll('.js-in2publish-confirmation-modal').forEach(element => this.registerClickHandler(element)) + } + + /** + * Register a click handler which will show the loading-overlay when the element is clicked. + * Use only for elements that will reload the page or disable the loading-overlay yourself. + * + * If you want to register an element automatically on page load, give the element the class js-loading-overlay. + * This method can be used to register the handler for elements loaded via fetch. + * + * @param {HTMLElement} node + */ + registerClickHandler(node) { + if (node.dataset.easyModalTitle) { + node.addEventListener('click', this.easyModalMethod, {capture: true}) + } else if (node.dataset.modalConfiguration) { + node.addEventListener('click', this.advancedModalMethod, {capture: true}) + } + } + + /** + * @param {Event} event + */ + handleClickEasyModal(event) { + event.preventDefault() + const target = event.currentTarget + const severity = parseInt(target.dataset.easyModalSeverity ?? 0) + + Modal.confirm( + target.dataset.easyModalTitle, + target.dataset.easyModalContent ?? '', + severity, + this.defaultEasyModalButtons(event, target, severity), + ) + } + + defaultEasyModalButtons(event, target, severity) { + let actionButtonClass = '' + switch (severity) { + /* + * TYPO3.Severity.error = 2 + * TYPO3.Severity.warning = 1 + * TYPO3.Severity.ok = 0 + * TYPO3.Severity.info = -1 + * TYPO3.Severity.notice = -2 + */ + case -2: + case -1: + actionButtonClass = 'btn-info' + break + case 0: + actionButtonClass = 'btn-success' + break + case 1: + actionButtonClass = 'btn-warning' + break + case 2: + actionButtonClass = 'btn-danger' + break + } + return [ + { + text: TYPO3.lang['tx_in2publishcore.action.abort'], + btnClass: 'btn-default', + name: 'abort', + active: true, + trigger: this.abortClick.bind(this) + }, + { + text: TYPO3.lang['tx_in2publishcore.actions.publish'], + btnClass: actionButtonClass, + name: 'publish', + trigger: () => this.confirmClick(event, target, this.easyModalMethod) + } + ] + } + + + /** + * @param {Event} event + */ + handleClickAdvancedModal(event) { + event.preventDefault() + + const target = event.currentTarget + const modalConfiguration = JSON.parse(target.dataset.modalConfiguration) + + let finalModalConfiguration = modalConfiguration.settings + finalModalConfiguration.buttons = [] + if (modalConfiguration.buttons.abort) { + let abortButton = modalConfiguration.buttons.abort + abortButton.trigger = this.abortClick.bind(this) + finalModalConfiguration.buttons.push(abortButton) + } + if (modalConfiguration.buttons.confirm) { + let confirmButton = modalConfiguration.buttons.confirm + confirmButton.trigger = () => this.confirmClick(event, target, this.advancedModalMethod) + finalModalConfiguration.buttons.push(confirmButton) + } + + Modal.advanced(finalModalConfiguration) + } + + abortClick() { + this.closeModal() + LoadingOverlay.hideOverlay() + } + + confirmClick(event, target, previousHandler) { + target.removeEventListener('click', previousHandler, {capture: true}) + LoadingOverlay.showOverlay() + this.closeModal() + if (target instanceof HTMLAnchorElement) { + target.dispatchEvent(event) + window.location = target.href + } else if (target instanceof HTMLButtonElement) { + if (target.getAttribute("type") === "submit") { + if (target.hasAttribute("form")) { + const targetForm = target.getAttribute("form") + document.getElementById(targetForm).submit() + } else { + target.dispatchEvent(event) + } + } + } + } + + closeModal() { + if (typeof Modal.currentModal.hideModal === "function") { + Modal.currentModal.hideModal() + } else { + Modal.currentModal.trigger('modal-dismiss') + } + } + } + + return new ConfirmationModal() +}) diff --git a/Resources/Public/JavaScript/LoadingOverlay.js b/Resources/Public/JavaScript/LoadingOverlay.js new file mode 100644 index 000000000..4e9fe2d0f --- /dev/null +++ b/Resources/Public/JavaScript/LoadingOverlay.js @@ -0,0 +1,62 @@ +'use strict' + +define([], function () { + 'use strict' + + class LoadingOverlay { + + eventListenerMethod = this.handleClick.bind(this) + /** + * @var {NodeListOf} + */ + overlays + + constructor() { + this.registerOverlays() + document.querySelectorAll('.js-in2publish-loading-overlay').forEach(element => this.registerClickHandler(element)) + } + + /** + * @param {NodeListOf} nodes + */ + registerOverlays(nodes = null) { + this.overlays = nodes ?? document.querySelectorAll('.in2publish-loading-overlay') + } + + /** + * Register a click handler which will show the loading-overlay + * when the element is clicked. Use only for elements that will + * reload the page or disable the loading-overlay yourself. + * + * If you want to register an element automatically on page load, + * give the element the class js-in2publish-loading-overlay. This + * method can be used to register the handler for elements loaded + * via fetch. + * + * @param {HTMLElement} node + */ + registerClickHandler(node) { + node.addEventListener('click', this.eventListenerMethod) + } + + handleClick() { + this.showOverlay() + } + + showOverlay() { + this.overlays.forEach(element => { + element.classList.remove('in2publish-loading-overlay--hidden') + element.classList.add('in2publish-loading-overlay--active') + }) + } + + hideOverlay() { + this.overlays.forEach(element => { + element.classList.add('in2publish-loading-overlay--hidden') + element.classList.remove('in2publish-loading-overlay--active') + }) + } + } + + return new LoadingOverlay() +}) From e4cab079e20c34d7b348efadfc77d8540c4ad291 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 20 Nov 2023 09:47:28 +0100 Subject: [PATCH 089/113] [BUGFIX] Query sys_file_reference.table_local only in TYPO3 v11 as it was removed --- .../Service/FileEdgeCacheInvalidationService.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php b/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php index 49fd20c0d..5a9e03a81 100644 --- a/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php +++ b/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php @@ -37,6 +37,8 @@ use function array_key_exists; use function in_array; +use const In2code\In2publishCore\TYPO3_V11; + class FileEdgeCacheInvalidationService { use LocalDatabaseInjection; @@ -96,12 +98,10 @@ protected function selectSysFileReferenceRecords(array $uidList): Result $query->getRestrictions()->removeAll(); $query->select('tablenames as table', 'uid_foreign as uid') ->from('sys_file_reference') - ->where( - $query->expr()->and( - $query->expr()->eq('table_local', '"sys_file"'), - $query->expr()->in('uid_local', $uidList), - ), - ); + ->where($query->expr()->in('uid_local', $uidList)); + if (TYPO3_V11) { + $query->andWhere($query->expr()->eq('table_local', '"sys_file"')); + } return $query->executeQuery(); } From 7e320b8aa0ab8ce6146bdc77cf3156fb4f9f55c3 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Mon, 20 Nov 2023 10:35:27 +0100 Subject: [PATCH 090/113] [BUGFIX] Validate the resolver cache --- .../CachedTcaPreprocessingService.php | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php b/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php index 97dbf96db..98013a9d3 100644 --- a/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php +++ b/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php @@ -4,9 +4,12 @@ namespace In2code\In2publishCore\Component\Core\PreProcessing; +use __PHP_Incomplete_Class; use In2code\In2publishCore\CommonInjection\CacheInjection; use TYPO3\CMS\Core\Utility\GeneralUtility; +use function array_column; + class CachedTcaPreprocessingService { use CacheInjection; @@ -44,9 +47,11 @@ protected function initialize(): void if ($this->cache->has('tca_preprocessing_results')) { $cacheEntry = $this->cache->get('tca_preprocessing_results'); - $this->compatibleTca = $cacheEntry['compatibleTca']; - $this->incompatibleTca = $cacheEntry['incompatibleTca']; - return; + if ($this->isCacheValid($cacheEntry['compatibleTca'])) { + $this->compatibleTca = $cacheEntry['compatibleTca']; + $this->incompatibleTca = $cacheEntry['incompatibleTca']; + return; + } } $tcaPreProcessingService = GeneralUtility::makeInstance(TcaPreProcessingService::class); @@ -59,4 +64,17 @@ protected function initialize(): void ]; $this->cache->set('tca_preprocessing_results', $cacheEntry); } + + protected function isCacheValid(array $compatibleTca): bool + { + foreach ($compatibleTca as $properties) { + foreach (array_column($properties, 'resolver') as $resolver) { + if ($resolver instanceof __PHP_Incomplete_Class) { + $this->cache->remove('tca_preprocessing_results'); + return false; + } + } + } + return true; + } } From d720fc70c6e34810758b374214d4db8ffd6d1a20 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 21 Nov 2023 10:28:33 +0100 Subject: [PATCH 091/113] [BUGFIX] Restore context menu publishing for TYPO3 v12 Resolves: https://projekte.in2code.de/issues/60449 --- .../ContextMenu/PublishItemProvider.php | 14 ++++---- .../Controller/PublishPageAjaxController.php | 2 +- Configuration/JavaScriptModules.php | 14 ++++++++ .../Public/JavaScript/context-menu-actions.js | 35 +++++++++++++++++++ ext_tables.php | 1 - 5 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 Configuration/JavaScriptModules.php create mode 100644 Resources/Public/JavaScript/context-menu-actions.js diff --git a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php index 3e4c5efc1..28bbeabdb 100644 --- a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php +++ b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php @@ -54,9 +54,7 @@ class PublishItemProvider extends AbstractProvider public function __construct() { - if (TYPO3_V11) { - parent::__construct(...func_get_args()); - } + parent::__construct(...func_get_args()); // Sorry, no DI available for Context Menu Item Provider $this->permissionService = GeneralUtility::makeInstance(PermissionService::class); @@ -95,10 +93,12 @@ protected function getAdditionalAttributes(string $itemName): array 'ajax_in2publishcore_contextmenupublishentry_publish', ['id' => $this->identifier], ); - $attributes += [ - 'data-publish-url' => $publishUrl, - 'data-callback-module' => 'TYPO3/CMS/In2publishCore/ContextMenuPublishEntry', - ]; + $attributes['data-publish-url'] = $publishUrl; + if (TYPO3_V11) { + $attributes['data-callback-module'] = 'TYPO3/CMS/In2publishCore/ContextMenuPublishEntry'; + } else { + $attributes['data-callback-module'] = '@in2code/in2publish_core/context-menu-actions'; + } } return $attributes; } diff --git a/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php b/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php index 5dd38cb24..9ca493a6d 100644 --- a/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php +++ b/Classes/Features/ContextMenuPublishEntry/Controller/PublishPageAjaxController.php @@ -56,7 +56,7 @@ public function publishPage(ServerRequestInterface $request): ResponseInterface { $response = new Response(); - $page = $request->getQueryParams()['page'] ?? null; + $page = $request->getQueryParams()['id'] ?? null; $content = [ 'success' => false, diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 000000000..0dd6b7df0 --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,14 @@ + [ + 'backend', + 'core', + ], + 'tags' => [ + 'backend.contextmenu', + ], + 'imports' => [ + '@in2code/in2publish_core/' => 'EXT:in2publish_core/Resources/Public/JavaScript/', + ], +]; diff --git a/Resources/Public/JavaScript/context-menu-actions.js b/Resources/Public/JavaScript/context-menu-actions.js new file mode 100644 index 000000000..00bd64f36 --- /dev/null +++ b/Resources/Public/JavaScript/context-menu-actions.js @@ -0,0 +1,35 @@ +import Notification from "@typo3/backend/notification.js"; + +class ContextMenuActions { + static publishRecord(table, uid, element) { + Notification.info("Page " + uid + " is published in the background") + if ("pages" !== table) { + Notification.warning("Can not publish non-page via context menu entry") + return; + } + const publishUrl = element["publishUrl"] + if (!publishUrl) { + Notification.error("Publish URL is not set for this page") + return + } + fetch(publishUrl) + .then(response => { + if (!response.ok) { + throw new Error("Something went wrong"); + } + return response.json() + }) + .then(body => { + console.log(body) + if (body.error) { + Notification.error(body.message) + return + } + Notification.success(body.message) + top.document.dispatchEvent(new CustomEvent("typo3:pagetree:refresh")) + }) + .catch(error => Notification.error(error.message)) + } +} + +export default ContextMenuActions; diff --git a/ext_tables.php b/ext_tables.php index 641dc283e..ed03d70b0 100755 --- a/ext_tables.php +++ b/ext_tables.php @@ -143,7 +143,6 @@ } } - /******************************************* Context Menu Publish Entry *******************************************/ if ($configContainer->get('features.contextMenuPublishEntry.enable')) { $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1595598780] = PublishItemProvider::class; From 7e0aa11e4193bcec6309f3087252f0d18eef17f5 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 21 Nov 2023 10:41:04 +0100 Subject: [PATCH 092/113] [BUGFIX] Redirect to the previous page after publishing, not the published page Resolves: https://projekte.in2code.de/issues/60455 --- Classes/Controller/RecordController.php | 14 ++++++++++---- .../Partials/Record/Publishing/PublishButton.html | 3 ++- .../Publishing/PublishButtonWithWarning.html | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index 816a23fe8..603510691 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -180,12 +180,12 @@ public function initializePublishRecordAction(): void } } - public function publishRecordAction(int $id): ResponseInterface + public function publishRecordAction(int $recordId): ResponseInterface { - $request = new RecordTreeBuildRequest('pages', $id, 0); + $request = new RecordTreeBuildRequest('pages', $recordId, 0); $recordTree = $this->recordTreeBuilder->buildRecordTree($request); - $actualRecord = $recordTree->getChild('pages', $id); + $actualRecord = $recordTree->getChild('pages', $recordId); if (null === $actualRecord) { return $this->addFlashMessagesAndRedirectToIndex(); } @@ -232,7 +232,13 @@ protected function addFlashMessagesAndRedirectToIndex(): ResponseInterface } $this->addFlashMessage($message, $title, $severity); - return $this->redirect('index', 'Record'); + $arguments = []; + $queryParams = $this->request->getQueryParams(); + if (isset($queryParams['id'])) { + $arguments['id'] = (int)$queryParams['id']; + } + + return $this->redirect('index', 'Record', null, $arguments); } public function getBackendUser(): BackendUserAuthentication diff --git a/Resources/Private/Partials/Record/Publishing/PublishButton.html b/Resources/Private/Partials/Record/Publishing/PublishButton.html index 1968e0590..189c0dc33 100644 --- a/Resources/Private/Partials/Record/Publishing/PublishButton.html +++ b/Resources/Private/Partials/Record/Publishing/PublishButton.html @@ -2,7 +2,8 @@ diff --git a/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html b/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html index b017fe280..d7412a6b7 100644 --- a/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html +++ b/Resources/Private/Partials/Record/Publishing/PublishButtonWithWarning.html @@ -5,7 +5,7 @@ From 42e072df2f9be072029f3e65a339344601433882 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 21 Nov 2023 11:41:18 +0100 Subject: [PATCH 093/113] [BUGFIX] Try to build absolute URLs to files for the preview buttons in the filelist module Resolves: https://projekte.in2code.de/issues/60460 --- .../Definer/In2publishCoreDefiner.php | 6 -- .../Filesystem/Service/FileInfoService.php | 16 +++- .../File/BuildResourcePathViewHelper.php | 90 ------------------- Resources/Private/Partials/File/FileList.html | 4 +- 4 files changed, 17 insertions(+), 99 deletions(-) delete mode 100644 Classes/ViewHelpers/File/BuildResourcePathViewHelper.php diff --git a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php index ba42038d6..954055f7a 100644 --- a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php +++ b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php @@ -148,12 +148,6 @@ public function getLocalDefinition(): NodeCollection ->addBoolean('includeSysFileReference', false) ->addBoolean('treatRemovedAndDeletedAsDifference', false), ) - ->addArray( - 'filePreviewDomainName', - Builder::start() - ->addString('local', 'stage.example.com') - ->addString('foreign', 'www.example.com'), - ) ->addArray( 'view', Builder::start() diff --git a/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php index c73077a58..d7ec535c3 100644 --- a/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php +++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php @@ -4,13 +4,19 @@ namespace In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Service; +use In2code\In2publishCore\CommonInjection\SiteFinderInjection; use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FileInfo; use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\FilesystemInfo; use In2code\In2publishCore\Component\Core\DemandResolver\Filesystem\Model\MissingFileInfo; use TYPO3\CMS\Core\Resource\Driver\DriverInterface; +use TYPO3\CMS\Core\Utility\PathUtility; + +use function array_values; class FileInfoService { + use SiteFinderInjection; + protected const PROPERTIES = [ 'size', 'mimetype', @@ -33,7 +39,15 @@ public function getFileInfo(DriverInterface $driver, int $storage, string $fileI $fileInfo['identifierHash'] = $fileInfo['identifier_hash']; unset($fileInfo['folder_hash'], $fileInfo['identifier_hash']); $fileInfo['sha1'] = $driver->hash($fileIdentifier, 'sha1'); - $fileInfo['publicUrl'] = $driver->getPublicUrl($fileInfo['identifier']); + $fileInfo['publicUrl'] = null; + $publicUrl = $driver->getPublicUrl($fileInfo['identifier']); + if ($publicUrl) { + if (!PathUtility::hasProtocolAndScheme($publicUrl)) { + $firstSite = array_values($this->siteFinder->getAllSites())[0]; + $publicUrl = $firstSite->getRouter()->generateUri($firstSite->getRootPageId()) . $publicUrl; + } + $fileInfo['publicUrl'] = $publicUrl; + } return new FileInfo(...$fileInfo); } } diff --git a/Classes/ViewHelpers/File/BuildResourcePathViewHelper.php b/Classes/ViewHelpers/File/BuildResourcePathViewHelper.php deleted file mode 100644 index 3b9c9e089..000000000 --- a/Classes/ViewHelpers/File/BuildResourcePathViewHelper.php +++ /dev/null @@ -1,90 +0,0 @@ -, - * Oliver Eglseder - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - */ - -use In2code\In2publishCore\CommonInjection\SiteFinderInjection; -use In2code\In2publishCore\Service\ForeignSiteFinderInjection; -use TYPO3\CMS\Core\Exception\SiteNotFoundException; -use TYPO3\CMS\Core\Http\Uri; -use TYPO3\CMS\Core\Resource\ResourceFactory; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; - -use function ltrim; -use function rtrim; - -class BuildResourcePathViewHelper extends AbstractViewHelper -{ - use SiteFinderInjection; - use ForeignSiteFinderInjection; - - protected ResourceFactory $resourceFactory; - /** @var Uri[] */ - protected array $domains; - - public function __construct( - ResourceFactory $resourceFactory - ) { - $this->resourceFactory = $resourceFactory; - } - - /** - * @throws SiteNotFoundException - */ - public function initialize(): void - { - $this->domains['local'] = $this->siteFinder->getSiteByIdentifier('main')->getBase(); - $this->domains['foreign'] = $this->foreignSiteFinder->getSiteByIdentifier('main')->getBase(); - } - - public function initializeArguments(): void - { - parent::initializeArguments(); - $this->registerArgument('publicUrl', 'string', 'Url of the record', true); - $this->registerArgument('stagingLevel', 'string', 'Sets the staging level [LOCAL/foreign]', true, 'local'); - } - - public function render(): string - { - /** @var string $stagingLevel */ - $stagingLevel = $this->arguments['stagingLevel']; - - /** @var string $publicUrl */ - $publicUrl = $this->arguments['publicUrl']; - - // If the URI is absolute we don't need to prefix it. - $resourceUri = new Uri($publicUrl); - if (!empty($resourceUri->getHost())) { - return $publicUrl; - } - - $uri = $this->domains[$stagingLevel]; - $uri = $uri->withPath(rtrim($uri->getPath(), '/') . '/' . ltrim($publicUrl, '/')); - return (string)$uri; - } -} diff --git a/Resources/Private/Partials/File/FileList.html b/Resources/Private/Partials/File/FileList.html index c876049bf..07f327ec4 100755 --- a/Resources/Private/Partials/File/FileList.html +++ b/Resources/Private/Partials/File/FileList.html @@ -52,7 +52,7 @@ class="btn btn-default" data-bs-toggle="tooltip" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:view')}" - href="{publish:File.BuildResourcePath(stagingLevel: 'local', publicUrl: record.localProps.publicUrl)}" + href="{record.localProps.publicUrl}" > @@ -152,7 +152,7 @@ class="btn btn-default" data-bs-toggle="tooltip" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:view')}" - href="{publish:File.BuildResourcePath(stagingLevel: 'foreign', publicUrl: record.foreignProps.publicUrl)}" + href="{record.foreignProps.publicUrl}" > From 068eeafd3d6ecad60c92e60f584d535fa28c8d20 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 21 Nov 2023 12:42:24 +0100 Subject: [PATCH 094/113] [BUGFIX] Fix ignoring ctrl.versioningWS --- Classes/Service/Configuration/IgnoredFieldsService.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Classes/Service/Configuration/IgnoredFieldsService.php b/Classes/Service/Configuration/IgnoredFieldsService.php index 69c57ce14..6812d97c1 100644 --- a/Classes/Service/Configuration/IgnoredFieldsService.php +++ b/Classes/Service/Configuration/IgnoredFieldsService.php @@ -34,6 +34,7 @@ use function explode; use function implode; use function is_array; +use function is_bool; use function is_string; use function preg_match; @@ -69,7 +70,7 @@ public function getIgnoredFields(string $table): array if (null === $ignoredCtrlFieldNames) { continue; } - if ($ignoredCtrl === 'versioningWS') { + if ($ignoredCtrl === 'versioningWS' && $ignoredCtrlFieldNames) { $ignoredCtrlFieldNames = 't3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage'; } $ignoredCtrlFields = GeneralUtility::trimExplode(',', $ignoredCtrlFieldNames); @@ -86,7 +87,10 @@ public function getIgnoredFields(string $table): array return $this->rtc[$table]; } - protected function getValueByPath(array $array, string $path): ?string + /** + * @return string|bool|null + */ + protected function getValueByPath(array $array, string $path) { /** @var array|scalar $value */ $value = $array; @@ -101,7 +105,7 @@ protected function getValueByPath(array $array, string $path): ?string if (is_array($value)) { return implode(',', $value); } - if (!is_string($value)) { + if (!is_string($value) && !is_bool($value)) { return null; } return $value; From 8cb30b581e8fece163f8d67b2fa9bd54cfe4fbb3 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Tue, 21 Nov 2023 12:44:02 +0100 Subject: [PATCH 095/113] [BUGFIX] Ignore _file.publicUrl because it will always be different and is a computed property --- .../Definer/In2publishCoreDefiner.php | 5 +++++ .../Core/Record/Factory/RecordFactory.php | 3 ++- .../Component/Core/Record/Model/AbstractRecord.php | 14 +++++++++++++- .../Component/Core/Record/Model/DatabaseRecord.php | 12 ++---------- Classes/Component/Core/Record/Model/FileRecord.php | 12 +++++++++++- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php index 954055f7a..5118194ce 100644 --- a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php +++ b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php @@ -117,6 +117,11 @@ public function getLocalDefinition(): NodeCollection 'transOrigDiffSourceField', ], ], + '_file' => [ + 'fields' => [ + 'publicUrl', + ], + ], 'pages' => [ 'fields' => [ 'perms_userid', diff --git a/Classes/Component/Core/Record/Factory/RecordFactory.php b/Classes/Component/Core/Record/Factory/RecordFactory.php index 031a55d1c..1bc500e86 100755 --- a/Classes/Component/Core/Record/Factory/RecordFactory.php +++ b/Classes/Component/Core/Record/Factory/RecordFactory.php @@ -98,7 +98,8 @@ public function createMmRecord( public function createFileRecord(array $localProps, array $foreignProps): ?FileRecord { - $record = new FileRecord($localProps, $foreignProps); + $ignoredFields = $this->ignoredFieldsService->getIgnoredFields(FileRecord::CLASSIFICATION); + $record = new FileRecord($localProps, $foreignProps, $ignoredFields); if ($this->shouldIgnoreRecord($record)) { return null; } diff --git a/Classes/Component/Core/Record/Model/AbstractRecord.php b/Classes/Component/Core/Record/Model/AbstractRecord.php index f36311729..7967cd351 100644 --- a/Classes/Component/Core/Record/Model/AbstractRecord.php +++ b/Classes/Component/Core/Record/Model/AbstractRecord.php @@ -17,6 +17,8 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_diff_assoc; +use function array_diff_key; +use function array_flip; use function array_keys; use function array_pop; use function count; @@ -48,6 +50,8 @@ abstract class AbstractRecord implements Record */ protected array $translations = []; protected ?Record $translationParent = null; + /** @var array */ + protected array $ignoredProps = []; /** @var array{reasons: Reasons} */ protected array $rtc = []; @@ -163,6 +167,14 @@ public function isChanged(): bool return $this->localProps !== $this->foreignProps; } + protected function calculateChangedProps(): array + { + $ignoredProps = array_flip($this->ignoredProps); + $relevantLocalProps = array_diff_key($this->localProps, $ignoredProps); + $relevantForeignProps = array_diff_key($this->foreignProps, $ignoredProps); + return array_keys(array_diff_assoc($relevantLocalProps, $relevantForeignProps)); + } + protected function calculateState(): string { $localRecordExists = [] !== $this->localProps; @@ -255,7 +267,7 @@ public function getTransOrigPointer(): int public function getChangedProps(): array { - return array_keys(array_diff_assoc($this->localProps, $this->foreignProps)); + return $this->calculateChangedProps(); } public function getDependencies(): array diff --git a/Classes/Component/Core/Record/Model/DatabaseRecord.php b/Classes/Component/Core/Record/Model/DatabaseRecord.php index 05eebfc11..3a321adb3 100644 --- a/Classes/Component/Core/Record/Model/DatabaseRecord.php +++ b/Classes/Component/Core/Record/Model/DatabaseRecord.php @@ -4,15 +4,10 @@ namespace In2code\In2publishCore\Component\Core\Record\Model; -use function array_diff_assoc; -use function array_diff_key; -use function array_flip; -use function array_keys; - class DatabaseRecord extends AbstractDatabaseRecord implements DatabaseEntityRecord { protected int $id; - protected array $ignoredProps; + /** @var array */ protected array $changedProps; public function __construct(string $table, int $id, array $localProps, array $foreignProps, array $ignoredProps) @@ -24,10 +19,7 @@ public function __construct(string $table, int $id, array $localProps, array $fo $this->foreignProps = $foreignProps; $this->ignoredProps = $ignoredProps; - $relevantLocalProps = array_diff_key($this->localProps, array_flip($ignoredProps)); - $relevantForeignProps = array_diff_key($this->foreignProps, array_flip($ignoredProps)); - $this->changedProps = array_keys(array_diff_assoc($relevantLocalProps, $relevantForeignProps)); - + $this->changedProps = $this->calculateChangedProps(); $this->state = $this->calculateState(); $this->dependencies = $this->calculateDependencies(); } diff --git a/Classes/Component/Core/Record/Model/FileRecord.php b/Classes/Component/Core/Record/Model/FileRecord.php index 415d89730..fcec77489 100644 --- a/Classes/Component/Core/Record/Model/FileRecord.php +++ b/Classes/Component/Core/Record/Model/FileRecord.php @@ -12,10 +12,15 @@ class FileRecord extends AbstractRecord { public const CLASSIFICATION = '_file'; - public function __construct(array $localProps, array $foreignProps) + /** @var array */ + protected array $changedProps; + + public function __construct(array $localProps, array $foreignProps, array $ignoredProps = []) { $this->localProps = $localProps; $this->foreignProps = $foreignProps; + $this->ignoredProps = $ignoredProps; + $this->changedProps = $this->calculateChangedProps(); $this->state = $this->calculateState(); } @@ -64,4 +69,9 @@ public function isMovedToDifferentFolder(): bool return PathUtility::dirname($this->localProps['identifier']) !== PathUtility::dirname($this->foreignProps['identifier']); } + + public function getChangedProps(): array + { + return $this->changedProps; + } } From 754705ebaadfc5f21aa2f525297c5ccae5c6ca15 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 22 Nov 2023 09:57:25 +0100 Subject: [PATCH 096/113] [BUGFIX] Restore the confirmation modal for file and folder publishing Resolves: https://projekte.in2code.de/issues/60487 --- Classes/Controller/FileController.php | 3 --- Classes/Controller/RecordController.php | 3 --- Resources/Private/Language/de.locallang.xlf | 8 ++++++++ Resources/Private/Language/de.locallang_js.xlf | 12 ------------ Resources/Private/Language/locallang.xlf | 6 ++++++ Resources/Private/Language/locallang_js.xlf | 9 --------- Resources/Private/Partials/File/FileList.html | 13 ++++++++++--- Resources/Private/Partials/File/FolderList.html | 11 +++++++++-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Classes/Controller/FileController.php b/Classes/Controller/FileController.php index b5f341436..8a0f9e61e 100755 --- a/Classes/Controller/FileController.php +++ b/Classes/Controller/FileController.php @@ -83,9 +83,6 @@ class FileController extends ActionController public function injectPageRenderer(PageRenderer $pageRenderer): void { $this->actualInjectPageRenderer($pageRenderer); - $this->pageRenderer->addInlineLanguageLabelFile( - 'EXT:in2publish_core/Resources/Private/Language/locallang_js.xlf', - ); $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/In2publishCore/BackendModule'); $this->pageRenderer->addCssFile( 'EXT:in2publish_core/Resources/Public/Css/Modules.css', diff --git a/Classes/Controller/RecordController.php b/Classes/Controller/RecordController.php index 603510691..eea3312a5 100755 --- a/Classes/Controller/RecordController.php +++ b/Classes/Controller/RecordController.php @@ -93,9 +93,6 @@ class RecordController extends ActionController public function injectPageRenderer(PageRenderer $pageRenderer): void { $this->actualInjectPageRenderer($pageRenderer); - $this->pageRenderer->addInlineLanguageLabelFile( - 'EXT:in2publish_core/Resources/Private/Language/locallang_js.xlf', - ); $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/In2publishCore/BackendModule'); $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/In2publishCore/BackendEnhancements'); $this->pageRenderer->addCssFile( diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index c5a10a4bd..2dc7b5ad8 100755 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -486,6 +486,14 @@ Confirm publish Veröffentlichung bestätigen + + Are you sure you want to publish the file %s? This cannot be reversed. + Möchten Sie die Datei %s wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden. + + + Are you sure you want to publish the folder %s? This cannot be reversed. + Möchten Sie den Ordner %s wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden. + diff --git a/Resources/Private/Language/de.locallang_js.xlf b/Resources/Private/Language/de.locallang_js.xlf index a84daf5bd..154ce3ff9 100755 --- a/Resources/Private/Language/de.locallang_js.xlf +++ b/Resources/Private/Language/de.locallang_js.xlf @@ -11,18 +11,6 @@ Abort Abbrechen - - Confirm publish - Veröffentlichung bestätigen - - - Are you sure you want to publish the file $name$? This cannot be reversed. - Möchten Sie die Datei $1 wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden. - - - Are you sure you want to publish the folder $name$? This cannot be reversed. - Möchten Sie den Ordner $name$ wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden. - diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index a3617b200..f4caad7b7 100755 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -365,6 +365,12 @@ Confirm publish + + Are you sure you want to publish the file %s? This cannot be reversed. + + + Are you sure you want to publish the folder %s? This cannot be reversed. + diff --git a/Resources/Private/Language/locallang_js.xlf b/Resources/Private/Language/locallang_js.xlf index f1de53505..88fc4c8d4 100755 --- a/Resources/Private/Language/locallang_js.xlf +++ b/Resources/Private/Language/locallang_js.xlf @@ -9,15 +9,6 @@ Abort - - Confirm publish - - - Are you sure you want to publish the file $name$? This cannot be reversed. - - - Are you sure you want to publish the folder $name$? This cannot be reversed. - diff --git a/Resources/Private/Partials/File/FileList.html b/Resources/Private/Partials/File/FileList.html index 07f327ec4..777e4e3e5 100755 --- a/Resources/Private/Partials/File/FileList.html +++ b/Resources/Private/Partials/File/FileList.html @@ -110,12 +110,19 @@ + + + + data="{ + easy-modal-severity: -1, + easy-modal-title: easy-modal-title, + easy-modal-content: easy-modal-content, + }" + > diff --git a/Resources/Private/Partials/File/FolderList.html b/Resources/Private/Partials/File/FolderList.html index 0a9f1dcdf..fa74d5c12 100755 --- a/Resources/Private/Partials/File/FolderList.html +++ b/Resources/Private/Partials/File/FolderList.html @@ -23,11 +23,18 @@ + + + From 12d9c33b0ee4dda67ec67d2568a3e9099a4d3c4e Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Wed, 22 Nov 2023 13:58:20 +0100 Subject: [PATCH 097/113] [DOCS] Adjust Feature List --- Documentation/Admins/Features/README.md | 86 ++++++++++++++++++------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/Documentation/Admins/Features/README.md b/Documentation/Admins/Features/README.md index d3724827e..423764415 100644 --- a/Documentation/Admins/Features/README.md +++ b/Documentation/Admins/Features/README.md @@ -1,23 +1,63 @@ -# List of Features (WIP) - -* AdminTools -* CacheInvalidation -* CompareDatabaseTool -* ContextMenuPublishEntry -* Services.yaml -* FileEdgeCacheInvalidator -* FullTablePublishing -* LogsIntegration -* MetricsAndDebug -* NewsSupport -* PreventParallelPublishing -* PublishSorting -* RecordBreadcrumbs -* RecordInspector -* [**Redirects Support**](RedirectsSupport.md) Publish redirects. -* RefIndexUpdate -* [**TreatRemovedAndDeletedAsDifference**](TreatRemovedAndDeletedAsDifference.md) Show records that have been removed on - one side and deleted on the other side in the OverviewModule. -* SysLogPublisher -* SystemInformationExport -* WarningOnForeign +# List of Features EXT:in2publish_core + +The `in2publish_core` extension offers a variety of configurable features, each residing in its own subfolder under `Configuration/Features`. Here's an overview of these features: + +## AdminTools +- Provides tools for administrators to ensure correct functioning of the content publisher and to analyse the system setup. + +## CacheInvalidation +- Manages cache invalidation strategies for efficient content delivery and performance optimization. + +## CompareDatabaseTool +- Offers a tool for comparing database states between foreign and local development, aiding in synchronization and troubleshooting. + +## ContextMenuPublishEntry +- Enhances the TYPO3 context menu with publishing options. + +## FileEdgeCacheInvalidator +- Handles invalidation of edge caches for files, ensuring clearing of caches on foreign systems after publishing + +## FullTablePublishing +- Allows for the publishing of entire database tables, useful in scenarios requiring bulk data transfers without related records. + +## HideRecordsDeletedDifferently +##[**HideRecordsDeletedDifferently**](HideRecordsDeletedDifferently.md) +- Offers the possibility to hide records from the Publish Overview Module if they are deleted on one side and removed from the database on the other, e.g. if using the Recycler. +- Configurable feature. Default: enabled. + +## MetricsAndDebug +- Offers metrics collection and debugging tools, helpful for performance analysis and issue resolution. + +## NewsSupport +- Specific support for handling news records and related content. + +## PreventParallelPublishing +- Prevents parallel publishing operations, ensuring data integrity and avoiding conflicts during content deployment. + +## PublishSorting +- Adds sorting capabilities to the publishing process, allowing for prioritization and organized content rollout. + +## RecordBreadcrumbs +- Enhances the backend interface with breadcrumbs for records, improving navigation and context awareness. + +## RecordInspector +- Provides an inspection tool for content records, aiding in content review and data analysis. + +## [**Redirects Support**](RedirectsSupport.md) +- Integrates support for manual publishing of redirects. +- Configurable feature. Default: enabled. + +## RefIndexUpdate +- Handles the updating of TYPO3's reference index, ensuring accurate content linking and reference management. + +## ResolveFilesForIndices +- Resolves file paths for indexing, aiding in efficient content retrieval and search functionality. + +## SysLogPublisher +- Integrates with TYPO3's system log for publishing-related logging, enhancing monitoring and auditing capabilities. + +## SystemInformationExport +- Enables the export of system information, useful for diagnostics and system overviews. + +## WarningOnForeign +- Implements warnings for operations performed on foreign (non-local) systems, enhancing operational safety. From 7c0928d877ffb0336cf5cbdb9328aabc27e9d27f Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Wed, 29 Nov 2023 13:27:10 +0100 Subject: [PATCH 098/113] [BUGFIX] Corrects Loading of Middleware Resolves: #60628 --- Classes/Middleware/InjectLoadingOverlayMiddleware.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/Middleware/InjectLoadingOverlayMiddleware.php b/Classes/Middleware/InjectLoadingOverlayMiddleware.php index 70aff8fbd..66e0e2780 100644 --- a/Classes/Middleware/InjectLoadingOverlayMiddleware.php +++ b/Classes/Middleware/InjectLoadingOverlayMiddleware.php @@ -36,6 +36,7 @@ class InjectLoadingOverlayMiddleware implements MiddlewareInterface '/typo3/module/site/in2publish', '/typo3/module/tools/in2publish', '/typo3/module/in2publish', + '/module/web/In2publishM2', ]; public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface @@ -80,7 +81,7 @@ protected function isInSupportedPath(ServerRequestInterface $request): bool { $requestPath = strtolower($request->getUri()->getPath()); foreach (self::SUPPORTED_PATHS as $path) { - if (str_starts_with($requestPath, $path)) { + if (str_starts_with($requestPath, $path) || str_starts_with($_GET['route'] ?? '', $path)) { return true; } } From 1459f149cce49bc3574345721d51e2ce9f269de0 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 29 Nov 2023 15:09:43 +0100 Subject: [PATCH 099/113] [BUGFIX] Add PreProcessor for TCA type file --- .../PreProcessor/FilePreprocessor.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Classes/Component/Core/PreProcessing/PreProcessor/FilePreprocessor.php diff --git a/Classes/Component/Core/PreProcessing/PreProcessor/FilePreprocessor.php b/Classes/Component/Core/PreProcessing/PreProcessor/FilePreprocessor.php new file mode 100644 index 000000000..d9bf27916 --- /dev/null +++ b/Classes/Component/Core/PreProcessing/PreProcessor/FilePreprocessor.php @@ -0,0 +1,29 @@ +container->get(InlineSelectResolver::class); + $resolver->configure( + $foreignTable, + $foreignField, + $foreignTableField, + '', + ); + return $resolver; + } +} From 4a1a73455942e78f57a44a10c5521c82ff67521d Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Wed, 29 Nov 2023 17:01:51 +0100 Subject: [PATCH 100/113] [DOCS] Add admin changelog for YAML --- ...60149-Change-ReplaceSpycWithSymfonyYaml.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md diff --git a/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md new file mode 100644 index 000000000..66a2abbf4 --- /dev/null +++ b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md @@ -0,0 +1,49 @@ +# 60149 Change Replace Spyc with symfony/yaml + +Issue https://projekte.in2code.de/issues/60149 + +## Description + +in2publish_core uses a YAML file for configuration since it was first develop in 2015. YAML has not been established as +a configuration language back then, so it was necessary to ship a YAML parser with the extension. Time flew by and some +TYPO3 versions later, TYPO3 uses YAML for site configuration, the Form Framework, CKE Editor configuration, and more. +We have not required any YAML parser via composer, because we also supported TYPO3 in non-composer installations. + +So eventually, TYPO3 requires a YAML parser, too. We can rely on the implementation shipped with TYPO3 to reduce the +code we have to maintain, which we did in in2publish_core v12.3.0. We are now using the YAML parser shipped with TYPO3. + +## Impact + +symfony/yaml does not support multiple documents and a specific list type. You will have to change your configuration or +else you will experience exceptions and probably unwanted side effects. + +## Affected Installations + +Possibly all, probably only those who do not have the Content Publisher Enterprise Edition installed. + +## Migration + +1. Remove the "end of directives marker" `---` from any Content Publisher configuration YAML file. +2. Replace block collections with arrays (see Example #1 Replace block collections with arrays) + +## Examples + +### #1 Replace block collections with arrays +Before: +```yaml + permission: + definition: + 2: + 3 + 4 + 5 + 6 + 7 + 8 +``` +After +```yaml + permission: + definition: + 2: [3,4,5,6,7,8] +``` From 9415343985d397f27e2d320a3ec2f75edd920fdb Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 09:46:04 +0100 Subject: [PATCH 101/113] [FEATURE] Add LinkProcessor for TYPO3 v12 --- .../PreProcessor/LinkProcessor.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 Classes/Component/Core/PreProcessing/PreProcessor/LinkProcessor.php diff --git a/Classes/Component/Core/PreProcessing/PreProcessor/LinkProcessor.php b/Classes/Component/Core/PreProcessing/PreProcessor/LinkProcessor.php new file mode 100755 index 000000000..5ca257499 --- /dev/null +++ b/Classes/Component/Core/PreProcessing/PreProcessor/LinkProcessor.php @@ -0,0 +1,20 @@ +container->get(TextResolver::class); + $resolver->configure($column); + return $resolver; + } +} From 22edd37e054021c119f6f6097f8cffcef7d9ec08 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 09:46:31 +0100 Subject: [PATCH 102/113] [BUGFIX] Increase max depth when dumping compatible TCA --- Resources/Private/Templates/Tca/Index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Private/Templates/Tca/Index.html b/Resources/Private/Templates/Tca/Index.html index e0eb66bc5..9a7a64a7b 100755 --- a/Resources/Private/Templates/Tca/Index.html +++ b/Resources/Private/Templates/Tca/Index.html @@ -17,7 +17,7 @@

    - {compatibleTca} + {compatibleTca}
    From 96e52b6fdacf21bfd721014edb413b52f8491945 Mon Sep 17 00:00:00 2001 From: Daniel Hoffmann Date: Thu, 30 Nov 2023 09:06:35 +0100 Subject: [PATCH 103/113] [FEATURE] Adds another test return to get more specific testresult Resolves: #32959 --- Classes/Testing/Tests/Adapter/TransmissionAdapterTest.php | 2 ++ Classes/Testing/Tests/SshConnection/SshConnectionTest.php | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Classes/Testing/Tests/Adapter/TransmissionAdapterTest.php b/Classes/Testing/Tests/Adapter/TransmissionAdapterTest.php index b790c8c59..04bbcc638 100644 --- a/Classes/Testing/Tests/Adapter/TransmissionAdapterTest.php +++ b/Classes/Testing/Tests/Adapter/TransmissionAdapterTest.php @@ -35,6 +35,7 @@ use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitterInjection; use In2code\In2publishCore\Component\TemporaryAssetTransmission\TransmissionAdapter\AdapterInterface; use In2code\In2publishCore\Testing\Tests\Configuration\ConfigurationFormatTest; +use In2code\In2publishCore\Testing\Tests\SshConnection\SshConnectionTest; use In2code\In2publishCore\Testing\Tests\TestCaseInterface; use In2code\In2publishCore\Testing\Tests\TestResult; use Throwable; @@ -174,6 +175,7 @@ public function getDependencies(): array $dependencies = [ ConfigurationFormatTest::class, AdapterSelectionTest::class, + SshConnectionTest::class, ]; if (isset($GLOBALS['in2publish_core']['virtual_tests'][AdapterInterface::class])) { $dependencies = array_merge( diff --git a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php index e7262b419..498466276 100644 --- a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php +++ b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php @@ -67,6 +67,14 @@ public function run(): TestResult // This is the first time a RCE is executed, so we have to test here for the missing document root folder if (!$response->isSuccessful()) { + if ($response->getExitStatus() === 1425401293 || $response->getExitStatus() === 1425401287) { + return new TestResult( + 'ssh_connection.connection_failed', + TestResult::ERROR, + ['ssh_connection.connection_failure_message', $response->getErrorsString()], + ); + } + return new TestResult( 'ssh_connection.foreign_document_root_missing', TestResult::ERROR, From 8852fe97a16ecd7a464510363b72065f4355c8ff Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 11:11:53 +0100 Subject: [PATCH 104/113] [BUGFIX] Show reasons why files are not publishable in the filelist --- Resources/Private/Language/de.locallang.xlf | 4 + Resources/Private/Language/locallang.xlf | 3 + .../Partials/File/DirtyPropertiesList.html | 77 ++++++++++++++++--- Resources/Private/Partials/File/FileList.html | 44 +++++++---- .../Private/Partials/File/FolderList.html | 2 +- 5 files changed, 104 insertions(+), 26 deletions(-) diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 2dc7b5ad8..e21be6339 100755 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -91,6 +91,10 @@ Publish Publizieren + + Not publishable + Nicht Veröffentlichbar + Publish this page Diese Seite publizieren diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index f4caad7b7..cb21e09aa 100755 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -69,6 +69,9 @@ Publish + + Not publishable + Publish this page diff --git a/Resources/Private/Partials/File/DirtyPropertiesList.html b/Resources/Private/Partials/File/DirtyPropertiesList.html index 51cd73cd7..33a9130da 100755 --- a/Resources/Private/Partials/File/DirtyPropertiesList.html +++ b/Resources/Private/Partials/File/DirtyPropertiesList.html @@ -2,15 +2,74 @@ xmlns:publish="http://typo3.org/ns/In2code/In2publishCore/ViewHelpers" data-namespace-typo3-fluid="true" > - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
    • {reason}
    • +
      +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + {stagingLevel}Props diff --git a/Resources/Private/Partials/File/FileList.html b/Resources/Private/Partials/File/FileList.html index 777e4e3e5..4fa18de54 100755 --- a/Resources/Private/Partials/File/FileList.html +++ b/Resources/Private/Partials/File/FileList.html @@ -110,22 +110,34 @@ - - - - - - - + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Partials/File/FolderList.html b/Resources/Private/Partials/File/FolderList.html index fa74d5c12..83520e43c 100755 --- a/Resources/Private/Partials/File/FolderList.html +++ b/Resources/Private/Partials/File/FolderList.html @@ -37,7 +37,7 @@ }" > - + From 51410914ed91d1ce41a1375301363cda980d95b4 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 11:19:44 +0100 Subject: [PATCH 105/113] [DOCS] Add instruction to quote asterisks in YAML for admins --- .../60149-Change-ReplaceSpycWithSymfonyYaml.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md index 66a2abbf4..397149043 100644 --- a/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md +++ b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md @@ -25,6 +25,7 @@ Possibly all, probably only those who do not have the Content Publisher Enterpri 1. Remove the "end of directives marker" `---` from any Content Publisher configuration YAML file. 2. Replace block collections with arrays (see Example #1 Replace block collections with arrays) +2. Quote all asterisks (see Example #2 Quote asterisk) ## Examples @@ -47,3 +48,15 @@ After definition: 2: [3,4,5,6,7,8] ``` + +### #2 Quote asterisk +Before: +```yaml + workflowTreeColors: + groups: * +``` +After +```yaml + workflowTreeColors: + groups: '*' +``` From 75e1251cfbb834f61826bbefd72ee3b522182bb9 Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 14:17:05 +0100 Subject: [PATCH 106/113] [TEST] Fix FileSystemPublisherTests --- .../AbstractFilesystemPublisherTest.php | 18 --- .../IsEqualIgnoringRequestToken.php | 114 ++++++++++++++++++ .../Publisher/FileRecordPublisherTest.php | 36 +++--- .../Publisher/FolderRecordPublisherTest.php | 14 +-- .../Publisher/PublisherCollectionTest.php | 4 +- .../Core/Record/Factory/RecordFactoryTest.php | 4 + 6 files changed, 143 insertions(+), 47 deletions(-) delete mode 100644 Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php create mode 100644 Tests/Unit/Component/Core/Publisher/Constraint/IsEqualIgnoringRequestToken.php diff --git a/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php b/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php deleted file mode 100644 index b605a70f7..000000000 --- a/Tests/Unit/Component/Core/Publisher/AbstractFilesystemPublisherTest.php +++ /dev/null @@ -1,18 +0,0 @@ -setAccessible(true); - return $reflectionProperty->getValue($filesystemRecordPublisher); - } -} diff --git a/Tests/Unit/Component/Core/Publisher/Constraint/IsEqualIgnoringRequestToken.php b/Tests/Unit/Component/Core/Publisher/Constraint/IsEqualIgnoringRequestToken.php new file mode 100644 index 000000000..8c7420001 --- /dev/null +++ b/Tests/Unit/Component/Core/Publisher/Constraint/IsEqualIgnoringRequestToken.php @@ -0,0 +1,114 @@ +value = $value; + $this->delta = $delta; + $this->canonicalize = $canonicalize; + $this->ignoreCase = $ignoreCase; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + unset($other[0]['request_token']); + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other, + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + $this->canonicalize, + $this->ignoreCase, + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f, + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + $delta = ''; + + if (is_string($this->value)) { + if (str_contains($this->value, "\n")) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value, + ); + } + + if ($this->delta != 0) { + $delta = sprintf( + ' with delta <%F>', + $this->delta, + ); + } + + return sprintf( + 'is equal to %s%s', + Exporter::export($this->value, $exportObjects), + $delta, + ); + } +} diff --git a/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php b/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php index 83a639aad..305437956 100644 --- a/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php +++ b/Tests/Unit/Component/Core/Publisher/FileRecordPublisherTest.php @@ -7,6 +7,7 @@ use In2code\In2publishCore\Component\Core\Publisher\FileRecordPublisher; use In2code\In2publishCore\Component\Core\Publisher\Instruction\AddFileInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFileInstruction; +use In2code\In2publishCore\Component\Core\Publisher\Instruction\DeleteFolderInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\MoveFileInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceAndRenameFileInstruction; use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceFileInstruction; @@ -16,6 +17,8 @@ use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse; use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitter; +use In2code\In2publishCore\Tests\Unit\Component\Core\Publisher\Constraint\IsEqualIgnoringRequestToken; +use In2code\In2publishCore\Tests\UnitTestCase; use TYPO3\CMS\Core\Database\Connection; use function json_encode; @@ -28,7 +31,7 @@ /** * @coversDefaultClass \In2code\In2publishCore\Component\Core\Publisher\FileRecordPublisher */ -class FileRecordPublisherTest extends AbstractFilesystemPublisherTest +class FileRecordPublisherTest extends UnitTestCase { /** * @covers ::__construct @@ -58,9 +61,8 @@ public function testPublishDeletesRemovedFile() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => DeleteFileInstruction::class, @@ -69,7 +71,7 @@ public function testPublishDeletesRemovedFile() 'fileIdentifier' => '/foo/bar', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -92,9 +94,8 @@ public function testPublishTransmitsAddedRecord() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => AddFileInstruction::class, @@ -104,7 +105,7 @@ public function testPublishTransmitsAddedRecord() 'foreignTargetFileIdentifier' => '/foo/bar', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -135,9 +136,8 @@ public function testPublishTransmitsRenamedRecord() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => MoveFileInstruction::class, @@ -147,7 +147,7 @@ public function testPublishTransmitsRenamedRecord() 'newFileIdentifier' => '/foo/bar2', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -170,9 +170,8 @@ public function testPublishTransmitsMovedRecord() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => MoveFileInstruction::class, @@ -182,7 +181,7 @@ public function testPublishTransmitsMovedRecord() 'newFileIdentifier' => '/foo/foo', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -205,9 +204,8 @@ public function testPublishTransmitsReplacedFileWithNewNameRecord() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => ReplaceAndRenameFileInstruction::class, @@ -218,7 +216,7 @@ public function testPublishTransmitsReplacedFileWithNewNameRecord() 'foreignTemporaryFileIdentifier' => '/var/tmp/transient/sadsdas.tmp', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -241,9 +239,8 @@ public function testPublishTransmitsReplacedFileWithSameNameRecord() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($fileRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => ReplaceFileInstruction::class, @@ -253,7 +250,7 @@ public function testPublishTransmitsReplacedFileWithSameNameRecord() 'foreignTemporaryFileIdentifier' => '/var/tmp/transient/sadsdas.tmp', ]), ], - ], + ]), ); $fileRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -285,7 +282,6 @@ protected function createFileInfo( protected function createFileRecordPublisher(string $temporaryFileIdentifier = '_undefined_'): FileRecordPublisher { $fileRecordPublisher = $this->createPartialMock(FileRecordPublisher::class, ['transmitTemporaryFile']); - $fileRecordPublisher->__construct(); $remoteCommandResponse = $this->createMock(RemoteCommandResponse::class); $remoteCommandResponse->method('isSuccessful')->willReturn(true); $remoteCommandDispatcher = $this->createMock(RemoteCommandDispatcher::class); diff --git a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php index 848796e2d..490989713 100644 --- a/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php +++ b/Tests/Unit/Component/Core/Publisher/FolderRecordPublisherTest.php @@ -13,6 +13,8 @@ use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse; +use In2code\In2publishCore\Tests\Unit\Component\Core\Publisher\Constraint\IsEqualIgnoringRequestToken; +use In2code\In2publishCore\Tests\UnitTestCase; use TYPO3\CMS\Core\Database\Connection; use function json_encode; @@ -20,7 +22,7 @@ /** * @coversDefaultClass \In2code\In2publishCore\Component\Core\Publisher\FolderRecordPublisher */ -class FolderRecordPublisherTest extends AbstractFilesystemPublisherTest +class FolderRecordPublisherTest extends UnitTestCase { /** * @covers ::__construct @@ -55,9 +57,8 @@ public function testPublishRemovesDeletedFolder() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($folderRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => DeleteFolderInstruction::class, @@ -66,7 +67,7 @@ public function testPublishRemovesDeletedFolder() 'folderIdentifier' => '/foo/bar', ]), ], - ], + ]), ); $folderRecordPublisher->injectForeignDatabase($foreignDatabase); @@ -89,9 +90,8 @@ public function testPublishAddsAddedFolder() $foreignDatabase = $this->createMock(Connection::class); $foreignDatabase->expects($this->once())->method('bulkInsert')->with( 'tx_in2publishcore_filepublisher_instruction', - [ + new IsEqualIgnoringRequestToken([ [ - 'request_token' => $this->getRequestTokenFromPublisher($folderRecordPublisher), 'crdate' => $GLOBALS['EXEC_TIME'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'instruction' => AddFolderInstruction::class, @@ -100,7 +100,7 @@ public function testPublishAddsAddedFolder() 'folderIdentifier' => '/foo/bar', ]), ], - ], + ]), ); $folderRecordPublisher->injectForeignDatabase($foreignDatabase); diff --git a/Tests/Unit/Component/Core/Publisher/PublisherCollectionTest.php b/Tests/Unit/Component/Core/Publisher/PublisherCollectionTest.php index 354cfd290..8b1b590f6 100644 --- a/Tests/Unit/Component/Core/Publisher/PublisherCollectionTest.php +++ b/Tests/Unit/Component/Core/Publisher/PublisherCollectionTest.php @@ -48,7 +48,7 @@ public function testAddPublisherAddsPublisher() /** * @covers ::addPublisher */ - public function testAddPublisherSortsPublishersCorrectly() + public function testAddPublisherSortsPublishersCorrectly(): void { $publisherCollection = new PublisherCollection(); $reflectionPropertyPublishers = new ReflectionProperty($publisherCollection, 'publishers'); @@ -56,7 +56,7 @@ public function testAddPublisherSortsPublishersCorrectly() $standardPublisher = $this->createMock(Publisher::class); $transactionalPublisher = $this->createMock(DatabaseRecordPublisher::class); - $finishablePublisher = $this->createMock(FileRecordPublisher::class); + $finishablePublisher = $this->createMock(FinishablePublisher::class); $publisherCollection->addPublisher($standardPublisher); $publisherCollection->addPublisher($transactionalPublisher); diff --git a/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php b/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php index 615496913..5ab774d36 100644 --- a/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php +++ b/Tests/Unit/Component/Core/Record/Factory/RecordFactoryTest.php @@ -168,6 +168,10 @@ public function testFileRecordIsCreatedAndAddedToRecordIndex(): void $eventDispatcher = $this->createMock(EventDispatcher::class); $eventDispatcher->expects($this->exactly(2))->method('dispatch'); + $ignoredFieldsService = $this->createMock(IgnoredFieldsService::class); + $ignoredFieldsService->method('getIgnoredFields')->willReturn([]); + + $recordFactory->injectIgnoredFieldsService($ignoredFieldsService); $recordFactory->injectEventDispatcher($eventDispatcher); $recordFactory->injectRecordIndex($recordIndex); From 0265012a4344a5511c0054b1782cdd982fc645ea Mon Sep 17 00:00:00 2001 From: Oliver Eglseder Date: Thu, 30 Nov 2023 14:17:37 +0100 Subject: [PATCH 107/113] [BUGFIX] Revert making file publisher reversible, they aren't! --- .../Publisher/AbstractFilesystemPublisher.php | 9 +------- .../Core/Publisher/FileRecordPublisher.php | 23 ------------------- .../Core/Publisher/FinishablePublisher.php | 2 +- .../Core/Publisher/PublisherCollection.php | 10 ++++++++ 4 files changed, 12 insertions(+), 32 deletions(-) diff --git a/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php index efec941dc..bd4100733 100644 --- a/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php +++ b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php @@ -17,7 +17,7 @@ use const JSON_THROW_ON_ERROR; -abstract class AbstractFilesystemPublisher implements Publisher, TransactionalPublisher, ReversiblePublisher +abstract class AbstractFilesystemPublisher implements Publisher, TransactionalPublisher { use ForeignDatabaseReconnectedInjection; use RemoteCommandDispatcherInjection; @@ -38,13 +38,6 @@ public function cancel(): void } } - public function reverse(): void - { - if ($this->foreignDatabase->isTransactionActive()) { - $this->foreignDatabase->rollBack(); - } - } - public function finish(): void { if (empty($this->instructions)) { diff --git a/Classes/Component/Core/Publisher/FileRecordPublisher.php b/Classes/Component/Core/Publisher/FileRecordPublisher.php index ae4d99aec..6eeae6aea 100644 --- a/Classes/Component/Core/Publisher/FileRecordPublisher.php +++ b/Classes/Component/Core/Publisher/FileRecordPublisher.php @@ -12,13 +12,10 @@ use In2code\In2publishCore\Component\Core\Publisher\Instruction\ReplaceFileInstruction; use In2code\In2publishCore\Component\Core\Record\Model\FileRecord; use In2code\In2publishCore\Component\Core\Record\Model\Record; -use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcher; use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcherInjection; -use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandRequest; use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitterInjection; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; -use TYPO3\CMS\Core\Utility\GeneralUtility; class FileRecordPublisher extends AbstractFilesystemPublisher implements LoggerAwareInterface { @@ -115,24 +112,4 @@ protected function transmitTemporaryFile(Record $record): string $localFile = $driver->getFileForLocalProcessing($identifier); return $this->assetTransmitter->transmitTemporaryFile($localFile); } - - /** - * Only a partial reverse. Will not un-publish files that have already been processed on foreign. - */ - public function reverse(): void - { - $options = []; - $options[] = '-f'; - foreach ($this->transmittedFiles as $transmittedFile) { - $options[] = $transmittedFile; - } - $request = new RemoteCommandRequest('rm', [], $options); - $response = $this->remoteCommandDispatcher->dispatch($request); - if ($response->isSuccessful()) { - $this->logger->alert( - 'Removing temporary files during rollback failed', - ['output' => $response->getOutput(), 'error' => $response->getErrors()], - ); - } - } } diff --git a/Classes/Component/Core/Publisher/FinishablePublisher.php b/Classes/Component/Core/Publisher/FinishablePublisher.php index cf154b0fc..fd1833af2 100644 --- a/Classes/Component/Core/Publisher/FinishablePublisher.php +++ b/Classes/Component/Core/Publisher/FinishablePublisher.php @@ -4,7 +4,7 @@ namespace In2code\In2publishCore\Component\Core\Publisher; -interface FinishablePublisher +interface FinishablePublisher extends Publisher { public function finish(): void; } diff --git a/Classes/Component/Core/Publisher/PublisherCollection.php b/Classes/Component/Core/Publisher/PublisherCollection.php index 2e903cdee..c640fc8a6 100644 --- a/Classes/Component/Core/Publisher/PublisherCollection.php +++ b/Classes/Component/Core/Publisher/PublisherCollection.php @@ -46,6 +46,16 @@ public function addPublisher(Publisher $publisher): void krsort($this->publishers); } + public function canPublish(Record $record): bool + { + foreach ($this->publishers as $publisher) { + if ($publisher->canPublish($record)) { + return true; + } + } + return false; + } + public function publish(Record $record): void { foreach ($this->publishers as $publisher) { From 37dc693a91342b0202689b76a436fc0834d16711 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 10:00:34 +0100 Subject: [PATCH 108/113] [DOCS] Add upgrading information for version 12.3.0 --- UPGRADING.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 23e1ea70d..9b1892689 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,3 +1,24 @@ +# v12.2 to v12.3 + +## For admins + +### Change TypoScript Paths For Templates +TYPO3 v12 compatibility requires changes in the TypoScript configuration. +The TypoScript path `module.tx_in2publish.view` can no longer be used to overwrite templates. +Please read [60149-Change-TypoScriptPathsForTemplates.md] for details on how to adjust your TypoScript configuration. + +### Change .yml configuration files +Up to version 12.2, the Content Publisher used the YAML parser [Spyc] for parsing the configuration files. Since TYPO3 +now ships with a YAML parser, we now use this parser to reduce the code we have to maintain. +This change has some impact on the configuration files. +Please read [60149-Change-ReplaceSpycWithSymfonyYaml.md] for details on how to adjust your configuration files. + + +## For developers + +The core events `PublishingOfOneRecordBegan` and `PublishingOfOneRecordEnded` were replaced. Please +read [54638-Deprecation-PublishingOfOneRecordBegan_Ended.md](Documentation/Developers/Changelog/54638-Deprecation-PublishingOfOneRecordBegan_Ended.md). + # v12.1 to v12.2 ## For developers From 1b09d70ac799a7a2c0d913cb928505997a699879 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 10:44:55 +0100 Subject: [PATCH 109/113] [DOCS] Remove section about Typoscript paths for templates in UPGRADING.md --- UPGRADING.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 9b1892689..47e134d9f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -2,11 +2,6 @@ ## For admins -### Change TypoScript Paths For Templates -TYPO3 v12 compatibility requires changes in the TypoScript configuration. -The TypoScript path `module.tx_in2publish.view` can no longer be used to overwrite templates. -Please read [60149-Change-TypoScriptPathsForTemplates.md] for details on how to adjust your TypoScript configuration. - ### Change .yml configuration files Up to version 12.2, the Content Publisher used the YAML parser [Spyc] for parsing the configuration files. Since TYPO3 now ships with a YAML parser, we now use this parser to reduce the code we have to maintain. From 81f4711e51cf5aa966937e26c6fc22f1669144c8 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 10:51:36 +0100 Subject: [PATCH 110/113] [DOCS] Add known issue about missing file links --- Documentation/KnownIssues.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/KnownIssues.md b/Documentation/KnownIssues.md index 209ebdb0c..3bafe073b 100644 --- a/Documentation/KnownIssues.md +++ b/Documentation/KnownIssues.md @@ -1,5 +1,10 @@ # Known Issues +## File Preview URLs in Publish Files Module are not shown when using EXT:fal_securedownload + +File Preview URLs are not rendered in the Publish Files Module, if EXT:fal_securedownload is installed. +However, the functionality of EXT:fal_securedownload and file publishing is not affected. + ## File Preview URLs in Publish Files Module broken for non-public file storages File Preview URLs rendered for files on Foreign are broken, if the file storage is not marked as public. From ae85d0490198f44b9754a8c996503221b4302235 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 11:03:10 +0100 Subject: [PATCH 111/113] [CLEANUP] Remove redundant PHP version constraints --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 94e31febd..2337b3ae5 100755 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "type": "typo3-cms-extension", "license": "GPL-3.0-or-later", "require": { - "php": "^7.4 || ^8.0 || ^8.1", + "php": "^7.4 || ^8.0", "ext-json": "*", "ext-pdo": "*", "ext-zip": "*", From 88a8596b3e374f20ce56b929ffc387992ce666e3 Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 10:24:27 +0100 Subject: [PATCH 112/113] [META] Set the EM conf version number to 12.3.0 --- ext_emconf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext_emconf.php b/ext_emconf.php index e56bb7047..526650d4b 100755 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -9,7 +9,7 @@ 'title' => 'in2publish Core', 'description' => 'Content publishing extension to connect stage and production server', 'category' => 'plugin', - 'version' => '12.2.0', + 'version' => '12.3.0', 'state' => 'stable', 'clearCacheOnLoad' => true, 'author' => 'Alex Kellner, Oliver Eglseder, Thomas Scheibitz, Stefan Busemann', From 9315882e3ed91b1eb279c97129cdc207b01fcc7e Mon Sep 17 00:00:00 2001 From: Christine Zoglmeier Date: Thu, 30 Nov 2023 14:32:17 +0100 Subject: [PATCH 113/113] [DOCS] Update Changelog.md --- CHANGELOG.md | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 590e46483..42dab0d2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,122 @@ # In2publish Core Change Log +12.3.0: + +- [DOCS] Update Changelog.md +- [META] Set the EM conf version number to 12.3.0 +- [CLEANUP] Remove redundant PHP version constraints +- [DOCS] Add known issue about missing file links +- [DOCS] Remove section about Typoscript paths for templates in UPGRADING.md +- [DOCS] Add upgrading information for version 12.3.0 +- [BUGFIX] Revert making file publisher reversible, they aren't! +- [TEST] Fix FileSystemPublisherTests +- [DOCS] Add instruction to quote asterisks in YAML for admins +- [BUGFIX] Show reasons why files are not publishable in the filelist +- [FEATURE] Adds another test return to get more specific testresult +- [BUGFIX] Increase max depth when dumping compatible TCA +- [FEATURE] Add LinkProcessor for TYPO3 v12 +- [DOCS] Add admin changelog for YAML +- [BUGFIX] Add PreProcessor for TCA type file +- [BUGFIX] Corrects Loading of Middleware +- [DOCS] Adjust Feature List +- [BUGFIX] Restore the confirmation modal for file and folder publishing +- [BUGFIX] Ignore _file.publicUrl because it will always be different and is a computed property +- [BUGFIX] Fix ignoring ctrl.versioningWS +- [BUGFIX] Try to build absolute URLs to files for the preview buttons in the filelist module +- [BUGFIX] Redirect to the previous page after publishing, not the published page +- [BUGFIX] Restore context menu publishing for TYPO3 v12 +- [BUGFIX] Validate the resolver cache +- [BUGFIX] Query sys_file_reference.table_local only in TYPO3 v11 as it was removed +- [BUGFIX] Use middleware to inject the loading overlay, split JS into specific modules +- [BUGFIX] Allow passing nodes directly to JS overlay and modal functions +- [BUGFIX] Use Connection::PARAM_STR_ARRAY instead of ArrayParameterType +- [REFACTOR] Extract $GLOBALS access to method +- [BUGFIX] Overwrite toString for PageTreeRootRecord to return the "sitename" +- [BUGFIX] Make PublisherService::publishRecordTree internal to force everyone to use the PublishingContext +- [BUGFIX] Correctly exclude folders and files for the recursiveState of Folder Records +- [BUGFIX] Resolve storage for StorageRootFolderRecords +- [BUGFIX] Access correct property to set the name attribute of folders +- [REFACTOR] Rename ResolverService::getResolversForTable to getResolversForClassification +- [BUGFIX] Introduce a special class for folders which are file storage roots and display the correct icon +- [FEATURE] Add some Injection Traits +- [BUGFIX] Close modals in TYPO3 v12 via new API +- [CLEANUP] Remove unused imports from FileController +- [BUGFIX] Fix multiple errors that occur when calling publishRecordTree more than once +- [FEATURE] Change Order of Modules in Publish Tools +- [CODESTYLE] Add Annotations for Exceptions +- [BUGFIX] Fix Database Compare Table View +- [CLEANUP] Remove Logs Integration +- [BUGFIX] Correct Caption of english Labels +- [FEATURE] Moved all Labels from Publish Tools Module to locallang_mod4.xlf +- [WIP] Changed all Templates of Publish Tools Module +- Revert "[DOC] Add documentation for changed ext_typoscript_template suffix" +- [BUGFIX] Fetch folder records with demand/resolver structure +- [DOC] Add documentation for changed ext_typoscript_template suffix +- [BUGFIX] Corrects styling of redirects module +- [BUGFIX] Add Padding at the Top of the module +- [BUGFIX] Jumpmenu Label is now rendered inline +- [BUGFIX] Change order of flashmessage container +- [REFACTOR] Remove outdated overlay div +- [REFACTOR] Replace version_compare calls with TYPO3_V11 constant +- [BUGFIX] Define (namespaced) constants for TYPO3 version for easier up/down-compatibility +- [BUGFIX] Tighten Colors between v11 & v12 +- [BUGFIX] Show colors of badges in file module again +- [REFACTOR] Removes deprecated QueryBuilder methods +- [BUGFIX] Removes deprecated getSchemamanager call +- [BUGFIX] Removes check for directory typo3conf in TYPO3v12 +- [REFACTOR] Use be.infobox viewhelper instead of own markup +- [REFACTOR] Simplifies the generation of an controller alias +- [FEATURE] Changes AdminButton to show primary styling correct +- [BUGFIX] Remove deprecations from RegistryController +- [BUGFIX] Remove deprecations from LetterBox +- [REFACTOR] Remove deprecations fomr LogsExporter +- [REFACTOR] Remove deprecated execute from GarbageCollectorTest +- [BUGFIX] Return ResponseInterface in publishFile and publishFolder action +- [REFACTOR] Removes unnecessary Event & Middleware +- [BUGFIX] Add correct hrefs to Buttons on Publish Tools +- [FEATURE] Register Publish Tools Menu in Modules.php +- [REFACTOR] Module Registration for Publish Tools Module refactored +- [REFACTOR] Changes backend module registration for m1, m3, m5 +- [BUGFIX] Make the PageTsProvider a Singleton to unlock it globally +- [BUGFIX] Return the RedirectResponse in TYPO3 v12 +- [BUGFIX] Rename ext_typoscript_setup suffix to typoscript +- [CLEANUP] Remove superfluous empty lines from ext_tables.php +- [BUGFIX] Enable autowiring of the dynamic PageTypeService +- [BUGFIX] Allow deserialization of TYPO3 v12 Site objects +- [BUGFIX] Create a TYPO3 version aware service to replace TcaService::getTablesAllowedOnPage +- [BUGFIX] Overwrite callActionMethod instead of initializeView to prevent version issues +- [BUGFIX] Implement TYPO3 version specific code to translate the label of the Publish Overview Module shortcut button +- [BUGFIX] Use withRequest to alter immutable request objects +- [BUGFIX] Use the objects view property instead of initializeView arguments +- [REFACTOR] Changes Icon from Tools Module to IconFactory +- [REFACTOR] Change compare of version +- [BUGFIX] Removes trailing slash in Module Configuration +- [REFACTOR] Changes backend module registration for m1, m3, m5 +- [BUGFIX] Do not register the BackendRouteInitialization XCLASS in TYPO3 v12 +- [BUGFIX] Replace deprecated EventManager::getListeners with getAllListeners +- [TASK] Remove deprecated TYPO3 constants +- [BUGFIX] Set correct narrowed return type hint for ConnectionFactory +- [BUGFIX] Handle constructor differences in PublishItemProvider between t3v11 and t3v12 +- [FEATURE] Cache the TcaPreProcessing result +- [CLEANUP] Remove unused import/empty line +- [BUGFIX] Reduce resolver meta info to required keys class and args +- [BUGFIX] Replace Spyc with symfony/yaml +- [TASK] Update composer requirements +- [TASK] Add new branch aliases for develop branch +- [TASK] Allow PHP8.1 as requirement and remove outdated branch-aliases +- [BUGFIX] Inherit the base Exception from in2publish_core, not in2publish +- [BUGFIX] Show debugged queries in separate tab for each request +- [BUGFIX] Show the sum of query duration when debugging queries +- [BUGFIX] Sort grouped queries by amount of calls +- [REFACTOR] Use the CachedRuntimeCache instead of the custom implementation in ForeignSiteFinder +- [BUGFIX] Use runtime cache to prevent multiple cache hits +- [BUGFIX] Increment logged SQL queries statically +- [TESTS] Update unit tests for PublishFileInstructions +- [BUGFIX] Disable the function bar if publishing is not available +- [BUGFIX] Ignore table tx_in2publishcore_filepublisher_instruction by default +- [BUGFIX] Require table tx_in2publishcore_filepublisher_instruction instead of _task +- [DOCS] Update changelog + 12.2.0: - [META] Set the EM conf version number to 12.2.0