mirror of
https://github.com/werkraum-media/form_file_collection.git
synced 2024-12-22 13:16:10 +01:00
Add files to template (#2)
Allow to implement custom templates working with files, e.g. providing a thumbnail, link to full file, etc.
This commit is contained in:
parent
e635b66d36
commit
5bb586a19a
9 changed files with 222 additions and 22 deletions
3
.github/workflows/ci.yaml
vendored
3
.github/workflows/ci.yaml
vendored
|
@ -131,6 +131,9 @@ jobs:
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
- name: Install graphicsmagick
|
||||||
|
run: sudo apt-get install -y graphicsmagick
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer req "typo3/cms-core:${{ matrix.typo3-version }}" --prefer-dist --no-progress --no-interaction
|
run: composer req "typo3/cms-core:${{ matrix.typo3-version }}" --prefer-dist --no-progress --no-interaction
|
||||||
|
|
||||||
|
|
|
@ -36,19 +36,29 @@ final class FileCollectionElement extends AbstractFormElement
|
||||||
public function setProperty(string $key, $value): void
|
public function setProperty(string $key, $value): void
|
||||||
{
|
{
|
||||||
if ($key === 'fileCollection' && is_array($value)) {
|
if ($key === 'fileCollection' && is_array($value)) {
|
||||||
$this->setProperty('options', $this->getOptions($value));
|
$this->setFileCollection($value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setProperty($key, $value);
|
parent::setProperty($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $value
|
||||||
|
*/
|
||||||
|
private function setFileCollection(array $value): void
|
||||||
|
{
|
||||||
|
$files = $this->getFiles($value);
|
||||||
|
$this->setProperty('files', $files);
|
||||||
|
$this->setProperty('options', $this->getOptions($value, $files));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, string> $configuration
|
* @param array<string, string> $configuration
|
||||||
*
|
*
|
||||||
* @return array<string, string>
|
* @return FileInterface[]
|
||||||
*/
|
*/
|
||||||
public function getOptions(array $configuration): array
|
private function getFiles(array $configuration): array
|
||||||
{
|
{
|
||||||
$uid = (int)($configuration['uid'] ?? 0);
|
$uid = (int)($configuration['uid'] ?? 0);
|
||||||
$collection = $this->getRepository()->findByUid($uid);
|
$collection = $this->getRepository()->findByUid($uid);
|
||||||
|
@ -60,12 +70,20 @@ final class FileCollectionElement extends AbstractFormElement
|
||||||
$collection->loadContents();
|
$collection->loadContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = [];
|
return $collection->getItems();
|
||||||
foreach ($collection->getItems() as $file) {
|
|
||||||
if (!$file instanceof FileInterface) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $configuration
|
||||||
|
* @param FileInterface[] $files
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getOptions(array $configuration, array $files): array
|
||||||
|
{
|
||||||
|
$options = [];
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
$options = $this->addOption($configuration, $options, $file);
|
$options = $this->addOption($configuration, $options, $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
README.rst
33
README.rst
|
@ -22,6 +22,24 @@ Use a free identifier:
|
||||||
80 = EXT:form_file_collection/Configuration/Form/Setup.yaml
|
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:
|
This will register a new form element type ``FileCollection`` that can be used like this:
|
||||||
|
|
||||||
.. code:: yaml
|
.. 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.
|
# Defines the property to use as label for form element.
|
||||||
labelProperty: 'identifier'
|
labelProperty: 'identifier'
|
||||||
|
|
||||||
No template is configured by default, choose one of the existing ones or provide your own:
|
The two options `valueProperty` and `labelProperty` are used to prepare the `options` variable used by the available default templates.
|
||||||
|
|
||||||
.. code:: yaml
|
|
||||||
|
|
||||||
TYPO3:
|
|
||||||
CMS:
|
|
||||||
Form:
|
|
||||||
prototypes:
|
|
||||||
standard:
|
|
||||||
formElementsDefinition:
|
|
||||||
FileCollection:
|
|
||||||
renderingOptions:
|
|
||||||
# Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc.
|
|
||||||
templateName: 'MultiCheckbox'
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
16
Resources/Public/Icons/Extension.svg
Normal file
16
Resources/Public/Icons/Extension.svg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 27.7.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="b" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#333333;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<g id="c">
|
||||||
|
<path class="st0" d="M16,16H0V0h16V16z"/>
|
||||||
|
<path class="st1" d="M8.9,2.5H5.3c-0.8,0-1.4,0.6-1.4,1.4v8.2c0,0.8,0.6,1.4,1.4,1.4h5.5c0.8,0,1.4-0.6,1.4-1.4V5.7
|
||||||
|
c0-0.2-0.1-0.4-0.2-0.5L9.4,2.7C9.2,2.6,9.1,2.5,8.9,2.5z M9,4.9V3.5l2.1,2.1H9.7C9.3,5.6,9,5.3,9,4.9z M10,7.9L7.9,10
|
||||||
|
c-0.1,0.1-0.4,0.1-0.5,0c0,0,0,0,0,0l-1-1c-0.1-0.1-0.1-0.4,0-0.5c0.1-0.1,0.4-0.1,0.5,0l0.8,0.8l1.8-1.8c0.1-0.1,0.4-0.1,0.5,0
|
||||||
|
C10.1,7.5,10.1,7.8,10,7.9z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 869 B |
76
Tests/Fixtures/CustomTemplate.php
Normal file
76
Tests/Fixtures/CustomTemplate.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'pages' => [
|
||||||
|
[
|
||||||
|
'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' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||||
|
<T3FlexForms>
|
||||||
|
<data>
|
||||||
|
<sheet index="sDEF">
|
||||||
|
<language index="lDEF">
|
||||||
|
<field index="settings.persistenceIdentifier">
|
||||||
|
<value index="vDEF">EXT:form_file_collection_example/Configuration/Forms/ExampleCustomTemplate.form.yaml</value>
|
||||||
|
</field>
|
||||||
|
<field index="settings.overrideFinishers">
|
||||||
|
<value index="vDEF">0</value>
|
||||||
|
</field>
|
||||||
|
</language>
|
||||||
|
</sheet>
|
||||||
|
</data>
|
||||||
|
</T3FlexForms>
|
||||||
|
',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'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',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
|
@ -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'
|
|
@ -12,3 +12,8 @@ TYPO3:
|
||||||
renderingOptions:
|
renderingOptions:
|
||||||
# Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc.
|
# Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc.
|
||||||
templateName: 'MultiCheckbox'
|
templateName: 'MultiCheckbox'
|
||||||
|
FileCollectionCustomTemplate:
|
||||||
|
implementationClassName: WerkraumMedia\FormFileCollection\Form\FormElement\FileCollectionElement
|
||||||
|
renderingOptions:
|
||||||
|
# Use custom template, ensure it can be found within partialRootPaths
|
||||||
|
templateName: 'Custom'
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||||
|
data-namespace-typo3-fluid="true"
|
||||||
|
>
|
||||||
|
|
||||||
|
<formvh:renderRenderable renderable="{element}">
|
||||||
|
<f:render partial="Field/Field" arguments="{element: element}" contentAs="elementContent">
|
||||||
|
<f:for each="{element.properties.files}" as="file" iteration="idIterator">
|
||||||
|
<f:form.checkbox
|
||||||
|
property="{element.identifier}"
|
||||||
|
multiple="1"
|
||||||
|
id="{element.uniqueIdentifier}-{idIterator.index}"
|
||||||
|
class="{element.properties.elementClassAttribute}"
|
||||||
|
value="{file.title}"
|
||||||
|
errorClass="{element.properties.elementErrorClassAttribute}"
|
||||||
|
additionalAttributes="{formvh:translateElementProperty(element: element, property: 'fluidAdditionalAttributes')}"
|
||||||
|
/>
|
||||||
|
{file.properties.title}
|
||||||
|
{file.properties.description}
|
||||||
|
<f:image image="{file}" width="100"/>
|
||||||
|
</f:for>
|
||||||
|
</f:render>
|
||||||
|
</formvh:renderRenderable>
|
||||||
|
|
||||||
|
</html>
|
|
@ -119,4 +119,21 @@ class FormIntegrationTest extends FunctionalTestCase
|
||||||
self::assertStringContainsString('value="29b827d0daa29658d8a0d952dfd20f559bbe3bcf"', $content);
|
self::assertStringContainsString('value="29b827d0daa29658d8a0d952dfd20f559bbe3bcf"', $content);
|
||||||
self::assertStringContainsString('<span>image/png</span>', $content);
|
self::assertStringContainsString('<span>image/png</span>', $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('<img src="/fileadmin/_processed_/2/9/csm_FirstResult_0f8fa1bb68.png" width="100" height="40" alt="Alternative" title="Example title for form" />', $content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue