diff --git a/.travis.yml b/.travis.yml index a0f2ece..5d854ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,6 +72,9 @@ jobs: echo; find . -name \*.php ! -path "./.Build/*" | parallel --gnu php -d display_errors=stderr -l {} > /dev/null \;; php: 8.1.0 + env: TYPO3=~12.3.0 + - <<: *tests + php: 8.1.0 env: TYPO3=~12.2.0 - <<: *tests php: 8.1.0 @@ -120,7 +123,7 @@ jobs: git: depth: false php: 8.1 - env: TYPO3="^11.5 ~12.0.0 ~12.1.0 ~12.2.0" + env: TYPO3="^11.5 ~12.0.0 ~12.1.0 ~12.2.0 ~12.3.0" before_install: - nvm install 12 - nvm use 12 diff --git a/Classes/Form/FormDataProvider/TcaCTypeItems.php b/Classes/Form/FormDataProvider/TcaCTypeItems.php index 7f4ed86..cf15d9f 100644 --- a/Classes/Form/FormDataProvider/TcaCTypeItems.php +++ b/Classes/Form/FormDataProvider/TcaCTypeItems.php @@ -19,6 +19,7 @@ use IchHabRecht\ContentDefender\BackendLayout\BackendLayoutConfiguration; use TYPO3\CMS\Backend\Form\FormDataProviderInterface; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Utility\GeneralUtility; class TcaCTypeItems implements FormDataProviderInterface @@ -50,26 +51,70 @@ public function addData(array $result) $allowedConfiguration = array_intersect_key($columnConfiguration['allowed.'] ?? [], $result['processedTca']['columns']); foreach ($allowedConfiguration as $field => $value) { + $currentRecordValue = is_array($result['databaseRow'][$field]) ? $result['databaseRow'][$field][0] : $result['databaseRow'][$field]; $allowedValues = GeneralUtility::trimExplode(',', $value); - $result['processedTca']['columns'][$field]['config']['items'] = array_filter( + $result['processedTca']['columns'][$field]['config']['items'] = $this->filterAllowedItems( $result['processedTca']['columns'][$field]['config']['items'], - function ($item) use ($allowedValues) { - return in_array($item[1], $allowedValues); - } + $allowedValues, + false, + $currentRecordValue ); } $disallowedConfiguration = array_intersect_key($columnConfiguration['disallowed.'] ?? [], $result['processedTca']['columns']); foreach ($disallowedConfiguration as $field => $value) { + $currentRecordValue = is_array($result['databaseRow'][$field]) ? $result['databaseRow'][$field][0] : $result['databaseRow'][$field]; $disallowedValues = GeneralUtility::trimExplode(',', $value); - $result['processedTca']['columns'][$field]['config']['items'] = array_filter( + $result['processedTca']['columns'][$field]['config']['items'] = $this->filterAllowedItems( $result['processedTca']['columns'][$field]['config']['items'], - function ($item) use ($disallowedValues) { - return !in_array($item[1], $disallowedValues); - } + $disallowedValues, + true, + $currentRecordValue ); } return $result; } + + /** + * Remove items not in filter list, unless it matches the current record value, then label it as 'invalid value' + * Remove items in filter list if $disallow=true + * + * @param $items + * @param $filterItems + * @param $disallow + * @param $currentRecordValue + * @return array + */ + protected function filterAllowedItems($items, $filterItems, $disallow, $currentRecordValue) + { + foreach ($items as $key => $item) { + // Associative array since TYPO3 v12.3 + $value = $item['value'] ?? $item[1]; + if ($disallow ? in_array($value, $filterItems) : !in_array($value, $filterItems)) { + if ($value !== $currentRecordValue) { + unset($items[$key]); + } else { + if (array_key_exists('label', $item)) { + $items[$key]['label'] = sprintf( + $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), + $item['label'] + ); + } else { + $items[$key][0] = sprintf( + $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), + $item[0] + ); + } + } + } + } + + return $items; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } } diff --git a/Classes/Form/FormDataProvider/TcaColPosItems.php b/Classes/Form/FormDataProvider/TcaColPosItems.php index 5db0f47..7ac002f 100644 --- a/Classes/Form/FormDataProvider/TcaColPosItems.php +++ b/Classes/Form/FormDataProvider/TcaColPosItems.php @@ -21,6 +21,7 @@ use IchHabRecht\ContentDefender\Form\Exception\AccessDeniedColPosException; use IchHabRecht\ContentDefender\Repository\ContentRepository; use TYPO3\CMS\Backend\Form\FormDataProviderInterface; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Utility\GeneralUtility; class TcaColPosItems implements FormDataProviderInterface @@ -57,9 +58,10 @@ public function addData(array $result) $record = $result['databaseRow']; $record['pid'] = $pageId; + $originalRecordColPos = $record['colPos'][0]; foreach ($result['processedTca']['columns']['colPos']['config']['items'] as $key => $item) { - $colPos = (int)$item[1]; + $colPos = (int)($item['value'] ?? $item[1]); $columnConfiguration = $backendLayoutConfiguration->getConfigurationByColPos($colPos, $record['uid']); if (empty($columnConfiguration)) { continue; @@ -75,7 +77,11 @@ public function addData(array $result) $allowedValues = GeneralUtility::trimExplode(',', $value); if ($this->fieldContainsDisallowedValues($record[$field], $allowedValues)) { - unset($result['processedTca']['columns']['colPos']['config']['items'][$key]); + $result['processedTca']['columns']['colPos']['config']['items'] = $this->unsetIfNotCurrent( + $result['processedTca']['columns']['colPos']['config']['items'], + $key, + $originalRecordColPos + ); } } @@ -87,7 +93,11 @@ public function addData(array $result) $disallowedValues = GeneralUtility::trimExplode(',', $value); if ($this->fieldContainsDisallowedValues($record[$field], $disallowedValues, false)) { - unset($result['processedTca']['columns']['colPos']['config']['items'][$key]); + $result['processedTca']['columns']['colPos']['config']['items'] = $this->unsetIfNotCurrent( + $result['processedTca']['columns']['colPos']['config']['items'], + $key, + $originalRecordColPos + ); } } @@ -101,7 +111,11 @@ public function addData(array $result) 1494605357 ); } elseif (!$isCurrentColPos) { - unset($result['processedTca']['columns']['colPos']['config']['items'][$key]); + $result['processedTca']['columns']['colPos']['config']['items'] = $this->unsetIfNotCurrent( + $result['processedTca']['columns']['colPos']['config']['items'], + $key, + $originalRecordColPos + ); } } } @@ -109,6 +123,35 @@ public function addData(array $result) return $result; } + /** + * Unset array item $items[$key] if colPos doesn't match current records colPos, otherwise add 'invalid' label + * + * @param $items + * @param $key + * @param $recordColPos + * @return array + */ + protected function unsetIfNotCurrent($items, $key, $recordColPos) + { + if (array_key_exists($key, $items)) { + if (array_key_exists('value', $items[$key]) && $recordColPos === $items[$key]['value']) { + $items[$key]['label'] = sprintf( + $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), + $items[$key]['label'] + ); + } elseif (array_key_exists(1, $items[$key]) && $recordColPos === $items[$key][1]) { + $items[$key][0] = sprintf( + $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue'), + $items[$key][0] + ); + } else { + unset($items[$key]); + } + } + + return $items; + } + /** * @param string|array $fieldValue * @param array $values @@ -127,4 +170,9 @@ protected function fieldContainsDisallowedValues($fieldValue, array $values, $al return false; } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } } diff --git a/Tests/Functional/Fixtures/Classes/Hooks/SimpleSelectboxSingleHook.php b/Tests/Functional/Fixtures/Classes/Hooks/SimpleSelectboxSingleHook.php index 8173ea6..a9cc423 100644 --- a/Tests/Functional/Fixtures/Classes/Hooks/SimpleSelectboxSingleHook.php +++ b/Tests/Functional/Fixtures/Classes/Hooks/SimpleSelectboxSingleHook.php @@ -10,6 +10,7 @@ public function addSimpleSelectboxItems(array &$parameters) { $parameters['items'] = [ 0 => [ + 0 => '', 1 => '0', ], 1 => [ diff --git a/Tests/Functional/Form/FormDataProvider/TcaCTypeItemsTest.php b/Tests/Functional/Form/FormDataProvider/TcaCTypeItemsTest.php index b505117..5d9ed5b 100644 --- a/Tests/Functional/Form/FormDataProvider/TcaCTypeItemsTest.php +++ b/Tests/Functional/Form/FormDataProvider/TcaCTypeItemsTest.php @@ -71,7 +71,7 @@ public function disallowedCTypesAreRemovedFromCTypeList() $items = array_values($result['processedTca']['columns']['CType']['config']['items']); $this->assertCount(1, $items); - $this->assertSame('bullets', $items[0][1]); + $this->assertSame('bullets', $items[0]['value'] ?? $items[0][1]); } /** @@ -100,6 +100,6 @@ public function disallowedItemsAreRemovedFromListWithItemsProcFunc() $items = array_values($result['processedTca']['columns']['tx_simpleselectboxsingle']['config']['items']); $this->assertCount(1, $items); - $this->assertSame('5', $items[0][1]); + $this->assertSame('5', $items[0]['value'] ?? $items[0][1]); } } diff --git a/Tests/Functional/Form/FormDataProvider/TcaColPosItemsTest.php b/Tests/Functional/Form/FormDataProvider/TcaColPosItemsTest.php index 803581c..360c6ba 100644 --- a/Tests/Functional/Form/FormDataProvider/TcaColPosItemsTest.php +++ b/Tests/Functional/Form/FormDataProvider/TcaColPosItemsTest.php @@ -72,9 +72,9 @@ public function loadedColumnIsRemovedFromColPosList() $items = array_values($result['processedTca']['columns']['colPos']['config']['items']); $this->assertCount(3, $items); - $this->assertSame('0', $items[0][1]); - $this->assertSame('10', $items[1][1]); - $this->assertSame('12', $items[2][1]); + $this->assertSame('0', $items[0]['value'] ?? $items[0][1]); + $this->assertSame('10', $items[1]['value'] ?? $items[1][1]); + $this->assertSame('12', $items[2]['value'] ?? $items[2][1]); } /** @@ -135,9 +135,9 @@ public function notAllowedColumnsAreRemovedFromColPosList() $items = array_values($result['processedTca']['columns']['colPos']['config']['items']); $this->assertCount(3, $items); - $this->assertSame('0', $items[0][1]); - $this->assertSame('11', $items[1][1]); - $this->assertSame('12', $items[2][1]); + $this->assertSame('0', $items[0]['value'] ?? $items[0][1]); + $this->assertSame('11', $items[1]['value'] ?? $items[1][1]); + $this->assertSame('12', $items[2]['value'] ?? $items[2][1]); } /** diff --git a/composer.json b/composer.json index 26e5c65..789b52c 100644 --- a/composer.json +++ b/composer.json @@ -21,13 +21,13 @@ ], "require": { "php": "^7.4 || ^8.0", - "typo3/cms-core": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2", - "typo3/cms-backend": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2" + "typo3/cms-core": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2 || ~12.3", + "typo3/cms-backend": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2 || ~12.3" }, "require-dev": { - "typo3/cms-fluid-styled-content": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2", - "typo3/cms-indexed-search": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2", - "typo3/cms-workspaces": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2", + "typo3/cms-fluid-styled-content": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2 || ~12.3", + "typo3/cms-indexed-search": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2 || ~12.3", + "typo3/cms-workspaces": "^10.4 || ^11.5 || ~12.0 || ~12.1 || ~12.2 || ~12.3", "phpspec/prophecy": "^1.12.1", "typo3/testing-framework": "^6.16 || 7.*@dev", "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge": "^0.1.0", diff --git a/ext_emconf.php b/ext_emconf.php index 8026919..98b7f59 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -26,7 +26,7 @@ array ( 'depends' => array ( - 'typo3' => '9.5.0-12.2.99', + 'typo3' => '9.5.0-12.3.99', ), 'conflicts' => array (