Initialize project

Provide first implementation with basic setup.
This commit is contained in:
Daniel Siepmann 2023-06-27 16:03:07 +02:00
parent 10ae3f5783
commit c7fe2ae955
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
24 changed files with 1024 additions and 1 deletions

11
.gitattributes vendored Normal file
View file

@ -0,0 +1,11 @@
Tests export-ignore
.github export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.php-cs-fixer.dist.php export-ignore
phpstan.neon export-ignore
phpunit.xml.dist export-ignore
shell.nix export-ignore

144
.github/workflows/ci.yaml vendored Normal file
View file

@ -0,0 +1,144 @@
name: CI
on:
- pull_request
jobs:
check-composer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Validate composer.json
run: nix-shell --pure --run project-validate-composer
php-linting:
runs-on: ubuntu-latest
strategy:
matrix:
php-version:
- 8.0
- 8.1
- 8.2
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
tools: composer:v2
- name: PHP lint
run: "find *.php Classes Configuration Tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l"
xml-linting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Validate XML
run: nix-shell --pure --run project-validate-xml
coding-guideline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Check Coding Guideline
run: nix-shell --pure --run project-coding-guideline
code-quality:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- php-version: '8.0'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^11.5'
- php-version: '8.2'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^12.4'
- php-version: '8.2'
typo3-version: '^12.4'
steps:
- uses: actions/checkout@v3
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
tools: composer:v2
- name: Install dependencies
run: composer req "typo3/cms-core:${{ matrix.typo3-version }}" --prefer-dist --no-progress --no-interaction
- name: Code Quality (by PHPStan)
run: ./vendor/bin/phpstan analyse
tests-mysql:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- php-version: '8.0'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^11.5'
- php-version: '8.2'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^12.4'
- php-version: '8.2'
typo3-version: '^12.4'
steps:
- uses: actions/checkout@v3
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
tools: composer:v2
- name: Setup MySQL
uses: mirromutth/mysql-action@v1.1
with:
mysql version: '8'
mysql database: 'typo3'
mysql root password: 'root'
- name: Wait for MySQL
run: |
while ! mysqladmin ping --host=127.0.0.1 --password=root --silent; do
sleep 1
done
- name: Install dependencies
run: composer req "typo3/cms-core:${{ matrix.typo3-version }}" --prefer-dist --no-progress --no-interaction
- name: PHPUnit Tests
env:
typo3DatabaseDriver: "pdo_mysql"
typo3DatabaseName: "typo3"
typo3DatabaseHost: "127.0.0.1"
typo3DatabaseUsername: "root"
typo3DatabasePassword: "root"
run: ./vendor/bin/phpunit --testdox

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/composer.lock
/.php-cs-fixer.cache
/.Build/
/vendor/

62
.php-cs-fixer.dist.php Normal file
View file

@ -0,0 +1,62 @@
<?php
$finder = (new PhpCsFixer\Finder())
->ignoreVCSIgnored(true)
->in(realpath(__DIR__));
return (new \PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@DoctrineAnnotation' => true,
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_line_after_opening_tag' => true,
'braces' => ['allow_single_line_closure' => true],
'cast_spaces' => ['space' => 'none'],
'compact_nullable_typehint' => true,
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'],
'dir_constant' => true,
'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']],
'function_typehint_space' => true,
'lowercase_cast' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'modernize_strpos' => true,
'modernize_types_casting' => true,
'native_function_casing' => true,
'new_with_braces' => true,
'no_alias_functions' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_null_property_initialization' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_superfluous_elseif' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_whitespace_in_blank_line' => true,
'ordered_imports' => true,
'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']],
'php_unit_mock_short_will_return' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'phpdoc_no_access' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_no_package' => true,
'phpdoc_scalar' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'return_type_declaration' => ['space_before' => 'none'],
'single_quote' => true,
'single_line_comment_style' => ['comment_types' => ['hash']],
'single_trait_insert_per_statement' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
'whitespace_after_comma_in_array' => true,
'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false],
])
->setFinder($finder);

