From 7779a0356c66f214c0550ace4ca05bc4d45f3e8c Mon Sep 17 00:00:00 2001 From: Simon Schaufelberger Date: Fri, 18 Oct 2024 11:41:38 +0200 Subject: [PATCH] [FEATURE] Add MigrateItemsIndexedKeysToAssociativeFractor --- composer.json | 2 +- packages/typo3-fractor/config/typo3-12.php | 2 + .../typo3-fractor/docs/typo3-fractor-rules.md | 57 ++++- .../Fixtures/fixture.xml | 217 ++++++++++++++++++ ...emsIndexedKeysToAssociativeFractorTest.php | 27 +++ .../config/fractor.php | 15 ++ ...teItemsIndexedKeysToAssociativeFractor.php | 182 +++++++++++++++ .../src/Helper/FlexFormHelperTrait.php | 25 ++ 8 files changed, 525 insertions(+), 2 deletions(-) create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/Fixtures/fixture.xml create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/MigrateItemsIndexedKeysToAssociativeFractorTest.php create mode 100644 packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/config/fractor.php create mode 100644 packages/typo3-fractor/rules/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor.php diff --git a/composer.json b/composer.json index 11689d1c..b53ff47f 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "ergebnis/composer-normalize": "^2.42", "phpstan/phpstan-phpunit": "^1.3", "phpunit/phpunit": "^10.5", - "rector/rector": "^1.0", + "rector/rector": "^1.2.6", "symplify/easy-coding-standard": "^12.3", "symplify/monorepo-builder": "^11.2", "symplify/rule-doc-generator": "12.1.3" diff --git a/packages/typo3-fractor/config/typo3-12.php b/packages/typo3-fractor/config/typo3-12.php index a79fc94b..4ba8e9f7 100644 --- a/packages/typo3-fractor/config/typo3-12.php +++ b/packages/typo3-fractor/config/typo3-12.php @@ -5,6 +5,7 @@ use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateEmailFlagToEmailTypeFlexFormFractor; use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateEvalIntAndDouble2ToTypeNumberFlexFormFractor; use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateInternalTypeFolderToTypeFolderFlexFormFractor; +use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateItemsIndexedKeysToAssociativeFractor; use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateNullFlagFlexFormFractor; use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigratePasswordAndSaltedPasswordToPasswordTypeFlexFormFractor; use a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateRenderTypeColorpickerToTypeColorFlexFormFractor; @@ -50,4 +51,5 @@ $services->set(RenameConfigXhtmlDoctypeToDoctypeFractor::class); $services->set(RenameTcemainLinkHandlerMailKeyFractor::class); $services->set(UseConfigArrayForTSFEPropertiesFractor::class); + $services->set(MigrateItemsIndexedKeysToAssociativeFractor::class); }; diff --git a/packages/typo3-fractor/docs/typo3-fractor-rules.md b/packages/typo3-fractor/docs/typo3-fractor-rules.md index 58d0f613..b9dc7514 100644 --- a/packages/typo3-fractor/docs/typo3-fractor-rules.md +++ b/packages/typo3-fractor/docs/typo3-fractor-rules.md @@ -1,4 +1,4 @@ -# 24 Rules Overview +# 25 Rules Overview ## AbstractMessageGetSeverityFluidFractor @@ -134,6 +134,61 @@ Migrates TCA internal_type into new new TCA type folder
+## MigrateItemsIndexedKeysToAssociativeFractor + +Migrates indexed item array keys to associative for type select, radio and check + +- class: [`a9f\Typo3Fractor\TYPO3v12\FlexForm\MigrateItemsIndexedKeysToAssociativeFractor`](../rules/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor.php) + +```diff + + + + + Sheet Title + array + + + + select + selectSingle + + +- +- ++ + +- Label 1 +- 1 ++ ++ 1 + + +- Label 2 +- 2 ++ ++ 2 + + +- Label 3 +- 3 ++ ++ 3 + + + + + + + + + +``` + +
+ ## MigrateNullFlagFlexFormFractor Migrate null flag diff --git a/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/Fixtures/fixture.xml b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/Fixtures/fixture.xml new file mode 100644 index 00000000..745006d6 --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/Fixtures/fixture.xml @@ -0,0 +1,217 @@ + + + + + + sheetTitle + array + + + + select + selectSingle + + + + + + + Label 1 + 1 + + + Label 2 + 2 + + + Label 3 + 3 + + + + + + + select + selectCheckBox + + + My label + 0 + my-icon + group1 + My Description + + + My label 1 + 1 + my-icon + group1 + My Description + + + + + + + radio + + + My label + 0 + + + My label 1 + 1 + + + My label 2 + 2 + + + + + + + check + + + My label + 1 + + + + 1 + + + + + + + select + selectCheckBox + + + + 0 + my-icon + group1 + My Description + + + + + + + + + +----- + + + + + + sheetTitle + array + + + + select + selectSingle + + + + + + 1 + + + + 2 + + + + 3 + + + + + + + select + selectCheckBox + + + + 0 + my-icon + group1 + My Description + + + + 1 + my-icon + group1 + My Description + + + + + + + radio + + + + 0 + + + + 1 + + + + 2 + + + + + + + check + + + + 1 + + + + 1 + + + + + + + select + selectCheckBox + + + + 0 + my-icon + group1 + My Description + + + + + + + + + diff --git a/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/MigrateItemsIndexedKeysToAssociativeFractorTest.php b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/MigrateItemsIndexedKeysToAssociativeFractorTest.php new file mode 100644 index 00000000..9737f94f --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/MigrateItemsIndexedKeysToAssociativeFractorTest.php @@ -0,0 +1,27 @@ +doTestFile($filePath); + } + + public static function provideData(): \Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixtures', '*.xml'); + } + + public function provideConfigFilePath(): ?string + { + return __DIR__ . '/config/fractor.php'; + } +} diff --git a/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/config/fractor.php b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/config/fractor.php new file mode 100644 index 00000000..60c4d99b --- /dev/null +++ b/packages/typo3-fractor/rules-tests/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor/config/fractor.php @@ -0,0 +1,15 @@ +withOptions([ + XmlProcessorOption::INDENT_CHARACTER => Indent::STYLE_TAB, + XmlProcessorOption::INDENT_SIZE => 1, + ]) + ->withRules([MigrateItemsIndexedKeysToAssociativeFractor::class]); diff --git a/packages/typo3-fractor/rules/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor.php b/packages/typo3-fractor/rules/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor.php new file mode 100644 index 00000000..c15bbcf6 --- /dev/null +++ b/packages/typo3-fractor/rules/TYPO3v12/FlexForm/MigrateItemsIndexedKeysToAssociativeFractor.php @@ -0,0 +1,182 @@ +nodeName === 'config'; + } + + public function beforeTraversal(File $file, \DOMDocument $rootNode): void + { + $this->file = $file; + $this->domDocument = $rootNode; + } + + public function getRuleDefinition(): RuleDefinition + { + return new RuleDefinition('Migrates indexed item array keys to associative for type select, radio and check', [ + new CodeSample( + <<<'CODE_SAMPLE' + + + + + Sheet Title + array + + + + select + selectSingle + + + + + + + Label 1 + 1 + + + Label 2 + 2 + + + Label 3 + 3 + + + + + + + + + +CODE_SAMPLE + , + <<<'CODE_SAMPLE' + + + + + Sheet Title + array + + + + select + selectSingle + + + + + + 1 + + + + 2 + + + + 3 + + + + + + + + + +CODE_SAMPLE + ), + ]); + } + + public function refactor(\DOMNode $node): \DOMNode|int|null + { + if (! $node instanceof \DOMElement) { + return null; + } + + if ( + ! $this->isConfigType($node, 'select') + && ! $this->isConfigType($node, 'radio') + && ! $this->isConfigType($node, 'check') + ) { + return null; + } + + $hasAstBeenChanged = false; + $exprArrayItemToChange = $this->extractDomElementByKey($node, 'items'); + if (! $exprArrayItemToChange instanceof \DOMElement) { + return null; + } + + foreach ($exprArrayItemToChange->childNodes as $itemNode) { + if (! $itemNode instanceof \DOMElement) { + continue; + } + + $numIndexZero = $this->extractDomElementFromArrayByIndex($itemNode, '0'); + if ($numIndexZero instanceof \DOMElement) { + $this->changeTagName($this->domDocument, $numIndexZero, 'label'); + $hasAstBeenChanged = true; + } + + if (! $this->isConfigType($node, 'check')) { + $numIndexOne = $this->extractDomElementFromArrayByIndex($itemNode, '1'); + if ($numIndexOne instanceof \DOMElement) { + $this->changeTagName($this->domDocument, $numIndexOne, 'value'); + $hasAstBeenChanged = true; + } + } + + if ($this->isConfigType($node, 'select')) { + $numIndexTwo = $this->extractDomElementFromArrayByIndex($itemNode, '2'); + if ($numIndexTwo instanceof \DOMElement) { + $this->changeTagName($this->domDocument, $numIndexTwo, 'icon'); + $hasAstBeenChanged = true; + } + + $numIndexThree = $this->extractDomElementFromArrayByIndex($itemNode, '3'); + if ($numIndexThree instanceof \DOMElement) { + $this->changeTagName($this->domDocument, $numIndexThree, 'group'); + $hasAstBeenChanged = true; + } + + $numIndexFour = $this->extractDomElementFromArrayByIndex($itemNode, '4'); + if ($numIndexFour instanceof \DOMElement) { + $this->changeTagName($this->domDocument, $numIndexFour, 'description'); + $hasAstBeenChanged = true; + } + } + } + + return $hasAstBeenChanged ? $node : null; + } +} diff --git a/packages/typo3-fractor/src/Helper/FlexFormHelperTrait.php b/packages/typo3-fractor/src/Helper/FlexFormHelperTrait.php index e4e8406f..3f53a611 100644 --- a/packages/typo3-fractor/src/Helper/FlexFormHelperTrait.php +++ b/packages/typo3-fractor/src/Helper/FlexFormHelperTrait.php @@ -26,6 +26,31 @@ protected function extractDomElementByKey(?\DOMElement $element, string $key): ? return null; } + protected function extractDomElementFromArrayByIndex(?\DOMElement $element, string $index): ?\DOMElement + { + if (! $element instanceof \DOMElement) { + return null; + } + + foreach ($element->childNodes as $childNode) { + if (! $childNode instanceof \DOMElement) { + continue; + } + + if (! $childNode->hasAttribute('index')) { + continue; + } + + $indexValue = $childNode->getAttribute('index'); + + if ($childNode->nodeName === 'numIndex' && $index === $indexValue) { + return $childNode; + } + } + + return null; + } + protected function hasKey(?\DOMElement $columnItemConfigurationArray, string $configKey): bool { if (! $columnItemConfigurationArray instanceof \DOMElement) {