Skip to content

Commit 02d5725

Browse files
authored
[FEATURE] Add MigrateLegacyFormTemplatesFractor (#373)
Resolves: sabbelasichon/typo3-rector#4586
1 parent 10de71c commit 02d5725

6 files changed

Lines changed: 202 additions & 1 deletion

File tree

packages/typo3-fractor/config/typo3-14.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use a9f\Typo3Fractor\TYPO3v14\TypoScript\RemoveFrontendAssetConcatenationAndCompressionFractor;
1313
use a9f\Typo3Fractor\TYPO3v14\TypoScript\RemoveModWebLayoutDefLangBindingFractor;
1414
use a9f\Typo3Fractor\TYPO3v14\TypoScript\RemoveUserTSConfigAuthBeRedirectToURLFractor;
15+
use a9f\Typo3Fractor\TYPO3v14\Yaml\MigrateLegacyFormTemplatesFractor;
1516
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
1617

1718
return static function (ContainerConfigurator $containerConfigurator): void {
@@ -30,4 +31,5 @@
3031
$services->set(RemoveExternalOptionFromTypoScriptFractor::class);
3132
$services->set(RemoveUserTSConfigAuthBeRedirectToURLFractor::class);
3233
$services->set(RemoveDuplicateDoktypeRestrictionConfigurationFractor::class);
34+
$services->set(MigrateLegacyFormTemplatesFractor::class);
3335
};

packages/typo3-fractor/docs/typo3-fractor-rules.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 40 Rules Overview
1+
# 41 Rules Overview
22

33
## AbstractMessageGetSeverityFluidFractor
44

@@ -249,6 +249,35 @@ Migrates indexed item array keys to associative for type select, radio and check
249249

250250
<br>
251251

252+
## MigrateLegacyFormTemplatesFractor
253+
254+
Migrate legacy form templates
255+
256+
- class: [`a9f\Typo3Fractor\TYPO3v14\Yaml\MigrateLegacyFormTemplatesFractor`](../rules/TYPO3v14/Yaml/MigrateLegacyFormTemplatesFractor.php)
257+
258+
```diff
259+
prototypes:
260+
standard:
261+
formElementsDefinition:
262+
Text:
263+
- variants:
264+
- -
265+
- identifier: template-variant
266+
- condition: 'getRootFormProperty("renderingOptions.templateVariant") == "version2"'
267+
- properties:
268+
- containerClassAttribute: 'form-element form-element-text mb-3'
269+
- elementClassAttribute: form-control
270+
- elementErrorClassAttribute: ~
271+
- labelClassAttribute: form-label
272+
+ properties:
273+
+ containerClassAttribute: 'form-element form-element-text mb-3'
274+
+ elementClassAttribute: form-control
275+
+ elementErrorClassAttribute: ~
276+
+ labelClassAttribute: form-label
277+
```
278+
279+
<br>
280+
252281
## MigrateNullFlagFlexFormFractor
253282

254283
Migrate null flag
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
prototypes:
2+
standard:
3+
formElementsDefinition:
4+
Text:
5+
variants:
6+
-
7+
identifier: template-variant
8+
condition: 'getRootFormProperty("renderingOptions.templateVariant") == "version2"'
9+
properties:
10+
containerClassAttribute: 'form-element form-element-text mb-3'
11+
elementClassAttribute: form-control
12+
elementErrorClassAttribute: ~
13+
labelClassAttribute: form-label
14+
-----
15+
prototypes:
16+
standard:
17+
formElementsDefinition:
18+
Text:
19+
properties:
20+
containerClassAttribute: 'form-element form-element-text mb-3'
21+
elementClassAttribute: form-control
22+
elementErrorClassAttribute: null
23+
labelClassAttribute: form-label
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\Typo3Fractor\Tests\TYPO3v14\Yaml\MigrateLegacyFormTemplatesFractor;
6+
7+
use a9f\Fractor\Testing\PHPUnit\AbstractFractorTestCase;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
10+
final class MigrateLegacyFormTemplatesFractorTest extends AbstractFractorTestCase
11+
{
12+
#[DataProvider('provideData')]
13+
public function test(string $filePath): void
14+
{
15+
$this->doTestFile($filePath);
16+
}
17+
18+
public static function provideData(): \Iterator
19+
{
20+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixtures', '*.yaml.fixture');
21+
}
22+
23+
public function provideConfigFilePath(): string
24+
{
25+
return __DIR__ . '/config/fractor.php';
26+
}
27+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use a9f\Fractor\Configuration\FractorConfiguration;
6+
use a9f\Fractor\ValueObject\Indent;
7+
use a9f\FractorXml\Configuration\XmlProcessorOption;
8+
use a9f\Typo3Fractor\TYPO3v14\Yaml\MigrateLegacyFormTemplatesFractor;
9+
10+
return FractorConfiguration::configure()
11+
->withOptions([
12+
XmlProcessorOption::INDENT_CHARACTER => Indent::STYLE_TAB,
13+
XmlProcessorOption::INDENT_SIZE => 1,
14+
])
15+
->withRules([MigrateLegacyFormTemplatesFractor::class]);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\Typo3Fractor\TYPO3v14\Yaml;
6+
7+
use a9f\FractorYaml\Contract\YamlFractorRule;
8+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
9+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
10+
11+
/**
12+
* @changelog https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.0/Breaking-106596-RemoveLegacyFormTemplates.html
13+
* @see \a9f\Typo3Fractor\Tests\TYPO3v14\Yaml\MigrateLegacyFormTemplatesFractor\MigrateLegacyFormTemplatesFractorTest
14+
*/
15+
final class MigrateLegacyFormTemplatesFractor implements YamlFractorRule
16+
{
17+
public function getRuleDefinition(): RuleDefinition
18+
{
19+
return new RuleDefinition('Migrate legacy form templates', [new CodeSample(
20+
<<<'CODE_SAMPLE'
21+
prototypes:
22+
standard:
23+
formElementsDefinition:
24+
Text:
25+
variants:
26+
-
27+
identifier: template-variant
28+
condition: 'getRootFormProperty("renderingOptions.templateVariant") == "version2"'
29+
properties:
30+
containerClassAttribute: 'form-element form-element-text mb-3'
31+
elementClassAttribute: form-control
32+
elementErrorClassAttribute: ~
33+
labelClassAttribute: form-label
34+
CODE_SAMPLE
35+
,
36+
<<<'CODE_SAMPLE'
37+
prototypes:
38+
standard:
39+
formElementsDefinition:
40+
Text:
41+
properties:
42+
containerClassAttribute: 'form-element form-element-text mb-3'
43+
elementClassAttribute: form-control
44+
elementErrorClassAttribute: ~
45+
labelClassAttribute: form-label
46+
CODE_SAMPLE
47+
)]);
48+
}
49+
50+
public function refactor(array $yaml): array
51+
{
52+
return $this->traverse($yaml);
53+
}
54+
55+
/**
56+
* @param mixed[] $yaml
57+
* @return mixed[]
58+
*/
59+
private function traverse(array $yaml): array
60+
{
61+
foreach ($yaml as $key => $value) {
62+
if (is_array($value)) {
63+
$yaml[$key] = $this->traverse($value);
64+
}
65+
}
66+
67+
if (isset($yaml['variants']) && is_array($yaml['variants'])) {
68+
$properties = $yaml['properties'] ?? [];
69+
$remainingVariants = [];
70+
$hasChanges = false;
71+
72+
foreach ($yaml['variants'] as $variant) {
73+
// Check if the variant condition matches the deprecated one
74+
if (isset($variant['condition']) && $this->isVersion2Condition($variant['condition'])) {
75+
if (isset($variant['properties']) && is_array($variant['properties'])) {
76+
// Merge properties: variant properties overwrite existing ones
77+
$properties = array_replace_recursive($properties, $variant['properties']);
78+
}
79+
$hasChanges = true;
80+
} else {
81+
$remainingVariants[] = $variant;
82+
}
83+
}
84+
85+
if ($hasChanges) {
86+
$yaml['properties'] = $properties;
87+
88+
if ($remainingVariants === []) {
89+
unset($yaml['variants']);
90+
} else {
91+
$yaml['variants'] = $remainingVariants;
92+
}
93+
}
94+
}
95+
96+
return $yaml;
97+
}
98+
99+
private function isVersion2Condition(string $condition): bool
100+
{
101+
// Normalize quotes and whitespace for comparison
102+
$normalized = str_replace(["'", ' '], ['"', ''], $condition);
103+
return $normalized === 'getRootFormProperty("renderingOptions.templateVariant")=="version2"';
104+
}
105+
}

0 commit comments

Comments
 (0)