View file

@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
/*
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
namespace WerkraumMedia\FormFileCollection\Form\FormElement;
use TYPO3\CMS\Core\Resource\FileCollectionRepository;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement;
/**
* Elements are created with constructor arguments and don't have DI available.
*/
final class FileCollectionElement extends AbstractFormElement
{
public function setProperty(string $key, $value): void
{
if ($key === 'fileCollection' && is_array($value)) {
$this->setProperty('options', $this->getOptions($value));
return;
}
parent::setProperty($key, $value);
}
/**
* @param array<string, string> $configuration
* @return array<string, string>
*/
public function getOptions(array $configuration): array
{
$uid = (int)($configuration['uid'] ?? 0);
$collection = $this->getRepository()->findByUid($uid);
if ($collection === null) {
return [];
}
if (method_exists($collection, 'loadContents')) {
$collection->loadContents();
}
$options = [];
foreach ($collection->getItems() as $file) {
if (!$file instanceof FileInterface) {
continue;
}
$options = $this->addOption($configuration, $options, $file);
}
return $options;
}
/**
* @param array<string, string> $configuration
* @param array<string, string> $options
*
* @return array<string, string>
*/
private function addOption(
array $configuration,
array $options,
FileInterface $file
): array {
$value = $file->getProperty($configuration['valueProperty'] ?? 'identifier');
$label = $file->getProperty($configuration['labelProperty'] ?? 'identifier');
$options[$value] = $label;
return $options;
}
private function getRepository(): FileCollectionRepository
{
return GeneralUtility::makeInstance(FileCollectionRepository::class);
}
}

View file

@ -0,0 +1,8 @@
TYPO3:
CMS:
Form:
prototypes:
standard:
formElementsDefinition:
FileCollection:
implementationClassName: WerkraumMedia\FormFileCollection\Form\FormElement\FileCollectionElement

View file

@ -1 +0,0 @@
# form_file_collection

62
README.rst Normal file
View file

@ -0,0 +1,62 @@
====================================
TYPO3 Extension Form File Collection
====================================
Adds new EXT:form element used to render a file collection allowing the visitor to choose files.
Concept
=======
The form element will fetch the configured file collection and assign proper options based on the contained files.
That allows for using existing templates that allow to select one or multiple options.
EXT:form integration
====================
The provided Configuration needs to be loaded via TypoScript.
Use a free identifier:
.. code:: plain
plugin.tx_form.settings.yamlConfigurations {
80 = EXT:form_file_collection/Configuration/Form/Setup.yaml
}
This will register a new form element type ``FileCollection`` that can be used like this:
.. code:: yaml
-
type: FileCollection
identifier: file-collection-1
label: 'File Collection'
properties:
fileCollection:
# UID of the sys_file_collection to use
uid: 1
# Optional, default is identifier
# Defines the property to use as value for form element.
valueProperty: 'identifier'
# Optional, default is identifier
# 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'
Example
-------
A concrete example can be found within ``Tests/Fixtures/form_file_collection_example``.

View file

@ -0,0 +1,66 @@
<?php
return [
'pages' => [
[
'uid' => 1,
'pid' => 0,
'slug' => '/',
'title' => 'Page Title',
],
[
'uid' => 2,
'pid' => 1,
'slug' => '/page-2',
'title' => 'Page 2 Title',
],
],
'tt_content' => [
[
'uid' => 1,
'pid' => 1,
'header' => 'Form',
'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/Example.form.yaml</value>
</field>
<field index="settings.overrideFinishers">
<value index="vDEF">0</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
],
[
'uid' => 2,
'pid' => 2,
'header' => 'Form',
'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/ExampleCustomLabelAndValue.form.yaml</value>
</field>
<field index="settings.overrideFinishers">
<value index="vDEF">0</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
],
],
];

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -0,0 +1,41 @@
<?php
return [
'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 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' => 2,
],
],
];

