Skip to content

Commit

Permalink
[TASK] Introduce AbstractFlexFormRector (#3994)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonschaufi authored Jan 9, 2024
1 parent 27b3bf9 commit f3f8d2a
Show file tree
Hide file tree
Showing 14 changed files with 358 additions and 353 deletions.
175 changes: 95 additions & 80 deletions src/FileProcessor/FlexForms/Rector/v7/v6/RenderTypeFlexFormRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,110 +4,125 @@

namespace Ssch\TYPO3Rector\FileProcessor\FlexForms\Rector\v7\v6;

use DOMDocument;
use DOMElement;
use DOMNode;
use DOMNodeList;
use DOMXPath;
use Ssch\TYPO3Rector\Contract\FileProcessor\FlexForms\Rector\FlexFormRectorInterface;
use Ssch\TYPO3Rector\Helper\FlexFormHelperTrait;
use Ssch\TYPO3Rector\Rector\FlexForm\AbstractFlexFormRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/7.6/Deprecation-69822-DeprecateSelectFieldTca.html
* @see \Ssch\TYPO3Rector\Tests\FileProcessor\FlexForms\Rector\v7\v6\RenderTypeFlexFormRector\RenderTypeFlexFormRectorTest
*/
final class RenderTypeFlexFormRector implements FlexFormRectorInterface
final class RenderTypeFlexFormRector extends AbstractFlexFormRector implements FlexFormRectorInterface
{
public function transform(DOMDocument $domDocument): bool
{
$xpath = new DOMXPath($domDocument);

/** @var DOMNodeList<DOMElement> $elements */
$elements = $xpath->query('//TCEforms/config');
use FlexFormHelperTrait;

$hasChanged = false;
foreach ($elements as $element) {
$type = $element->getElementsByTagName('type')
->item(0);
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add renderType node in FlexForm', [
new CodeSample(
<<<'CODE_SAMPLE'
<T3DataStructure>
<ROOT>
<sheetTitle>aTitle</sheetTitle>
<type>array</type>
<el>
<a_select_field>
<label>Select field</label>
<config>
<type>select</type>
<items>
<numIndex index="0" type="array">
<numIndex index="0">Label</numIndex>
</numIndex>
</items>
</config>
</a_select_field>
</el>
</ROOT>
</T3DataStructure>
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
<T3DataStructure>
<ROOT>
<sheetTitle>aTitle</sheetTitle>
<type>array</type>
<el>
<a_select_field>
<label>Select field</label>
<config>
<type>select</type>
<renderType>selectSingle</renderType>
<items>
<numIndex index="0" type="array">
<numIndex index="0">Label</numIndex>
</numIndex>
</items>
</config>
</a_select_field>
</el>
</ROOT>
</T3DataStructure>
CODE_SAMPLE
),
]);
}

if (! $type instanceof DOMElement) {
continue;
}
protected function refactorColumn(?DOMElement $configElement): void
{
if (! $configElement instanceof DOMElement) {
return;
}

if ($type->textContent !== 'select') {
continue;
}
if (! $this->isConfigType($configElement, 'select')) {
return;
}

$renderType = $element->getElementsByTagName('renderType')
->item(0);
// Do not handle field where the render type is set.
if ($this->hasRenderType($configElement)) {
return;
}

// If renderType is already set, migration can be skipped
if ($renderType instanceof DOMElement) {
continue;
$renderModeDomElement = $this->extractDomElementByKey($configElement, 'renderMode');
if ($renderModeDomElement instanceof DOMElement) {
$renderMode = $renderModeDomElement->nodeValue;
switch ($renderMode) {
case 'tree':
$renderTypeName = 'selectTree';
break;
case 'singlebox':
$renderTypeName = 'selectSingleBox';
break;
case 'checkbox':
$renderTypeName = 'selectCheckBox';
break;
default:
$renderTypeName = null;
}

$renderMode = $element->getElementsByTagName('renderMode')
->item(0);
$size = $element->getElementsByTagName('size')
->item(0);
if ($renderTypeName !== null) {
$configElement->appendChild($this->domDocument->createElement('renderType', $renderTypeName));

$renderTypeName = 'selectSingle';
$insertBefore = $type;

if ($renderMode instanceof DOMNode) {
$renderTypeName = 'selectTree';
$insertBefore = $renderMode;
} elseif ($size instanceof DOMNode && (int) $size->textContent > 1) {
// Could be also selectCheckBox. This is a sensitive default
$renderTypeName = 'selectMultipleSideBySide';
$this->domDocumentHasBeenChanged = true;
}

$renderType = $domDocument->createElement('renderType', $renderTypeName);
return;
}

if (! $insertBefore->parentNode instanceof DOMNode) {
continue;
}
$maxItemsDomElement = $this->extractDomElementByKey($configElement, 'maxitems');
if ($maxItemsDomElement instanceof DOMElement) {
$maxItems = (int) $maxItemsDomElement->nodeValue;

if (! $insertBefore->nextSibling instanceof DOMNode) {
continue;
}

$hasChanged = true;
$insertBefore->parentNode->insertBefore($renderType, $insertBefore->nextSibling);
$insertBefore->parentNode->insertBefore($domDocument->createTextNode("\n"), $insertBefore->nextSibling);
$renderTypeName = $maxItems <= 1 ? 'selectSingle' : 'selectMultipleSideBySide';
} else {
$renderTypeName = 'selectSingle';
}

return $hasChanged;
}
$configElement->appendChild($this->domDocument->createElement('renderType', $renderTypeName));

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add renderType node in Flexforms xml', [
new CodeSample(
<<<'CODE_SAMPLE'
<type>select</type>
<items>
<numIndex index="0" type="array">
<numIndex index="0">
LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:flexforms_general.no-constraint
</numIndex>
</numIndex>
</items>
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
<type>select</type>
<renderType>selectSingle</renderType>
<items>
<numIndex index="0" type="array">
<numIndex index="0">
LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:flexforms_general.no-constraint
</numIndex>
</numIndex>
</items>
CODE_SAMPLE
),
]);
$this->domDocumentHasBeenChanged = true;
}
}
39 changes: 39 additions & 0 deletions src/Rector/FlexForm/AbstractFlexFormRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\Rector\FlexForm;

