diff --git a/.github/workflows/nightly-main.yml b/.github/workflows/nightly-main.yml index 86029fa9..1faec511 100644 --- a/.github/workflows/nightly-main.yml +++ b/.github/workflows/nightly-main.yml @@ -20,9 +20,3 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh workflow run ci.yml --ref main - - - name: Execute multi-version tests on 'main' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh workflow run typo3-multi-version-tests.yml --ref main -f force_full_test=true diff --git a/Classes/DataHandler/ProcessCmdmap.php b/Classes/DataHandler/ProcessCmdmap.php index a38f07f0..5909babd 100644 --- a/Classes/DataHandler/ProcessCmdmap.php +++ b/Classes/DataHandler/ProcessCmdmap.php @@ -86,7 +86,7 @@ public function execute_processCmdmap( $clipBoard = $queryParams['CB'] ??= null; if (!empty($clipBoard)) { - $updateArray = $clipBoard['update']; + $updateArray = $clipBoard['update']; // false positive of #99586 / #100963 in Extension Scanner if (!empty($updateArray)) { $dataArray = array_merge($dataArray, $updateArray); } diff --git a/Classes/Domain/Repository/TtContentRepository.php b/Classes/Domain/Repository/TtContentRepository.php index 77db37e1..2ddb7a78 100644 --- a/Classes/Domain/Repository/TtContentRepository.php +++ b/Classes/Domain/Repository/TtContentRepository.php @@ -29,6 +29,7 @@ use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Exception\DriverException as DBALDriverException; use EHAERER\PasteReference\Helper\BackendHelper; +use TYPO3\CMS\Backend\Domain\Repository\Localization\LocalizationRepository; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\Connection; @@ -52,6 +53,7 @@ class TtContentRepository implements SingletonInterface protected bool $showHidden = true; protected BackendHelper $backendHelper; protected string $table = 'tt_content'; + protected LocalizationRepository $localizationRepository; public function __construct() { @@ -59,6 +61,7 @@ public function __construct() $emConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('paste_reference') ?? []; $this->extensionConfiguration = $emConf; $this->backendHelper = GeneralUtility::makeInstance(BackendHelper::class); + $this->localizationRepository = GeneralUtility::makeInstance(LocalizationRepository::class); } /** @@ -69,7 +72,7 @@ public function __construct() * @param string $shortcutItem The single page to be used as the tree root * @param-out array $collectedItems The collected item data rows ordered by parent position, column position and sorting * @param int $parentUid uid of the referencing tt_content record - * @param int $language sys_language_uid of the referencing tt_content record + * @param int $languageId sys_language_uid of the referencing tt_content record * @param int $recursive The number of levels for the recursion * @throws DBALException */ @@ -77,7 +80,7 @@ public function collectContentDataFromPages( string $shortcutItem, array &$collectedItems, int $parentUid = 0, - int $language = 0, + int $languageId = 0, int $recursive = 0 // TODO: $recursive never seems being used ): void { $itemList = str_replace('pages_', '', $shortcutItem); @@ -113,11 +116,8 @@ public function collectContentDataFromPages( /** @ var array|false $item */ while ($item = $result->fetchAssociative()) { - if (!empty($this->extensionConfiguration['overlayShortcutTranslation']) && $language > 0) { - $translatedItem = BackendUtility::getRecordLocalization('tt_content', (int)($item['uid'] ?? 0), $language) ?: []; - if (is_array($translatedItem) && $translatedItem !== []) { - $item = array_shift($translatedItem); - } + if (!empty($this->extensionConfiguration['overlayShortcutTranslation']) && (int)$languageId > 0) { + $translatedItem = $this->localizationRepository->getRecordTranslation($this->table, (int)($item['uid'] ?? 0), (int)$languageId); } if ($this->backendHelper->getBackendUser()->workspace > 0) { unset($item['inSet']); @@ -137,14 +137,14 @@ public function collectContentDataFromPages( * @param string $shortcutItem The tt_content element to fetch the data fromom * @param-out array $collectedItems The collected item data row * @param int $parentUid uid of the referencing tt_content record - * @param int $language sys_language_uid of the referencing tt_content record + * @param int $languageId sys_language_uid of the referencing tt_content record * @throws DBALException */ public function collectContentData( string $shortcutItem, array &$collectedItems, int $parentUid, - int $language + int $languageId ): void { $shortcutItem = str_replace('tt_content_', '', $shortcutItem); if ((int)$shortcutItem !== $parentUid) { @@ -167,11 +167,8 @@ public function collectContentData( ->setMaxResults(1) ->executeQuery() ->fetchAssociative(); - if (!empty($this->extensionConfiguration['overlayShortcutTranslation']) && $language > 0) { - $translatedItem = BackendUtility::getRecordLocalization('tt_content', (int)($item['uid'] ?? 0), $language) ?: []; - if (is_array($translatedItem) && $translatedItem !== []) { - $item = array_shift($translatedItem); - } + if (!empty($this->extensionConfiguration['overlayShortcutTranslation']) && (int)$languageId > 0) { + $translatedItem = $this->localizationRepository->getRecordTranslation($this->table, (int)($item['uid'] ?? 0), (int)$languageId); } if ($this->backendHelper->getBackendUser()->workspace > 0) { @@ -235,10 +232,6 @@ public function cleanupWorkspacesAfterFinalizing(): void ->executeStatement(); } - /** - * @param string $table - * @return QueryBuilder - */ public function getQueryBuilder(string $table = 'tt_content'): QueryBuilder { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) diff --git a/Classes/PageLayoutView/ShortcutPreviewRenderer.php b/Classes/PageLayoutView/ShortcutPreviewRenderer.php index f0eed86e..02eebd00 100644 --- a/Classes/PageLayoutView/ShortcutPreviewRenderer.php +++ b/Classes/PageLayoutView/ShortcutPreviewRenderer.php @@ -103,7 +103,7 @@ public function renderPageModulePreviewContent(GridColumnItem $gridColumnItem): foreach ($shortCutRenderItems as $shortcutRecord) { $shortcutItem = GeneralUtility::makeInstance( GridColumnItem::class, - $gridColumnItem->getContext(), + $gridColumnItem->getContext(), // false positive of #102621 in Extension Scanner $gridColumnItem->getColumn(), $shortcutRecord ); @@ -172,8 +172,8 @@ protected function addShortcutRenderItems(GridColumnItem $gridColumnItem): array $dataRow['shortcutItems'] = []; foreach ($collectedItems as $item) { if ($item) { - $itemObj = $this->recordFactory->createFromDatabaseRow('tt_content', $item); - $renderItems[] = $itemObj; // $this->prepareRecord($itemObj); + $itemObj = $this->recordFactory->createResolvedRecordFromDatabaseRow('tt_content', $item); + $renderItems[] = $itemObj; } } } @@ -251,9 +251,8 @@ protected function getFakeItemForPreview(GridColumnItem $gridColumnItem): GridCo $rawRecord->getComputedProperties(), $rawRecord->getFullType() ); - $fakeRecord = GeneralUtility::makeInstance( - Record::class, - $rawFakeRecord, + $fakeRecord = $this->recordFactory->createResolvedRecordFromDatabaseRow( + 'tt_content', $fakeRecordDataRow ); $gridColumnItem->setRecord($fakeRecord); diff --git a/README.md b/README.md index d7e3ec7b..a4d4eafc 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,8 @@ Paste reference uses [**semantic versioning**][5], which means, that #### 4.3.1 Releases -* for TYPO3 v13: [4.0.3](https://github.com/Kephson/paste_reference/releases/tag/4.0.3) +* for TYPO3 v14: [5.0.0](https://github.com/Kephson/paste_reference/releases/tag/5.0.0) +* for TYPO3 v13: [4.0.5](https://github.com/Kephson/paste_reference/releases/tag/4.0.5) * for TYPO3 v12: [3.0.5](https://github.com/Kephson/paste_reference/releases/tag/3.0.5) * for TYPO3 v11: [2.0.5](https://github.com/Kephson/paste_reference/releases/tag/2.0.5) * for TYPO3 v10: [1.0.3](https://github.com/Kephson/paste_reference/releases/tag/1.0.3) @@ -76,21 +77,23 @@ Paste reference uses [**semantic versioning**][5], which means, that To get the most recent development for the branch 4, consider installing the branch instead of the release. The branch [v4-dev](https://github.com/Kephson/paste_reference/tree/v4-dev) supports also -TYPO3 v14 up to v14.1 and includes unreleased bug-fixes. +TYPO3 v14 up to v14.1 and includes unreleased bug-fixes. +The sub-versions above might not be always the newest, so please check the +[RELEASES](https://github.com/Kephson/paste_reference/releases) instead of relying on the list above. #### 4.3.2 Branches The following branches are of interest: -* for TYPO3 v13 and v14: [v4-dev](https://github.com/Kephson/paste_reference/tree/v4-dev) +* for TYPO3 v14: [v5-dev](https://github.com/Kephson/paste_reference/tree/v5-dev) +* for TYPO3 v13: [v4-dev](https://github.com/Kephson/paste_reference/tree/v4-dev) + for TYPO3 v12: [TYPO3_12](https://github.com/Kephson/paste_reference/tree/TYPO3_12) * for TYPO3 v11: [TYPO3_11-5](https://github.com/Kephson/paste_reference/tree/TYPO3_11-5) * for TYPO3 v10: [TYPO3_10-4](https://github.com/Kephson/paste_reference/tree/TYPO3_10-4) Note, that releases are usually to prefer, if possible. -The branch [v4-dev](https://github.com/Kephson/paste_reference/tree/v4-dev) is -ahead of the releases currently, so in this case using the branch is better and -gives you most recent development changes. +If it's advisable to install a branch instead of a release, according info can be found in +the issues of the repository. ### 4.4 Contribution diff --git a/Tests/Extensions/test_container.zip b/Tests/Extensions/test_container.zip new file mode 100644 index 00000000..53b24c93 Binary files /dev/null and b/Tests/Extensions/test_container.zip differ diff --git a/Tests/Extensions/test_container/Configuration/TCA/Overrides/tt_content.php b/Tests/Extensions/test_container/Configuration/TCA/Overrides/tt_content.php deleted file mode 100644 index 29caa183..00000000 --- a/Tests/Extensions/test_container/Configuration/TCA/Overrides/tt_content.php +++ /dev/null @@ -1,77 +0,0 @@ - 'Left Column', 'colPos' => 101], - ['name' => 'Right Column', 'colPos' => 102], - ], - ] // grid configuration - ); - - $containerConfiguration->setIcon('EXT:test_container/Resources/Public/Icons/container-2col.svg'); - $containerConfiguration->setSaveAndCloseInNewContentElementWizard(false); - - $containerRegistry->configureContainer($containerConfiguration); - - // Register a nested container for advanced testing - $nestedContainerConfiguration = new ContainerConfiguration( - 'test_container_nested', // CType - 'Test Nested Container', // label - 'Nested container for testing complex paste-reference scenarios', // description - [ - [ - ['name' => 'Main Area', 'colPos' => 201], - ], - [ - ['name' => 'Sub Left', 'colPos' => 202], - ['name' => 'Sub Right', 'colPos' => 203], - ], - ] // grid configuration - ); - - $nestedContainerConfiguration->setIcon('EXT:test_container/Resources/Public/Icons/container-nested.svg'); - $nestedContainerConfiguration->setSaveAndCloseInNewContentElementWizard(false); - - $containerRegistry->configureContainer($nestedContainerConfiguration); - - // Add containers to content element wizard - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( - 'tt_content', - 'CType', - [ - 'label' => 'Test Two Columns', - 'value' => 'test_container_2col', - 'icon' => 'content-container-columns-2', - 'group' => 'container', - 'description' => 'Two column container for testing', - ] - ); - - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( - 'tt_content', - 'CType', - [ - 'label' => 'Test Nested Container', - 'value' => 'test_container_nested', - 'icon' => 'content-container-columns-3', - 'group' => 'container', - 'description' => 'Nested container for testing', - ] - ); -} diff --git a/Tests/Extensions/test_container/Resources/Public/Icons/container-2col.svg b/Tests/Extensions/test_container/Resources/Public/Icons/container-2col.svg deleted file mode 100644 index 24c6ccbe..00000000 --- a/Tests/Extensions/test_container/Resources/Public/Icons/container-2col.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - L - R - \ No newline at end of file diff --git a/Tests/Extensions/test_container/Resources/Public/Icons/container-nested.svg b/Tests/Extensions/test_container/Resources/Public/Icons/container-nested.svg deleted file mode 100644 index b2ec92f1..00000000 --- a/Tests/Extensions/test_container/Resources/Public/Icons/container-nested.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - MAIN - L - R - \ No newline at end of file diff --git a/Tests/Extensions/test_container/ext_emconf.php b/Tests/Extensions/test_container/ext_emconf.php deleted file mode 100644 index 67847500..00000000 --- a/Tests/Extensions/test_container/ext_emconf.php +++ /dev/null @@ -1,20 +0,0 @@ - 'Test Container Extension', - 'description' => 'Minimal container extension for testing paste-reference functionality', - 'category' => 'misc', - 'author' => 'Test Author', - 'author_email' => 'test@example.com', - 'state' => 'stable', - 'version' => '1.0.0', - 'constraints' => [ - 'depends' => [ - 'typo3' => '13.0.0-14.99.99', - 'container' => '3.0.0-3.99.99', - ], - 'conflicts' => [], - 'suggests' => [], - ], -]; diff --git a/Tests/Extensions/test_container/ext_localconf.php b/Tests/Extensions/test_container/ext_localconf.php deleted file mode 100644 index f655fb90..00000000 --- a/Tests/Extensions/test_container/ext_localconf.php +++ /dev/null @@ -1,8 +0,0 @@ -request->getAttributes()['routing']->getPageId(); + $cObj = $this->request->getAttribute('currentContentObject'); + $data = $cObj->data; // false positive of #101995 in Extension Scanner + $currentRecord = $this->irreRepository->findByUid((int)$data['uid']); + $childRecords = $this->irreRepository->getChildRecords((int)$data['uid']); + $this->view->assign('data', $data); + $this->view->assign('childRecords', $childRecords); + return $this->htmlResponse(); + } + + public function showAction(): ResponseInterface + { + // $pageId = $this->request->getAttributes()['routing']->getPageId(); + $cObj = $this->request->getAttribute('currentContentObject'); + $data = $cObj->data; // false positive of #101995 in Extension Scanner + $currentRecord = $this->irreRepository->findByUid((int)$data['uid']); + $childRecords = $this->irreRepository->getChildRecords((int)$data['uid']); + $this->view->assign('data', $data); + $this->view->assign('childRecords', $childRecords); + return $this->htmlResponse(); + } + + public function listAction(): ResponseInterface + { + // $pageId = $this->request->getAttributes()['routing']->getPageId(); + $cObj = $this->request->getAttribute('currentContentObject'); + $data = $cObj->data; // false positive of #101995 in Extension Scanner + $currentRecord = $this->irreRepository->findByUid((int)$data['uid']); + $childRecords = $this->irreRepository->getChildRecords((int)$data['uid']); + $this->view->assign('data', $data); + $this->view->assign('childRecords', $childRecords); + return $this->htmlResponse(); + } +} diff --git a/Tests/Extensions/test_sitepackage/Classes/Domain/Model/Irre.php b/Tests/Extensions/test_sitepackage/Classes/Domain/Model/Irre.php new file mode 100644 index 00000000..e668c4fb --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Classes/Domain/Model/Irre.php @@ -0,0 +1,71 @@ + + */ + protected ?ObjectStorage $childRecords = null; + + public function __construct() + { + $this->initializeObject(); + } + + public function initializeObject(): void + { + $this->childRecords = new ObjectStorage(); + } + + public function getTxTestsitepackeParent(): int + { + return $this->txTestsitepackeParent; + } + + public function setTxTestsitepackeParent(int $txTestsitepackeParent): void + { + $this->txTestsitepackeParent = $txTestsitepackeParent; + } + + /** + * @return ObjectStorage + */ + public function getChildRecords(): ObjectStorage + { + return $this->childRecords; // ?? new ObjectStorage(); + } + + /** + * @param ObjectStorage $childRecords + */ + public function setChildRecords(ObjectStorage $childRecords): void + { + $this->childRecords = $childRecords; + } + + public function addChildRecord(Irre $childRecord): void + { + $this->childRecords->attach($childRecord); + } + + public function removeChildRecord(Irre $childRecord): void + { + $this->childRecords->detach($childRecord); + } +} diff --git a/Tests/Extensions/test_sitepackage/Classes/Domain/Repository/IrreRepository.php b/Tests/Extensions/test_sitepackage/Classes/Domain/Repository/IrreRepository.php new file mode 100644 index 00000000..884a785d --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Classes/Domain/Repository/IrreRepository.php @@ -0,0 +1,42 @@ +createQuery()->getQuerySettings(); + // Show comments from all pages + $querySettings->setRespectStoragePage(false); + $this->setDefaultQuerySettings($querySettings); + } + + public function getChildRecords(int $uid): QueryResultInterface + { + $currentRecord = $this->findByUid($uid); + $childRecords = []; + $query = $this->createQuery(); + $childRecords = $query + ->matching( + $query->logicalAnd( + $query->equals('tablenames', 'tt_content'), + $query->equals('tx_testsitepacke_parent', $uid), + ), + ) + ->execute(); + return $childRecords; + } +} diff --git a/Tests/Extensions/test_sitepackage/Configuration/Extbase/Persistence/Classes.php b/Tests/Extensions/test_sitepackage/Configuration/Extbase/Persistence/Classes.php new file mode 100644 index 00000000..7dbb935c --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/Extbase/Persistence/Classes.php @@ -0,0 +1,14 @@ + [ + 'tableName' => 'tt_content', + 'properties' => [ + 'childRecords' => [ + 'fieldName' => 'tx_testsitepacke_kids', + ], + ], + ], +]; diff --git a/Tests/Extensions/test_sitepackage/Configuration/Icons.php b/Tests/Extensions/test_sitepackage/Configuration/Icons.php new file mode 100644 index 00000000..3a5b80d1 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/Icons.php @@ -0,0 +1,14 @@ + [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:test_sitepackage/Resources/Public/Icons/Plugin.svg', + ], + 'tx-testsitepacke-parent-icon' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:test_sitepackage/Resources/Public/Icons/tx_testsitepacke_parent.svg', + ], +]; diff --git a/Tests/Extensions/test_sitepackage/Configuration/Services.yaml b/Tests/Extensions/test_sitepackage/Configuration/Services.yaml new file mode 100644 index 00000000..693ce0c1 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/Services.yaml @@ -0,0 +1,16 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Test\Sitepackage\Controller\: + resource: '../Classes/Controller' + + Test\Sitepackage\Domain\Repository\: + resource: '../Classes/Domain/Repository' + + Test\Sitepackage\: + resource: '../Classes/*' + exclude: + - '../Classes/Domain/Model/*' diff --git a/Tests/Extensions/test_sitepackage/Configuration/TCA/Overrides/tt_content.php b/Tests/Extensions/test_sitepackage/Configuration/TCA/Overrides/tt_content.php new file mode 100644 index 00000000..0f8d12f8 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/TCA/Overrides/tt_content.php @@ -0,0 +1,101 @@ + 'Left Column', + 'colPos' => 101, + ], + [ + 'name' => 'Right Column', + 'colPos' => 102, + ], + ], + ] +); +$containerConfiguration->setIcon( + 'EXT:test_sitepackage/Resources/Public/Icons/ce_columns2.svg', +); +$containerConfiguration->setSaveAndCloseInNewContentElementWizard(false); +$containerRegistry->configureContainer($containerConfiguration); + +// Add the container to the content element wizard +ExtensionManagementUtility::addTcaSelectItem( + 'tt_content', + 'CType', + [ + 'label' => 'Two Columns Container', + 'value' => 'ce_columns2', + 'icon' => 'content-container-columns-2', + 'group' => 'container', + 'description' => 'Container with two columns for content elements', + ], +); + +ExtensionManagementUtility::addTCAcolumns( + 'tt_content', + [ + 'tx_testsitepacke_parent' => [ + 'label' => 'Inline Element parent field', + 'config' => [ + 'type' => 'passthrough', + ], + ], + 'tx_testsitepacke_kids' => [ + 'label' => 'Inline Elements', + 'description' => 'Group several content elements', + 'exclude' => 0, + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tt_content', + 'foreign_field' => 'tx_testsitepacke_parent', + 'foreign_table_field' => 'tablenames', + 'appearance' => [ + 'showSynchronizationLink' => true, + 'showAllLocalizationLink' => true, + 'showPossibleLocalizationRecords' => true, + ], + ], + ], + ], +); + +$tmpConfig = $GLOBALS['TCA']['tt_content']['types']['text']; +$tmpConfigArray = explode(',', $tmpConfig['showitem']); +foreach ($tmpConfigArray as $count => $tmpConfigValue) { + if (trim($tmpConfigValue) == 'bodytext') { + $tmpConfigArray[$count] = 'tx_testsitepacke_kids'; + } +} +$GLOBALS['TCA']['tt_content']['types']['testsitepackage_inlinerecordsirre']['showitem'] = implode(',', $tmpConfigArray); + +ExtensionUtility::registerPlugin( + 'TestSitepackage', // extensionName or extension_key + 'InlineRecordsIrre', // pluginName + 'Inline Records (IRRE)', // pluginTitle + 'tx-testsitepacke-parent-icon', // pluginIcon + 'plugins', // group + 'Simple Content Element with IRRE relations' // pluginDescription + // $$flexForm // Either a reference to a flex-form XML file or the XML directly +); + +$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes']['testsitepackage_inlinerecordsirre'] = 'tx-testsitepacke-parent-icon'; diff --git a/Tests/Extensions/test_sitepackage/Configuration/TypoScript/constants.typoscript b/Tests/Extensions/test_sitepackage/Configuration/TypoScript/constants.typoscript new file mode 100644 index 00000000..96875ca5 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/TypoScript/constants.typoscript @@ -0,0 +1,13 @@ +# Constants for test sitepackage +styles.content.loginform.pid = 1 + +plugin.tx_testsitepackage_inlinerecordsirre { + view { + templateRootPath = EXT:test_sitepackage/Resources/Private/Templates/ + partialRootPath = EXT:test_sitepackage/Resources/Private/Partials/ + layoutRootPath = EXT:test_sitepackage/Resources/Private/Layouts/ + } + persistence { + storagePid = 0 + } +} diff --git a/Tests/Extensions/test_sitepackage/Configuration/TypoScript/setup.typoscript b/Tests/Extensions/test_sitepackage/Configuration/TypoScript/setup.typoscript new file mode 100644 index 00000000..0fdf736a --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/TypoScript/setup.typoscript @@ -0,0 +1,96 @@ +# Basic page configuration +page = PAGE +page { + typeNum = 0 + + 10 = FLUIDTEMPLATE + 10 { + templateName = Default + templateRootPaths { + 0 = EXT:test_sitepackage/Resources/Private/Templates/Page/ + } + partialRootPaths { + 0 = EXT:test_sitepackage/Resources/Private/Partials/Page/ + } + layoutRootPaths { + 0 = EXT:test_sitepackage/Resources/Private/Layouts/Page/ + } + + variables { + content = CONTENT + content { + table = tt_content + select { + orderBy = sorting + where = {#colPos}=0 + } + } + + sidebar = CONTENT + sidebar { + table = tt_content + select { + orderBy = sorting + where = {#colPos}=1 + } + } + } + } + + includeCSS { + theme = EXT:test_sitepackage/Resources/Public/Css/theme.css + } +} + +# Container rendering for ce_columns2 +tt_content.ce_columns2 = FLUIDTEMPLATE +tt_content.ce_columns2 { + templateName = Columns2 + templateRootPaths { + 0 = EXT:test_sitepackage/Resources/Private/Templates/ContentElements/ + } + + dataProcessing { + 100 = B13\Container\DataProcessing\ContainerProcessor + } +} + +plugin.tx_testsitepackage_inlinerecordsirre { + extensionName = TestSitepackage + pluginName = InlineRecordsIrre + vendorName = Test + + mvc { + callDefaultActionIfActionCantBeResolved = 1 + } + persistence { + storagePid = {$plugin.plugin.tx_testsitepackage_inlinerecordsirre.persistence.storagePid} + } + settings { + detailPid = {$plugin.plugin.tx_testsitepackage_inlinerecordsirre.persistence.storagePid} + settings.foo = bar + } + view { + layoutRootPaths { + 10 = EXT:test_sitepackage/Resources/Private/Layouts/ContentElements/ + 20 = {$plugin.tx_testsitepackage_inlinerecordsirre.view.layoutRootPath} + } + partialRootPaths { + 10 = EXT:test_sitepackage/Resources/Private/Partials/ContentElements/ + 20 = {$plugin.tx_testsitepackage_inlinerecordsirre.view.partialRootPath} + } + templateRootPaths { + 10 = EXT:test_sitepackage/Resources/Private/Templates/ + 20 = EXT:test_sitepackage/Resources/Private/Templates/ContentElements/ + 30 = {$plugin.tx_testsitepackage_inlinerecordsirre.view.templateRootPath} + } + } +} + +tt_content.testsitepackage_inlinerecordsirre = EXTBASEPLUGIN +tt_content.testsitepackage_inlinerecordsirre { + extensionName = TestSitepackage + pluginName = InlineRecordsIrre + vendorName = Test +} + diff --git a/Tests/Extensions/test_sitepackage/Configuration/page.tsconfig b/Tests/Extensions/test_sitepackage/Configuration/page.tsconfig new file mode 100644 index 00000000..c386a321 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Configuration/page.tsconfig @@ -0,0 +1,70 @@ +## TCEFORM.tt_content.CType.addItems.tx_testsitepacke_parent = IRRE Element + +mod.wizards.newContentElement.wizardItems { + + container { + header = Container Elements + elements { + ce_columns2 { + iconIdentifier = content-container-columns-2 + title = Two Columns Container + description = Container with two columns for content elements + tt_content_defValues { + CType = ce_columns2 + } + } + } + show = * + } + + tx_testsitepacke_parent { + header = testsitepacke IRRE + elements { + tx_testsitepacke_parent { + iconIdentifier = tx-testsitepacke-parent-icon + title = testsitepacke IRRE + description = Content Element including IRRE Elements + tt_content_defValues { + CType = tx_testsitepacke_parent + } + } + } + show = * + } +} + + +# Page TSconfig for backend layout +mod { + web_layout { + BackendLayouts { + default { + title = Default Layout + config { + backend_layout { + colCount = 2 + rowCount = 1 + rows { + 1 { + columns { + 1 { + name = Main Content + colPos = 0 + colspan = 1 + allowed = * + } + 2 { + name = Sidebar + colPos = 1 + colspan = 1 + allowed = * + } + } + } + } + } + } + } + } + } +} diff --git a/Tests/Extensions/test_sitepackage/README.md b/Tests/Extensions/test_sitepackage/README.md new file mode 100644 index 00000000..e16422a7 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/README.md @@ -0,0 +1,63 @@ +# Test Sitepackage + +A simple TYPO3 sitepackage for testing the paste-reference extension with container elements. + +## Features + +- 2-column backend layout (Main Content + Sidebar) +- Container element `ce_columns2` with two columns (colPos 101 and 102) +- Basic Fluid templates and CSS styling +- Integration with the container extension + +## Installation + +1. Place this extension in your TYPO3 installation +2. Activate the extension in the Extension Manager +3. Include the static TypoScript template "Test Sitepackage" +4. Create a page and set the backend layout to "Default Layout" + +## Container Element + +The `ce_columns2` container element provides: +- Two columns with colPos 101 (left) and 102 (right) +- Responsive layout using flexbox +- Integration with the container extension for proper backend editing + +## Testing with paste-reference + +This sitepackage is designed to test the paste-reference extension functionality with: +- Regular page columns (colPos 0 and 1) +- Container columns (colPos 101 and 102) +- Mixed environments with both types of columns + +## File Structure + +``` +test_sitepackage/ +├── Configuration/ +│ ├── TCA/Overrides/ +│ │ └── tt_content.php # Container registration +│ ├── TsConfig/Page/ +│ │ └── container.tsconfig # Backend layout & container config +│ └── TypoScript/ +│ ├── constants.typoscript +│ └── setup.typoscript # Page & container rendering +├── Resources/ +│ ├── Private/ +│ │ ├── Layouts/ +│ │ │ └── Default.html +│ │ └── Templates/ +│ │ ├── ContentElements/ +│ │ │ └── Columns2.html # Container template +│ │ └── Page/ +│ │ └── Default.html # Page template +│ └── Public/ +│ ├── Css/ +│ │ └── theme.css # Basic styling +│ └── Icons/ +│ └── ce_columns2.svg # Container icon +├── ext_emconf.php +├── ext_localconf.php +├── ext_tables.php +└── composer.json +``` \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/ContentElements/Default.html b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/ContentElements/Default.html new file mode 100644 index 00000000..f4a3d1e7 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/ContentElements/Default.html @@ -0,0 +1,6 @@ + +

CEs Layout Default

+
+ +
+ diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Default.html b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Default.html new file mode 100644 index 00000000..c07e8768 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Default.html @@ -0,0 +1,17 @@ + + +
+
+

Test Sitepackage

+
+ +
+ +
+ +
+

© 2024 Test Sitepackage

+
+
+ + diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Page/Default.html b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Page/Default.html new file mode 100644 index 00000000..c07e8768 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Layouts/Page/Default.html @@ -0,0 +1,17 @@ + + +
+
+

Test Sitepackage

+
+ +
+ +
+ +
+

© 2024 Test Sitepackage

+
+
+ + diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Templates/ContentElements/Columns2.html b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/ContentElements/Columns2.html new file mode 100644 index 00000000..36f3649a --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/ContentElements/Columns2.html @@ -0,0 +1,22 @@ + + +
+
+
+ + + + + +
+
+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Index.fluid.html b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Index.fluid.html new file mode 100644 index 00000000..552c1a7e --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Index.fluid.html @@ -0,0 +1,22 @@ + + + + + +

IRRE Template index

+
+ {_all} + + + + + + {data} + +
+
+ + diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/List.fluid.html b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/List.fluid.html new file mode 100644 index 00000000..5a086b74 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/List.fluid.html @@ -0,0 +1,22 @@ + + + + + +

IRRE Template List

+
+ {_all} + + + + + + {data} + +
+
+ + diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Show.fluid.html b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Show.fluid.html new file mode 100644 index 00000000..5f3f4e82 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Irre/Show.fluid.html @@ -0,0 +1,9 @@ + + +{_all} + +
+

txTestsitepackeParent

+
+Main + diff --git a/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Page/Default.html b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Page/Default.html new file mode 100644 index 00000000..abac9343 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Private/Templates/Page/Default.html @@ -0,0 +1,17 @@ + + + +

Page Template Default

+ + +
+ {content} +
+ + +
+ + + diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Css/theme.css b/Tests/Extensions/test_sitepackage/Resources/Public/Css/theme.css new file mode 100644 index 00000000..c62c5537 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Public/Css/theme.css @@ -0,0 +1,67 @@ +/* Basic styling for test sitepackage */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +header { + background-color: #f8f9fa; + padding: 20px; + margin-bottom: 20px; + border-radius: 5px; +} + +.main-content { + display: flex; + gap: 20px; + margin-bottom: 20px; +} + +.content-area { + flex: 2; +} + +.sidebar { + flex: 1; + background-color: #f8f9fa; + padding: 20px; + border-radius: 5px; +} + +/* Container element styling */ +.ce-columns2 { + margin: 20px 0; +} + +.ce-columns2 .row { + display: flex; + gap: 20px; +} + +.ce-columns2 .col-md-6 { + flex: 1; + padding: 15px; + background-color: #f8f9fa; + border-radius: 5px; + min-height: 100px; +} + +footer { + background-color: #343a40; + color: white; + padding: 20px; + text-align: center; + border-radius: 5px; +} + +/* Backend styling hints */ +.t3-page-ce-wrapper { + border: 1px dashed #ccc; + margin: 5px 0; + padding: 10px; +} + +.t3-page-ce-wrapper:hover { + border-color: #007cba; +} \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Extension.svg b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Extension.svg new file mode 100644 index 00000000..bca7a175 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Extension.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Plugin.svg b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Plugin.svg new file mode 100644 index 00000000..e35be03c --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/Plugin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Icons/ce_columns2.svg b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/ce_columns2.svg new file mode 100644 index 00000000..ab6429f0 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/ce_columns2.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Icons/favicon.ico b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/favicon.ico new file mode 100644 index 00000000..90fdfe18 Binary files /dev/null and b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/favicon.ico differ diff --git a/Tests/Extensions/test_sitepackage/Resources/Public/Icons/tx_testsitepacke_parent.svg b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/tx_testsitepacke_parent.svg new file mode 100644 index 00000000..e35be03c --- /dev/null +++ b/Tests/Extensions/test_sitepackage/Resources/Public/Icons/tx_testsitepacke_parent.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Tests/Extensions/test_sitepackage/composer.json b/Tests/Extensions/test_sitepackage/composer.json new file mode 100644 index 00000000..734833df --- /dev/null +++ b/Tests/Extensions/test_sitepackage/composer.json @@ -0,0 +1,20 @@ +{ + "name": "test/sitepackage", + "type": "typo3-cms-extension", + "description": "Simple sitepackage for testing paste-reference with container extension", + "license": "GPL-2.0-or-later", + "require": { + "typo3/cms-core": "^12.0 || ^13.0 || ^14.0", + "b13/container": "^3.0" + }, + "autoload": { + "psr-4": { + "Test\\Sitepackage\\": "Classes/" + } + }, + "extra": { + "typo3/cms": { + "extension-key": "test_sitepackage" + } + } +} diff --git a/Tests/Extensions/test_sitepackage/ext_emconf.php b/Tests/Extensions/test_sitepackage/ext_emconf.php new file mode 100644 index 00000000..580d9b61 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/ext_emconf.php @@ -0,0 +1,27 @@ + 'Test Sitepackage', + 'description' => 'Simple sitepackage for testing paste-reference with container extension', + 'category' => 'templates', + 'author' => 'David Bruchmann', + 'author_email' => 'david.bruchmann@gmail.com', + 'state' => 'stable', + 'version' => '1.1.0', + 'constraints' => [ + 'depends' => [ + 'typo3' => '12.0.0-14.99.99', + 'container' => '3.0.0-3.99.99', + ], + 'conflicts' => [], + 'suggests' => [], + ], +]; diff --git a/Tests/Extensions/test_sitepackage/ext_localconf.php b/Tests/Extensions/test_sitepackage/ext_localconf.php new file mode 100644 index 00000000..12e4f175 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/ext_localconf.php @@ -0,0 +1,20 @@ + 'index, list, show', + ], + [ + IrreController::class => '', + ], + ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT, +); diff --git a/Tests/Extensions/test_sitepackage/ext_tables.php b/Tests/Extensions/test_sitepackage/ext_tables.php new file mode 100644 index 00000000..643d2b28 --- /dev/null +++ b/Tests/Extensions/test_sitepackage/ext_tables.php @@ -0,0 +1,10 @@ +typo3Version->getMajorVersion(); // Test that priority method returns expected type - $priority = $provider->getPriority(); + $priority = $provider->getPriority(); // false positive of #94107, #100963 in Extension Scanner self::assertGreaterThan(0, $priority); } diff --git a/Tests/Unit/DeprecatedApiDetectionTest.php b/Tests/Unit/DeprecatedApiDetectionTest.php index d5fe2f45..9640c800 100644 --- a/Tests/Unit/DeprecatedApiDetectionTest.php +++ b/Tests/Unit/DeprecatedApiDetectionTest.php @@ -139,7 +139,7 @@ public function extensionDoesNotUseRemovedConstants(): void { $extensionFiles = $this->getExtensionPhpFiles(); $removedConstants = [ - 'TYPO3_MODE', // Removed in TYPO3 v11 + 'TYPO3_MODE', // Removed in TYPO3 v11 // false positive of #92947, #96107 in Extension Scanner 'TYPO3_version', // Use Typo3Version class instead 'TYPO3_branch', // Use Typo3Version class instead ];