View file

@ -0,0 +1,32 @@
base: /
languages:
-
title: English
enabled: true
base: /
typo3Language: default
locale: en_GB.UTF-8
iso-639-1: en
websiteTitle: ''
navigationTitle: English
hreflang: en-GB
direction: ''
flag: gb
languageId: 0
fallbackType: strict
fallbacks: '0'
-
title: Deutsch
enabled: true
base: /de
typo3Language: de
locale: de_DE.UTF-8
iso-639-1: de
navigationTitle: Deutsch
hreflang: de-DE
direction: ''
flag: de
websiteTitle: ''
languageId: 1
rootPageId: 1
websiteTitle: 'Example Website'

View file

@ -0,0 +1,66 @@
<?php
return [
'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',
],
[
'uid' => 2,
'pid' => 0,
'missing' => 0,
'storage' => 1,
'type' => 2,
'metadata' => 0,
'identifier' => '/Files/SecondResult.png',
'identifier_hash' => '29b827d0daa29658d8a0d952dfd20f559bbe3bcf',
'folder_hash' => '86d12d536195df2100a5ec04ab80c08f9bed3d31',
'extension' => 'png',
'mime_type' => 'image/png',
'name' => 'SecondResult.png',
'sha1' => 'b13f2bbf275d592534eab659c1430c2702ce31fc',
'size' => '42383',
],
],
'sys_file_collection' => [
[
'uid' => 1,
'pid' => 1,
'title' => 'Example 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' => 2,
],
[
'uid' => 2,
'pid' => 1,
'uid_local' => 2,
'uid_foreign' => 1,
'tablenames' => 'sys_file_collection',
'fieldname' => 'files',
'sorting_foreign' => 1,
],
],
];

View file

@ -0,0 +1,34 @@
renderingOptions:
submitButtonLabel: Submit
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: FileCollection
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'

View file

@ -0,0 +1,36 @@
renderingOptions:
submitButtonLabel: Submit
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: FileCollection
identifier: file-collection-1
label: 'File Collection'
properties:
fileCollection:
uid: 1
valueProperty: 'identifier_hash'
labelProperty: 'mime_type'
-
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'

View file

@ -0,0 +1,14 @@
TYPO3:
CMS:
Form:
persistenceManager:
allowedExtensionPaths:
10: EXT:form_file_collection_example/Configuration/Forms/
prototypes:
standard:
formElementsDefinition:
FileCollection:
renderingOptions:
# Allows to switch between different rendering like "Checkbox", "MultiCheckbox" or "RadioButton", etc.
templateName: 'MultiCheckbox'

View file

@ -0,0 +1,10 @@
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:form/Configuration/TypoScript/setup.typoscript">
plugin.tx_form.settings.yamlConfigurations {
80 = EXT:form_file_collection/Configuration/Form/Setup.yaml
90 = EXT:form_file_collection_example/Configuration/Forms/Setup.yaml
}
page >
page = PAGE
page.10 =< styles.content.get

View file

@ -0,0 +1,16 @@
{
"name": "werkraummedia/form-file-collection-example",
"description": "Example usage of form file collection",
"type": "typo3-cms-extension",
"license": "GPL-2.0-or-later",
"require": {
"typo3/cms-core": "*",
"typo3/cms-form": "*",
"werkraummedia/form-file-collection": "*"
},
"extra": {
"typo3/cms": {
"extension-key": "form_file_collection_example"
}
}
}

View file

