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/.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/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
diff --git a/Classes/Backend/Button/ModuleShortcutButton.php b/Classes/Backend/Button/ModuleShortcutButton.php
index ee28ee610..d4a8d01ca 100644
--- a/Classes/Backend/Button/ModuleShortcutButton.php
+++ b/Classes/Backend/Button/ModuleShortcutButton.php
@@ -30,6 +30,7 @@
*/
use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Module\ExtbaseModule;
use TYPO3\CMS\Backend\Template\Components\Buttons\Action\ShortcutButton;
use TYPO3\CMS\Core\Routing\Route;
use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters;
@@ -37,6 +38,8 @@
use function ucfirst;
+use const In2code\In2publishCore\TYPO3_V11;
+
class ModuleShortcutButton extends ShortcutButton
{
public function setRequest(ServerRequestInterface $request): void
@@ -44,9 +47,19 @@ 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');
+
+ if (TYPO3_V11) {
+ $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) {
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..5c8f3ca8d
--- /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/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/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/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/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;
+ }
+}
diff --git a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php
index 581b86b27..5118194ce 100644
--- a/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php
+++ b/Classes/Component/ConfigContainer/Definer/In2publishCoreDefiner.php
@@ -52,9 +52,9 @@ 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',
+ 'tx_in2publishcore_filepublisher_instruction',
];
public function getLocalDefinition(): NodeCollection
@@ -117,6 +117,11 @@ public function getLocalDefinition(): NodeCollection
'transOrigDiffSourceField',
],
],
+ '_file' => [
+ 'fields' => [
+ 'publicUrl',
+ ],
+ ],
'pages' => [
'fields' => [
'perms_userid',
@@ -148,12 +153,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/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/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/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/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/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 74%
rename from Classes/Component/Core/FileHandling/Service/FalDriverService.php
rename to Classes/Component/Core/DemandResolver/Filesystem/Service/FalDriverService.php
index 30b19953b..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;
@@ -42,7 +40,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);
}
@@ -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->execute();
- $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..d7ec535c3
--- /dev/null
+++ b/Classes/Component/Core/DemandResolver/Filesystem/Service/FileInfoService.php
@@ -0,0 +1,53 @@
+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'] = 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/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/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 a145b4a15..d485b07a8 100644
--- a/Classes/Component/Core/FileHandling/DefaultFalFinder.php
+++ b/Classes/Component/Core/FileHandling/DefaultFalFinder.php
@@ -31,41 +31,42 @@
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;
+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;
+ use DemandBuilderInjection;
/**
* Creates a Record instance representing the current chosen folder in the
@@ -97,221 +98,51 @@ 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);
+ $demands = $this->demandBuilder->buildDemandForRecords($recordCollection);
+ $recordCollection = new RecordCollection();
+ $this->demandResolver->resolveDemand($demands, $recordCollection);
+
+ $folderRecord = $recordTree->getChild(FolderRecord::CLASSIFICATION, $combinedIdentifier);
if (null === $folderRecord) {
- return new RecordTree();
+ throw new FolderDoesNotExistOnBothSidesException($combinedIdentifier, $folder->getCombinedIdentifier());
}
if ($onlyRoot) {
- return new RecordTree([$folderRecord]);
- }
-
- $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);
+ $this->eventDispatcher->dispatch(new RecordRelationsWereResolved($recordTree));
+ return $recordTree;
}
- $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 +152,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 +174,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 +192,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 +215,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/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..98013a9d3
--- /dev/null
+++ b/Classes/Component/Core/PreProcessing/CachedTcaPreprocessingService.php
@@ -0,0 +1,80 @@
+
+ */
+ 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');
+ if ($this->isCacheValid($cacheEntry['compatibleTca'])) {
+ $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);
+ }
+
+ 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;
+ }
+}
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;
+ }
+}
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;
+ }
+}
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/Publisher/AbstractFilesystemPublisher.php b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php
index e2a781fd4..bd4100733 100644
--- a/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php
+++ b/Classes/Component/Core/Publisher/AbstractFilesystemPublisher.php
@@ -11,47 +11,68 @@
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
{
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 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 d3f612043..f4880efa9 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;
@@ -13,6 +13,9 @@
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;
class FalPublisherCommand extends Command
@@ -28,18 +31,24 @@ 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)));
- $result = $query->execute();
+ ->where(
+ $query->expr()->in(
+ 'request_token',
+ $query->createNamedParameter($requestTokens, Connection::PARAM_STR_ARRAY)
+ )
+ );
+ $result = $query->executeQuery();
$rows = $result->fetchAllAssociative();
/** @var array $instructions */
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 d42ebc936..6eeae6aea 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;
@@ -12,12 +12,20 @@
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\RemoteCommandDispatcherInjection;
use In2code\In2publishCore\Component\TemporaryAssetTransmission\AssetTransmitterInjection;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
-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 +80,7 @@ public function publish(Record $record): void
);
} else {
$transmitTemporaryFile = $this->transmitTemporaryFile($record);
+ $this->transmittedFiles[] = $transmitTemporaryFile;
$instruction = new ReplaceAndRenameFileInstruction(
$storage,
$foreignFileIdentifier,
@@ -81,6 +90,7 @@ public function publish(Record $record): void
}
} else {
$transmitTemporaryFile = $this->transmitTemporaryFile($record);
+ $this->transmittedFiles[] = $transmitTemporaryFile;
$instruction = new ReplaceFileInstruction(
$storage,
$localFileIdentifier,
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/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/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) {
diff --git a/Classes/Component/Core/Publisher/PublisherService.php b/Classes/Component/Core/Publisher/PublisherService.php
index 4c7b1c1f2..68494e6ea 100644
--- a/Classes/Component/Core/Publisher/PublisherService.php
+++ b/Classes/Component/Core/Publisher/PublisherService.php
@@ -7,7 +7,7 @@
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;
use In2code\In2publishCore\Event\RecordWasPublished;
@@ -16,12 +16,21 @@
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;
- protected TaskExecutionService $taskExecutionService;
+ /** @var array> */
+ protected array $visitedRecords = [];
public function __construct()
{
@@ -29,36 +38,46 @@ 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);
}
+ /**
+ * @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();
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 +98,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 +125,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/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/Component/Core/Record/Factory/RecordFactory.php b/Classes/Component/Core/Record/Factory/RecordFactory.php
index 6e99513ec..1bc500e86 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;
@@ -97,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;
}
@@ -105,12 +107,13 @@ 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
+ {
+ 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/AbstractRecord.php b/Classes/Component/Core/Record/Model/AbstractRecord.php
index 259de68fc..7967cd351 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;
@@ -15,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;
@@ -33,7 +37,6 @@ abstract class AbstractRecord implements Record
* @var array
*/
protected array $dependencies = [];
- protected bool $hasBeenAskedForRecursiveState = false;
/**
* @var array>
*/
@@ -47,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 = [];
@@ -162,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;
@@ -220,24 +233,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
@@ -257,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;
+ }
}
diff --git a/Classes/Component/Core/Record/Model/FolderRecord.php b/Classes/Component/Core/Record/Model/FolderRecord.php
index b39737e74..afe3ca872 100644
--- a/Classes/Component/Core/Record/Model/FolderRecord.php
+++ b/Classes/Component/Core/Record/Model/FolderRecord.php
@@ -4,16 +4,17 @@
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;
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 +26,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 +36,31 @@ 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;
+ }
+ $children = $this->getChildren();
+ unset($children[FolderRecord::CLASSIFICATION], $children[FileRecord::CLASSIFICATION]);
+
+ $stateRecursive = Record::S_UNCHANGED;
+ $recordIterator = new RecordIterator();
+ 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;
+ }
}
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'];
+ }
}
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 @@
+children[$table][$id] ?? null;
+ return $this->children[$classification][$id] ?? null;
}
public function getCurrentPage(): ?Record
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/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/Core/Resolver/AbstractResolver.php b/Classes/Component/Core/Resolver/AbstractResolver.php
index 790ba5fe2..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()
{
@@ -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;
}
}
}
diff --git a/Classes/Component/Core/Resolver/FlexResolver.php b/Classes/Component/Core/Resolver/FlexResolver.php
index ea22fd276..e7ec8ac5a 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;
@@ -87,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) {
@@ -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/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/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..848542097 100644
--- a/Classes/Component/Core/Service/ResolverService.php
+++ b/Classes/Component/Core/Service/ResolverService.php
@@ -4,30 +4,44 @@
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;
+use In2code\In2publishCore\Component\Core\Resolver\StaticResolver;
class ResolverService
{
use RelevantTablesServiceInjection;
- use TcaPreProcessingServiceInjection;
+ use CachedTcaPreProcessingServiceInjection;
/**
* @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
{
- $compatibleTcaParts = $this->tcaPreProcessingService->getCompatibleTcaParts();
- foreach ($compatibleTcaParts as $table => $properties) {
+ $compatibleTcaParts = $this->cachedTcaPreProcessingService->getCompatibleTcaParts();
+ 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 +50,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/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/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/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/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/Controller/FileController.php b/Classes/Controller/FileController.php
index 1c2ea7cc2..8a0f9e61e 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;
@@ -47,19 +48,13 @@
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;
-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;
@@ -88,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',
@@ -101,14 +93,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 = [];
@@ -131,21 +120,23 @@ 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());
}
/**
* @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): void
+ public function publishFolderAction(string $combinedIdentifier, bool $skipNotification = false): ResponseInterface
{
- $recordTree = $this->tryToGetFolderInstance($combinedIdentifier, true);
+ $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]),
@@ -166,20 +157,20 @@ public function publishFolderAction(string $combinedIdentifier, bool $skipNotifi
}
}
- $this->redirect('index');
+ return $this->redirect('index');
}
/**
* @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): void
+ 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(
@@ -216,7 +207,7 @@ public function publishFileAction(string $combinedIdentifier, bool $skipNotifica
}
}
- $this->redirect('index');
+ return $this->redirect('index');
}
/**
@@ -235,15 +226,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/Controller/RecordController.php b/Classes/Controller/RecordController.php
index fc428c13b..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(
@@ -109,17 +106,18 @@ 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->setArgument('pageRecursionLimit', $data['pageRecursionLimit'] ?? 1);
+ $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');
@@ -179,20 +177,20 @@ public function initializePublishRecordAction(): void
}
}
- public function publishRecordAction(int $id): void
+ 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) {
- $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 +207,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 +229,17 @@ protected function addFlashMessagesAndRedirectToIndex(): void
}
$this->addFlashMessage($message, $title, $severity);
- $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
+ {
+ return $GLOBALS['BE_USER'];
}
}
diff --git a/Classes/Controller/Traits/CommonViewVariables.php b/Classes/Controller/Traits/CommonViewVariables.php
index 3f5a68105..81e95c1ce 100644
--- a/Classes/Controller/Traits/CommonViewVariables.php
+++ b/Classes/Controller/Traits/CommonViewVariables.php
@@ -7,7 +7,8 @@
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;
+use Psr\Http\Message\ResponseInterface;
+use TYPO3\CMS\Extbase\Mvc\RequestInterface;
trait CommonViewVariables
{
@@ -15,10 +16,11 @@ trait CommonViewVariables
use EnvironmentServiceInjection;
use ExtensionServiceInjection;
- protected function initializeView(ViewInterface $view): void
+ protected function callActionMethod(RequestInterface $request): ResponseInterface
{
- $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());
+ return parent::callActionMethod($request);
}
}
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/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;
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/AbstractAdminToolsController.php b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php
new file mode 100644
index 000000000..7fbfd9b10
--- /dev/null
+++ b/Classes/Features/AdminTools/Controller/AbstractAdminToolsController.php
@@ -0,0 +1,62 @@
+
+ *
+ * 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->addInlineLanguageLabelFile(
+ 'EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf',
+ );
+ $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 a08b0bc30..8a6e3b264 100644
--- a/Classes/Features/AdminTools/Controller/LetterboxController.php
+++ b/Classes/Features/AdminTools/Controller/LetterboxController.php
@@ -30,15 +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\Mvc\Exception\StopActionException;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
-class LetterboxController extends ActionController
+class LetterboxController extends AbstractAdminToolsController
{
- use AdminToolsModuleTemplate;
use LetterboxInjection;
public function indexAction(): ResponseInterface
@@ -47,16 +43,14 @@ public function indexAction(): ResponseInterface
return $this->htmlResponse();
}
- /** @throws StopActionException */
- public function flushEnvelopesAction(): void
+ 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',
),
);
- $this->redirect('index');
+ return $this->redirect('index');
}
}
diff --git a/Classes/Features/AdminTools/Controller/RegistryController.php b/Classes/Features/AdminTools/Controller/RegistryController.php
index 1c5dcf108..a1bb7604e 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
@@ -47,10 +44,14 @@ 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');
+ $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/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 4aa8411f7..9bf2d8d14 100644
--- a/Classes/Features/AdminTools/Controller/TcaController.php
+++ b/Classes/Features/AdminTools/Controller/TcaController.php
@@ -29,20 +29,17 @@
* This copyright notice MUST APPEAR in all copies of the script!
*/
-use In2code\In2publishCore\Component\Core\PreProcessing\TcaPreProcessingServiceInjection;
-use In2code\In2publishCore\Features\AdminTools\Controller\Traits\AdminToolsModuleTemplate;
+use In2code\In2publishCore\Component\Core\PreProcessing\CachedTcaPreProcessingServiceInjection;
use Psr\Http\Message\ResponseInterface;
-use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
-class TcaController extends ActionController
+class TcaController extends AbstractAdminToolsController
{
- 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/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..247912ac0 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
@@ -63,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:introduction.help.github_issues'
+ ),
+ LocalizationUtility::translate(
+ 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf:introduction.help.slack_channel'
+ ),
];
$event = new CreatedDefaultHelpLabels($supports);
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);
}
diff --git a/Classes/Features/AdminTools/Service/ToolsRegistry.php b/Classes/Features/AdminTools/Service/ToolsRegistry.php
index 43e298488..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,25 +64,21 @@ 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'];
$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'];
- }
+ $processedTools[$key]['alias'] = ExtensionUtility::resolveControllerAliasFromControllerClassName($controller);
}
}
@@ -90,13 +87,11 @@ public function getEntries(): array
/**
* @throws ClassNotFoundException
+ * @throws ExtensionConfigurationExtensionNotConfiguredException
+ * @throws ExtensionConfigurationPathDoesNotExistException
*/
- 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,24 +108,28 @@ public function processData(): void
}
}
+ return $controllerActions;
+ }
+
+ /**
+ * @throws ClassNotFoundException
+ * @throws ExtensionConfigurationExtensionNotConfiguredException
+ * @throws ExtensionConfigurationPathDoesNotExistException
+ * @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',
- 'icon' => 'EXT:in2publish_core/Resources/Public/Icons/Tools.svg',
- 'labels' => 'LLL:EXT:in2publish_core/Resources/Private/Language/locallang_mod4.xlf',
- ],
- );
+ return $controllerActions;
}
+ /**
+ * @throws ExtensionConfigurationPathDoesNotExistException
+ * @throws ExtensionConfigurationExtensionNotConfiguredException
+ */
protected function evaluateCondition(array $config): bool
{
if (null === $config['condition']) {
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/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php
index 036a9cb60..28bbeabdb 100644
--- a/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php
+++ b/Classes/Features/ContextMenuPublishEntry/ContextMenu/PublishItemProvider.php
@@ -37,6 +37,10 @@
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Utility\GeneralUtility;
+use function func_get_args;
+
+use const In2code\In2publishCore\TYPO3_V11;
+
class PublishItemProvider extends AbstractProvider
{
protected $itemsConfiguration = [
@@ -48,9 +52,10 @@ class PublishItemProvider extends AbstractProvider
];
protected PermissionService $permissionService;
- public function __construct(string $table, string $identifier, string $context = '')
+ public function __construct()
{
- parent::__construct($table, $identifier, $context);
+ parent::__construct(...func_get_args());
+
// Sorry, no DI available for Context Menu Item Provider
$this->permissionService = GeneralUtility::makeInstance(PermissionService::class);
}
@@ -88,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 bc7e872a3..9ca493a6d 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;
@@ -55,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,
@@ -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/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php b/Classes/Features/FileEdgeCacheInvalidator/Domain/Service/FileEdgeCacheInvalidationService.php
index 699fb6ada..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;
@@ -77,12 +79,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();
}
/**
@@ -96,13 +98,11 @@ 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()->andX(
- $query->expr()->eq('table_local', '"sys_file"'),
- $query->expr()->in('uid_local', $uidList),
- ),
- );
- return $query->execute();
+ ->where($query->expr()->in('uid_local', $uidList));
+ if (TYPO3_V11) {
+ $query->andWhere($query->expr()->eq('table_local', '"sys_file"'));
+ }
+ 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/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/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php b/Classes/Features/MetricsAndDebug/Database/Logging/ContentPublisherSqlLogger.php
index 27a858f7e..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;
@@ -33,7 +34,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 +114,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
@@ -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/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php
index bdf6ec37a..d050f5162 100644
--- a/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php
+++ b/Classes/Features/MetricsAndDebug/Middleware/MetricsAndDebugMiddleware.php
@@ -21,6 +21,7 @@
use function date;
use function str_replace;
use function str_starts_with;
+use function uniqid;
class MetricsAndDebugMiddleware implements MiddlewareInterface
{
@@ -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);
@@ -90,8 +93,11 @@ protected function debugSqlQueries(): void
$queriesByCaller["$caller ($duration)"] = $callerQueries;
}
if (!empty($queries)) {
- DebugUtility::debug($queries, 'Content Publisher Queries');
- DebugUtility::debug($queriesByCaller, 'Queries By Caller');
+ /** @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);
}
}
}
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/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/RedirectsSupport/Controller/RedirectController.php b/Classes/Features/RedirectsSupport/Controller/RedirectController.php
index 4c49fed6c..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;
@@ -47,10 +48,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;
@@ -112,7 +113,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();
}
@@ -120,8 +121,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 +128,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 +169,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');
}
@@ -185,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)));
@@ -196,9 +197,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/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/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/Features/SystemInformationExport/Controller/SystemInformationExportController.php b/Classes/Features/SystemInformationExport/Controller/SystemInformationExportController.php
index 51a68681a..32ceb8bb4 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;
@@ -92,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/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'];
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/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/Classes/Middleware/InjectLoadingOverlayMiddleware.php b/Classes/Middleware/InjectLoadingOverlayMiddleware.php
new file mode 100644
index 000000000..66e0e2780
--- /dev/null
+++ b/Classes/Middleware/InjectLoadingOverlayMiddleware.php
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+HTML;
+ protected const SUPPORTED_PATHS = [
+ '/typo3/module/web/',
+ '/typo3/module/file/in2publish',
+ '/typo3/module/site/in2publish',
+ '/typo3/module/tools/in2publish',
+ '/typo3/module/in2publish',
+ '/module/web/In2publishM2',
+ ];
+
+ 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) || str_starts_with($_GET['route'] ?? '', $path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
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/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;
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/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/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
diff --git a/Classes/Service/ForeignSiteFinder.php b/Classes/Service/ForeignSiteFinder.php
index 0fb9d3180..8785e7ff0 100644
--- a/Classes/Service/ForeignSiteFinder.php
+++ b/Classes/Service/ForeignSiteFinder.php
@@ -29,10 +29,9 @@
* 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;
-use In2code\In2publishCore\CommonInjection\CacheInjection;
use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandDispatcherInjection;
use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandRequest;
use In2code\In2publishCore\Component\RemoteCommandExecution\RemoteCommandResponse;
@@ -43,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;
@@ -55,9 +56,15 @@ class ForeignSiteFinder implements LoggerAwareInterface
{
use LoggerAwareTrait;
use RemoteCommandDispatcherInjection;
- use CacheInjection;
+ 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
{
@@ -87,7 +94,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 +117,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 +141,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);
- }
}
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/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/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/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/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/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 = [];
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/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,
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/Classes/Testing/Tests/SshConnection/SshConnectionTest.php b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php
index bddd63ce5..498466276 100644
--- a/Classes/Testing/Tests/SshConnection/SshConnectionTest.php
+++ b/Classes/Testing/Tests/SshConnection/SshConnectionTest.php
@@ -40,6 +40,8 @@
use function array_diff;
use function preg_match;
+use const In2code\In2publishCore\TYPO3_V11;
+
class SshConnectionTest implements TestCaseInterface
{
use ConfigContainerInjection;
@@ -65,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,
@@ -99,8 +109,10 @@ public function run(): TestResult
$requiredNames = [
'typo3',
'index.php',
- 'typo3conf',
];
+ if (TYPO3_V11) {
+ $requiredNames[] = 'typo3conf';
+ }
if (!empty(array_diff($requiredNames, $documentRootFiles))) {
return new TestResult('ssh_connection.foreign_document_root_wrong', TestResult::ERROR);
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/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 2e5374ad4..e775286a7 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);
}
@@ -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/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/Classes/ViewHelpers/File/IconViewHelper.php b/Classes/ViewHelpers/File/IconViewHelper.php
index 59a1d254e..1fe371bd8 100644
--- a/Classes/ViewHelpers/File/IconViewHelper.php
+++ b/Classes/ViewHelpers/File/IconViewHelper.php
@@ -28,7 +28,9 @@
*/
use In2code\In2publishCore\CommonInjection\IconFactoryInjection;
+use In2code\In2publishCore\Component\Core\Record\Model\FolderRecord;
use In2code\In2publishCore\Component\Core\Record\Model\Record;
+use In2code\In2publishCore\Component\Core\Record\Model\StorageRootFolderRecord;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconRegistry;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
@@ -70,6 +72,12 @@ public function render(): string
protected function getIconIdentifier(Record $record): ?string
{
+ if ($record instanceof StorageRootFolderRecord) {
+ return 'apps-filetree-mount';
+ }
+ if ($record instanceof FolderRecord) {
+ return 'files-folder';
+ }
$mimeType = $record->getProp('mime_type');
if ($mimeType === null) {
return $this->getIconIdentifierForFileExtension($record);
diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php
new file mode 100644
index 000000000..b5e9dfe83
--- /dev/null
+++ b/Configuration/Backend/Modules.php
@@ -0,0 +1,108 @@
+
+ *
+ * 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\AdminTools\Service\ToolsRegistry;
+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',
+ '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',
+ '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('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',
+ 'position' => ['after' => 'redirects'],
+ 'access' => 'user',
+ '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/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/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'));
diff --git a/Configuration/Component/Core/Services.yaml b/Configuration/Component/Core/Services.yaml
index 6df2a5d27..260126f97 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'
@@ -52,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
diff --git a/Configuration/Features/AdminTools/Services.yaml b/Configuration/Features/AdminTools/Services.yaml
index 2ddee778a..612a523ed 100644
--- a/Configuration/Features/AdminTools/Services.yaml
+++ b/Configuration/Features/AdminTools/Services.yaml
@@ -7,52 +7,46 @@ 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'
- 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'
+ after: 'In2code\In2publishCore\Features\AdminTools\Controller\ToolsController'
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/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/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/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/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/Configuration/Icons.php b/Configuration/Icons.php
new file mode 100644
index 000000000..b9d6edcbe
--- /dev/null
+++ b/Configuration/Icons.php
@@ -0,0 +1,49 @@
+
+ *
+ * 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',
+ ],
+ 'in2publish-core-tools-module' => [
+ 'provider' => SvgIconProvider::class,
+ 'source' => 'EXT:in2publish_core/Resources/Public/Icons/Tools.svg',
+ ],
+];
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/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/Configuration/Services.php b/Configuration/Services.php
index 9081a2f0f..796b9bba9 100644
--- a/Configuration/Services.php
+++ b/Configuration/Services.php
@@ -3,13 +3,19 @@
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\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');
@@ -20,10 +26,27 @@
$configurator->import('ForeignServices.php');
}
- $builder->registerForAutoconfiguration(TestCaseInterface::class)->addTag('in2publish_core.testing.test');
- $builder->registerForAutoconfiguration(DatabaseRecordFactory::class)->addTag(
- 'in2publish_core.factory.database_record',
- );
+ if ($builder->hasDefinition(PageTypeService::class)) {
+ $pageTypeServiceDefinition = $builder->hasDefinition(PageTypeService::class);
+ } else {
+ $pageTypeServiceDefinition = new Definition(PageTypeService::class);
+ }
+ $pageTypeServiceDefinition->setAutoconfigured(true);
+ $pageTypeServiceDefinition->setAutowired(true);
+ $pageTypeServiceDefinition->setShared(true);
+ $pageTypeServiceDefinition->setPublic(true);
+
+ if (TYPO3_V11) {
+ $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',);
$builder->addCompilerPass(new PublicServicePass('in2publish_core.testing.test'));
};
diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml
index cf54abfc4..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:
@@ -60,7 +56,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 +69,6 @@ services:
In2code\In2publishCore\Testing\Tests\SshConnection\SftpRequirementsTest:
tags:
- name: 'in2publish_core.adapter.ssh.transmission_adapter_test'
+
+ In2code\In2publishCore\Service\ReplaceMarkersService:
+ public: true
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 18613c035..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:
@@ -61,9 +59,9 @@ excludeRelatedTables:
- tx_in2code_in2publish_task
- tx_in2code_rpc_data
- tx_in2code_rpc_request
- - tx_in2publishcore_filepublisher_task
- tx_in2publishcore_log
- tx_in2publishcore_running_request
+ - tx_in2publishcore_filepublisher_instruction
# Ignore these fields for difference view (Publish Overview, Record Comparison).
diff --git a/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md
new file mode 100644
index 000000000..397149043
--- /dev/null
+++ b/Documentation/Admins/Changelog/60149-Change-ReplaceSpycWithSymfonyYaml.md
@@ -0,0 +1,62 @@
+# 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)
+2. Quote all asterisks (see Example #2 Quote asterisk)
+
+## 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]
+```
+
+### #2 Quote asterisk
+Before:
+```yaml
+ workflowTreeColors:
+ groups: *
+```
+After
+```yaml
+ workflowTreeColors:
+ groups: '*'
+```
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.
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/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.
diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf
index 9667a0c67..e21be6339 100755
--- a/Resources/Private/Language/de.locallang.xlf
+++ b/Resources/Private/Language/de.locallang.xlf
@@ -1,812 +1,502 @@
-
-
-
+
+
+
-
+
- Publisher Ãœbersicht
+ Publisher Ãœbersicht
-
-
+
- TYPO3 Content Publisher
+ TYPO3 Content Publisher
-
+
- Übersicht Seiten und Datensätze veröffentlichen
+ Übersicht Seiten und Datensätze veröffentlichen
-
+
- Dateien veröffentlichen
-
-
-
- Tools für Administratoren
+ Dateien veröffentlichen
-
+
- Redirects veröffentlichen
+ Redirects veröffentlichen
-
-
+
- Tiefe
+ Tiefe
-
+
- %d Ebene
+ %d Ebene
-
+
- %d Ebenen
+ %d Ebenen
-
-
+
- Redaktionssystem
+ Redaktionssystem
-
+
- Produktivsystem
+ Produktivsystem
-
+
- Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. (Dauer: %s)
+ Der ausgewählte Datensatz wurde erfolgreich veröffentlicht. (Dauer: %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)
-
+
- 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.
-
+
- Der ausgewählte Datensatz wurde erfolgreich veröffentlicht.
+ Der ausgewählte Datensatz wurde erfolgreich veröffentlicht.
-
+
- Der ausgewählte Ordner wurde erfolgreich angelegt.
+ Der ausgewählte Ordner wurde erfolgreich angelegt.
-
+
- Der ausgewählte Ordner konnte nicht angelegt werden.
+ Der ausgewählte Ordner konnte nicht angelegt werden.
-
+
- Der ausgewählte Ordner wurde erfolgreich gelöscht.
+ Der ausgewählte Ordner wurde erfolgreich gelöscht.
-
+
- Der ausgewählte Ordner konnte nicht gelöscht werden.
+ Der ausgewählte Ordner konnte nicht gelöscht werden.
-
-
- 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 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.
-
-
- Veröffentlichen der Seite "%s" und ihrer Unterseiten
+
+
+ Veröffentlichen der Seite "%s" und ihrer Unterseiten
-
-
- Möchten Sie wirklich alle Seiten veröffentlichen?
-
-
+
- Möchten Sie diese Seite wirklich veröffentlichen?
+ Möchten Sie diese Seite wirklich veröffentlichen?
-
+ Publizieren
-
+
+
+ Nicht Veröffentlichbar
+
+
- Diese Seite publizieren
+ Diese Seite publizieren
-
+
- Diese Seite wird gerade veröffentlicht
+ Diese Seite wird gerade veröffentlicht
-
+
- Diese Datei wird gerade veröffentlicht
+ Diese Datei wird gerade veröffentlicht
-
-
- Veröffentlichen aller Dateien innerhalb von "%s"
+
+
+ Veröffentlichen aller Dateien innerhalb von "%s"
-
+
- Möchten Sie wirklich alle Dateien veröffentlichen?
+ Möchten Sie wirklich alle Dateien veröffentlichen?
-
+
- Möchten Sie diese Datei wirklich veröffentlichen?
+ Möchten Sie diese Datei wirklich veröffentlichen?
-
+
- Vorschau
+ Vorschau
-
+
- Vergleichsansicht
+ Vergleichsansicht
-
+
- Historie
+ Historie
-
+
- Dateivorschau
+ Dateivorschau
-
+
- Bearbeiten
+ Bearbeiten
-
+
- Eigenschaften von %s
+ Eigenschaften von %s
-
+
- Seiteneigenschaften
+ Seiteneigenschaften
-
+
- Datensatz Historie
+ Datensatz Historie
-
+
- Datensatz bearbeiten
+ Datensatz bearbeiten
-
+
- Verknüpfte Datensätze
+ Verknüpfte Datensätze
-
+
- Datensatz Status
-
-
-
-
- Ãœbersicht
-
-
-
- Dieses Tool listet nur alle anderen Tools auf
-
-
-
- Konfigurationsübersicht
-
-
-
- Zeige die aktuelle Konfiguration von in2publish von der LocalConfiguration.yaml Datei
-
-
-
- Logs anzeigen
-
-
-
- Zeigt die Logeinträge des Content Publishers mit vielen Filteroptionen an
-
-
-
- Tests
+ Datensatz Status
-
-
- Teste in2publish auf Funktionsfähigkeit
-
-
-
- TCA inspection
-
-
-
- Zeige die Teile des TCA die verwendet werden und alle anderen mit der Begründung warum sie nicht verwendet werden.
-
-
-
- Überflüssige Envelopes löschen
-
-
-
- Löscht alle Envelopes ("Remote Procedure Call"-Datenbankeinträge) die bereits genutzt wurden (Diese sind Einweg-Einträge)
-
-
-
- Registereinträge löschen
-
-
-
- Löscht alle Registereinträge, welche Informationen über das lokale und entfernte System vorhalten. Danach müssen die Tests erneut ausgeführt werden.
-
-
-
- Systeminformationen
-
-
-
- Anzeige von Informationen welche erforderlich oder nützlich sind Probleme zu identifizieren und sie zu beheben.
-
-
-
- Datenbankvergleich
-
-
-
- Zeigt unterschiede zwischen den Datenbanken an. Dieses Tools soll Administratoren dabei helfen UID-Konflikte zu lösen.
-
-
-
- RecordTree Untersuchen
-
-
-
- Hier kann ein RecordTree mittels Klassifikation und Identifikation aufgebaut und untersucht werden..
-
-
-
-
- Systeminformationen anzeigen
-
-
-
- Systeminformationen herunterladen
-
-
-
- JSON dekodieren
-
-
-
- JSON Text
-
-
-
- Dekodieren
-
-
-
- Fehler während des dekodierens
-
-
-
- JSON dekodierfehler #%d: %s
-
-
-
- Systeminformationen JSON Datei
-
-
-
- Hochladen!
-
-
-
+ Filtern nach:
-
-
+ Dateiname
-
-
+ Status
-
-
+
- Unverändert
+ Unverändert
-
+
- Datensatz geändert
+ Datensatz geändert
-
+
- Neuer Datensatz
+ Neuer Datensatz
-
+
- Gelöschter Datensatz
+ Gelöschter Datensatz
-
+
- Datensatz verschoben
+ Datensatz verschoben
-
-
-
+
- Unverändert
+ Unverändert
-
+
- Verändert
+ Verändert
-
+
- Neu
+ Neu
-
+
- Gelöscht
+ Gelöscht
-
+
- Verschoben
+ Verschoben
-
+
- Verschoben/Verändert
-
-
-
-
- Konfiguration
-
-
-
- Globale Konfiguration
-
-
-
- Persönliche Konfiguration
-
-
-
- Config Container Konfiguration
-
-
-
- Seiten-ID für Seitenspezifische konfiguration angeben
-
-
-
- Ãœbersicht
-
-
-
- Filter
-
-
-
- TCA Inspizieren
-
-
-
- Kompatibles TCA
-
-
-
- Inkompatibles TCA
-
-
-
- Controls
-
-
-
- Zu inkompatiblem TCA springen
-
-
-
- Zu kompatiblem TCA springen
-
-
-
- Zu controls springen
-
-
-
- Alle zugehörigen Registereinträge wurden gelöscht.
-
-
-
- Alle überflüssigen Envelopes wurden gelöscht.
-
-
-
- Überflüssigen Envelopes löschen.
-
-
-
- Es gibt keine Envelopes zum löschen.
-
-
-
- Registry-Einträge löschen.
-
-
-
- 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.
+ Verschoben/Verändert
-
+
- In2publish könnte vom erwarteten Verhalten abweichen.
+ In2publish könnte vom erwarteten Verhalten abweichen.
-
+
- 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.
-
+
- Einige Tests von in2publish schlagen fehl.
+ Einige Tests von in2publish schlagen fehl.
-
+
- Ihre TYPO3 Installation hat sich verändert.
+ Ihre TYPO3 Installation hat sich verändert.
-
+
- Die In2publish Konfiguration wurde verändert.
+ Die In2publish Konfiguration wurde verändert.
-
-
+
- Vertikal
+ Vertikal
-
+
- Horizontal
+ Horizontal
-
-
-
- Erfolgreich publiziert.
+
+
+ Erfolgreich publiziert.
-
+
- Ein Fehler ist aufgetreten.
+ Ein Fehler ist aufgetreten.
-
+
- Das Verzeichnis %s wurde erfolgreich publiziert.
+ Das Verzeichnis %s wurde erfolgreich publiziert.
-
+
- Das Verzeichnis %s konnte nicht publiziert werden.
+ Das Verzeichnis %s konnte nicht publiziert werden.
-
+
- Die Datei %s wurde erfolgreich publiziert.
+ Die Datei %s wurde erfolgreich publiziert.
-
+
- Die Datei %s konnte nicht vollständig publiziert werden.
+ Die Datei %s konnte nicht vollständig publiziert werden.
-
-
+
- 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.
-
-
+
- Sichere, authentifizierte und verschlüsselte Befehlsausführung
+ Sichere, authentifizierte und verschlüsselte Befehlsausführung
-
+
- Sichere, zuverlässige und Verschlüsselte Dateiübertragung
+ Sichere, zuverlässige und Verschlüsselte Dateiübertragung
-
-
-
- https://typo3.slack.com/archives/C2ULY79MZ]]>
-
-
-
- https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]>
-
-
-
+
- Sie dürfen diese Seite nicht veröffentlichen.
+ Sie dürfen diese Seite nicht veröffentlichen.
-
+
- Es wurde keine Seiten-ID zum veröffentlichen übertragen.
+ Es wurde keine Seiten-ID zum veröffentlichen übertragen.
-
-
- Die Seite "%s" wurde veröffentlicht.
+
+
+ Die Seite "%s" wurde veröffentlicht.
-
-
- Beim veröffentlichen der Seite "%s" ist ein Fehler aufgetreten. Weitere Informationen finden Sie in den Logs.
+
+
+ Beim veröffentlichen der Seite "%s" ist ein Fehler aufgetreten. Weitere Informationen finden Sie in den Logs.
-
+
- Diese Seite ist noch nicht veröffentlichbar.
+ Diese Seite ist noch nicht veröffentlichbar.
-
-
+
- Verknüpfte Seite
+ Verknüpfte Seite
-
+
- Verknüpfte Site des entfernten Systems
+ Verknüpfte Site des entfernten Systems
-
+
- Site der verknüpften Seite benutzen
+ Site der verknüpften Seite benutzen
-
+
- Seite/Site Verknüpfung
+ Seite/Site Verknüpfung
-
-
+
- Speichern und veröffentlichen
+ Speichern und veröffentlichen
-
+
- Gewählte veröffentlichen
+ Gewählte veröffentlichen
-
+
- Status Legende
+ Status Legende
-
+
- 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
-
+
- Die verknüpfte Seite ist nicht publiziert.
+ Die verknüpfte Seite ist nicht publiziert.
-
+
- 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
-
+
- Dieser Redirect ist publiziert
+ Dieser Redirect ist publiziert
-
+
- Aktionen Legende
+ Aktionen Legende
-
+
- Dieser Redorect kann publiziert werden. Klicken um zu publizieren.
+ Dieser Redorect kann publiziert werden. Klicken um zu publizieren.
-
+
- 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.
-
-
+
- Eigenschaft
+ Eigenschaft
-
+
- Alt
+ Alt
-
+
- Neu
+ Neu
-
+
- ID
+ ID
-
+
- Domain
+ Domain
-
+
- Quelle
+ Quelle
-
+
- Ziel
+ Ziel
-
+
- Status
+ Status
-
+
- Aktionen
+ Aktionen
-
-
+
- Fehlende Seite oder Seitenkonfiguration
+ Fehlende Seite oder Seitenkonfiguration
-
-
- Die verknüpfte Seite [%d] "%s" ist nicht publiziert
+
+
+ Die verknüpfte Seite [%d] "%s" ist nicht publiziert
-
+
- Dieser Redirect ist publiziert
+ Dieser Redirect ist publiziert
-
-
+
- Bereit zur Veröffentlichung
+ Bereit zur Veröffentlichung
-
+
- Fehlende Seite oder Seitenkonfiguration
+ Fehlende Seite oder Seitenkonfiguration
-
+
- Fehlende Veröffentlichung der Seite
+ Fehlende Veröffentlichung der Seite
-
+
- Veröffentlicht
+ Veröffentlicht
-
-
+
- Filtern
+ Filtern
-
+
- Verknüpfung
+ Verknüpfung
-
+
- Verknüpft
+ Verknüpft
-
+
- Verknüpfung fehlend
+ Verknüpfung fehlend
-
-
+
- Seite neu laden
+ Seite neu laden
-
-
-
- Neu
-
-
-
- Gelöscht
-
-
-
- Unterschiede
-
-
-
- Generell
-
-
-
- Die Tabelle is auf Local leer.
-
-
-
- Die Tabelle is auf Foreign leer.
-
-
-
- Übertrage diese Änderungen auf das entfernte System
-
-
-
- Es wurden keine Unterschiede in den Daten der gewählten Tabellen entdeckt.
-
-
-
- Tabellen für den Vergleich auswählen
-
-
-
- Tabellen
-
-
-
- Vergleichen
-
-
-
- Dies ist kein Publishing
-
-
-
- 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.
-
-
-
- Datensatztitle
-
-
-
- Aktionen
-
-
-
- Unterschiede
-
-
-
- Fehler
-
-
-
- Erfolg
-
-
-
- Der Datensatz der übertragen werden sollte existiert nicht mehr.
-
-
-
- Der Datensatz der übertragen werden sollte sollte nicht auf Foreign existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit veröffentlicht.
+
+
+ Administrationswerkzeuge
-
-
- Der Datensatz der übertragen werden sollte sollte nicht auf Local existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit erstellt.
+
+
+ "%s" erfordert, dass der Datensatz "%s" (das ist die Standardsprachversion) zuerst veröffentlicht wird.
-
-
- 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.
+
+
+ Der Datensatz "%s" kann nicht veröffentlicht werden, bevor nicht alle Sichtbarkeitseinstellung (%s) der Standardsprache "%s" veröffentlicht wurden.
-
-
- Der Datensatz %s[%d] wurde auf Foreign gelöscht.
+
+
+ "%s" erfordert, dass die Seite "%s" zuerst veröffentlicht wird.
-
-
- Der Datensatz %s[%d] wurde auf Foreign erstellt.
+
+
+ "%s" setzt voraus, dass die Seite "%s" alle seine Eigenschaften veröffentlicht hat (%s), die bestimmen, ob der Datensatz sichtbar ist.
-
-
- Der Datensatz %s[%d] wurde auf Foreign aktualisiert.
+
+
+ Der Datensatz mit der klassifizierung "%s" und Eigenschaften "%s" existiert nicht.
-
-
-
- Administrationswerkzeuge
+
+
+ Der Datensatz "%s" ist ein Ziel des Verknüpfungsdatensatzes "%s". Das Ziel muss veröffentlicht werden, bevor der Verknüpfungsdatensatz veröffentlicht werden kann.
-
-
-
- "%s" erfordert, dass der Datensatz "%s" (das ist die Standardsprachversion) zuerst veröffentlicht wird.
+
+
+ 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.
-
-
- Der Datensatz "%s" kann nicht veröffentlicht werden, bevor nicht alle Sichtbarkeitseinstellung (%s) der Standardsprache "%s" veröffentlicht wurden.
+
+
+ Veröffentlichen
-
-
- "%s" erfordert, dass die Seite "%s" zuerst veröffentlicht wird.
+
+
+ Abbrechen
-
-
- "%s" setzt voraus, dass die Seite "%s" alle seine Eigenschaften veröffentlicht hat (%s), die bestimmen, ob der Datensatz sichtbar ist.
+
+
+ Veröffentlichung bestätigen
-
-
- Der Datensatz mit der klassifizierung "%s" und Eigenschaften "%s" existiert nicht.
+
+
+ Möchten Sie die Datei %s wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden.
-
-
- Der Datensatz "%s" ist ein Ziel des Verknüpfungsdatensatzes "%s". Das Ziel muss veröffentlicht werden, bevor der Verknüpfungsdatensatz veröffentlicht werden kann.
+
+
+ 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 6a846ba8f..154ce3ff9 100755
--- a/Resources/Private/Language/de.locallang_js.xlf
+++ b/Resources/Private/Language/de.locallang_js.xlf
@@ -11,24 +11,6 @@
Abbrechen
-
-
- Veröffentlichung bestätigen
-
-
-
- Möchten Sie die Datei $1 wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden.
-
-
-
- Möchten Sie den Ordner $name$ wirklich veröffentlichen? Dies kann nicht rückgängig gemacht werden.
-
-
-
- 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/de.locallang_mod4.xlf b/Resources/Private/Language/de.locallang_mod4.xlf
index f63133db9..839a9fef2 100755
--- a/Resources/Private/Language/de.locallang_mod4.xlf
+++ b/Resources/Private/Language/de.locallang_mod4.xlf
@@ -1,19 +1,315 @@
-
-
-
+
+
+
-
-
- Publisher Tools
+
+
+ Publisher Tools
-
+
- 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
+
+
+
+ Systeminformationen anzeigen
+
+
+
+ Systeminformationen herunterladen
+
+
+
+ JSON dekodieren
+
+
+
+ JSON Text
+
+
+
+ Dekodieren
+
+
+
+ JSON dekodierfehler #%d: %s
+
+
+
+ Systeminformationen JSON Datei
+
+
+
+ Hochladen!
+
+
+
+ Bitte Klassifizierung und Identität auswählen
+
+
+
+ Alle Relationen umschalten
+
+
+
+ Neu
+
+
+
+ Gelöscht
+
+
+
+ Unterschiede
+
+
+
+ Generell
+
+
+
+ Die Tabelle is auf Local leer.
+
+
+
+ Die Tabelle is auf Foreign leer.
+
+
+
+ Übertrage diese Änderungen auf das entfernte System
+
+
+
+ Es wurden keine Unterschiede in den Daten der gewählten Tabellen entdeckt.
+
+
+
+ Tabellen für den Vergleich auswählen
+
+
+
+ Tabellen
+
+
+
+ Vergleichen
+
+
+
+ Dies ist kein Publishing
+
+
+
+ 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.
+
+
+
+ Datensatztitle
+
+
+
+ Aktionen
+
+
+
+ Fehler
+
+
+
+ Erfolg
+
+
+
+ Der Datensatz der übertragen werden sollte existiert nicht mehr.
+
+
+
+ Der Datensatz der übertragen werden sollte sollte nicht auf Foreign existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit veröffentlicht.
+
+
+
+ Der Datensatz der übertragen werden sollte sollte nicht auf Local existieren, jedoch ist er vorhanden. Möglicherweise wurde er in der Zwischenzeit erstellt.
+
+
+
+ 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.
+
+
+
+ Der Datensatz %s[%d] wurde auf Foreign gelöscht.
+
+
+
+ Der Datensatz %s[%d] wurde auf Foreign erstellt.
+
+
+
+ Der Datensatz %s[%d] wurde auf Foreign aktualisiert.
+
+
+
+ Ãœbersicht
+
+
+
+ Hilfe
+
+
+
+ https://typo3.slack.com/archives/C2ULY79MZ]]>
+
+
+
+ https://github.com/in2code-de/in2publish_core/tree/master/Documentation]]>
+
+
+
+ Zu inkompatiblem TCA springen
+
+
+
+ Zu kompatiblem TCA springen
+
+
+
+ Inkompatibles TCA
+
+
+
+ Kompatibles TCA
+
+
+
+ zur persönlichen Konfiguration springen
+
+
+
+ zur globalen Konfiguration springen
+
+
+
+ zum Dump des Config Containers springen
+
+
+
+ Seiten-ID für Seitenspezifische konfiguration angeben
+
+
+
+ Config Container Konfiguration
+
+
+
+ Globale Konfiguration
+
+
+
+ Persönliche Konfiguration
+
+
+
+ Alle zugehörigen Registereinträge wurden gelöscht.
+
+
+
+ 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.
+
+
+
+ Entferne Registrierungseinträge
+
+
+
+ Alle überflüssigen Envelopes wurden gelöscht.
+
+
+
+ In der Foreign Datenbank sind überflüssige Envelopes vorhanden.
+
+
+
+ Es gibt keine Envelopes zum löschen.
+
+
+
+ Entferne überflüssige Envelopes
+
+
+
+ Ãœbersicht
+
+
+
+ Dieses Tool listet nur alle anderen Tools auf
+
+
+
+ Konfigurationsübersicht
+
+
+
+ Zeige die aktuelle Konfiguration von in2publish von der LocalConfiguration.yaml Datei
+
+
+
+ Tests
+
+
+
+ Teste in2publish auf Funktionsfähigkeit
+
+
+
+ TCA inspection
+
+
+
+ Zeige die Teile des TCA die verwendet werden und alle anderen mit der Begründung warum sie nicht verwendet werden.
+
+
+
+ Überflüssige Envelopes löschen
+
+
+
+ Löscht alle Envelopes ("Remote Procedure Call"-Datenbankeinträge) die bereits genutzt wurden (Diese sind Einweg-Einträge)
+
+
+
+ Registereinträge löschen
+
+
+
+ Löscht alle Registereinträge, welche Informationen über das lokale und entfernte System vorhalten. Danach müssen die Tests erneut ausgeführt werden.
+
+
+
+ Systeminformationen
+
+
+
+ Anzeige von Informationen welche erforderlich oder nützlich sind Probleme zu identifizieren und sie zu beheben.
+
+
+
+ Datenbankvergleich
+
+
+
+ Zeigt unterschiede zwischen den Datenbanken an. Dieses Tools soll Administratoren dabei helfen UID-Konflikte zu lösen.
+
+
+
+ RecordTree Untersuchen
+
+
+
+ Hier kann ein RecordTree mittels Klassifikation und Identifikation aufgebaut und untersucht werden..
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
index d107911cf..cb21e09aa 100755
--- a/Resources/Private/Language/locallang.xlf
+++ b/Resources/Private/Language/locallang.xlf
@@ -1,617 +1,378 @@
-
-
-
+
+
+
-
+
-
-
+
-
+
-
+
-
-
-
-
+
-
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
+
-
+
-
+
+
+
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
-
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
-
-
+
+
-
+
-
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/Resources/Private/Language/locallang_js.xlf b/Resources/Private/Language/locallang_js.xlf
index 2a3d884e5..88fc4c8d4 100755
--- a/Resources/Private/Language/locallang_js.xlf
+++ b/Resources/Private/Language/locallang_js.xlf
@@ -9,19 +9,6 @@
-
-
-
-
-
-
-
-
-
-
-
-