From 2b05d6d6623d7e3fefeadd005294ddb4b6bd7592 Mon Sep 17 00:00:00 2001 From: Philipp Kitzberger Date: Thu, 16 Apr 2026 10:25:10 +0200 Subject: [PATCH] [FEATURE] Migrate legacy condition conjunctions --- packages/typo3-fractor/config/typo3-10.php | 2 + .../typo3-fractor/docs/typo3-fractor-rules.md | 26 +++- .../Fixtures/fixture10.typoscript.fixture | 7 + .../Fixtures/fixture20.typoscript.fixture | 7 + .../Fixtures/fixture30.typoscript.fixture | 7 + .../Fixtures/fixture40.typoscript.fixture | 7 + ...ptMultipleConditionBracketsFractorTest.php | 27 ++++ .../config/fractor.php | 20 +++ ...ScriptMultipleConditionBracketsFractor.php | 122 ++++++++++++++++++ 9 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture10.typoscript.fixture create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture20.typoscript.fixture create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture30.typoscript.fixture create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture40.typoscript.fixture create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/MigrateTypoScriptMultipleConditionBracketsFractorTest.php create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/config/fractor.php create mode 100644 packages/typo3-fractor/rules/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor.php diff --git a/packages/typo3-fractor/config/typo3-10.php b/packages/typo3-fractor/config/typo3-10.php index ec2d6c0c..295e7023 100644 --- a/packages/typo3-fractor/config/typo3-10.php +++ b/packages/typo3-fractor/config/typo3-10.php @@ -4,6 +4,7 @@ use a9f\Typo3Fractor\TYPO3v10\Fluid\RemoveNoCacheHashAndUseCacheHashAttributeFluidFractor; use a9f\Typo3Fractor\TYPO3v10\TypoScript\MigrateLegacyTypoScriptConditionsFractor; +use a9f\Typo3Fractor\TYPO3v10\TypoScript\MigrateTypoScriptMultipleConditionBracketsFractor; use a9f\Typo3Fractor\TYPO3v10\TypoScript\MigrateTypoScriptPageConditionPipeAccessFractor; use a9f\Typo3Fractor\TYPO3v10\TypoScript\RemoveConfigConcatenateJsAndCssFractor; use a9f\Typo3Fractor\TYPO3v10\TypoScript\RemoveConfigDefaultGetVarsFractor; @@ -39,6 +40,7 @@ $services->set(RemoveNoCacheHashAndUseCacheHashAttributeFluidFractor::class); $services->set(RemoveUseCacheHashFromTypolinkTypoScriptFractor::class); $services->set(MigrateLegacyTypoScriptConditionsFractor::class); + $services->set(MigrateTypoScriptMultipleConditionBracketsFractor::class); $services->set(MigrateTypoScriptPageConditionPipeAccessFractor::class); $services->set(RemoveConfigConcatenateJsAndCssFractor::class); $services->set(RemoveConfigDefaultGetVarsFractor::class); diff --git a/packages/typo3-fractor/docs/typo3-fractor-rules.md b/packages/typo3-fractor/docs/typo3-fractor-rules.md index 1ae883aa..6754bd18 100644 --- a/packages/typo3-fractor/docs/typo3-fractor-rules.md +++ b/packages/typo3-fractor/docs/typo3-fractor-rules.md @@ -1,4 +1,4 @@ -# 68 Rules Overview +# 69 Rules Overview ## AbstractMessageGetSeverityFluidFractor @@ -744,6 +744,30 @@ Migrate TypoScript loginUser and usergroup conditions (both function-call and eq
+## MigrateTypoScriptMultipleConditionBracketsFractor + +Merge multiple TypoScript condition bracket pairs into a single bracket with logical operators inside + +- class: [`a9f\Typo3Fractor\TYPO3v10\TypoScript\MigrateTypoScriptMultipleConditionBracketsFractor`](../rules/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor.php) + +```diff +-[conditionA] || [conditionB] ++[conditionA || conditionB] + page = PAGE + [end] +``` + +
+ +```diff +-[conditionA] && [conditionB] ++[conditionA && conditionB] + page = PAGE + [end] +``` + +
+ ## MigrateTypoScriptPageConditionPipeAccessFractor Migrate page pipe access in TypoScript conditions to bracket array access syntax diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture10.typoscript.fixture b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture10.typoscript.fixture new file mode 100644 index 00000000..a4e540ab --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture10.typoscript.fixture @@ -0,0 +1,7 @@ +[conditionA] || [conditionB] + page = PAGE +[end] +----- +[conditionA || conditionB] + page = PAGE +[end] diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture20.typoscript.fixture b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture20.typoscript.fixture new file mode 100644 index 00000000..c461c7c8 --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture20.typoscript.fixture @@ -0,0 +1,7 @@ +[conditionA] && [conditionB] + page = PAGE +[end] +----- +[conditionA && conditionB] + page = PAGE +[end] diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture30.typoscript.fixture b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture30.typoscript.fixture new file mode 100644 index 00000000..2d8cbc8e --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture30.typoscript.fixture @@ -0,0 +1,7 @@ +[conditionA] || [conditionB] || [conditionC] + page = PAGE +[end] +----- +[conditionA || conditionB || conditionC] + page = PAGE +[end] diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture40.typoscript.fixture b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture40.typoscript.fixture new file mode 100644 index 00000000..c6c04b8a --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/Fixtures/fixture40.typoscript.fixture @@ -0,0 +1,7 @@ +[traverse(request?.getQueryParams(), 'tx_t3extblog_blogsystem/post') > 0] || [traverse(request?.getQueryParams(), 'tx_news_pi1/news') > 0] + page = PAGE +[end] +----- +[traverse(request?.getQueryParams(), 'tx_t3extblog_blogsystem/post') > 0 || traverse(request?.getQueryParams(), 'tx_news_pi1/news') > 0] + page = PAGE +[end] diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/MigrateTypoScriptMultipleConditionBracketsFractorTest.php b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/MigrateTypoScriptMultipleConditionBracketsFractorTest.php new file mode 100644 index 00000000..d0aa354f --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/MigrateTypoScriptMultipleConditionBracketsFractorTest.php @@ -0,0 +1,27 @@ +doTestFile($filePath); + } + + public static function provideData(): \Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixtures', '*.typoscript.fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/fractor.php'; + } +} diff --git a/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/config/fractor.php b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/config/fractor.php new file mode 100644 index 00000000..8fdf8d5b --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor/config/fractor.php @@ -0,0 +1,20 @@ +withOptions([ + TypoScriptProcessorOption::INDENT_SIZE => 4, + TypoScriptProcessorOption::INDENT_CHARACTER => PrettyPrinterConfiguration::INDENTATION_STYLE_SPACES, + TypoScriptProcessorOption::ADD_CLOSING_GLOBAL => false, + TypoScriptProcessorOption::INCLUDE_EMPTY_LINE_BREAKS => true, + TypoScriptProcessorOption::INDENT_CONDITIONS => true, + TypoScriptProcessorOption::CONDITION_TERMINATION => PrettyPrinterConditionTermination::Keep, + ]) + ->withRules([MigrateTypoScriptMultipleConditionBracketsFractor::class]); diff --git a/packages/typo3-fractor/rules/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor.php b/packages/typo3-fractor/rules/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor.php new file mode 100644 index 00000000..fb8b7276 --- /dev/null +++ b/packages/typo3-fractor/rules/TYPO3v10/TypoScript/MigrateTypoScriptMultipleConditionBracketsFractor.php @@ -0,0 +1,122 @@ +condition; + $originalCondition = $condition; + + $condition = $this->mergeMultipleBracketConditions($condition); + + if ($condition === $originalCondition) { + return null; + } + + $statement->condition = $condition; + + return $statement; + } + + private function mergeMultipleBracketConditions(string $condition): string + { + // Quick check: does it contain the pattern '] ||' or '] &&'? + if (! preg_match('/\]\s*(\|\||&&)\s*\[/', $condition)) { + return $condition; + } + + $expressions = []; + $operators = []; + $remaining = trim($condition); + + while ($remaining !== '') { + if (! preg_match('/^\[([^\]]*)\](.*)$/s', $remaining, $m)) { + // Unexpected format, bail out without changing anything + return $condition; + } + + $expressions[] = $m[1]; + $remaining = trim($m[2]); + + if ($remaining === '') { + break; + } + + if (preg_match('/^(\|\||&&)\s*(.*)$/s', $remaining, $opMatch)) { + $operators[] = $opMatch[1]; + $remaining = trim($opMatch[2]); + } else { + // Unexpected token after closing bracket, bail out + return $condition; + } + } + + if (count($expressions) < 2) { + return $condition; + } + + $merged = ''; + foreach ($expressions as $i => $expr) { + if ($i > 0) { + $merged .= ' ' . $operators[$i - 1] . ' '; + } + + $merged .= $expr; + } + + return '[' . $merged . ']'; + } +}