Initialize project (#1)

Provide first implementation with basic setup.
This commit is contained in:
Daniel Siepmann 2023-07-03 10:08:33 +02:00 committed by GitHub
parent 10ae3f5783
commit e635b66d36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1027 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/

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

@ -0,0 +1,63 @@
<?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_separation' => 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,97 @@
<?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 using existing templates that allow to select a single 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,5 @@
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:fluid_styled_content/Configuration/TypoScript/setup.typoscript">
page >
page = PAGE
page.10 =< styles.content.get

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,6 @@
<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
}

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:form_file_collection/Tests/Fixtures/Rendering.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
'';
}