@ -0,0 +1,122 @@
<?php
declare(strict_types=1);
/*
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
namespace WerkraumMedia\FormFileCollection\Tests\Functional;
use Codappix\Typo3PhpDatasets\TestingFramework;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
class FormIntegrationTest extends FunctionalTestCase
{
use TestingFramework;
public function setUp(): void
{
$this->coreExtensionsToLoad = [
'fluid_styled_content',
'form',
];
$this->testExtensionsToLoad = [
'typo3conf/ext/form_file_collection',
'typo3conf/ext/form_file_collection/Tests/Fixtures/form_file_collection_example',
];
$this->pathsToLinkInTestInstance = [
'typo3conf/ext/form_file_collection/Tests/Fixtures/Sites' => 'typo3conf/sites',
'typo3conf/ext/form_file_collection/Tests/Fixtures/Fileadmin/Files' => 'fileadmin/Files',
];
parent::setUp();
$this->importPHPDataSet(__DIR__ . '/../Fixtures/BasicDatabase.php');
$this->setUpFrontendRootPage(1, [
'setup' => [
'EXT:fluid_styled_content/Configuration/TypoScript/setup.typoscript',
'EXT:form_file_collection_example/Configuration/TypoScript/Form.typoscript',
],
]);
}
/**
* @test
*/
public function rendersFileFromSelectedCollection(): void
{
$this->importPHPDataSet(__DIR__ . '/../Fixtures/SingleFileDatabase.php');
$request = new InternalRequest();
$response = $this->executeFrontendRequest($request);
$content = $response->getBody()->__toString();
self::assertStringContainsString('name="tx_form_formframework[test-1][file-collection-1]"', $content);
self::assertStringContainsString('FirstResult.png', $content);
self::assertStringContainsString('value="/Files/FirstResult.png"', $content);
self::assertStringContainsString('<span>/Files/FirstResult.png</span>', $content);
self::assertStringNotContainsString('SecondResult.png', $content);
}
/**
* @test
*/
public function providesMultipleFilesFromSelectedCollection(): void
{
$this->importPHPDataSet(__DIR__ . '/../Fixtures/TwoFilesDatabase.php');
$request = new InternalRequest();
$response = $this->executeFrontendRequest($request);
$content = $response->getBody()->__toString();
self::assertStringContainsString('name="tx_form_formframework[test-1][file-collection-1][]"', $content);
self::assertStringContainsString('FirstResult.png', $content);
self::assertStringContainsString('value="/Files/FirstResult.png"', $content);
self::assertStringContainsString('<span>/Files/FirstResult.png</span>', $content);
self::assertStringContainsString('SecondResult.png', $content);
self::assertStringContainsString('value="/Files/SecondResult.png"', $content);
self::assertStringContainsString('<span>/Files/SecondResult.png</span>', $content);
}
/**
* @test
*/
public function rendersConfiguredLabel(): void
{
$this->importPHPDataSet(__DIR__ . '/../Fixtures/SingleFileDatabase.php');
$request = new InternalRequest();
$request = $request->withPageId(2);
$response = $this->executeFrontendRequest($request);
$content = $response->getBody()->__toString();
self::assertStringContainsString('name="tx_form_formframework[test-2][file-collection-1][]"', $content);
self::assertStringContainsString('value="29b827d0daa29658d8a0d952dfd20f559bbe3bcf"', $content);
self::assertStringContainsString('<span>image/png</span>', $content);
}
}

68
composer.json Normal file
View file

