Skip to content

Commit

Permalink
[FEATURE] Add file, files, filereference and filereferences form data…
Browse files Browse the repository at this point in the history
… transform types

A `flux:field.inline.fal` with transform types will result in:

* `transform="file"` gives File instance
* `transform="files"` gives array of File instances
* `transform="filereference"` gives FileReference instance
* `transform="filereferences"` gives array of FileReferences instances
  • Loading branch information
NamelessCoder committed Jul 15, 2023
1 parent bd6d31e commit d14ca2f
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 9 deletions.
33 changes: 32 additions & 1 deletion Classes/Form/Transformation/FormDataTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@
use FluidTYPO3\Flux\Form\ContainerInterface;
use FluidTYPO3\Flux\Form\FieldInterface;
use FluidTYPO3\Flux\Hooks\HookHandler;
use TYPO3\CMS\Core\Resource\FileRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
use TYPO3\CMS\Extbase\Persistence\RepositoryInterface;

class FormDataTransformer
{
private FileRepository $fileRepository;

public function __construct(FileRepository $fileRepository)
{
$this->fileRepository = $fileRepository;
}

/**
* Transforms members on $values recursively according to the provided
* Flux configuration extracted from a Flux template. Uses "transform"
Expand Down Expand Up @@ -96,7 +104,30 @@ protected function extractTransformableObjectByPath(ContainerInterface $subject,
*/
protected function transformValueToType(string $value, string $dataType, string $fieldName, Form $form)
{
if ('int' === $dataType || 'integer' === $dataType) {
if (in_array($dataType, ['file', 'files', 'filereference', 'filereferences'], true)) {
/** @var string $table */
$table = $form->getOption(Form::OPTION_RECORD_TABLE);
/** @var array $record */
$record = $form->getOption(Form::OPTION_RECORD);
$references = $this->fileRepository->findByRelation($table, $fieldName, $record['uid']);
switch ($dataType) {
case 'file':
if (!empty($references)) {
return $references[0]->getOriginalFile();
}
return null;
case 'files':
$files = [];
foreach ($references as $reference) {
$files[] = $reference->getOriginalFile();
}
return $files;
case 'filereference':
return $references[0] ?? null;
case 'filereferences':
return $references;
}
} elseif ('int' === $dataType || 'integer' === $dataType) {
return intval($value);
} elseif ('float' === $dataType) {
return floatval($value);
Expand Down
2 changes: 2 additions & 0 deletions Classes/Provider/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ public function getForm(array $row, ?string $forField = null): ?Form
?? $this->extractConfiguration($row, 'form', $forField)
?? Form::create();
$form->setOption(Form::OPTION_RECORD, $row);
$form->setOption(Form::OPTION_RECORD_TABLE, $this->getTableName($row));
$form->setOption(Form::OPTION_RECORD_FIELD, $this->getFieldName($row));
return $form;
}

Expand Down
2 changes: 2 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ services:
public: true
FluidTYPO3\Flux\Utility\RenderingContextBuilder:
public: true
FluidTYPO3\Flux\Form\Transformation\FormDataTransformer:
public: true

FluidTYPO3\Flux\Integration\Event\PageContentPreviewRenderingEventListener:
tags:
Expand Down
76 changes: 68 additions & 8 deletions Tests/Unit/Form/Transformation/FormDataTransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use FluidTYPO3\Flux\Form;
use FluidTYPO3\Flux\Form\Transformation\FormDataTransformer;
use FluidTYPO3\Flux\Tests\Unit\AbstractTestCase;
use TYPO3\CMS\Core\Resource\FileRepository;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser;
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserGroupRepository;
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository;
Expand All @@ -22,8 +24,10 @@
*/
class FormDataTransformerTest extends AbstractTestCase
{
private ?FileRepository $fileRepository = null;
private ?FrontendUserRepository $frontendUserRepository = null;
private ?FrontendUser $frontendUser = null;
private ?FormDataTransformer $subject = null;

protected function setUp(): void
{
Expand All @@ -48,6 +52,16 @@ protected function setUp(): void
->disableOriginalConstructor()
->getMock();

$this->fileRepository = $this->getMockBuilder(FileRepository::class)
->onlyMethods(['findByRelation'])
->disableOriginalConstructor()
->getMock();

$this->subject = $this->getMockBuilder(FormDataTransformer::class)
->onlyMethods(['loadObjectsFromRepository'])
->setConstructorArgs([$this->fileRepository])
->getMock();

parent::setUp();
}

Expand All @@ -61,15 +75,12 @@ public function fixtureTransformToFooString(): string
* @param mixed $value
* @param mixed $expected
*/
public function testTransformation($value, string $transformation, $expected)
public function testTransformation($value, string $transformation, $expected): void
{
$instance = $this->getMockBuilder(FormDataTransformer::class)
->setMethods(['loadObjectsFromRepository'])
->getMock();
$instance->method('loadObjectsFromRepository')->willReturn([]);
$this->subject->method('loadObjectsFromRepository')->willReturn([]);
$form = $this->getMockBuilder(Form::class)->setMethods(['dummy'])->getMock();
$form->createField(Form\Field\Input::class, 'field')->setTransform($transformation);
$transformed = $instance->transformAccordingToConfiguration(['field' => $value], $form);
$transformed = $this->subject->transformAccordingToConfiguration(['field' => $value], $form);
$this->assertNotSame(
$expected,
$transformed,
Expand All @@ -94,6 +105,56 @@ public function getValuesAndTransformations(): array
];
}

/**
* @dataProvider getTransformWithFileTargetTypesTestValues
* @param mixed $expected
*/
public function testTransformationWithFileTargetTypes(string $type, array $files, $expected): void
{
$this->fileRepository->method('findByRelation')->willReturn($files);

$form = $this->getMockBuilder(Form::class)->setMethods(['dummy'])->getMock();
$form->setOption(Form::OPTION_RECORD_TABLE, 'tt_content');
$form->setOption(Form::OPTION_RECORD, ['uid' => 1]);

$form->createField(Form\Field\Input::class, 'field')->setTransform($type);
$transformed = $this->subject->transformAccordingToConfiguration(['field' => '1'], $form);

self::assertSame(['field' => $expected], $transformed);
}

public function getTransformWithFileTargetTypesTestValues(): array
{
$file1 = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock();
$fileReference1 = $this->getMockBuilder(FileReference::class)
->onlyMethods(['getOriginalFile'])
->disableOriginalConstructor()
->getMock();
$fileReference1->method('getOriginalFile')->willReturn($file1);

$file2 = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock();
$fileReference2 = $this->getMockBuilder(FileReference::class)
->onlyMethods(['getOriginalFile'])
->disableOriginalConstructor()
->getMock();
$fileReference2->method('getOriginalFile')->willReturn($file2);

return [
'file, non-empty' => ['file', [$fileReference1], $file1],
'files, non-empty' => ['files', [$fileReference1, $fileReference2], [$file1, $file2]],
'filereference, non-empty' => ['filereference', [$fileReference1], $fileReference1],
'filesreferences, non-empty' => [
'filereferences',
[$fileReference1, $fileReference2],
[$fileReference1, $fileReference2]
],
'file, empty' => ['file', [], null],
'files, empty' => ['files', [], []],
'filereference, empty' => ['filereference', [], null],
'filereferences, empty' => ['filereferences', [], []],
];
}

public function testSupportsFindByIdentifiers(): void
{
$repository = $this->getMockBuilder(FrontendUserGroupRepository::class)
Expand All @@ -102,11 +163,10 @@ public function testSupportsFindByIdentifiers(): void
->getMock();
$repository->expects($this->exactly(2))->method('findByUid')->willReturnArgument(0);

$instance = new FormDataTransformer();
$identifiers = array('foobar', 'foobar2');

$result = $this->callInaccessibleMethod(
$instance,
new FormDataTransformer($this->fileRepository),
'loadObjectsFromRepository',
$repository,
$identifiers
Expand Down

0 comments on commit d14ca2f

Please sign in to comment.