use DOMDocument;
use DOMElement;
use DOMNodeList;
use DOMXPath;

abstract class AbstractFlexFormRector
{
protected DOMDocument $domDocument;

protected bool $domDocumentHasBeenChanged = false;

public function transform(DOMDocument $domDocument): bool
{
$this->domDocument = $domDocument;

$xpath = new DOMXPath($domDocument);

/** @var DOMNodeList<DOMElement> $elements */
$elements = $xpath->query('//config');

if ($elements->count() === 0) {
return false;
}

foreach ($elements as $element) {
$this->refactorColumn($element);
}

return $this->domDocumentHasBeenChanged;
}

abstract protected function refactorColumn(?DOMElement $configElement): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,23 @@

namespace Ssch\TYPO3Rector\Rector\v12\v0\flexform;

use DOMDocument;
use DOMElement;
use DOMNodeList;
use DOMXPath;
use Ssch\TYPO3Rector\Contract\FileProcessor\FlexForms\Rector\FlexFormRectorInterface;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
use Ssch\TYPO3Rector\Helper\FlexFormHelperTrait;
use Ssch\TYPO3Rector\Helper\StringUtility;
use Ssch\TYPO3Rector\Rector\FlexForm\AbstractFlexFormRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/12.0/Feature-97013-NewTCATypeEmail.html
* @see \Ssch\TYPO3Rector\Tests\Rector\v12\v0\flexform\MigrateEmailFlagToEmailTypeFlexFormRector\MigrateEmailFlagToEmailTypeFlexFormRectorTest
*/
final class MigrateEmailFlagToEmailTypeFlexFormRector implements FlexFormRectorInterface
final class MigrateEmailFlagToEmailTypeFlexFormRector extends AbstractFlexFormRector implements FlexFormRectorInterface
{
use FlexFormHelperTrait;

private bool $domDocumentHasBeenChanged = false;

public function transform(DOMDocument $domDocument): bool
{
$xpath = new DOMXPath($domDocument);

/** @var DOMNodeList<DOMElement> $elements */
$elements = $xpath->query('//config');

if ($elements->count() === 0) {
return false;
}

foreach ($elements as $element) {
$this->refactorColumn($domDocument, $element);
}

return $this->domDocumentHasBeenChanged;
}

/**
* @codeCoverageIgnore
*/
Expand Down Expand Up @@ -87,7 +65,7 @@ public function getRuleDefinition(): RuleDefinition
)]);
}

private function refactorColumn(DOMDocument $domDocument, ?DOMElement $configElement): void
protected function refactorColumn(?DOMElement $configElement): void
{
if (! $configElement instanceof DOMElement) {
return;
Expand Down Expand Up @@ -116,7 +94,7 @@ private function refactorColumn(DOMDocument $domDocument, ?DOMElement $configEle
}

// Set the TCA type to "email"
$this->changeTcaType($domDocument, $configElement, 'email');
$this->changeTcaType($this->domDocument, $configElement, 'email');

$this->removeChildElementFromDomElementByKey($configElement, 'max');

Expand All @@ -128,7 +106,7 @@ private function refactorColumn(DOMDocument $domDocument, ?DOMElement $configEle
if ($evalList !== []) {
// Write back filtered 'eval'
$evalDomElement->nodeValue = '';
$evalDomElement->appendChild($domDocument->createTextNode(implode(',', $evalList)));
$evalDomElement->appendChild($this->domDocument->createTextNode(implode(',', $evalList)));
} elseif ($evalDomElement->parentNode instanceof DOMElement) {
// 'eval' is empty, remove whole configuration
$evalDomElement->parentNode->removeChild($evalDomElement);
Expand Down
Loading

0 comments on commit f3f8d2a

Please sign in to comment.