@ -0,0 +1,68 @@
{
"name": "werkraummedia/form-file-collection",
"description": "Add a form element to render file collection to EXT:form of TYPO3",
"type": "typo3-cms-extension",
"license": "GPL-2.0-or-later",
"homepage": "https://github.com/werkraum-media/form_file_collection",
"support": {
"docs": "https://docs.typo3.org/p/werkraummedia/form_file_collection/master/en-us/",
"email": "coding@daniel-siepmann.de",
"issues": "https://github.com/werkraum-media/form_file_collection/issues",
"source": "https://github.com/werkraum-media/form_file_collection"
},
"authors": [
{
"name": "Daniel Siepmann",
"email": "coding@daniel-siepmann.de",
"homepage": "https://daniel-siepmann.de/",
"role": "Developer"
}
],
"autoload": {
"psr-4": {
"WerkraumMedia\\FormFileCollection\\": "Classes/"
}
},
"autoload-dev": {
"psr-4": {
"WerkraumMedia\\FormFileCollection\\Tests\\": "Tests/",
"WerkraumMedia\\FormFileCollectionExample\\": "Tests/Fixtures/form_file_collection_example/Classes/"
}
},
"require": {
"php": "~8.0.0 || ~8.1.0 || ~8.2.0",
"typo3/cms-backend": "^11.5 || ^12.4",
"typo3/cms-core": "^11.5 || ^12.4",
"typo3/cms-fluid-styled-content": "^11.5 || ^12.4",
"typo3/cms-form": "^11.5 || ^12.4",
"typo3/cms-frontend": "^11.5 || ^12.4"
},
"require-dev": {
"codappix/typo3-php-datasets": "^1.3",
"friendsofphp/php-cs-fixer": "^3.11",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5",
"saschaegerer/phpstan-typo3": "^1.8",
"typo3/testing-framework": "^7.0"
},
"config": {
"sort-packages": true,
"lock": false,
"allow-plugins": {
"typo3/cms-composer-installers": true,
"typo3/class-alias-loader": true,
"ocramius/package-versions": true,
"phpstan/extension-installer": true,
"cweagans/composer-patches": true
}
},
"extra": {
"typo3/cms": {
"app-dir": ".Build",
"extension-key": "form_file_collection",
"web-dir": ".Build/web"
}
}
}

6
phpstan.neon Normal file
View file

@ -0,0 +1,6 @@
parameters:
level: max
paths:
- Classes
- Tests
reportUnmatchedIgnoredErrors: true

35
phpunit.xml.dist Normal file
View file

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/typo3/testing-framework/Resources/Core/Build/FunctionalTestsBootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
verbose="false"
>
<testsuites>
<testsuite name="functional">
<directory>Tests/Functional/</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">Classes</directory>
</include>
</coverage>
<php>
<env name="typo3DatabaseDriver" value="pdo_sqlite"/>
</php>
</phpunit>

91
shell.nix Normal file
View file

@ -0,0 +1,91 @@
{
pkgs ? import <nixpkgs> { }
}:
let
php = pkgs.php82.buildEnv {
extensions = { enabled, all }: enabled ++ (with all; [
xdebug
]);
extraConfig = ''
xdebug.mode = debug
memory_limit = 4G
'';
};
inherit(php.packages) composer;
projectInstall = pkgs.writeShellApplication {
name = "project-install";
runtimeInputs = [
php
composer
];
text = ''
rm -rf .Build/ vendor/
composer install --prefer-dist --no-progress --working-dir="$PROJECT_ROOT"
'';
};
projectValidateComposer = pkgs.writeShellApplication {
name = "project-validate-composer";
runtimeInputs = [
php
composer
];
text = ''
composer validate
'';
};
projectValidateXml = pkgs.writeShellApplication {
name = "project-validate-xml";
runtimeInputs = [
pkgs.libxml2
pkgs.wget
projectInstall
];
text = ''
project-install
xmllint --schema vendor/phpunit/phpunit/phpunit.xsd --noout phpunit.xml.dist
'';
};
projectCodingGuideline = pkgs.writeShellApplication {
name = "project-coding-guideline";
runtimeInputs = [
php
projectInstall
];
text = ''
project-install
./vendor/bin/php-cs-fixer fix --dry-run --diff
'';
};
projectCodingGuidelineFix = pkgs.writeShellApplication {
name = "project-coding-guideline-fix";
runtimeInputs = [
php
projectInstall
];
text = ''
project-install
./vendor/bin/php-cs-fixer fix
'';
};
in pkgs.mkShell {
name = "TYPO3 Extension FormFileCollection";
buildInputs = [
projectInstall
projectValidateComposer
projectValidateXml
projectCodingGuideline
projectCodingGuidelineFix
php
composer
];
shellHook = ''
export PROJECT_ROOT="$(pwd)"
export typo3DatabaseDriver=pdo_sqlite
'';
}