diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eb468b6..9860d7e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -131,6 +131,9 @@ jobs: sleep 1 done + - name: Install graphicsmagick + run: sudo apt-get install -y graphicsmagick + - name: Install dependencies run: composer req "typo3/cms-core:${{ matrix.typo3-version }}" --prefer-dist --no-progress --no-interaction diff --git a/Classes/Form/FormElement/FileCollectionElement.php b/Classes/Form/FormElement/FileCollectionElement.php index cff437a..c101976 100644 --- a/Classes/Form/FormElement/FileCollectionElement.php +++ b/Classes/Form/FormElement/FileCollectionElement.php @@ -36,19 +36,29 @@ final class FileCollectionElement extends AbstractFormElement public function setProperty(string $key, $value): void { if ($key === 'fileCollection' && is_array($value)) { - $this->setProperty('options', $this->getOptions($value)); + $this->setFileCollection($value); return; } parent::setProperty($key, $value); } + /** + * @param array $value + */ + private function setFileCollection(array $value): void + { + $files = $this->getFiles($value); + $this->setProperty('files', $files); + $this->setProperty('options', $this->getOptions($value, $files)); + } + /** * @param array $configuration * - * @return array + * @return FileInterface[] */ - public function getOptions(array $configuration): array + private function getFiles(array $configuration): array { $uid = (int)($configuration['uid'] ?? 0); $collection = $this->getRepository()->findByUid($uid); @@ -60,12 +70,20 @@ final class FileCollectionElement extends AbstractFormElement $collection->loadContents(); } - $options = []; - foreach ($collection->getItems() as $file) { - if (!$file instanceof FileInterface) { - continue; - } + return $collection->getItems(); + } + /** + * @param array $configuration + * @param FileInterface[] $files + * + * @return array + */ + public function getOptions(array $configuration, array $files): array + { + $options = []; + + foreach ($files as $file) { $options = $this->addOption($configuration, $options, $file); } diff --git a/README.rst b/README.rst index 1d2c986..582de26 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,24 @@ Use a free identifier: 80 = EXT:form_file_collection/Configuration/Form/Setup.yaml } +No template is configured by default, choose one of the existing ones or provide your own: + +.. code:: yaml + + TYPO3: + CMS: + Form: + prototypes: + standard: + formElementsDefinition: + FileCollection: + renderingOptions: + # Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc. + templateName: 'MultiCheckbox' + +The existing templates will work out of the box. +An additional variable `files` is added for usage within custom templates. + This will register a new form element type ``FileCollection`` that can be used like this: .. code:: yaml @@ -41,20 +59,7 @@ This will register a new form element type ``FileCollection`` that can be used l # Defines the property to use as label for form element. labelProperty: 'identifier' -No template is configured by default, choose one of the existing ones or provide your own: - -.. code:: yaml - - TYPO3: - CMS: - Form: - prototypes: - standard: - formElementsDefinition: - FileCollection: - renderingOptions: - # Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc. - templateName: 'MultiCheckbox' +The two options `valueProperty` and `labelProperty` are used to prepare the `options` variable used by the available default templates. Example ------- diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg new file mode 100644 index 0000000..944dfaf --- /dev/null +++ b/Resources/Public/Icons/Extension.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/Tests/Fixtures/CustomTemplate.php b/Tests/Fixtures/CustomTemplate.php new file mode 100644 index 0000000..8a55600 --- /dev/null +++ b/Tests/Fixtures/CustomTemplate.php @@ -0,0 +1,76 @@ + [ + [ + 'uid' => 3, + 'pid' => 1, + 'slug' => '/page-3', + 'title' => 'Page 3 Custom Template', + ], + ], + 'tt_content' => [ + [ + 'uid' => 3, + 'pid' => 3, + 'header' => 'Form with custom template', + 'header_layout' => '0', + 'CType' => 'form_formframework', + 'pi_flexform' => ' + + + + + + EXT:form_file_collection_example/Configuration/Forms/ExampleCustomTemplate.form.yaml + + + 0 + + + + + + ', + ], + ], + 'sys_file' => [ + [ + 'uid' => 1, + 'pid' => 0, + 'missing' => 0, + 'storage' => 1, + 'type' => 2, + 'metadata' => 0, + 'identifier' => '/Files/FirstResult.png', + 'identifier_hash' => '29b827d0daa29658d8a0d952dfd20f559bbe3bcf', + 'folder_hash' => '86d12d536195df2100a5ec04ab80c08f9bed3d31', + 'extension' => 'png', + 'mime_type' => 'image/png', + 'name' => 'FirstResult.png', + 'sha1' => 'b13f2bbf275d592534eab659c1430c2702ce31fc', + 'size' => '42383', + ], + ], + 'sys_file_collection' => [ + [ + 'uid' => 1, + 'pid' => 1, + 'title' => 'Example Collection for form', + 'files' => 1, + ], + ], + 'sys_file_reference' => [ + [ + 'uid' => 1, + 'pid' => 1, + 'uid_local' => 1, + 'uid_foreign' => 1, + 'tablenames' => 'sys_file_collection', + 'fieldname' => 'files', + 'sorting_foreign' => 1, + 'title' => 'Example title for form', + 'alternative' => 'Alternative', + ], + ], +]; diff --git a/Tests/Fixtures/form_file_collection_example/Configuration/Forms/ExampleCustomTemplate.form.yaml b/Tests/Fixtures/form_file_collection_example/Configuration/Forms/ExampleCustomTemplate.form.yaml new file mode 100644 index 0000000..ab683d2 --- /dev/null +++ b/Tests/Fixtures/form_file_collection_example/Configuration/Forms/ExampleCustomTemplate.form.yaml @@ -0,0 +1,36 @@ +renderingOptions: + submitButtonLabel: Submit + partialRootPaths: + 20: EXT:form_file_collection_example/Resources/Private/Partials/ +type: Form +identifier: test +label: Test +prototypeName: standard +renderables: + - + renderingOptions: + previousButtonLabel: 'Previous step' + nextButtonLabel: 'Next step' + type: Page + identifier: page-1 + label: First Step + renderables: + - + type: FileCollectionCustomTemplate + identifier: file-collection-1 + label: 'File Collection' + properties: + fileCollection: + uid: 1 + - + defaultValue: '' + type: Text + identifier: text-1 + label: 'Example text field' + - + renderingOptions: + previousButtonLabel: 'Previous step' + nextButtonLabel: 'Next step' + type: SummaryPage + identifier: summarypage-1 + label: 'Summary step' diff --git a/Tests/Fixtures/form_file_collection_example/Configuration/Forms/Setup.yaml b/Tests/Fixtures/form_file_collection_example/Configuration/Forms/Setup.yaml index aa74a3a..bc16bf3 100644 --- a/Tests/Fixtures/form_file_collection_example/Configuration/Forms/Setup.yaml +++ b/Tests/Fixtures/form_file_collection_example/Configuration/Forms/Setup.yaml @@ -12,3 +12,8 @@ TYPO3: renderingOptions: # Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc. templateName: 'MultiCheckbox' + FileCollectionCustomTemplate: + implementationClassName: WerkraumMedia\FormFileCollection\Form\FormElement\FileCollectionElement + renderingOptions: + # Use custom template, ensure it can be found within partialRootPaths + templateName: 'Custom' diff --git a/Tests/Fixtures/form_file_collection_example/Resources/Private/Partials/Custom.html b/Tests/Fixtures/form_file_collection_example/Resources/Private/Partials/Custom.html new file mode 100644 index 0000000..7b1105d --- /dev/null +++ b/Tests/Fixtures/form_file_collection_example/Resources/Private/Partials/Custom.html @@ -0,0 +1,24 @@ + + + + + + + {file.properties.title} + {file.properties.description} + + + + + + diff --git a/Tests/Functional/FormIntegrationTest.php b/Tests/Functional/FormIntegrationTest.php index 56cf63d..025cb82 100644 --- a/Tests/Functional/FormIntegrationTest.php +++ b/Tests/Functional/FormIntegrationTest.php @@ -119,4 +119,21 @@ class FormIntegrationTest extends FunctionalTestCase self::assertStringContainsString('value="29b827d0daa29658d8a0d952dfd20f559bbe3bcf"', $content); self::assertStringContainsString('image/png', $content); } + + /** + * @test + */ + public function rendersCustomTemplateWithAccessToFiles(): void + { + $this->importPHPDataSet(__DIR__ . '/../Fixtures/CustomTemplate.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(3); + + $response = $this->executeFrontendRequest($request); + + $content = $response->getBody()->__toString(); + self::assertStringContainsString('name="tx_form_formframework[test-3][file-collection-1][]" value="Example title for form"', $content); + self::assertStringContainsString('Alternative', $content); + } }