From 56991c77a746f76ca7af260c89c6c0e51c5dd2f5 Mon Sep 17 00:00:00 2001 From: mhofmann Date: Wed, 30 Aug 2023 14:38:49 +0200 Subject: [PATCH 1/2] [TASK] Update for TYPO3 v11 --- .../TableConfigurationPostProcessing.php | 13 +- Classes/Listener/PageTsConfig.php | 14 +- Classes/Tca/Registry.php | 42 +- Classes/Tca/SceConfiguration.php | 169 ++-- Configuration/Services.yaml | 10 +- README.md | 6 +- Resources/Private/Language/locallang.xlf | 22 +- Resources/Public/Icons/Extension.svg | 948 +++++++++--------- composer.json | 17 +- ext_emconf.php | 7 +- ext_localconf.php | 18 +- 11 files changed, 594 insertions(+), 672 deletions(-) diff --git a/Classes/Hooks/TableConfigurationPostProcessing.php b/Classes/Hooks/TableConfigurationPostProcessing.php index b56d528..fe6aca0 100644 --- a/Classes/Hooks/TableConfigurationPostProcessing.php +++ b/Classes/Hooks/TableConfigurationPostProcessing.php @@ -18,22 +18,15 @@ class TableConfigurationPostProcessing implements TableConfigurationPostProcessingHookInterface { + protected Registry $tcaRegistry; - /** - * @var Registry - */ - protected $tcaRegistry; - - /** - * @param Registry|null $tcaRegistry - */ public function __construct(Registry $tcaRegistry = null) { $this->tcaRegistry = $tcaRegistry ?? GeneralUtility::makeInstance(Registry::class); } - public function processData() + public function processData(): void { $this->tcaRegistry->registerIcons(); } -} \ No newline at end of file +} diff --git a/Classes/Listener/PageTsConfig.php b/Classes/Listener/PageTsConfig.php index 87f9b8e..b8e7a10 100644 --- a/Classes/Listener/PageTsConfig.php +++ b/Classes/Listener/PageTsConfig.php @@ -14,22 +14,18 @@ use D3M\Sce\Tca\Registry; use TYPO3\CMS\Core\Configuration\Event\ModifyLoadedPageTsConfigEvent; -use TYPO3\CMS\Core\Utility\GeneralUtility; -class PageTsConfig +final class PageTsConfig { - /** - * @var Registry - */ - protected $tcaRegistry; + protected Registry $tcaRegistry; - public function __construct(Registry $tcaRegistry = null) + public function __construct(Registry $tcaRegistry) { - $this->tcaRegistry = $tcaRegistry ?? GeneralUtility::makeInstance(Registry::class); + $this->tcaRegistry = $tcaRegistry; } public function __invoke(ModifyLoadedPageTsConfigEvent $event): void { $event->addTsConfig($this->tcaRegistry->getPageTsString()); } -} \ No newline at end of file +} diff --git a/Classes/Tca/Registry.php b/Classes/Tca/Registry.php index 24e4b82..b43fb32 100644 --- a/Classes/Tca/Registry.php +++ b/Classes/Tca/Registry.php @@ -12,6 +12,7 @@ * of the License, or any later version. */ +use TYPO3\CMS\Core\Exception; use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider; use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider; use TYPO3\CMS\Core\Imaging\IconRegistry; @@ -19,11 +20,8 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -class Registry implements SingletonInterface +final class Registry implements SingletonInterface { - /** - * @param SceConfiguration $sceConfiguration - */ public function configureSce(SceConfiguration $sceConfiguration): void { ExtensionManagementUtility::addTcaSelectItem( @@ -33,7 +31,7 @@ public function configureSce(SceConfiguration $sceConfiguration): void $sceConfiguration->getLabel(), $sceConfiguration->getCType(), $sceConfiguration->getCType(), - $sceConfiguration->getGroup() + $sceConfiguration->getGroup(), ] ); @@ -42,7 +40,7 @@ public function configureSce(SceConfiguration $sceConfiguration): void } else { $fieldsArray = []; foreach ($sceConfiguration->getFields() as $fieldName => $fieldConfig) { - $fieldsArray[] = $fieldName . ($fieldConfig['label'] ? ';' . $fieldConfig['label'] : ''); + $fieldsArray[] = $fieldName . (isset($fieldConfig['label']) ? ';' . $fieldConfig['label'] : ''); } $generalTab = implode(',', $fieldsArray); } @@ -86,10 +84,10 @@ public function configureSce(SceConfiguration $sceConfiguration): void $GLOBALS['TCA']['tt_content']['types'][$sceConfiguration->getCType()]['showitem'] = $showitem; $overrides = []; - foreach ($sceConfiguration->getFields() as $fieldName => $fieldConfig) { - if ($fieldConfig['columnOverrides']) { + foreach ($sceConfiguration->getFields() as $fieldName => $fieldConfig) { + if (isset($fieldConfig['columnOverrides'])) { $columnOverrides = $fieldConfig['columnOverrides']; - if ($columnOverrides['allowedFileTypes']) { + if (isset($columnOverrides['allowedFileTypes'])) { $columnOverrides['overrideChildTca']['columns']['uid_local']['config']['appearance']['elementBrowserAllowed'] = $columnOverrides['allowedFileTypes']; } $overrides[$fieldName]['config'] = $columnOverrides; @@ -104,12 +102,12 @@ public function configureSce(SceConfiguration $sceConfiguration): void public function registerIcons(): void { - if (is_array($GLOBALS['TCA']['tt_content']['sceConfiguration'])) { + if (isset($GLOBALS['TCA']['tt_content']['sceConfiguration'])) { $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); foreach ($GLOBALS['TCA']['tt_content']['sceConfiguration'] as $sceConfiguration) { if (file_exists(GeneralUtility::getFileAbsFileName($sceConfiguration['icon']))) { $provider = BitmapIconProvider::class; - if (strpos($sceConfiguration['icon'], '.svg') !== false) { + if (str_ends_with($sceConfiguration['icon'], '.svg')) { $provider = SvgIconProvider::class; } $iconRegistry->registerIcon( @@ -125,7 +123,7 @@ public function registerIcons(): void $existingIconConfiguration['provider'], $existingIconConfiguration['options'] ); - } catch (\TYPO3\CMS\Core\Exception $e) { + } catch (Exception $_) { } } } @@ -134,22 +132,7 @@ public function registerIcons(): void /** * Adds TSconfig - * - * @param array $TSdataArray - * @param int $id - * @param array $rootLine - * @param array $returnPartArray - * @return array */ - public function addPageTS($TSdataArray, $id, $rootLine, $returnPartArray): array - { - if (empty($GLOBALS['TCA']['tt_content']['sceConfiguration'])) { - return [$TSdataArray, $id, $rootLine, $returnPartArray]; - } - $TSdataArray['default'] = $this->getPageTsString(); - return [$TSdataArray, $id, $rootLine, $returnPartArray]; - } - public function getPageTsString(): string { if (empty($GLOBALS['TCA']['tt_content']['sceConfiguration'])) { @@ -170,8 +153,9 @@ public function getPageTsString(): string } } + $pageTs = ''; foreach ($groupedByGroup as $group => $sceConfigurations) { - $groupLabel = $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['itemGroups'][$group] ? $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['itemGroups'][$group] : $group; + $groupLabel = $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['itemGroups'][$group] ?: $group; $content = ' mod.wizards.newContentElement.wizardItems.' . $group . '.header = ' . $groupLabel . ' @@ -195,4 +179,4 @@ public function getPageTsString(): string return $pageTs; } -} \ No newline at end of file +} diff --git a/Classes/Tca/SceConfiguration.php b/Classes/Tca/SceConfiguration.php index 2f815dc..2fabdc6 100644 --- a/Classes/Tca/SceConfiguration.php +++ b/Classes/Tca/SceConfiguration.php @@ -12,63 +12,39 @@ * of the License, or any later version. */ -class SceConfiguration +final class SceConfiguration { - /** - * @var string - */ - protected $cType = ''; + protected string $cType = ''; - /** - * @var string - */ - protected $label = ''; + protected string $label = ''; - /** - * @var string - */ - protected $description = ''; + protected string $description = ''; /** - * @var mixed[] + * @var array */ - protected $fields = []; + protected array $fields = []; /** - * @var mixed[] + * @var array */ - protected $palettes = []; + protected array $palettes = []; - /** - * @var string - */ - protected $additionalTabs = 'none'; + protected string $additionalTabs = 'none'; - /** - * @var string - */ - protected $showitem = ''; + protected string $showitem = ''; - /** - * @var string - */ - protected $icon = 'EXT:sce/Resources/Public/Icons/Extension.svg'; + protected string $icon = 'EXT:sce/Resources/Public/Icons/Extension.svg'; - /** - * @var bool - */ - protected $saveAndCloseInNewContentElementWizard = false; + protected bool $saveAndCloseInNewContentElementWizard = false; - /** - * @var bool - */ - protected $registerInNewContentElementWizard = true; + protected bool $registerInNewContentElementWizard = true; + + protected string $group = 'sce'; /** - * @var string + * @param array> $fields */ - protected $group = 'sce'; - public function __construct( string $cType, string $label, @@ -81,94 +57,36 @@ public function __construct( $this->fields = $fields; } - /** - * @param mixed[] $palettes - * @return SceConfiguration - */ - public function setPalettes(array $palettes): SceConfiguration - { - $this->palettes = $palettes; - return $this; - } - - /** - * @param string $icon - * @return SceConfiguration - */ public function setIcon(string $icon): SceConfiguration { $this->icon = $icon; return $this; } - /** - * @param string $additionalTabs - * @return SceConfiguration - */ - public function setAdditionalTabs(string $additionalTabs): SceConfiguration - { - $this->additionalTabs = $additionalTabs; - return $this; - } - - /** - * @param string $showitem - * @return SceConfiguration - */ - public function setShowitem(string $showitem): SceConfiguration - { - $this->showitem = $showitem; - return $this; - } - - /** - * @param bool $saveAndCloseInNewContentElementWizard - * @return SceConfiguration - */ public function setSaveAndCloseInNewContentElementWizard(bool $saveAndCloseInNewContentElementWizard): SceConfiguration { $this->saveAndCloseInNewContentElementWizard = $saveAndCloseInNewContentElementWizard; return $this; } - /** - * @param bool $registerInNewContentElementWizard - * @return SceConfiguration - */ public function setRegisterInNewContentElementWizard(bool $registerInNewContentElementWizard): SceConfiguration { $this->registerInNewContentElementWizard = $registerInNewContentElementWizard; return $this; } - /** - * @param string $group - * @return SceConfiguration - */ - public function setGroup(string $group): SceConfiguration - { - $this->group = $group; - return $this; - } - - /** - * @return string - */ public function getCType(): string { return $this->cType; } - /** - * @return string - */ public function getLabel(): string { return $this->label; } /** - * @return mixed[] + * @return array */ public function getFields(): array { @@ -176,7 +94,7 @@ public function getFields(): array } /** - * @return mixed[] + * @return array */ public function getPalettes(): array { @@ -184,31 +102,49 @@ public function getPalettes(): array } /** - * @return string + * @param array $palettes */ + public function setPalettes(array $palettes): SceConfiguration + { + $this->palettes = $palettes; + return $this; + } + public function getAdditionalTabs(): string { return $this->additionalTabs; } - /** - * @return string - */ + public function setAdditionalTabs(string $additionalTabs): SceConfiguration + { + $this->additionalTabs = $additionalTabs; + return $this; + } + public function getShowitem(): string { return $this->showitem; } - /** - * @return string - */ + public function setShowitem(string $showitem): SceConfiguration + { + $this->showitem = $showitem; + return $this; + } + public function getGroup(): string { return $this->group; } + public function setGroup(string $group): SceConfiguration + { + $this->group = $group; + return $this; + } + /** - * @return mixed[] + * @return array */ public function toArray(): array { @@ -222,7 +158,20 @@ public function toArray(): array 'registerInNewContentElementWizard' => $this->registerInNewContentElementWizard, 'additionalTabs' => $this->additionalTabs, 'showitem' => $this->showitem, - 'group' => $this->group + 'group' => $this->group, ]; } -} \ No newline at end of file + + /** + * @param array> $fields + */ + public static function showItemGenerator(array $fields, string ...$showItems): string + { + $fieldKeys = array_keys($fields); + $showItem = implode(',', $showItems); + return sprintf( + $showItem, + implode(',', $fieldKeys) + ); + } +} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 205d36e..968e21a 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,6 +1,14 @@ services: + _defaults: + autowire: true + autoconfigure: true + public: false + + D3M\Sce\: + resource: '../Classes/*' + D3M\Sce\Listener\PageTsConfig: tags: - name: event.listener identifier: 'tx-sce-page-ts-config' - event: TYPO3\CMS\Core\Configuration\Event\ModifyLoadedPageTsConfigEvent \ No newline at end of file + event: TYPO3\CMS\Core\Configuration\Event\ModifyLoadedPageTsConfigEvent diff --git a/README.md b/README.md index d46e46e..c06f55d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # EXT:sce - A TYPO3 extension for creating simple content elements -Webpages ca be seen as a composition of 3 elements: grids building the structure (sections or columns), containers like a card container containing several cards and very often quite simple content elements (like text elements with header and text). Some of these content elements may have the same fields, but they 'behave' differently in different contexts e.g. a text element can be a rendered as 'normal' text or as a card in a card container. +Webpages ca be seen as a composition of 3 elements: grids building the structure (sections or columns), containers like a card container containing several cards and very often quite simple content elements (like text elements with header and text). Some of these content elements may have the same fields, but they 'behave' differently in different contexts e.g. a text element can be a rendered as 'normal' text or as a card in a card container. The idea of this extension is to have a simple way to build content elements from scratch, which are easy to configure by integrators easy to use by editors. Instead of using several layout options in the content element itself to make it fit a certain context, the suggestion of this extension is, to build as many content elements as there are contexts in your webpage. By using mainly default fields of the tt_content table, the content type can be easily switched in bulk from TYPO3-default content type to site-package-specific content type and vice versa in the database. @@ -101,5 +101,5 @@ To find out, which variables are available, you can add `{_all} - - - - Simple Content Elements - - - Context - - - - \ No newline at end of file + + + + Simple Content Elements + + + Context + + + + diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg index 234523e..0bd5737 100755 --- a/Resources/Public/Icons/Extension.svg +++ b/Resources/Public/Icons/Extension.svg @@ -1,474 +1,474 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/composer.json b/composer.json index 91c10ec..3dd5ecb 100644 --- a/composer.json +++ b/composer.json @@ -5,19 +5,16 @@ "license": "GPL-2.0-or-later", "require": { "typo3/cms-backend": "^9.5 || ^10.4 || ^11.5", - "typo3/cms-fluid-styled-content": "^9.5 || ^11.5" + "typo3/cms-fluid-styled-content": "^9.5 || ^10.4 || ^11.5" }, - "autoload": { - "psr-4": { - "D3M\\Sce\\": "Classes/" - } - }, - "replace": { - "typo3-ter/sce": "self.version" - }, "extra": { "typo3/cms": { "extension-key": "sce" } - } + }, + "autoload": { + "psr-4": { + "D3M\\Sce\\": "Classes" + } + } } diff --git a/ext_emconf.php b/ext_emconf.php index 9d81a42..dbc6ccb 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -10,11 +10,10 @@ 'state' => 'stable', 'uploadfolder' => false, 'createDirs' => '', - 'clearCacheOnLoad' => true, 'version' => '1.0.0', 'constraints' => [ 'depends' => ['typo3' => '9.5.0-11.5.99'], 'conflicts' => [], - 'suggests' => [] - ] -]; \ No newline at end of file + 'suggests' => [], + ], +]; diff --git a/ext_localconf.php b/ext_localconf.php index 686f45d..d7fcaf4 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -3,18 +3,14 @@ defined('TYPO3_MODE') || die('Access denied.'); call_user_func(static function () { - $typo3Version = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Information\Typo3Version::class); - if ($typo3Version->getMajorVersion() === 9) { - // Else PageTsConfig Listener is used for ModifyLoadedPageTsConfigEvent - \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class)->connect( - \TYPO3\CMS\Backend\Utility\BackendUtility::class, - 'getPagesTSconfigPreInclude', - D3M\Sce\Tca\Registry::class, - 'addPageTS' - ); - } + \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class)->connect( + \TYPO3\CMS\Backend\Utility\BackendUtility::class, + 'getPagesTSconfigPreInclude', + D3M\Sce\Tca\Registry::class, + 'addPageTS' + ); // Register icons $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing']['tx_sce'] = \D3M\Sce\Hooks\TableConfigurationPostProcessing::class; -}); \ No newline at end of file +}); From d99735cffc1ace6aa0b60a850e9e0e914e42da93 Mon Sep 17 00:00:00 2001 From: mhofmann Date: Fri, 12 Apr 2024 17:31:49 +0200 Subject: [PATCH 2/2] [TASK] Introduce basic testing and code quality framework --- .editorconfig | 41 ++ .gitattributes | 6 + .github/workflows/tests11i3.yml | 80 ++++ .github/workflows/tests11i4.yml | 80 ++++ .github/workflows/tests12.yml | 80 ++++ .gitignore | 10 + Build/Scripts/runTests.sh | 420 ++++++++++++++++++++ Build/php-cs-fixer/config.php | 110 ++++++ Build/phpstan/phpstan-baseline.neon | 2 + Build/phpstan/phpstan.neon | 24 ++ Build/phpunit/FunctionalTests-11i3.xml | 61 +++ Build/phpunit/FunctionalTests-11i4.xml | 61 +++ Build/phpunit/FunctionalTests-12.xml | 30 ++ Build/phpunit/FunctionalTestsBootstrap.php | 20 + Build/phpunit/UnitTests-11i3.xml | 61 +++ Build/phpunit/UnitTests-11i4.xml | 61 +++ Build/phpunit/UnitTests-12.xml | 30 ++ Build/phpunit/UnitTestsBootstrap.php | 67 ++++ Build/testing-docker/docker-compose.yml | 422 +++++++++++++++++++++ Classes/Tca/Registry.php | 2 +- composer.json | 62 ++- 21 files changed, 1712 insertions(+), 18 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/tests11i3.yml create mode 100644 .github/workflows/tests11i4.yml create mode 100644 .github/workflows/tests12.yml create mode 100644 .gitignore create mode 100755 Build/Scripts/runTests.sh create mode 100644 Build/php-cs-fixer/config.php create mode 100644 Build/phpstan/phpstan-baseline.neon create mode 100644 Build/phpstan/phpstan.neon create mode 100644 Build/phpunit/FunctionalTests-11i3.xml create mode 100644 Build/phpunit/FunctionalTests-11i4.xml create mode 100644 Build/phpunit/FunctionalTests-12.xml create mode 100644 Build/phpunit/FunctionalTestsBootstrap.php create mode 100644 Build/phpunit/UnitTests-11i3.xml create mode 100644 Build/phpunit/UnitTests-11i4.xml create mode 100644 Build/phpunit/UnitTests-12.xml create mode 100644 Build/phpunit/UnitTestsBootstrap.php create mode 100644 Build/testing-docker/docker-compose.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fa80b4a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,41 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# TS/JS-Files +[*.{ts,js}] +indent_size = 2 + +# JSON-Files +[*.json] +indent_size = 2 + +# YAML-Files +[*.{yaml,yml}] +indent_size = 2 + +# NEON-Files +[*.neon] +indent_size = 2 + +# TypoScript +[*.{typoscript,tsconfig}] +indent_size = 2 + +# XLF-Files +[*.xlf] +indent_style = tab + +# .htaccess +[{_.htaccess,.htaccess}] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..31f853b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +/.editorconfig export-ignore +/.gitattributes export-ignore +/.github/ export-ignore +/.gitignore export-ignore +/Build/ export-ignore +/Tests/ export-ignore diff --git a/.github/workflows/tests11i3.yml b/.github/workflows/tests11i3.yml new file mode 100644 index 0000000..4e65439 --- /dev/null +++ b/.github/workflows/tests11i3.yml @@ -0,0 +1,80 @@ +name: tests11i3 + +on: + push: + pull_request: + schedule: + - cron: '42 5 * * *' + +jobs: + testsuite: + name: all tests + runs-on: ubuntu-20.04 + strategy: + # This prevents cancellation of matrix job runs, if one or more already failed + # and let the remaining matrix jobs be executed anyway. + fail-fast: false + matrix: + php: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install dependencies + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s composerUpdate + + - name: Composer validate + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s composerValidate + + - name: Lint PHP + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s lint + + - name: CGL + # php-cs-fixer has isues with php8.2, so avoid executing it with that php version. + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 11i3 -n -p ${{ matrix.php }} -s cgl + + - name: phpstan + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s phpstan -e "--error-format=github" + + - name: Unit Tests + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s unit + + - name: Functional Tests with mariadb and mysqli + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d mariadb -a mysqli -s functional + + - name: Functional Tests with mariadb and pdo_mysql + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d mariadb -a pdo_mysql -s functional + + - name: Functional Tests with mysql and mysqli + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d mysql -a mysqli -s functional + + - name: Functional Tests with mysql and pdo_mysql + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d mysql -a pdo_mysql -s functional + + - name: Functional Tests with postgres + # v11 postgres functional disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 + # is not fixed in doctrine core v11 doctrine 2.13.9 + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d postgres -s functional + + - name: Functional Tests with sqlite + run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -d sqlite -s functional + +# - name: Acceptance Tests mariadb and mysqli +# run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s acceptance -d mariadb -a mysqli +# +# - name: Acceptance Tests mariadb and pdo_mysql +# run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s acceptance -d mariadb -a pdo_mysql +# +# - name: Acceptance Tests mysql and mysqli +# run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s acceptance -d mysql -a mysqli +# +# - name: Acceptance Tests mysql and pdo_mysql +# run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s acceptance -d mysql -a pdo_mysql +# +# - name: Acceptance Tests postgres +# # v11 postgres acceptance disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 +# # is not fixed in doctrine core v11 doctrine 2.13.9 +# if: ${{ matrix.php <= '8.1' }} +# run: Build/Scripts/runTests.sh -t 11i3 -p ${{ matrix.php }} -s acceptance -d postgres diff --git a/.github/workflows/tests11i4.yml b/.github/workflows/tests11i4.yml new file mode 100644 index 0000000..6dd3926 --- /dev/null +++ b/.github/workflows/tests11i4.yml @@ -0,0 +1,80 @@ +name: tests11i4 + +on: + push: + pull_request: + schedule: + - cron: '42 5 * * *' + +jobs: + testsuite: + name: all tests + runs-on: ubuntu-20.04 + strategy: + # This prevents cancellation of matrix job runs, if one or more already failed + # and let the remaining matrix jobs be executed anyway. + fail-fast: false + matrix: + php: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install dependencies + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s composerUpdate + + - name: Composer validate + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s composerValidate + + - name: Lint PHP + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s lint + + - name: CGL + # php-cs-fixer has isues with php8.2, so avoid executing it with that php version. + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 11i4 -n -p ${{ matrix.php }} -s cgl + + - name: phpstan + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s phpstan -e "--error-format=github" + + - name: Unit Tests + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s unit + + - name: Functional Tests with mariadb and mysqli + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d mariadb -a mysqli -s functional + + - name: Functional Tests with mariadb and pdo_mysql + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d mariadb -a pdo_mysql -s functional + + - name: Functional Tests with mysql and mysqli + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d mysql -a mysqli -s functional + + - name: Functional Tests with mysql and pdo_mysql + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d mysql -a pdo_mysql -s functional + + - name: Functional Tests with postgres + # v11 postgres functional disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 + # is not fixed in doctrine core v11 doctrine 2.13.9 + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d postgres -s functional + + - name: Functional Tests with sqlite + run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -d sqlite -s functional + +# - name: Acceptance Tests mariadb and mysqli +# run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s acceptance -d mariadb -a mysqli +# +# - name: Acceptance Tests mariadb and pdo_mysql +# run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s acceptance -d mariadb -a pdo_mysql +# +# - name: Acceptance Tests mysql and mysqli +# run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s acceptance -d mysql -a mysqli +# +# - name: Acceptance Tests mysql and pdo_mysql +# run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s acceptance -d mysql -a pdo_mysql +# +# - name: Acceptance Tests postgres +# # v11 postgres acceptance disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 +# # is not fixed in doctrine core v11 doctrine 2.13.9 +# if: ${{ matrix.php <= '8.1' }} +# run: Build/Scripts/runTests.sh -t 11i4 -p ${{ matrix.php }} -s acceptance -d postgres diff --git a/.github/workflows/tests12.yml b/.github/workflows/tests12.yml new file mode 100644 index 0000000..8ec12b5 --- /dev/null +++ b/.github/workflows/tests12.yml @@ -0,0 +1,80 @@ +name: tests12 + +on: + push: + pull_request: + schedule: + - cron: '42 5 * * *' + +jobs: + testsuite: + name: all tests + runs-on: ubuntu-20.04 + strategy: + # This prevents cancellation of matrix job runs, if one or more already failed + # and let the remaining matrix jobs be executed anyway. + fail-fast: false + matrix: + php: [ '8.1', '8.2', '8.3' ] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install dependencies + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s composerUpdate + + - name: Composer validate + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s composerValidate + + - name: Lint PHP + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s lint + + - name: CGL + # php-cs-fixer has isues with php8.2, so avoid executing it with that php version. + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 12 -n -p ${{ matrix.php }} -s cgl + + - name: phpstan + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s phpstan -e "--error-format=github" + + - name: Unit Tests + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s unit + + - name: Functional Tests with mariadb and mysqli + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d mariadb -a mysqli -s functional + + - name: Functional Tests with mariadb and pdo_mysql + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d mariadb -a pdo_mysql -s functional + + - name: Functional Tests with mysql and mysqli + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d mysql -a mysqli -s functional + + - name: Functional Tests with mysql and pdo_mysql + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d mysql -a pdo_mysql -s functional + + - name: Functional Tests with postgres + # v11 postgres functional disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 + # is not fixed in doctrine core v11 doctrine 2.13.9 + if: ${{ matrix.php <= '8.1' }} + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d postgres -s functional + + - name: Functional Tests with sqlite + run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -d sqlite -s functional + +# - name: Acceptance Tests mariadb and mysqli +# run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s acceptance -d mariadb -a mysqli +# +# - name: Acceptance Tests mariadb and pdo_mysql +# run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s acceptance -d mariadb -a pdo_mysql +# +# - name: Acceptance Tests mysql and mysqli +# run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s acceptance -d mysql -a mysqli +# +# - name: Acceptance Tests mysql and pdo_mysql +# run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s acceptance -d mysql -a pdo_mysql +# +# - name: Acceptance Tests postgres +# # v11 postgres acceptance disabled with PHP 8.2 since https://github.com/doctrine/dbal/commit/73eec6d882b99e1e2d2d937accca89c1bd91b2d7 +# # is not fixed in doctrine core v11 doctrine 2.13.9 +# if: ${{ matrix.php <= '8.1' }} +# run: Build/Scripts/runTests.sh -t 12 -p ${{ matrix.php }} -s acceptance -d postgres diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796358e --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.Build/ +.idea/ +Build/testing-docker/.env +/var +composer.json.testing +composer.lock +# Ignore files generated by tests +Tests/Acceptance/Support/_generated/ +/favicon.ico +/.php-cs-fixer.cache diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh new file mode 100755 index 0000000..5f525e9 --- /dev/null +++ b/Build/Scripts/runTests.sh @@ -0,0 +1,420 @@ +#!/usr/bin/env bash + +# +# TYPO3 core test runner based on docker and docker-compose. +# + +# Function to write a .env file in Build/testing-docker +# This is read by docker-compose and vars defined here are +# used in Build/testing-docker/docker-compose.yml +setUpDockerComposeDotEnv() { + # Delete possibly existing local .env file if exists + [ -e .env ] && rm .env + # Set up a new .env file for docker-compose + { + echo "COMPOSE_PROJECT_NAME=local" + # To prevent access rights of files created by the testing, the docker image later + # runs with the same user that is currently executing the script. docker-compose can't + # use $UID directly itself since it is a shell variable and not an env variable, so + # we have to set it explicitly here. + echo "HOST_UID=`id -u`" + # Your local user + echo "ROOT_DIR=${ROOT_DIR}" + echo "HOST_USER=${USER}" + echo "TEST_FILE=${TEST_FILE}" + echo "TYPO3_VERSION=${TYPO3_VERSION}" + echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}" + echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}" + echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}" + echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}" + echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}" + echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}" + echo "DATABASE_DRIVER=${DATABASE_DRIVER}" + echo "DOCKER_SELENIUM_IMAGE=${DOCKER_SELENIUM_IMAGE}" + echo "IMAGE_PREFIX=${IMAGE_PREFIX}" + } > .env +} + +# Options -a and -d depend on each other. The function +# validates input combinations and sets defaults. +handleDbmsAndDriverOptions() { + case ${DBMS} in + mysql|mariadb) + [ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli" + if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then + echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2 + echo >&2 + echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + fi + ;; + postgres|sqlite) + if [ -n "${DATABASE_DRIVER}" ]; then + echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2 + echo >&2 + echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + fi + ;; + esac +} + +# Load help text into $HELP +read -r -d '' HELP < + Specifies which test suite to run + - acceptance: backend acceptance tests + - cgl: cgl test and fix all php files + - clean: clean up test related build files + - composerUpdate: "composer update", handy if host has no PHP + - composerValidate: "composer validate" + - functional: functional tests + - lint: PHP linting + - phpstan: phpstan analyze + - phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates + - unit (default): PHP unit tests + + -a + Only with -s acceptance,functional + Specifies to use another driver, following combinations are available: + - mysql + - mysqli (default) + - pdo_mysql + - mariadb + - mysqli (default) + - pdo_mysql + + -d + Only with -s acceptance,functional + Specifies on which DBMS tests are performed + - mariadb (default): use mariadb + - mysql: use mysql + - postgres: use postgres + - sqlite: use sqlite (not for -s acceptance) + + -p <7.4|8.0|8.1|8.2|8.3> + Specifies the PHP minor version to be used + - 7.4 (default): use PHP 7.4 + - 8.0: use PHP 8.0 + - 8.1: use PHP 8.1 + - 8.2: use PHP 8.2 + - 8.3: use PHP 8.3 + + -t <11i3|11i4|12> + Only with -s composerUpdate + Specifies the TYPO3 core major version to be used + - 11i3 (default): use TYPO3 core v11 with typo3/cms-composer-installers 3.x + - 11i4: use TYPO3 core v11 with typo3/cms-composer-installers 4.0-RC1 + - 12: use TYPO3 core v12 + + -e "" + Only with -s acceptance|functional|unit + Additional options to send to phpunit (unit & functional tests) or codeception (acceptance + tests). For phpunit, options starting with "--" must be added after options starting with "-". + Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests + named "canRetrieveValueWithGP" + + -x + Only with -s functional|unit|acceptance + Send information to host instance for test or system under test break points. This is especially + useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port + can be selected with -y + + -y + Send xdebug information to a different port than default 9003 if an IDE like PhpStorm + is not listening on default port. + + -n + Only with -s cgl + Activate dry-run in CGL check that does not actively change files and only prints broken ones. + + -u + Update existing typo3/core-testing-*:latest docker images. Maintenance call to docker pull latest + versions of the main php images. The images are updated once in a while and only the youngest + ones are supported by core testing. Use this if weird test errors occur. Also removes obsolete + image versions of typo3/core-testing-*. + + -v + Enable verbose script output. Shows variables and docker commands. + + -h + Show this help. + +Examples: + # Run unit tests using PHP 8.1 + ./Build/Scripts/runTests.sh +EOF + +# Test if docker-compose exists, else exit out with error +if ! type "docker-compose" > /dev/null; then + echo "This script relies on docker and docker-compose. Please install" >&2 + exit 1 +fi + +# Go to the directory this script is located, so everything else is relative +# to this dir, no matter from where this script is called. +THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +cd "$THIS_SCRIPT_DIR" || exit 1 + +# Go to directory that contains the local docker-compose.yml file +cd ../testing-docker || exit 1 + +# Option defaults +if ! command -v realpath &> /dev/null; then + echo "This script works best with realpath installed" >&2 + ROOT_DIR="${PWD}/../../" +else + ROOT_DIR=`realpath ${PWD}/../../` +fi +TEST_SUITE="unit" +TYPO3_VERSION="11i3" +DBMS="mariadb" +PHP_VERSION="7.4" +PHP_XDEBUG_ON=0 +PHP_XDEBUG_PORT=9003 +EXTRA_TEST_OPTIONS="" +SCRIPT_VERBOSE=0 +CGLCHECK_DRY_RUN="" +DATABASE_DRIVER="" +DOCKER_SELENIUM_IMAGE="selenium/standalone-chrome:3.141.59-20210713" +IMAGE_PREFIX="ghcr.io/typo3/" + +# Detect arm64 and use a seleniarm image. +# In a perfect world selenium would have a arm64 integrated, but that is not on the horizon. +# So for the time being we have to use seleniarm image. +ARCH=$(uname -m) +if [ $ARCH = "arm64" ]; then + DOCKER_SELENIUM_IMAGE="seleniarm/standalone-chromium:4.1.2-20220227" + echo "Architecture" $ARCH "requires" $DOCKER_SELENIUM_IMAGE "to run acceptance tests." +fi + +# Option parsing +# Reset in case getopts has been used previously in the shell +OPTIND=1 +# Array for invalid options +INVALID_OPTIONS=(); +# Simple option parsing based on getopts (! not getopt) +while getopts ":s:a:d:p:t:e:xy:nhuv" OPT; do + case ${OPT} in + s) + TEST_SUITE=${OPTARG} + ;; + a) + DATABASE_DRIVER=${OPTARG} + ;; + d) + DBMS=${OPTARG} + ;; + p) + PHP_VERSION=${OPTARG} + if ! [[ ${PHP_VERSION} =~ ^(7.4|8.0|8.1|8.2|8.3)$ ]]; then + INVALID_OPTIONS+=("p ${OPTARG}") + fi + ;; + t) + TYPO3_VERSION=${OPTARG} + if ! [[ ${TYPO3_VERSION} =~ ^(11i3|11i4|12)$ ]]; then + INVALID_OPTIONS+=("t ${OPTARG}") + fi + ;; + e) + EXTRA_TEST_OPTIONS=${OPTARG} + ;; + x) + PHP_XDEBUG_ON=1 + ;; + y) + PHP_XDEBUG_PORT=${OPTARG} + ;; + h) + echo "${HELP}" + exit 0 + ;; + n) + CGLCHECK_DRY_RUN="-n" + ;; + u) + TEST_SUITE=update + ;; + v) + SCRIPT_VERBOSE=1 + ;; + \?) + INVALID_OPTIONS+=(${OPTARG}) + ;; + :) + INVALID_OPTIONS+=(${OPTARG}) + ;; + esac +done + +# Exit on invalid options +if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then + echo "Invalid option(s):" >&2 + for I in "${INVALID_OPTIONS[@]}"; do + echo "-"${I} >&2 + done + echo >&2 + echo "${HELP}" >&2 + exit 1 +fi + +# Move "7.4" to "php74", the latter is the docker container name +DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'` + +# Set $1 to first mass argument, this is the optional test file or test directory to execute +shift $((OPTIND - 1)) +TEST_FILE=${1} +#if [ -n "${1}" ]; then +# TEST_FILE="Web/typo3conf/ext/styleguide/${1}" +#fi + +if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x +fi + +# Suite execution +case ${TEST_SUITE} in + acceptance) + handleDbmsAndDriverOptions + setUpDockerComposeDotEnv + case ${DBMS} in + mysql) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run acceptance_backend_mysql80 + SUITE_EXIT_CODE=$? + ;; + mariadb) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run acceptance_backend_mariadb10 + SUITE_EXIT_CODE=$? + ;; + postgres) + docker-compose run acceptance_backend_postgres10 + SUITE_EXIT_CODE=$? + ;; + *) + echo "Acceptance tests don't run with DBMS ${DBMS}" >&2 + echo >&2 + echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + esac + docker-compose down + ;; + cgl) + # Active dry-run for cgl needs not "-n" but specific options + if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then + CGLCHECK_DRY_RUN="--dry-run --diff" + fi + setUpDockerComposeDotEnv + docker-compose run cgl + SUITE_EXIT_CODE=$? + docker-compose down + ;; + clean) + echo -n "Clean builds ... " ; rm -rf \ + ../../Build/testing-docker/.env \ + ../../composer.lock \ + ../../.Build \ + ../../Tests/Acceptance/Support/_generated/; + echo "done" + ;; + composerUpdate) + setUpDockerComposeDotEnv + cp ../../composer.json ../../composer.json.orig + if [ -f "../../composer.json.testing" ]; then + cp ../../composer.json ../../composer.json.orig + fi + docker-compose run composer_update + cp ../../composer.json ../../composer.json.testing + mv ../../composer.json.orig ../../composer.json + SUITE_EXIT_CODE=$? + docker-compose down + ;; + composerValidate) + setUpDockerComposeDotEnv + docker-compose run composer_validate + SUITE_EXIT_CODE=$? + docker-compose down + ;; + functional) + handleDbmsAndDriverOptions + setUpDockerComposeDotEnv + case ${DBMS} in + mariadb) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run functional_mariadb10 + SUITE_EXIT_CODE=$? + ;; + mysql) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run functional_mysql80 + SUITE_EXIT_CODE=$? + ;; + postgres) + docker-compose run functional_postgres10 + SUITE_EXIT_CODE=$? + ;; + sqlite) + # sqlite has a tmpfs as .Build/Web/typo3temp/var/tests/functional-sqlite-dbs/ + # Since docker is executed as root (yay!), the path to this dir is owned by + # root if docker creates it. Thank you, docker. We create the path beforehand + # to avoid permission issues. + mkdir -p ${ROOT_DIR}/.Build/Web/typo3temp/var/tests/functional-sqlite-dbs/ + docker-compose run functional_sqlite + SUITE_EXIT_CODE=$? + ;; + *) + echo "Invalid -d option argument ${DBMS}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 + esac + docker-compose down + ;; + lint) + setUpDockerComposeDotEnv + docker-compose run lint + SUITE_EXIT_CODE=$? + docker-compose down + ;; + phpstan) + setUpDockerComposeDotEnv + docker-compose run phpstan + SUITE_EXIT_CODE=$? + docker-compose down + ;; + phpstanGenerateBaseline) + setUpDockerComposeDotEnv + docker-compose run phpstan_generate_baseline + SUITE_EXIT_CODE=$? + docker-compose down + ;; + unit) + setUpDockerComposeDotEnv + docker-compose run unit + SUITE_EXIT_CODE=$? + docker-compose down + ;; + update) + # pull typo3/core-testing-*:latest versions of those ones that exist locally + docker images ${IMAGE_PREFIX}core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {} + # remove "dangling" typo3/core-testing-* images (those tagged as ) + docker images ${IMAGE_PREFIX}core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {} + ;; + *) + echo "Invalid -s option argument ${TEST_SUITE}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 +esac + +exit $SUITE_EXIT_CODE diff --git a/Build/php-cs-fixer/config.php b/Build/php-cs-fixer/config.php new file mode 100644 index 0000000..1d62eed --- /dev/null +++ b/Build/php-cs-fixer/config.php @@ -0,0 +1,110 @@ + Build/Scripts/runTests.sh -s cgl + * + * Fix your current patch: + * > Build/Scripts/runTests.sh -s cglGit + */ +if (PHP_SAPI !== 'cli') { + die('This script supports command line usage only. Please check your command.'); +} + +// Return a Code Sniffing configuration using +// all sniffers needed for PER +// and additionally: +// - Remove leading slashes in use clauses. +// - PHP single-line arrays should not have trailing comma. +// - Single-line whitespace before closing semicolon are prohibited. +// - Remove unused use statements in the PHP source code +// - Ensure Concatenation to have at least one whitespace around +// - Remove trailing whitespace at the end of blank lines. +return (new \PhpCsFixer\Config()) + ->setFinder( + (new PhpCsFixer\Finder()) + ->ignoreVCSIgnored(true) + ->in(realpath(__DIR__ . '/../../')) + ) + ->setRiskyAllowed(true) + ->setRules([ + '@DoctrineAnnotation' => true, + // @todo: Switch to @PER-CS2.0 once php-cs-fixer's todo list is done: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues/7247 + '@PER-CS1.0' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'cast_spaces' => ['space' => 'none'], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'declare_parentheses' => true, + 'dir_constant' => true, + // @todo: Can be dropped once we enable @PER-CS2.0 + 'function_declaration' => [ + 'closure_fn_spacing' => 'none', + ], + 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']], + 'type_declaration_spaces' => true, + 'global_namespace_import' => ['import_classes' => false, 'import_constants' => false, 'import_functions' => false], + 'list_syntax' => ['syntax' => 'short'], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'method_argument_space' => true, + 'modernize_strpos' => true, + 'modernize_types_casting' => true, + 'native_function_casing' => 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_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' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_nullsafe_operator' => true, + 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], + '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_space_around_construct' => true, + 'single_line_comment_style' => ['comment_types' => ['hash']], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'single_line_empty_body' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'whitespace_after_comma_in_array' => ['ensure_single_space' => true], + 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], + ]); diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon new file mode 100644 index 0000000..aab4991 --- /dev/null +++ b/Build/phpstan/phpstan-baseline.neon @@ -0,0 +1,2 @@ +parameters: + ignoreErrors: [] diff --git a/Build/phpstan/phpstan.neon b/Build/phpstan/phpstan.neon new file mode 100644 index 0000000..49f05c7 --- /dev/null +++ b/Build/phpstan/phpstan.neon @@ -0,0 +1,24 @@ +includes: + - phpstan-baseline.neon + - ../../.Build/vendor/bnf/phpstan-psr-container/extension.neon + - ../../.Build/vendor/saschaegerer/phpstan-typo3/extension.neon + - ../../.Build/vendor/phpstan/phpstan-phpunit/extension.neon + - ../../.Build/vendor/jangregor/phpstan-prophecy/extension.neon + +parameters: + level: 8 + typo3: + requestGetAttributeMapping: + oauth_client_id: string + oauth_user_id: int + + # Use local cache dir instead of /tmp + tmpDir: ../../.Build/.cache/phpstan + + paths: + - ../../Classes + - ../../Tests + + excludePaths: + # Checking acceptance Cest and Support files is cumbersome due to codeception dynamic mixin generation + - ../../Tests/Acceptance/* diff --git a/Build/phpunit/FunctionalTests-11i3.xml b/Build/phpunit/FunctionalTests-11i3.xml new file mode 100644 index 0000000..fa4d04e --- /dev/null +++ b/Build/phpunit/FunctionalTests-11i3.xml @@ -0,0 +1,61 @@ + + + + + + + ../../Tests/Functional/ + + + + + + + + + + + diff --git a/Build/phpunit/FunctionalTests-11i4.xml b/Build/phpunit/FunctionalTests-11i4.xml new file mode 100644 index 0000000..fa4d04e --- /dev/null +++ b/Build/phpunit/FunctionalTests-11i4.xml @@ -0,0 +1,61 @@ + + + + + + + ../../Tests/Functional/ + + + + + + + + + + + diff --git a/Build/phpunit/FunctionalTests-12.xml b/Build/phpunit/FunctionalTests-12.xml new file mode 100644 index 0000000..1e8f810 --- /dev/null +++ b/Build/phpunit/FunctionalTests-12.xml @@ -0,0 +1,30 @@ + + + + + ../../Tests/Functional/ + + + + + + + + diff --git a/Build/phpunit/FunctionalTestsBootstrap.php b/Build/phpunit/FunctionalTestsBootstrap.php new file mode 100644 index 0000000..443197d --- /dev/null +++ b/Build/phpunit/FunctionalTestsBootstrap.php @@ -0,0 +1,20 @@ +defineOriginalRootPath(); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/tests'); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/transient'); +}); diff --git a/Build/phpunit/UnitTests-11i3.xml b/Build/phpunit/UnitTests-11i3.xml new file mode 100644 index 0000000..2244da6 --- /dev/null +++ b/Build/phpunit/UnitTests-11i3.xml @@ -0,0 +1,61 @@ + + + + + + ../../Tests/Unit/ + + + + + + ../../Tests/Unit/ + + + + + + + + + + diff --git a/Build/phpunit/UnitTests-11i4.xml b/Build/phpunit/UnitTests-11i4.xml new file mode 100644 index 0000000..2244da6 --- /dev/null +++ b/Build/phpunit/UnitTests-11i4.xml @@ -0,0 +1,61 @@ + + + + + + ../../Tests/Unit/ + + + + + + ../../Tests/Unit/ + + + + + + + + + + diff --git a/Build/phpunit/UnitTests-12.xml b/Build/phpunit/UnitTests-12.xml new file mode 100644 index 0000000..37d9788 --- /dev/null +++ b/Build/phpunit/UnitTests-12.xml @@ -0,0 +1,30 @@ + + + + + ../../Tests/Unit/ + + + + + + + + diff --git a/Build/phpunit/UnitTestsBootstrap.php b/Build/phpunit/UnitTestsBootstrap.php new file mode 100644 index 0000000..a4ca910 --- /dev/null +++ b/Build/phpunit/UnitTestsBootstrap.php @@ -0,0 +1,67 @@ +getWebRoot(), '/')); + } + if (!getenv('TYPO3_PATH_WEB')) { + putenv('TYPO3_PATH_WEB=' . rtrim($testbase->getWebRoot(), '/')); + } + + $testbase->defineSitePath(); + + $composerMode = defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE === true; + $requestType = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_BE | \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI; + \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(0, $requestType, $composerMode); + + $testbase->createDirectory(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/typo3conf/ext'); + $testbase->createDirectory(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/typo3temp/assets'); + $testbase->createDirectory(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/typo3temp/var/tests'); + $testbase->createDirectory(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/typo3temp/var/transient'); + + // Retrieve an instance of class loader and inject to core bootstrap + $classLoader = require $testbase->getPackagesPath() . '/autoload.php'; + \TYPO3\CMS\Core\Core\Bootstrap::initializeClassLoader($classLoader); + + // Initialize default TYPO3_CONF_VARS + $configurationManager = new \TYPO3\CMS\Core\Configuration\ConfigurationManager(); + $GLOBALS['TYPO3_CONF_VARS'] = $configurationManager->getDefaultConfiguration(); + + $cache = new \TYPO3\CMS\Core\Cache\Frontend\PhpFrontend( + 'core', + new \TYPO3\CMS\Core\Cache\Backend\NullBackend('production', []), + ); + // Set all packages to active + $packageManager = \TYPO3\CMS\Core\Core\Bootstrap::createPackageManager( + \TYPO3\CMS\Core\Package\UnitTestPackageManager::class, + \TYPO3\CMS\Core\Core\Bootstrap::createPackageCache($cache) + ); + + \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance(\TYPO3\CMS\Core\Package\PackageManager::class, $packageManager); + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::setPackageManager($packageManager); + + $testbase->dumpClassLoadingInformation(); + + \TYPO3\CMS\Core\Utility\GeneralUtility::purgeInstances(); +}); diff --git a/Build/testing-docker/docker-compose.yml b/Build/testing-docker/docker-compose.yml new file mode 100644 index 0000000..b427d43 --- /dev/null +++ b/Build/testing-docker/docker-compose.yml @@ -0,0 +1,422 @@ +version: '2.3' +services: + chrome: + image: ${DOCKER_SELENIUM_IMAGE} + tmpfs: + - /dev/shm:rw,nosuid,nodev,noexec,relatime + + mariadb10: + # not using mariadb:10 for the time being, because 10.5.7 (currently latest) is broken + image: mariadb:10.5.6 + environment: + MYSQL_ROOT_PASSWORD: funcp + tmpfs: + - /var/lib/mysql/:rw,noexec,nosuid + + mysql80: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: funcp + tmpfs: + - /var/lib/mysql/:rw,noexec,nosuid + + postgres10: + image: postgres:10-alpine + environment: + POSTGRES_PASSWORD: funcp + POSTGRES_USER: ${HOST_USER} + tmpfs: + - /var/lib/postgresql/data:rw,noexec,nosuid + + web: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + stop_grace_period: 1s + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + environment: + TYPO3_PATH_ROOT: ${ROOT_DIR}/.Build/Web/typo3temp/var/tests/acceptance + TYPO3_PATH_APP: ${ROOT_DIR}/.Build/Web/typo3temp/var/tests/acceptance + command: > + /bin/sh -c " + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" php -S web:8000 -t ${ROOT_DIR}/.Build/Web + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" php -S web:8000 -t ${ROOT_DIR}/.Build/Web + fi + " + + acceptance_backend_mariadb10: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mariadb10 + - chrome + - web + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mariadb10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mariadb10 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p .Build/Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Application -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" $${COMMAND}; + fi + " + + acceptance_backend_mysql80: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mysql80 + - chrome + - web + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mysql80 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mysql80 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Application -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" $${COMMAND}; + fi + " + + acceptance_backend_postgres10: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - postgres10 + - chrome + - web + environment: + typo3DatabaseDriver: pdo_pgsql + typo3DatabaseName: bamboo + typo3DatabaseUsername: ${HOST_USER} + typo3DatabaseHost: postgres10 + typo3DatabasePassword: funcp + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z postgres10 5432; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Application -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" $${COMMAND}; + fi + " + + cgl: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --config=Build/php-cs-fixer/config.php + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" PHP_CS_FIXER_ALLOW_XDEBUG=1 .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --config=Build/php-cs-fixer/config.php + fi + " + + composer_update: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + environment: + COMPOSER_CACHE_DIR: ".Build/.cache/composer" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ "${TYPO3_VERSION}" == "11i3" ]; then + composer req --dev --no-update "phpunit/phpunit":"^9.6.7" "typo3/cms-composer-installers":"^3" "typo3/cms-core":"~11.5@dev" + fi + if [ "${TYPO3_VERSION}" == "11i4" ]; then + composer req --dev --no-update "phpunit/phpunit":"^9.6.7" "typo3/cms-composer-installers":"4.0.x@dev" "typo3/cms-core":"~11.5@dev" + fi + if [ "${TYPO3_VERSION}" == "12" ]; then + composer req --dev --no-update "phpunit/phpunit":"^10.1" "typo3/cms-composer-installers":"^5" "typo3/cms-core":"~12.4@dev" + fi + composer update --no-progress --no-interaction; + " + + composer_validate: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + environment: + COMPOSER_CACHE_DIR: ".Build/.cache/composer" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + composer validate --no-check-lock; + " + + functional_mariadb10: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mariadb10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mariadb10 + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mariadb10 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " + + functional_mysql80: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mysql80 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mysql80 + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mysql80 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " + + functional_postgres10: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - postgres10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: pdo_pgsql + typo3DatabaseName: bamboo + typo3DatabaseUsername: ${HOST_USER} + typo3DatabaseHost: postgres10 + typo3DatabasePassword: funcp + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z postgres10 5432; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-postgres ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-postgres ${TEST_FILE}; + fi + " + + functional_sqlite: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + tmpfs: + - ${ROOT_DIR}/.Build/Web/typo3temp/var/tests/functional-sqlite-dbs/:rw,noexec,nosuid,uid=${HOST_UID} + environment: + typo3DatabaseDriver: pdo_sqlite + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-sqlite ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" .Build/bin/phpunit -c Build/phpunit/FunctionalTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-sqlite ${TEST_FILE}; + fi + " + + lint: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + find . -name \\*.php ! -path "./.Build/\\*" -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null + " + + phpstan: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + mkdir -p .Build/.cache + php -v | grep '^PHP'; + php -dxdebug.mode=off .Build/bin/phpstan analyze -c Build/phpstan/phpstan.neon --no-progress --no-interaction ${EXTRA_TEST_OPTIONS} + " + + phpstan_generate_baseline: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + mkdir -p .Build/.cache + php -v | grep '^PHP'; + php -dxdebug.mode=off .Build/bin/phpstan analyze -c Build/phpstan/phpstan.neon --no-progress --no-interaction --allow-empty-baseline --generate-baseline=Build/phpstan/phpstan-baseline.neon + " + + unit: + image: ${IMAGE_PREFIX}core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/phpunit/UnitTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" .Build/bin/phpunit -c Build/phpunit/UnitTests-${TYPO3_VERSION}.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " diff --git a/Classes/Tca/Registry.php b/Classes/Tca/Registry.php index b43fb32..e2e6cd1 100644 --- a/Classes/Tca/Registry.php +++ b/Classes/Tca/Registry.php @@ -45,7 +45,7 @@ public function configureSce(SceConfiguration $sceConfiguration): void $generalTab = implode(',', $fieldsArray); } - switch($sceConfiguration->getAdditionalTabs()) { + switch ($sceConfiguration->getAdditionalTabs()) { case 'default': $defaultTabs = implode(',', [ '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance', diff --git a/composer.json b/composer.json index 3dd5ecb..a0a2304 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,48 @@ { - "name": "d3m/sce", - "type": "typo3-cms-extension", - "description": "Create Simple Content Elements for TYPO3", - "license": "GPL-2.0-or-later", - "require": { - "typo3/cms-backend": "^9.5 || ^10.4 || ^11.5", - "typo3/cms-fluid-styled-content": "^9.5 || ^10.4 || ^11.5" + "name": "d3m/sce", + "type": "typo3-cms-extension", + "description": "Create Simple Content Elements for TYPO3", + "license": "GPL-2.0-or-later", + "require": { + "typo3/cms-backend": "^9.5 || ^10.4 || ^11.5", + "typo3/cms-fluid-styled-content": "^9.5 || ^10.4 || ^11.5" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v3.52", + "jangregor/phpstan-prophecy": "^1.0", + "league/oauth2-client": "^2.7", + "phpspec/prophecy": "^1.19", + "phpspec/prophecy-phpunit": "^v2.2", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.6 || ^10.0", + "saschaegerer/phpstan-typo3": "^1.10", + "typo3/testing-framework": "^7.0" + }, + "extra": { + "typo3/cms": { + "app-dir": ".Build", + "web-dir": ".Build/Web", + "extension-key": "sce" + } + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "typo3/class-alias-loader": true, + "typo3/cms-composer-installers": true }, - "extra": { - "typo3/cms": { - "extension-key": "sce" - } - }, - "autoload": { - "psr-4": { - "D3M\\Sce\\": "Classes" - } - } + "bin-dir": ".Build/bin", + "vendor-dir": ".Build/vendor" + }, + "autoload": { + "psr-4": { + "D3M\\Sce\\": "Classes" + } + }, + "autoload-dev": { + "psr-4": { + "D3M\\Sce\\Tests\\": "Tests" + } + } }