├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Classes ├── Backend │ ├── ContentTypeFilter.php │ └── TableConfigurationPostProcessor.php ├── Controller │ ├── AbstractContentController.php │ ├── ContentController.php │ └── ContentControllerInterface.php ├── Hooks │ ├── ContentIconUserFunction.php │ ├── GroupAccessListPostProcessor.php │ └── WizardItemsHookSubscriber.php ├── Provider │ ├── BackendUserGroupProvider.php │ └── ContentProvider.php └── Service │ └── ConfigurationService.php ├── Configuration └── TCA │ └── Overrides │ ├── be_groups.php │ └── tt_content.php ├── Documentation └── Changelog │ ├── 1.0.0.md │ ├── 1.3.3.md │ ├── 2.0.0.md │ ├── 2.1.0.md │ ├── 2.1.1.md │ ├── 2.2.0.md │ ├── 2.2.1.md │ ├── 2.2.2.md │ ├── 3.0.0.md │ ├── 3.1.0.md │ ├── 4.0.0.md │ ├── 4.1.0.md │ ├── 4.1.1.md │ ├── 4.2.0.md │ ├── 4.2.1.md │ ├── 4.2.2.md │ ├── 4.2.3.md │ ├── 4.2.4.md │ ├── 4.3.0.md │ ├── 4.3.1.md │ ├── 4.3.2.md │ ├── 4.3.3.md │ ├── 4.4.0.md │ ├── 4.4.1.md │ ├── 5.0.0.md │ ├── 5.1.0.md │ └── 5.2.0.md ├── LICENSE.md ├── README.md ├── Resources ├── Private │ ├── .htaccess │ ├── Language │ │ └── locallang.xlf │ ├── Layouts │ │ ├── Content.html │ │ └── FCE.html │ └── Templates │ │ └── Content │ │ └── Error.html └── Public │ └── Icons │ └── Plugin.svg ├── Tests ├── Fixtures │ └── Templates │ │ └── Content │ │ ├── DisabledContent.html │ │ ├── DummyContent.html │ │ └── EmptyTemplate.html ├── Unit │ ├── Backend │ │ └── TableConfigurationPostProcessorTest.php │ ├── Controller │ │ └── ContentControllerTest.php │ ├── Hooks │ │ └── WizardItemsHookSubscriberTest.php │ ├── Provider │ │ └── ContentProviderTest.php │ └── Service │ │ └── ConfigurationServiceTest.php └── bootstrap.php ├── bower.json ├── class.ext_update.php ├── composer.json ├── ext_emconf.php ├── ext_icon.gif ├── ext_localconf.php ├── ext_tables.php ├── ext_tables.sql └── phpunit.xml.dist /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | charset = utf-8 6 | 7 | # Get rid of whitespace to avoid diffs with a bunch of EOL changes 8 | trim_trailing_whitespace = true 9 | 10 | [*] 11 | end_of_line = lf 12 | insert_final_newline = true 13 | 14 | [*.{php}] 15 | indent_size = 4 16 | indent_style = space 17 | 18 | [*.{html,js,css}] 19 | indent_size = 4 20 | indent_style = tab 21 | 22 | [*.{json,yml,txt,md,sql}] 23 | indent_size = 2 24 | indent_style = space 25 | 26 | [*.{xml,xlf,xsd}] 27 | indent_size = 2 28 | indent_style = tab 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/logs 2 | vendor 3 | .idea 4 | composer.lock 5 | /index.php 6 | /typo3 7 | /typo3_src 8 | /typo3conf 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: false 4 | 5 | env: COVERAGE="YES" TYPO3_VERSION=">=7.6.13, <7.6.99" 6 | 7 | php: 8 | - "7.0" 9 | 10 | matrix: 11 | include: 12 | - php: "7.0" 13 | env: COVERAGE="YES" TYPO3_VERSION="8.7.*" 14 | - php: "7.1" 15 | env: COVERAGE="NO" TYPO3_VERSION="8.7.*" 16 | - php: "7.0" 17 | env: COVERAGE="NO" TYPO3_VERSION="dev-master as 8.x-dev" 18 | - php: "7.1" 19 | env: COVERAGE="NO" TYPO3_VERSION="dev-master as 8.x-dev" 20 | 21 | cache: 22 | directories: 23 | - $HOME/.composer/cache 24 | 25 | install: 26 | - composer require "typo3/cms:$TYPO3_VERSION" 27 | - composer install --prefer-dist 28 | 29 | before_script: mkdir -p build/logs 30 | 31 | script: if [[ "$COVERAGE" != "NO" ]]; then ./vendor/bin/phpunit --coverage-clover=build/logs/clover.xml; else ./vendor/bin/phpunit; fi 32 | 33 | after_script: 34 | - ln -s Classes src 35 | - if [[ "$COVERAGE" != "NO" ]]; then ./vendor/bin/coveralls; fi 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Latest release: 5.2.0 (2017/04/26) 2 | 3 | All previous release change logs: 4 | 5 | * [5.2.0 (2017/04/26)](Documentation/Changelog/5.2.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/5.1.0...5.2.0) 6 | * [5.1.0 (2017/03/04)](Documentation/Changelog/5.1.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/5.0.0...5.1.0) 7 | * [5.0.0 (2017/01/28)](Documentation/Changelog/5.0.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.4.1...5.0.0) 8 | * [4.4.1 (2016/03/02)](Documentation/Changelog/4.4.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.4.0...4.4.1) 9 | * [4.4.0 (2015/11/21)](Documentation/Changelog/4.4.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.3.3...4.4.0) 10 | * [4.3.3 (2015/10/24)](Documentation/Changelog/4.3.3.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.3.2...4.3.3) 11 | * [4.3.2 (2015/09/10)](Documentation/Changelog/4.3.2.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.3.1...4.3.2) 12 | * [4.3.1 (2015/08/08)](Documentation/Changelog/4.3.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.3.0...4.3.1) 13 | * [4.3.0 (2015/08/08)](Documentation/Changelog/4.3.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.2.4...4.3.0) 14 | * [4.2.4 (2015/07/01)](Documentation/Changelog/4.2.4.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.2.3...4.2.4) 15 | * [4.2.3 (2015/06/26)](Documentation/Changelog/4.2.3.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.2.2...4.2.3) 16 | * [4.2.2 (2015/05/20)](Documentation/Changelog/4.2.2.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.2.1...4.2.2) 17 | * [4.2.1 (2015/03/19)](Documentation/Changelog/4.2.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.2.0...4.2.1) 18 | * [4.2.0 (2015/03/18)](Documentation/Changelog/4.2.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.1.1...4.2.0) 19 | * [4.1.1 (2014/10/31)](Documentation/Changelog/4.1.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.1.0...4.1.1) 20 | * [4.1.0 (2014/09/19)](Documentation/Changelog/4.1.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/4.0.0...4.1.0) 21 | * [4.0.0 (2014/03/25)](Documentation/Changelog/4.0.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/3.1.0...4.0.0) 22 | * [3.1.0 (2013/06/30)](Documentation/Changelog/3.1.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/3.0.0...3.1.0) 23 | * [3.0.0 (2013/05/18)](Documentation/Changelog/3.0.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.2.2...3.0.0) 24 | * [2.2.2 (2013/03/16)](Documentation/Changelog/2.2.2.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.2.1...2.2.2) 25 | * [2.2.1 (2013/03/02)](Documentation/Changelog/2.2.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.2.0...2.2.1) 26 | * [2.2.0 (2013/01/13)](Documentation/Changelog/2.2.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.1.1...2.2.0) 27 | * [2.1.1 (2013/01/09)](Documentation/Changelog/2.1.1.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.1.0...2.1.1) 28 | * [2.1.0 (2012/12/31)](Documentation/Changelog/2.1.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/2.0.0...2.1.0) 29 | * [2.0.0 (2012/12/31)](Documentation/Changelog/2.0.0.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/1.3.3...2.0.0) 30 | * [1.3.3 (2012/12/16)](Documentation/Changelog/1.3.3.md) [Full list of changes](https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...1.3.3) 31 | * [1.0.0 (2012/10/16)](Documentation/Changelog/1.0.0.md) First release -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Welcome, Contributor! 2 | ===================== 3 | 4 | It's great to see you here - and we welcome your contributions. But first, take a look at 5 | our official contribution guide which explains what we expect from you - in order to make 6 | sure you can expect the best possible result from our extensions. Without further ado: 7 | 8 | > https://fluidtypo3.org/documentation/contributing/contribution-guide.html 9 | -------------------------------------------------------------------------------- /Classes/Backend/ContentTypeFilter.php: -------------------------------------------------------------------------------- 1 | items = $items; 34 | } 35 | 36 | /** 37 | * @param Grid $grid 38 | * @param string $column 39 | * @return array 40 | */ 41 | public function extractBlacklistAndWhitelistFromGridColumns(Grid $grid, $column) 42 | { 43 | $blacklist = []; 44 | $whitelist = []; 45 | foreach ($grid->getRows() as $gridRow) { 46 | foreach ($gridRow->getColumns() as $gridColumn) { 47 | $blacklistedTypes = $gridColumn->getVariable('Fluidcontent.deniedContentTypes'); 48 | $whitelistedTypes = $gridColumn->getVariable('Fluidcontent.allowedContentTypes'); 49 | if (!empty($blacklistedTypes)) { 50 | $blacklist += GeneralUtility::trimExplode(',', $blacklistedTypes); 51 | } 52 | if (!empty($whitelistedTypes)) { 53 | $whitelist += GeneralUtility::trimExplode(',', $whitelistedTypes); 54 | } 55 | } 56 | } 57 | $blacklist = array_unique($blacklist); 58 | $whitelist = array_unique($whitelist); 59 | return array($blacklist, $whitelist); 60 | } 61 | 62 | /** 63 | * @return array 64 | */ 65 | public function extractBlacklistAndWhitelistFromCurrentBackendUser() 66 | { 67 | $user = $this->getCurrentBackendUser(); 68 | if (!$user->isAdmin()) { 69 | return [$user->dataLists['fluidcontentBlacklist'], $user->dataLists['fluidcontentWhitelist']]; 70 | } 71 | return [[], []]; 72 | } 73 | 74 | /** 75 | * @param Grid $grid 76 | * @param string $columnName 77 | * @return array 78 | */ 79 | public function filterItemsByGridColumn(Grid $grid, $columnName) 80 | { 81 | list ($blacklist, $whitelist) = $this->extractBlacklistAndWhitelistFromGridColumns($grid, $columnName); 82 | return $this->filterByBlacklistAndWhitelist($blacklist, $whitelist); 83 | } 84 | 85 | /** 86 | * @return array 87 | */ 88 | public function filterItemsByGroupAccess() 89 | { 90 | list ($blacklist, $whitelist) = $this->extractBlacklistAndWhitelistFromCurrentBackendUser(); 91 | return $this->filterByBlacklistAndWhitelist($blacklist, $whitelist); 92 | } 93 | 94 | /** 95 | * @param array $whitelist 96 | * @param array $blacklist 97 | * @return array 98 | */ 99 | public function filterByBlacklistAndWhitelist(array $whitelist, array $blacklist) 100 | { 101 | $items = $this->items; 102 | if (!empty($whitelist) || !empty($blacklist)) { 103 | foreach ($items as $index => $item) { 104 | $whitelisted = in_array($item[1], $whitelist, true) || empty($whitelist); 105 | $blacklisted = in_array($item[1], $blacklist, true); 106 | if (!$blacklisted && $whitelisted) { 107 | unset($items[$index]); 108 | } 109 | } 110 | } 111 | return $items; 112 | } 113 | 114 | /** 115 | * @return RecordService 116 | */ 117 | protected function getRecordService() 118 | { 119 | return GeneralUtility::makeInstance(ObjectManager::class)->get(RecordService::class); 120 | } 121 | 122 | /** 123 | * @return BackendUserAuthentication 124 | */ 125 | protected function getCurrentBackendUser() 126 | { 127 | return $GLOBALS['BE_USER']; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Classes/Backend/TableConfigurationPostProcessor.php: -------------------------------------------------------------------------------- 1 | getConfigurationService()->getPageTsConfig()); 30 | } 31 | 32 | /** 33 | * @return ConfigurationService 34 | */ 35 | protected function getConfigurationService() 36 | { 37 | /** @var ConfigurationService $configurationService */ 38 | $configurationService = GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager') 39 | ->get('FluidTYPO3\Fluidcontent\Service\ConfigurationService'); 40 | return $configurationService; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Classes/Controller/AbstractContentController.php: -------------------------------------------------------------------------------- 1 | contentConfigurationService = $configurationService; 36 | } 37 | 38 | /** 39 | * @param ViewInterface $view 40 | * @return void 41 | */ 42 | public function initializeView(ViewInterface $view) 43 | { 44 | parent::initializeView($view); 45 | $view->assign('page', $GLOBALS['TSFE']->page); 46 | $view->assign('user', $GLOBALS['TSFE']->fe_user->user); 47 | $view->assign('record', $this->getRecord()); 48 | $view->assign('contentObject', $this->configurationManager->getContentObject()); 49 | $view->assign('cookies', $_COOKIE); 50 | $view->assign('session', $_SESSION); 51 | } 52 | 53 | /** 54 | * @return void 55 | */ 56 | protected function initializeViewVariables() 57 | { 58 | $row = $this->getRecord(); 59 | $form = $this->provider->getForm($row); 60 | $generalSettings = $this->contentConfigurationService->convertFlexFormContentToArray( 61 | $row['pi_flexform'], 62 | $form 63 | ); 64 | $this->settings = RecursiveArrayUtility::merge($this->settings, $generalSettings); 65 | // Add fluidcontent_core form settings (to avoid flux:form.data in templates) 66 | if (false === empty($row['content_options'])) { 67 | $contentSettings = $this->contentConfigurationService->convertFlexFormContentToArray( 68 | $row['content_options'], 69 | $form 70 | ); 71 | if (false === isset($this->settings['content'])) { 72 | $this->settings['content'] = $contentSettings; 73 | } else { 74 | $this->settings['content'] = RecursiveArrayUtility::merge($this->settings['content'], $contentSettings); 75 | } 76 | } 77 | parent::initializeViewVariables(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Classes/Controller/ContentController.php: -------------------------------------------------------------------------------- 1 | /Classes/Controller/ContentController by convention. 18 | * 19 | * @route off 20 | */ 21 | interface ContentControllerInterface extends ControllerInterface 22 | { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Classes/Hooks/ContentIconUserFunction.php: -------------------------------------------------------------------------------- 1 | getIconFromCache($cacheId); 46 | if ($iconIdentifierFromCache) { 47 | return $iconIdentifierFromCache; 48 | } 49 | 50 | $field = $this->detectFirstFlexTypeFieldInTableFromPossibilities('tt_content', array_keys($record)); 51 | $provider = $this->getProviderResolver()->resolvePrimaryConfigurationProvider('tt_content', $field, $record); 52 | if (!$provider) { 53 | return ''; 54 | } 55 | 56 | $form = $provider->getForm($parameters['row']); 57 | if (!$form) { 58 | return ''; 59 | } 60 | 61 | $icon = MiscellaneousUtility::getIconForTemplate($form); 62 | if (0 === strpos($icon, 'EXT:')) { 63 | $icon = GeneralUtility::getFileAbsFileName($icon); 64 | } elseif ('/' === $icon[0]) { 65 | $icon = rtrim(PATH_site, '/') . $icon; 66 | } 67 | $iconIdentifier = null; 68 | if (!file_exists($icon)) { 69 | return 'apps-pagetree-root'; 70 | } 71 | $extension = pathinfo($icon, PATHINFO_EXTENSION); 72 | switch (strtolower($extension)) { 73 | case 'svg': 74 | case 'svgz': 75 | $iconProvider = SvgIconProvider::class; 76 | break; 77 | default: 78 | $iconProvider = BitmapIconProvider::class; 79 | } 80 | $iconIdentifier = 'icon-flux-' . $form->getId(); 81 | $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); 82 | $iconRegistry->registerIcon($iconIdentifier, $iconProvider, ['source' => $icon]); 83 | $this->storeIconMetadataInCache( 84 | $cacheId, 85 | [ 86 | 'identifier' => $iconIdentifier, 87 | 'provider' => $iconProvider, 88 | 'configuration' => [ 89 | 'source' => $icon 90 | ] 91 | ] 92 | ); 93 | return $iconIdentifier; 94 | } 95 | 96 | /** 97 | * @param string $identifier 98 | * @return string 99 | */ 100 | protected function getIconFromCache($identifier) 101 | { 102 | $entry = $this->getCache()->get($identifier); 103 | if (!$entry) { 104 | return ''; 105 | } 106 | $iconIdentifier = $entry['identifier']; 107 | if (!empty($entry['provider'])) { 108 | $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); 109 | $iconRegistry->registerIcon($iconIdentifier, $entry['provider'], $entry['configuration']); 110 | } 111 | return $iconIdentifier; 112 | } 113 | 114 | /** 115 | * @param string $table 116 | * @param array $fields 117 | * @return string 118 | */ 119 | protected function detectFirstFlexTypeFieldInTableFromPossibilities($table, $fields) 120 | { 121 | foreach ($fields as $fieldName) { 122 | if ('flex' === $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['type']) { 123 | return $fieldName; 124 | } 125 | } 126 | return null; 127 | } 128 | 129 | /** 130 | * @param string $identifier 131 | * @param array $iconMetadata 132 | */ 133 | protected function storeIconMetadataInCache($identifier, array $iconMetadata) 134 | { 135 | $this->getCache()->set($identifier, $iconMetadata); 136 | } 137 | 138 | /** 139 | * @return VariableFrontend 140 | */ 141 | protected function getCache() 142 | { 143 | $objectManager = $this->getObjectManager(); 144 | return $objectManager->get(CacheManager::class, $objectManager)->getCache('flux'); 145 | } 146 | 147 | /** 148 | * @return ProviderResolver 149 | */ 150 | protected function getProviderResolver() 151 | { 152 | return $this->getObjectManager()->get(ProviderResolver::class); 153 | } 154 | 155 | /** 156 | * @return ObjectManager 157 | */ 158 | protected function getObjectManager() 159 | { 160 | return GeneralUtility::makeInstance(ObjectManager::class); 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /Classes/Hooks/GroupAccessListPostProcessor.php: -------------------------------------------------------------------------------- 1 | userGroups as $groupData) { 30 | $blacklist = array_merge( 31 | $blacklist, 32 | GeneralUtility::trimExplode(',', $groupData['tx_fluidcontent_deniedfluidcontent']) 33 | ); 34 | $whitelist = array_merge( 35 | $whitelist, 36 | GeneralUtility::trimExplode(',', $groupData['tx_fluidcontent_allowedfluidcontent']) 37 | ); 38 | } 39 | $reference->dataLists['fluidcontentBlacklist'] = array_unique(array_diff($blacklist, [''])); 40 | $reference->dataLists['fluidcontentWhitelist'] = array_unique(array_diff($whitelist, [''])); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Classes/Hooks/WizardItemsHookSubscriber.php: -------------------------------------------------------------------------------- 1 | objectManager->get(ConfigurationService::class); 38 | $this->injectConfigurationService($configurationService); 39 | } 40 | 41 | /** 42 | * @param array $items 43 | * @param NewContentElementController $parentObject 44 | * @return void 45 | */ 46 | public function manipulateWizardItems(&$items, &$parentObject) 47 | { 48 | $this->configurationService->writeCachedConfigurationIfMissing(); 49 | $items = $this->filterPermittedFluidContentTypesByInsertionPosition($items, $parentObject); 50 | $items = $this->filterPermittedFluidContentTypesByUserGroupAccessList($items, $parentObject); 51 | } 52 | 53 | /** 54 | * @param array $items 55 | * @param NewContentElementController $parentObject 56 | * @return array 57 | */ 58 | protected function filterPermittedFluidContentTypesByUserGroupAccessList(array $items, $parentObject) 59 | { 60 | $filter = $this->getContentTypeFilter( 61 | (array) $GLOBALS['TCA']['tt_content']['columns']['tx_fed_fcefile']['config']['items'] 62 | ); 63 | list ($blacklist, $whitelist) = $filter->extractBlacklistAndWhitelistFromCurrentBackendUser(); 64 | // Filter by which fluidcontent types are allowed by backend user group 65 | $items = $this->applyWhitelist($items, (array) $whitelist); 66 | $items = $this->applyBlacklist($items, (array) $blacklist); 67 | return $items; 68 | } 69 | 70 | /** 71 | * @param array $items 72 | * @param array $whitelist 73 | * @return array 74 | */ 75 | protected function applyWhitelist(array $items, array $whitelist) 76 | { 77 | if (0 < count($whitelist)) { 78 | foreach ($items as $name => $item) { 79 | if (false !== strpos($name, '_') && 'fluidcontent_content' === $item['tt_content_defValues']['CType'] 80 | && false === in_array($item['tt_content_defValues']['tx_fed_fcefile'], $whitelist)) { 81 | unset($items[$name]); 82 | } 83 | } 84 | } 85 | return $items; 86 | } 87 | 88 | /** 89 | * @param array $items 90 | * @param array $blacklist 91 | * @return array 92 | */ 93 | protected function applyBlacklist(array $items, array $blacklist) 94 | { 95 | if (0 < count($blacklist)) { 96 | foreach ($blacklist as $contentElementType) { 97 | foreach ($items as $name => $item) { 98 | if ('fluidcontent_content' === $item['tt_content_defValues']['CType'] 99 | && $item['tt_content_defValues']['tx_fed_fcefile'] === $contentElementType) { 100 | unset($items[$name]); 101 | } 102 | } 103 | } 104 | } 105 | return $items; 106 | } 107 | 108 | /** 109 | * @param FormInterface $component 110 | * @param array $whitelist 111 | * @param array $blacklist 112 | * @return array 113 | */ 114 | protected function appendToWhiteAndBlacklistFromComponent( 115 | FormInterface $component, 116 | array $whitelist, 117 | array $blacklist 118 | ) { 119 | $allowed = $component->getVariable('Fluidcontent.allowedContentTypes'); 120 | if (null !== $allowed) { 121 | $whitelist = array_merge($whitelist, GeneralUtility::trimExplode(',', $allowed)); 122 | } 123 | $denied = $component->getVariable('Fluidcontent.deniedContentTypes'); 124 | if (null !== $denied) { 125 | $blacklist = array_merge($blacklist, GeneralUtility::trimExplode(',', $denied)); 126 | } 127 | return [$whitelist, $blacklist]; 128 | } 129 | 130 | /** 131 | * @param array $items 132 | * @return ContentTypeFilter 133 | */ 134 | protected function getContentTypeFilter(array $items) 135 | { 136 | return new ContentTypeFilter($items); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Classes/Provider/BackendUserGroupProvider.php: -------------------------------------------------------------------------------- 1 | contentConfigurationService = $configurationService; 43 | } 44 | 45 | /**+ 46 | * @param array $row 47 | * @param array $configuration 48 | * @return array 49 | */ 50 | public function processTableConfiguration(array $row, array $configuration) 51 | { 52 | 53 | // Create values for the fluidcontent type selectors 54 | $configuration['processedTca']['columns']['tx_fluidcontent_allowedfluidcontent']['config']['items'] = 55 | $this->contentConfigurationService->getContentTypeSelectorItems(); 56 | $configuration['processedTca']['columns']['tx_fluidcontent_deniedfluidcontent']['config']['items'] = 57 | $this->contentConfigurationService->getContentTypeSelectorItems(); 58 | 59 | return $configuration; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Classes/Provider/ContentProvider.php: -------------------------------------------------------------------------------- 1 | configurationManager = $configurationManager; 75 | } 76 | 77 | /** 78 | * @param ConfigurationService $configurationService 79 | * @return void 80 | */ 81 | public function injectContentConfigurationService(ConfigurationService $configurationService) 82 | { 83 | $this->contentConfigurationService = $configurationService; 84 | } 85 | 86 | /** 87 | * @param array $items 88 | * @return ContentTypeFilter 89 | */ 90 | protected function getContentTypeFilter(array $items) 91 | { 92 | return new ContentTypeFilter($items); 93 | } 94 | 95 | /** 96 | * @param array $row 97 | * @param array $configuration 98 | * @return array 99 | */ 100 | public function processTableConfiguration(array $row, array $configuration) 101 | { 102 | if ($row['CType'] === $this->contentObjectType && isset($configuration['processedTca']['columns']['tx_fed_fcefile'])) { 103 | // Create values for the fluidcontent type selector 104 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] = array_merge( 105 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'], 106 | $this->contentConfigurationService->getContentTypeSelectorItems() 107 | ); 108 | 109 | // Filter by which fluidcontent types are allowed by backend user group 110 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] = 111 | $this->getContentTypeFilter( 112 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] 113 | )->filterItemsByGroupAccess(); 114 | 115 | // Filter by which fluidcontent types are allowed by content area, if element is nested 116 | if (!empty($row['tx_flux_parent']) && !empty($row['tx_flux_column'])) { 117 | $filter = $this->getContentTypeFilter( 118 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] 119 | ); 120 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] = 121 | $this->getContentTypeFilter( 122 | $configuration['processedTca']['columns']['tx_fed_fcefile']['config']['items'] 123 | )->filterItemsByGridColumn( 124 | $this->getGrid( 125 | $this->recordService->getSingle( 126 | 'tt_content', 127 | '*', 128 | (integer) $row['tx_flux_parent'] 129 | ) 130 | ), 131 | $row['tx_flux_column'] 132 | ); 133 | } 134 | } 135 | return $configuration; 136 | } 137 | 138 | /** 139 | * @param array $row 140 | * @return \FluidTYPO3\Flux\Form|NULL 141 | */ 142 | public function getForm(array $row) 143 | { 144 | $form = parent::getForm($row); 145 | if ($form) { 146 | $moveSortingProperty = ( 147 | false === $form->hasOption(Form::OPTION_SORTING) 148 | && true === $form->hasOption('Fluidcontent.sorting') 149 | ); 150 | if (true === $moveSortingProperty) { 151 | $form->setOption(Form::OPTION_SORTING, $form->getOption('Fluidcontent.sorting')); 152 | } 153 | } 154 | return $form; 155 | } 156 | 157 | /** 158 | * @param array $row 159 | * @return string 160 | */ 161 | public function getTemplatePathAndFilename(array $row) 162 | { 163 | if (false === empty($this->templatePathAndFilename)) { 164 | $templateReference = $this->templatePathAndFilename; 165 | if ('/' !== $templateReference{0}) { 166 | $templateReference = GeneralUtility::getFileAbsFileName($templateReference); 167 | } 168 | if (true === file_exists($templateReference)) { 169 | return $templateReference; 170 | } 171 | return null; 172 | } 173 | $templateReference = $this->getControllerActionReferenceFromRecord($row); 174 | list (, $filename) = explode(':', $templateReference); 175 | list (, $format) = explode('.', $filename); 176 | $controllerAction = $this->getControllerActionFromRecord($row); 177 | $templatePaths = new TemplatePaths($this->getExtensionKey($row)); 178 | return $templatePaths->resolveTemplateFileForControllerAndActionAndFormat( 179 | 'Content', 180 | $controllerAction, 181 | $format 182 | ); 183 | } 184 | 185 | /** 186 | * @param array $row 187 | * @return string 188 | */ 189 | public function getExtensionKey(array $row) 190 | { 191 | $extensionKey = $this->extensionKey; 192 | $action = $row['tx_fed_fcefile']; 193 | if (false !== strpos($action, ':')) { 194 | $extensionName = array_shift(explode(':', $action)); 195 | if (false === empty($extensionName)) { 196 | $extensionKey = ExtensionNamingUtility::getExtensionKey($extensionName); 197 | } 198 | } 199 | return $extensionKey; 200 | } 201 | 202 | /** 203 | * @param array $row 204 | * @return string 205 | */ 206 | public function getControllerExtensionKeyFromRecord(array $row) 207 | { 208 | $fileReference = $this->getControllerActionReferenceFromRecord($row); 209 | $identifier = explode(':', $fileReference); 210 | $extensionName = array_shift($identifier); 211 | return $extensionName; 212 | } 213 | 214 | /** 215 | * @param array $row 216 | * @return string 217 | */ 218 | public function getControllerActionFromRecord(array $row) 219 | { 220 | $fileReference = $this->getControllerActionReferenceFromRecord($row); 221 | $identifier = explode(':', $fileReference); 222 | $actionName = array_pop($identifier); 223 | $actionName = basename($actionName, '.html'); 224 | $actionName = lcfirst($actionName); 225 | return $actionName; 226 | } 227 | 228 | /** 229 | * @param array $row 230 | * @return string 231 | */ 232 | public function getControllerActionReferenceFromRecord(array $row) 233 | { 234 | if ($this->templatePathAndFilename && $this->extensionKey) { 235 | return $this->extensionKey . ':' . pathinfo($this->templatePathAndFilename, PATHINFO_BASENAME); 236 | } 237 | $fileReference = $row['tx_fed_fcefile']; 238 | return true === empty($fileReference) ? 'Fluidcontent:error.html' : $fileReference; 239 | } 240 | 241 | /** 242 | * Switchable priority: highest possible for records matching 243 | * this Provider's targeted CType - lowest possible for others. 244 | * 245 | * @param array $row 246 | * @return integer 247 | */ 248 | public function getPriority(array $row) 249 | { 250 | if (true === isset($row['CType']) && $this->contentObjectType === $row['CType']) { 251 | return 100; 252 | } 253 | return 0; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /Classes/Service/ConfigurationService.php: -------------------------------------------------------------------------------- 1 | manager = $manager; 76 | } 77 | 78 | /** 79 | * @param WorkspacesAwareRecordService $recordService 80 | * @return void 81 | */ 82 | public function injectRecordService(WorkspacesAwareRecordService $recordService) 83 | { 84 | $this->recordService = $recordService; 85 | } 86 | 87 | /** 88 | * Constructor 89 | */ 90 | public function __construct() 91 | { 92 | $this->defaultIcon = '../' . ExtensionManagementUtility::siteRelPath('fluidcontent') . 93 | 'Resources/Public/Icons/Plugin.svg'; 94 | } 95 | 96 | /** 97 | * @return string 98 | */ 99 | public function getDefaultIcon() 100 | { 101 | return $this->defaultIcon; 102 | } 103 | 104 | /** 105 | * @return boolean 106 | */ 107 | protected function isBackendMode() 108 | { 109 | return ('BE' === TYPO3_MODE); 110 | } 111 | 112 | /** 113 | * Get definitions of paths for FCEs defined in TypoScript 114 | * 115 | * @param string $extensionName 116 | * @return array 117 | * @api 118 | */ 119 | public function getContentConfiguration($extensionName = null) 120 | { 121 | if (null !== $extensionName) { 122 | return (new TemplatePaths(ExtensionNamingUtility::getExtensionKey($extensionName)))->toArray(); 123 | } 124 | $registeredExtensionKeys = (array) Core::getRegisteredProviderExtensionKeys('Content'); 125 | $configuration = []; 126 | foreach ($registeredExtensionKeys as $registeredExtensionKey) { 127 | $configuration[$registeredExtensionKey] = $this->getContentConfiguration($registeredExtensionKey); 128 | } 129 | return $configuration; 130 | } 131 | 132 | /** 133 | * @return string 134 | */ 135 | public function getPageTsConfig() 136 | { 137 | // cache is not available during installation of extension, however 138 | // this method needs to still succeed (otherwise exception will prevent 139 | // installation to complete) 140 | $cacheExists = $this->manager->hasCache('fluidcontent'); 141 | $cache = $cacheExists ? $this->manager->getCache('fluidcontent') : null; 142 | $cachedPageTsConfigExists = ($cache !== null) && $cache->has('pageTsConfig'); 143 | 144 | $pageTsConfig = ''; 145 | if ($cachedPageTsConfigExists) { 146 | // just use the cached PageTSConfig if available 147 | $pageTsConfig = $cache->get('pageTsConfig'); 148 | // load all cached icons and register them them IconRegistry because it won't do it automatically 149 | $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); 150 | foreach ($cache->getByTag(self::ICON_CACHE_TAG) as $iconIdentifier => $entry) { 151 | $iconRegistry->registerIcon($entry['identifier'], $entry['provider'], $entry); 152 | } 153 | } else { 154 | // PageTSConfig is not yet available from cache, get it now 155 | $templates = $this->getAllRootTypoScriptTemplates(); 156 | $processed = []; 157 | foreach ($templates as $template) { 158 | $pageUid = (integer) $template['pid']; 159 | if (isset($processed[$pageUid])) { 160 | continue; 161 | } 162 | $pageTsConfig .= $this->renderPageTypoScriptForPageUid($pageUid); 163 | $processed[$pageUid] = 1; 164 | } 165 | 166 | // remember in cache for next call, if available 167 | if ($cache !== null) { 168 | $cache->set('pageTsConfig', $pageTsConfig, [], 86400); 169 | } 170 | } 171 | 172 | return $pageTsConfig; 173 | } 174 | 175 | /** 176 | * Delegates to $this->getPageTsConfig() which pre-warms the cached TS 177 | * 178 | * @return void 179 | */ 180 | public function writeCachedConfigurationIfMissing() 181 | { 182 | $this->getPageTsConfig(); 183 | } 184 | 185 | /** 186 | * @param $pageUid 187 | * @return string 188 | */ 189 | protected function renderPageTypoScriptForPageUid($pageUid) 190 | { 191 | $this->backupPageUidForConfigurationManager(); 192 | $this->overrideCurrentPageUidForConfigurationManager($pageUid); 193 | $pageTsConfig = ''; 194 | try { 195 | $wizardTabs = $this->buildAllWizardTabGroups(); 196 | $collectionPageTsConfig = $this->buildAllWizardTabsPageTsConfig($wizardTabs); 197 | $pageTsConfig .= '[PIDinRootline = ' . strval($pageUid) . ']' . LF; 198 | $pageTsConfig .= $collectionPageTsConfig . LF; 199 | $pageTsConfig .= '[GLOBAL]' . LF; 200 | } catch (\RuntimeException $error) { 201 | $this->message($error); 202 | } 203 | $this->restorePageUidForConfigurationManager(); 204 | return $pageTsConfig; 205 | } 206 | 207 | /** 208 | * @param integer $newPageUid 209 | * @return void 210 | */ 211 | protected function overrideCurrentPageUidForConfigurationManager($newPageUid) 212 | { 213 | if (true === $this->configurationManager instanceof ConfigurationManager) { 214 | $this->configurationManager->setCurrentPageUid($newPageUid); 215 | } 216 | } 217 | 218 | /** 219 | * @return void 220 | */ 221 | protected function backupPageUidForConfigurationManager() 222 | { 223 | if (true === $this->configurationManager instanceof ConfigurationManager) { 224 | $this->pageUidBackup = $this->configurationManager->getCurrentPageId(); 225 | } 226 | } 227 | 228 | /** 229 | * @return void 230 | */ 231 | protected function restorePageUidForConfigurationManager() 232 | { 233 | if (true === $this->configurationManager instanceof ConfigurationManager) { 234 | $this->configurationManager->setCurrentPageUid($this->pageUidBackup); 235 | } 236 | } 237 | 238 | /** 239 | * @return array 240 | */ 241 | protected function getAllRootTypoScriptTemplates() 242 | { 243 | $condition = 'root = 1 AND deleted = 0 AND hidden = 0 AND starttime <= :starttime AND (endtime = 0 OR endtime > :endtime)'; 244 | $parameters = [ 245 | ':starttime' => $GLOBALS['SIM_ACCESS_TIME'], 246 | ':endtime' => $GLOBALS['SIM_ACCESS_TIME'] 247 | ]; 248 | $rootTypoScriptTemplates = $this->recordService->preparedGet('sys_template', 'pid', $condition, $parameters); 249 | return $rootTypoScriptTemplates; 250 | } 251 | 252 | /** 253 | * @return array 254 | */ 255 | protected function getTypoScriptTemplatesInRootline() 256 | { 257 | $rootline = $this->getPageRepository()->getRootLine($this->configurationManager->getCurrentPageId()); 258 | $pageUids = []; 259 | foreach ($rootline as $page) { 260 | $pageUids[] = $page['uid']; 261 | } 262 | if (empty($pageUids)) { 263 | return []; 264 | } 265 | $condition = 'deleted = 0 AND hidden = 0 AND starttime <= :starttime AND (endtime = 0 OR ' . 266 | 'endtime > :endtime) AND pid IN (' . implode(',', $pageUids) . ')'; 267 | $parameters = [ 268 | ':starttime' => $GLOBALS['SIM_ACCESS_TIME'], 269 | ':endtime' => $GLOBALS['SIM_ACCESS_TIME'] 270 | ]; 271 | $rootTypoScriptTemplates = $this->recordService->preparedGet('sys_template', 'pid', $condition, $parameters); 272 | return $rootTypoScriptTemplates; 273 | } 274 | 275 | /** 276 | * Scans all folders in registered provider extensions for Form instances. 277 | * 278 | * @return array 279 | */ 280 | protected function buildAllWizardTabGroups() 281 | { 282 | $wizardTabs = []; 283 | $forms = $this->getContentElementFormInstances(); 284 | foreach ($forms as $extensionKey => $formSet) { 285 | $formSet = $this->sortObjectsByProperty($formSet, 'options.Fluidcontent.sorting', 'ASC'); 286 | foreach ($formSet as $id => $form) { 287 | /** @var Form $form */ 288 | $group = $form->getOption(Form::OPTION_GROUP); 289 | if (true === empty($group)) { 290 | $group = 'common'; 291 | } 292 | if (true === (boolean) $form->getOption('Fluidcontent.hidden')) { 293 | continue; 294 | } 295 | $sanitizedGroup = $this->sanitizeString($group); 296 | $tabId = $group === $sanitizedGroup ? $group : 'group' . $sanitizedGroup; 297 | if (!isset($wizardTabs[$tabId]['title'])) { 298 | $wizardTabs[$tabId]['title'] = $this->translateLabel( 299 | 'fluidcontent.newContentWizard.group.' . $group, 300 | ExtensionNamingUtility::getExtensionKey($extensionKey) 301 | ) ?? $group; 302 | } 303 | $contentElementId = $form->getOption('contentElementId'); 304 | $elementTsConfig = $this->buildWizardTabItem($tabId, $id, $form, $contentElementId); 305 | $wizardTabs[$tabId]['elements'][$id] = $elementTsConfig; 306 | } 307 | } 308 | return $wizardTabs; 309 | } 310 | 311 | /** 312 | * @return Form[][] 313 | */ 314 | public function getContentElementFormInstances() 315 | { 316 | $elements = []; 317 | $allTemplatePaths = $this->getContentConfiguration(); 318 | $controllerName = 'Content'; 319 | $provider = $this->objectManager->get(ContentProvider::class); 320 | 321 | foreach ($allTemplatePaths as $registeredExtensionKey => $templatePathSet) { 322 | $files = []; 323 | if (isset($templatePathSet['extensionKey'])) { 324 | $extensionKey = $templatePathSet['extensionKey']; 325 | } else { 326 | $extensionKey = $registeredExtensionKey; 327 | } 328 | $extensionKey = ExtensionNamingUtility::getExtensionKey($extensionKey); 329 | $provider->setExtensionKey($extensionKey); 330 | $templatePaths = new TemplatePaths($templatePathSet); 331 | foreach ($templatePaths->getTemplateRootPaths() as $templateRootPath) { 332 | $files = GeneralUtility::getAllFilesAndFoldersInPath( 333 | $files, 334 | rtrim($templateRootPath, '/') . '/' . $controllerName .'/', 335 | 'html', 336 | false, 337 | 0 338 | ); 339 | if (0 < count($files)) { 340 | foreach ($files as $templateFilename) { 341 | $actionName = pathinfo($templateFilename, PATHINFO_FILENAME); 342 | $fileRelPath = $actionName . '.html'; 343 | 344 | $provider->setTemplatePathAndFilename($templateFilename); 345 | $provider->setControllerAction($actionName); 346 | $form = $provider->getForm([]); 347 | if (empty($form) || !$form->getEnabled()) { 348 | $this->sendDisabledContentWarning($templateFilename); 349 | continue; 350 | } 351 | if ($form->getOption('Fluidcontent.hidden')) { 352 | continue; 353 | } 354 | $id = preg_replace('/[\.\/]/', '_', $extensionKey . '/' . $actionName . '.html'); 355 | $form->setOption('contentElementId', $extensionKey . ':' . $fileRelPath); 356 | $elements[$extensionKey][$id] = $form; 357 | } 358 | } 359 | } 360 | } 361 | return $elements; 362 | } 363 | 364 | /** 365 | * @return array 366 | */ 367 | public function getContentTypeSelectorItems() 368 | { 369 | $types = $this->getContentElementFormInstances(); 370 | 371 | // use from option.group as group name, if exists 372 | $groups = []; 373 | foreach ($types as $extension => $forms) { 374 | foreach ($forms as $form) { 375 | $groupName = $form->getOption('group') ?: $extension; 376 | $label = $form->getLabel(); 377 | $groups[$groupName][$label] = $form; 378 | } 379 | } 380 | $items = []; 381 | foreach ($groups as $extension => $forms) { 382 | ksort($forms); 383 | $enabledElements = []; 384 | foreach ($forms as $form) { 385 | $icon = MiscellaneousUtility::getIconForTemplate($form); 386 | $enabledElements[] = [ 387 | $form->getLabel(), 388 | $form->getOption('contentElementId'), 389 | strpos($icon, 'EXT:') === 0 ? $icon : '..' . $icon 390 | ]; 391 | } 392 | if (!empty($enabledElements)) { 393 | $items[] = [ 394 | $extension, 395 | '--div--' 396 | ]; 397 | $items = array_merge($items, $enabledElements); 398 | } 399 | } 400 | return $items; 401 | } 402 | 403 | /** 404 | * Builds a big piece of pageTSconfig setup, defining 405 | * every detected content element's wizard tabs and items. 406 | * 407 | * @param array $wizardTabs 408 | * @return string 409 | */ 410 | protected function buildAllWizardTabsPageTsConfig($wizardTabs) 411 | { 412 | $existingItems = $this->getExistingNewContentWizardItems(); 413 | 414 | $pageTsConfig = ''; 415 | foreach ($wizardTabs as $tabId => $tab) { 416 | $pageTsConfig .= sprintf( 417 | ' 418 | mod.wizards.newContentElement.wizardItems.%s.header = %s 419 | mod.wizards.newContentElement.wizardItems.%s.show := addToList(%s) 420 | mod.wizards.newContentElement.wizardItems.%s.position = 0 421 | ', 422 | $tabId, 423 | !empty($existingItems[$tabId]['header']) ? $existingItems[$tabId]['header'] : $tab['title'], 424 | $tabId, 425 | implode(',', array_keys($tab['elements'])), 426 | $tabId 427 | ); 428 | foreach ($tab['elements'] as $elementTsConfig) { 429 | $pageTsConfig .= $elementTsConfig; 430 | } 431 | } 432 | return $pageTsConfig; 433 | } 434 | 435 | /** 436 | * Builds a single Wizard item (one FCE) based on the 437 | * tab id, element id, configuration array and special 438 | * template identity (groupName:Relative/Path/File.html) 439 | * 440 | * @param string $tabId 441 | * @param string $id 442 | * @param Form $form 443 | * @param string $templateFileIdentity 444 | * @return string 445 | */ 446 | protected function buildWizardTabItem($tabId, $id, $form, $templateFileIdentity) 447 | { 448 | if (true === method_exists('FluidTYPO3\\Flux\\Utility\\MiscellaneousUtility', 'getIconForTemplate')) { 449 | $icon = MiscellaneousUtility::getIconForTemplate($form); 450 | $icon = ($icon ? $icon : $this->defaultIcon); 451 | } else { 452 | $icon = $this->defaultIcon; 453 | } 454 | $description = $form->getDescription(); 455 | if (0 === strpos($icon, '../')) { 456 | $icon = substr($icon, 2); 457 | } 458 | 459 | $iconIdentifier = null; 460 | if (true === method_exists('FluidTYPO3\\Flux\\Utility\\MiscellaneousUtility', 'createIcon')) { 461 | if (0 === strpos($icon, 'EXT:')) { 462 | $icon = GeneralUtility::getFileAbsFileName($icon); 463 | } elseif ('/' === $icon[0]) { 464 | $icon = rtrim(PATH_site, '/') . $icon; 465 | } 466 | if (true === file_exists($icon) && true === is_file($icon)) { 467 | $extension = pathinfo($icon, PATHINFO_EXTENSION); 468 | switch (strtolower($extension)) { 469 | case 'svg': 470 | case 'svgz': 471 | $iconProvider = SvgIconProvider::class; 472 | break; 473 | default: 474 | $iconProvider = BitmapIconProvider::class; 475 | } 476 | $iconIdentifier = 'icon-fluidcontent-' . $id; 477 | $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); 478 | $iconRegistry->registerIcon($iconIdentifier, $iconProvider, ['source' => $icon]); 479 | 480 | if ($this->manager->hasCache('fluidcontent')) { 481 | $this->manager->getCache('fluidcontent')->set( 482 | $iconIdentifier, 483 | [ 484 | 'provider' => $iconProvider, 485 | 'source' => $icon, 486 | 'identifier' => $iconIdentifier 487 | ], 488 | [ 489 | self::ICON_CACHE_TAG 490 | ] 491 | ); 492 | } 493 | } 494 | } 495 | $defaultValues = []; 496 | if ($form->hasOption(Form::OPTION_DEFAULT_VALUES)) { 497 | foreach ($form->getOption(Form::OPTION_DEFAULT_VALUES) as $key => $value) { 498 | $defaultValues[] = $key . ' = ' . $value; 499 | } 500 | } 501 | 502 | return sprintf( 503 | ' 504 | mod.wizards.newContentElement.wizardItems.%s.elements.%s { 505 | iconIdentifier = %s 506 | title = %s 507 | description = %s 508 | tt_content_defValues { 509 | %s 510 | CType = fluidcontent_content 511 | tx_fed_fcefile = %s 512 | } 513 | } 514 | ', 515 | $tabId, 516 | $id, 517 | $iconIdentifier, 518 | $form->getLabel(), 519 | $description, 520 | implode(chr(10), $defaultValues), 521 | $templateFileIdentity 522 | ); 523 | } 524 | 525 | /** 526 | * @param string $string 527 | * @return string 528 | */ 529 | protected function sanitizeString($string) 530 | { 531 | $pattern = '/([^a-z0-9\-]){1,}/i'; 532 | $replaced = preg_replace($pattern, '', $string); 533 | $replaced = trim($replaced); 534 | return empty($replaced) ? md5($string) : $replaced; 535 | } 536 | 537 | /** 538 | * @param string $templatePathAndFilename 539 | * @return void 540 | */ 541 | protected function sendDisabledContentWarning($templatePathAndFilename) 542 | { 543 | GeneralUtility::sysLog('Disabled Fluid Content Element: ' . $templatePathAndFilename, GeneralUtility::SYSLOG_SEVERITY_NOTICE); 544 | } 545 | 546 | /** 547 | * @param string $key 548 | * @param string $extensionName 549 | * @param array $arguments 550 | * @return string|null 551 | */ 552 | protected function translateLabel($key, $extensionName, $arguments = []) 553 | { 554 | return LocalizationUtility::translate($key, $extensionName, $arguments); 555 | } 556 | 557 | /** 558 | * @return array 559 | */ 560 | protected function getExistingNewContentWizardItems() 561 | { 562 | static $pageTSconfig; 563 | if (!isset($pageTSconfig)) { 564 | $parser = $this->getTypoScriptParser(); 565 | $config = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig']; 566 | $inclusions = $parser::checkIncludeLines($config, 1, true); 567 | $config .= $inclusions['typoscript']; 568 | foreach ($inclusions['files'] as $include) { 569 | $config .= file_get_contents($include); 570 | } 571 | $parser->parse($config); 572 | if (isset($parser->setup['mod.']['wizards.']['newContentElement.']['wizardItems.'])) { 573 | $pageTSconfig = GeneralUtility::removeDotsFromTS($parser->setup['mod.']['wizards.']['newContentElement.']['wizardItems.']); 574 | } else { 575 | $pageTSconfig = []; 576 | } 577 | } 578 | return $pageTSconfig; 579 | } 580 | 581 | /** 582 | * @return TypoScriptParser 583 | */ 584 | protected function getTypoScriptParser() 585 | { 586 | return new TypoScriptParser(); 587 | } 588 | 589 | /** 590 | * @return PageRepository 591 | */ 592 | protected function getPageRepository() 593 | { 594 | return $this->objectManager->get(PageRepository::class); 595 | } 596 | } 597 | -------------------------------------------------------------------------------- /Configuration/TCA/Overrides/be_groups.php: -------------------------------------------------------------------------------- 1 | [ 10 | 'exclude' => 0, 11 | 'label' => 'LLL:EXT:fluidcontent/Resources/Private/Language/locallang.xlf:be_groups.tx_fluidcontent_allowedfluidcontent', 12 | 'config' => [ 13 | 'type' => 'select', 14 | 'renderType' => 'selectCheckBox', 15 | 'size' => 10, 16 | 'maxitems' => 99999999, 17 | 'multiple' => true, 18 | 'items' => [], 19 | ], 20 | ], 21 | 'tx_fluidcontent_deniedfluidcontent' => [ 22 | 'exclude' => 0, 23 | 'label' => 'LLL:EXT:fluidcontent/Resources/Private/Language/locallang.xlf:be_groups.tx_fluidcontent_deniedfluidcontent', 24 | 'config' => [ 25 | 'type' => 'select', 26 | 'renderType' => 'selectCheckBox', 27 | 'size' => 10, 28 | 'maxitems' => 99999999, 29 | 'multiple' => true, 30 | 'items' => [], 31 | ], 32 | ], 33 | ] 34 | ); 35 | 36 | \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( 37 | 'be_groups', 38 | 'tx_fluidcontent_allowedfluidcontent,tx_fluidcontent_deniedfluidcontent', 39 | '0', 40 | 'after:pagetypes_select' 41 | ); 42 | -------------------------------------------------------------------------------- /Configuration/TCA/Overrides/tt_content.php: -------------------------------------------------------------------------------- 1 | [ 23 | 'exclude' => 1, 24 | 'label' => $languageFilePrefix.'tt_content.tx_fed_fcefile', 25 | 'displayCond' => 'FIELD:CType:=:fluidcontent_content', 26 | 'config' => [ 27 | 'type' => 'select', 28 | 'renderType' => 'selectSingle', 29 | 'items' => [ 30 | [$languageFilePrefix.'tt_content.tx_fed_fcefile', ''], 31 | ], 32 | 'showIconTable' => false, 33 | 'selicon_cols' => 0, 34 | ], 35 | ], 36 | ] 37 | ); 38 | 39 | $GLOBALS['TCA']['tt_content']['ctrl']['useColumnsForDefaultValues'] .= ',tx_fed_fcefile'; 40 | $GLOBALS['TCA']['tt_content']['ctrl']['requestUpdate'] .= ',tx_fed_fcefile'; 41 | $GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes']['userFunc'] = \FluidTYPO3\Fluidcontent\Hooks\ContentIconUserFunction::class . '->getIcon'; 42 | $GLOBALS['TCA']['tt_content']['types']['fluidcontent_content']['showitem'] = ' 43 | --palette--;' . $frontendLanguageFilePrefix . 'palette.general;general, 44 | --palette--;' . $frontendLanguageFilePrefix . 'palette.header;header, 45 | --div--;' . $frontendLanguageFilePrefix . 'tabs.appearance, layout;' . $frontendLanguageFilePrefix . 'layout_formlabel, 46 | --palette--; '. $frontendLanguageFilePrefix . 'palette.frames;frames, 47 | --palette--;' . $frontendLanguageFilePrefix . 'palette.appearanceLinks;appearanceLinks, 48 | --div--;' . $tabsLanguageFilePrefix . 'access, 49 | --palette--;' . $frontendLanguageFilePrefix . ';visibility, 50 | --palette--;' . $frontendLanguageFilePrefix . ':palette.access;access, 51 | --div--;' . $categoryTabLabel . ', categories, 52 | --div--;' . $tabsLanguageFilePrefix . 'extended, 53 | --div--;LLL:EXT:flux/Resources/Private/Language/locallang.xlf:tt_content.tabs.relation, tx_flux_parent, tx_flux_column 54 | '; 55 | 56 | if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('core'), '8.0', '>=')) { 57 | \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tt_content', ',--div--;' . $tabsLanguageFilePrefix . 'language, --palette--;;language,', 'fluidcontent_content', 'before:access'); 58 | \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tt_content', ',--div--;' . $tabsLanguageFilePrefix . 'notes, rowDescription,', 'fluidcontent_content', 'after:language'); 59 | } 60 | 61 | \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( 62 | 'tt_content', 63 | 'general', 64 | 'tx_fed_fcefile', 65 | 'after:CType' 66 | ); 67 | \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( 68 | 'tt_content', 69 | 'pi_flexform', 70 | 'fluidcontent_content', 71 | 'after:header' 72 | ); 73 | } 74 | ); 75 | -------------------------------------------------------------------------------- /Documentation/Changelog/1.0.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 1.0.0 (2012/10/16) 2 | 3 | * 2012-10-14 [FEATURE] AJAX Content Loader Container Element (Commit ad57c9c by Claus Due) 4 | 5 | Generated by: 6 | 7 | ``` 8 | git log --since="2010/01/01" --until="2012/10/16" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 9 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 10 | ``` 11 | 12 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...1.0.0 13 | 14 | *Please note: the change list above does not contain any TASK commits since they are considered 15 | infrastructure-only and not relevant to end users. The full list includes these!* 16 | 17 | -------------------------------------------------------------------------------- /Documentation/Changelog/1.3.3.md: -------------------------------------------------------------------------------- 1 | ## Release: 1.3.3 (2012/12/16) 2 | 3 | * 2012-11-25 [BUGFIX] Remove test usage of v:iterator.slice, Bootstrap FluidRow element (Commit bf44d37 by Claus Due) 4 | * 2012-11-25 [BUGFIX] Missing closing tag, Bootstrap / Alert element (Commit 8bc6fda by Claus Due) 5 | * 2012-11-22 [FEATURE] Port all content element features from FED (Commit be5d9f8 by Claus Due) 6 | 7 | Generated by: 8 | 9 | ``` 10 | git log --since="2012/10/16" --until="2012/12/16" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 11 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 12 | ``` 13 | 14 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...1.3.3 15 | 16 | *Please note: the change list above does not contain any TASK commits since they are considered 17 | infrastructure-only and not relevant to end users. The full list includes these!* 18 | 19 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.0.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.0.0 (2012/12/31) 2 | 3 | * 2012-12-29 [BUGFIX] Added autoloader (Commit 2f28542 by Egbert van der Hout) 4 | * 2012-12-29 [BUGFIX] Use native default icon instead of FED icon, prevents exception "fed not installed" when icon not specified. (Commit 4260491 by Claus Due) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2012/12/16" --until="2012/12/31" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.0.0 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.1.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.1.0 (2012/12/31) 2 | 3 | * 2012-12-29 [BUGFIX] Added autoloader (Commit 2f28542 by Egbert van der Hout) 4 | * 2012-12-29 [BUGFIX] Use native default icon instead of FED icon, prevents exception "fed not installed" when icon not specified. (Commit 4260491 by Claus Due) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2012/12/16" --until="2012/12/31" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.1.0 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.1.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.1.1 (2013/01/09) 2 | 3 | * 2013-01-02 [BUGFIX] Don't shutdown GLOBALS exec time, apparently makes 6.0 crash (Commit a17a966 by Claus Due) 4 | 5 | Generated by: 6 | 7 | ``` 8 | git log --since="2012/12/31" --until="2013/01/09" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 9 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 10 | ``` 11 | 12 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.1.1 13 | 14 | *Please note: the change list above does not contain any TASK commits since they are considered 15 | infrastructure-only and not relevant to end users. The full list includes these!* 16 | 17 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.2.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.2.0 (2013/01/13) 2 | 3 | * 2013-01-13 [BUGFIX] Set default wizard tab label (Commit be2b482 by Björn Fromme) 4 | 5 | Generated by: 6 | 7 | ``` 8 | git log --since="2013/01/09" --until="2013/01/13" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 9 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 10 | ``` 11 | 12 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.2.0 13 | 14 | *Please note: the change list above does not contain any TASK commits since they are considered 15 | infrastructure-only and not relevant to end users. The full list includes these!* 16 | 17 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.2.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.2.1 (2013/03/02) 2 | 3 | * 2013-01-27 [BUGFIX] Remove superfluous plugin registration which caused double entry (Commit 38dc9de by Claus Due) 4 | * 2013-01-27 [BUGFIX] Ensure writing of cached TSconfig on cache clear (Commit 8a349cc by Claus Due) 5 | * 2013-01-13 [FEATURE] Use Flux's FlexForm Service to get FCE object configurations (Commit 1364a6e by Claus Due) 6 | * 2013-01-13 [FEATURE] Implement clearCacheCommand to remove cached pageTSconfig file (Commit 180bca9 by Claus Due) 7 | 8 | Generated by: 9 | 10 | ``` 11 | git log --since="2013/01/13" --until="2013/03/02" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 12 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 13 | ``` 14 | 15 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.2.1 16 | 17 | *Please note: the change list above does not contain any TASK commits since they are considered 18 | infrastructure-only and not relevant to end users. The full list includes these!* 19 | 20 | -------------------------------------------------------------------------------- /Documentation/Changelog/2.2.2.md: -------------------------------------------------------------------------------- 1 | ## Release: 2.2.2 (2013/03/16) 2 | 3 | * 2013-02-21 [BUGFIX] Using simulated acces time as timestamp (Commit d62c44b by Steffen Roßkamp) 4 | * 2013-02-20 [BUGFIX] Fixed choosing of inaccessible root template (Commit e54f8ca by Steffen Roßkamp) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2013/02/03" --until="2013/03/16" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...2.2.2 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/3.0.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 3.0.0 (2013/05/18) 2 | 3 | * 2013-05-14 [BUGFIX] Fix inproper argument for t3lib_div::getAllFilesAndFoldersInPath (Commit 23e50e6 by Thomas Maroschik) 4 | * 2013-04-17 [BUGFIX] Pass missing original FlexForm variables, add missing variable array merge (Commit 29ca9e2 by Claus Due) 5 | * 2013-04-13 [BUGFIX] Call ancestor method "message" (Commit 021c85b by Fabien Udriot) 6 | * 2013-04-11 [BUGFIX] Make sure templates are not on deleted page (Commit 56fb71a by Fabien Udriot) 7 | * 2013-04-06 [FEATURE] Do not require TS templates to be root templates (Commit 4c9c021 by Claus Due) 8 | * 2013-04-06 [FEATURE] Consider every page root line when building FCE list (Commit 200052b by Claus Due) 9 | * 2013-04-03 [BUGFIX] Ensure uid selected for and proper quoting of conditions in update script (Commit 77d12ad by Claus Due) 10 | * 2013-02-22 [FEATURE] EM update script for changing cType (Commit adc2185 by Soren Malling) 11 | * 2013-04-03 [BUGFIX] Ensure validity of template paths before compiling file path (Commit b00b0e2 by Claus Due) 12 | * 2013-04-01 [FEATURE] Content Controller with abstract class and interface (Commit a7bea5a by Claus Due) 13 | * 2013-04-01 [BUGFIX] Restore mistakenly removed cObject in Content Controller (Commit edacbb1 by Claus Due) 14 | * 2013-03-30 [BUGFIX] Manually translate LLL labels in content type selector (Commit 67aa69d by Claus Due) 15 | * 2013-03-30 [FEATURE] Pass extension name when reading Flux data (Commit d7d7cda by Claus Due) 16 | * 2013-03-26 [FEATURE] Extension configuration toggle to not use "Content Settings" tab (Commit 6230053 by Claus Due) 17 | * 2013-03-26 [FEATURE] Possibility to exclude rendering of default record fields (Commit 3898209 by Claus Due) 18 | * 2013-03-25 [FEATURE] Use new Flux Debug Service to improve error feedback (Commit a29f59a by Claus Due) 19 | 20 | Generated by: 21 | 22 | ``` 23 | git log --since="2013/03/17" --until="2013/05/18" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 24 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 25 | ``` 26 | 27 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...3.0.0 28 | 29 | *Please note: the change list above does not contain any TASK commits since they are considered 30 | infrastructure-only and not relevant to end users. The full list includes these!* 31 | 32 | -------------------------------------------------------------------------------- /Documentation/Changelog/3.1.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 3.1.0 (2013/06/30) 2 | 3 | * 2013-06-26 [BUGFIX] Ensure native view locations is array before merge (Commit f3c7f70 by Claus Due) 4 | * 2013-06-26 [BUGFIX] Order of legacy -> native view locations (Commit 6b0e165 by Claus Due) 5 | * 2013-06-17 [FEATURE] Overlay paths like EXT:view but not depending on EXT:view (Commit 20517d0 by Claus Due) 6 | 7 | Generated by: 8 | 9 | ``` 10 | git log --since="2013/05/19" --until="2013/06/30" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 11 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 12 | ``` 13 | 14 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...3.1.0 15 | 16 | *Please note: the change list above does not contain any TASK commits since they are considered 17 | infrastructure-only and not relevant to end users. The full list includes these!* 18 | 19 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.0.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.0.0 (2014/03/25) 2 | 3 | * 2014-03-22 [BUGFIX] Avoid operation on cache if not previously created (Commit 7fd784c by Claus Due) 4 | * 2014-01-19 [BUGFIX] Syntax error: removed bracket (Commit e9d7cef by Martin Hummer) 5 | * 2014-01-15 [BUGFIX] Only clear cache when "Clear configuration cache" is pressed (Commit f800389 by Benjamin Mack) 6 | * 2013-12-27 [BUGFIX] Move creation of cached FCE definitions to own hook (Commit 66473b6 by Claus Due) 7 | * 2013-12-13 [BUGFIX] ConditionMatcher Namespace (Commit abbd1bd by Danilo Bürger) 8 | * 2013-12-03 [BUGFIX] Fixed blocker with vendor namespaces (Commit c04ef53 by Danilo Bürger) 9 | * 2013-11-24 [BUGFIX] Cache must be protected (Commit f9e304b by Danilo Bürger) 10 | * 2013-10-29 [BUGFIX] Translate paths from configuration service (Commit ee7f2b5 by Danilo Bürger) 11 | * 2013-10-24 [BUGFIX] ContentProvider should rely on AbstractProvider to get template paths (Commit 5af94d7 by Danilo Bürger) 12 | * 2013-09-03 [BUGFIX] Content Selector options werent filled in list view (Commit f5e2565 by Benjamin Rau) 13 | * 2013-08-26 [FEATURE] Add minimum composer.json (Commit 90a7959 by Cedric Ziel) 14 | * 2013-07-11 [BUGFIX] Don't add unnecessary slash to template path (Commit 749c8f6 by Claus Due) 15 | 16 | Generated by: 17 | 18 | ``` 19 | git log --since="2013/06/30" --until="2014/03/25" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 20 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 21 | ``` 22 | 23 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.0.0 24 | 25 | *Please note: the change list above does not contain any TASK commits since they are considered 26 | infrastructure-only and not relevant to end users. The full list includes these!* 27 | 28 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.1.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.1.0 (2014/09/19) 2 | 3 | * 2014-07-24 [BUGFIX] WizardItemsHookSubscriber: column areas removed (Commit 5e30c3f by David Frerich) 4 | * 2014-06-18 [BUGFIX] Classname namespace typo of the WorkspaceAwareRecordService fixed (Commit fe5143d by Daniel Hürtgen) 5 | * 2014-04-03 [BUGFIX] Remove bodytext RTE field from fluidcontent elements before TYPO3 6.2 (Commit 0f4503b by Benjamin Rau) 6 | * 2014-04-10 [FEATURE] Added Bower support (Commit 8c18a09 by Joschi Kuphal) 7 | * 2014-04-03 [BUGFIX] Remove bodytext RTE field from fluidcontent elements before TYPO3 6.2 (Commit 1b1eca0 by Benjamin Rau) 8 | * 2014-04-03 [FEATURE] Support white/blacklist allowed FCE types (Commit 5d63b57 by Claus Due) 9 | * 2014-04-03 [FEATURE] Support flux:form options.Fluidcontent.sorting (Commit 8c26fef by Claus Due) 10 | * 2014-04-02 [BUGFIX] Fix namespace in use statement (Commit f6c7208 by G. Bodenschatz) 11 | * 2014-04-01 [FEATURE] TYPO3 application context support (6.2+) (Commit d6adc9e by Claus Due) 12 | 13 | Generated by: 14 | 15 | ``` 16 | git log --since="2014/03/25" --until="2014/09/19" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 17 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 18 | ``` 19 | 20 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.1.0 21 | 22 | *Please note: the change list above does not contain any TASK commits since they are considered 23 | infrastructure-only and not relevant to end users. The full list includes these!* 24 | 25 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.1.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.1.1 (2014/10/31) 2 | 3 | * 2014-10-28 [BUGFIX] Include vendor prefix when building the wizard tab (Commit 2a12e5d by Danilo Bürger) 4 | * 2014-10-24 [FEATURE] Clear caches with the clearCache=system (Commit aabbee5 by mneuhaus) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2014/09/19" --until="2014/10/31" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.1.1 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.2.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.2.0 (2015/03/18) 2 | 3 | * 2015-03-03 [BUGFIX] Reorder SQL queries in EM upgrade script to report changed rows (Commit 53e7b95 by Claus Due) 4 | * 2015-01-18 [FEATURE] Add Icon in Fluid content type select (Commit 3313553 by Xaver Maierhofer) 5 | * 2015-02-05 [BUGFIX] Avoid incorrectly getFileAbsFilename'ing absolute paths (Commit 79a0415 by Claus Due) 6 | * 2015-02-04 [BUGFIX] White/blacklist from parent instead of sibling (Commit 58c886c by Claus Due) 7 | * 2014-11-08 [BUGFIX] Change wrong brace expressions in .editorconfig (Commit edab130 by G. Bodenschatz) 8 | * 2014-11-03 [BUGFIX] FormViewHelper option: group default (Commit 75b1fd4 by David Frerich) 9 | 10 | Generated by: 11 | 12 | ``` 13 | git log --since="2014/10/31" --until="2015/03/18" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 14 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 15 | ``` 16 | 17 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.2.0 18 | 19 | *Please note: the change list above does not contain any TASK commits since they are considered 20 | infrastructure-only and not relevant to end users. The full list includes these!* 21 | 22 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.2.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.2.1 (2015/03/19) 2 | 3 | * 2015-03-17 [BUGFIX] Fix declaration #225 (Commit e44d317 by Alexander Grein) 4 | 5 | Generated by: 6 | 7 | ``` 8 | git log --since="2015/03/18" --until="2015/03/19" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 9 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 10 | ``` 11 | 12 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.2.1 13 | 14 | *Please note: the change list above does not contain any TASK commits since they are considered 15 | infrastructure-only and not relevant to end users. The full list includes these!* 16 | 17 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.2.2.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.2.2 (2015/05/20) 2 | 3 | Generated by: 4 | 5 | ``` 6 | git log --since="2015/03/18" --until="2015/05/20" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 7 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 8 | ``` 9 | 10 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.2.2 11 | 12 | *Please note: the change list above does not contain any TASK commits since they are considered 13 | infrastructure-only and not relevant to end users. The full list includes these!* 14 | 15 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.2.3.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.2.3 (2015/06/26) 2 | 3 | * 2015-06-02 [BUGFIX] Use lcfirst() on action name to prevent array return (Commit bf741cf by Claus Due) 4 | * 2015-06-02 [BUGFIX] Rebuild pageTSconfig cache only in BE context (Commit ed1cffa by Claus Due) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2015/05/20" --until="2015/06/26" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.2.3 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.2.4.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.2.4 (2015/07/01) 2 | 3 | * 2015-06-26 [BUGFIX] remove duplicated appearance tab in TCA override (Commit 834fde3 by Daniel Goerz) 4 | 5 | Generated by: 6 | 7 | ``` 8 | git log --since="2015/06/26" --until="2015/07/01" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 9 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 10 | ``` 11 | 12 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.2.4 13 | 14 | *Please note: the change list above does not contain any TASK commits since they are considered 15 | infrastructure-only and not relevant to end users. The full list includes these!* 16 | 17 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.3.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.3.0 (2015/08/08) 2 | 3 | * 2015-08-08 [FEATURE] Icon size can be set individually (Commit 4bc2f32 by Frank Rakow) 4 | * 2015-08-08 [BUGFIX] Avoid calls on non-object (Commit e2e9bb7 by Claus Due) 5 | * 2015-08-07 [BUGFIX] Get rid of default file Index.html (Commit c05dbd2 by Claus Due) 6 | * 2015-08-04 [FEATURE] Adds support for FluidcontentCore settings values by default (Commit f2d5690 by jmverges) 7 | * 2015-07-28 [BUGFIX] Restores PR 255 (Commit 0d1ceaa by jmverges) 8 | * 2015-07-28 [BUGFIX] Fix missing paths for Icons (Commit 325125a by jmverges) 9 | * 2015-07-28 [BUGFIX] Fix relation problems with Save and New button (Commit 9b5ef94 by jmverges) 10 | * 2015-07-26 [BUGFIX] Variable not initialized (Commit 6565af4 by jmverges) 11 | * 2015-07-26 [BUGFIX] Fix contents for new content element wizard. Implements new hook (Commit 931592f by jmverges) 12 | 13 | Generated by: 14 | 15 | ``` 16 | git log --since="2015/07/01" --until="2015/08/08" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 17 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 18 | ``` 19 | 20 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.3.0 21 | 22 | *Please note: the change list above does not contain any TASK commits since they are considered 23 | infrastructure-only and not relevant to end users. The full list includes these!* 24 | 25 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.3.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.3.1 (2015/08/08) 2 | 3 | Generated by: 4 | 5 | ``` 6 | git log --since="2015/08/08" --until="2015/08/08" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 7 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 8 | ``` 9 | 10 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.3.1 11 | 12 | *Please note: the change list above does not contain any TASK commits since they are considered 13 | infrastructure-only and not relevant to end users. The full list includes these!* 14 | 15 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.3.2.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.3.2 (2015/09/10) 2 | 3 | * 2015-09-10 [BUGFIX] Avoid realpath on icon with older Flux versions (Commit 76a98ff by Claus Due) 4 | * 2015-09-04 [BUGFIX] Remove wrong information (Commit a453d56 by Xaver Maierhofer) 5 | * 2015-08-29 [BUGFIX] Allow string and keeping the aspect ratio for icon (Commit b5be222 by Xaver Maierhofer) 6 | * 2015-08-24 [BUGFIX] Use empty() around possibly non-existing array index (Commit 6436d1c by Claus Due) 7 | * 2015-08-14 [BUGFIX] Avoid BE-related cache loading when in FE (Commit f87ce58 by Claus Due) 8 | * 2015-08-08 [BUGFIX] Remove Fatal error: Call to a member function hasOption() on a non-object (Commit dbc1d20 by Frank Rakow) 9 | 10 | Generated by: 11 | 12 | ``` 13 | git log --since="2015/08/08" --until="2015/09/10" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 14 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 15 | ``` 16 | 17 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.3.2 18 | 19 | *Please note: the change list above does not contain any TASK commits since they are considered 20 | infrastructure-only and not relevant to end users. The full list includes these!* 21 | 22 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.3.3.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.3.3 (2015/10/24) 2 | 3 | * 2015-10-14 [BUGFIX] Check file_exists after realpath (Commit 436e943 by Benedict Burckhart) 4 | * 2015-09-11 [BUGFIX] Show only the preview if CType is equal to 'fluidcontent_content' (Commit b233401 by monosize) 5 | 6 | Generated by: 7 | 8 | ``` 9 | git log --since="2015/09/10" --until="2015/10/24" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 10 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 11 | ``` 12 | 13 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.3.3 14 | 15 | *Please note: the change list above does not contain any TASK commits since they are considered 16 | infrastructure-only and not relevant to end users. The full list includes these!* 17 | 18 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.4.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.4.0 (2015/11/21) 2 | 3 | * 2015-11-16 [FEATURE] Add option to specify defValues (Commit d1bbbd0 by Marc Neuhaus) 4 | * 2015-11-19 [BUGFIX] New content element wizard - tabs not created if translation not found. LocalizationUtillity::translate could also be NULL The elements are displayed in the previous named tab. (Commit 339193d by monosize) 5 | * 2015-11-13 [FEATURE] Allow/deny fluidcontent types via user group ACL (Commit bd9a0e8 by Claus Due) 6 | * 2015-11-08 [BUGFIX] Avoid building pageTSconfig when no pages exist (Commit d7c7a0d by Claus Due) 7 | * 2015-11-06 [FEATURE] Extend Wizard groups instead of replacing (Commit b493962 by Marc Neuhaus) 8 | * 2015-11-06 [BUGFIX] ConfigurationService: Avoid double-slash in Path (Commit e0652f3 by Stefan Neufeind) 9 | 10 | Generated by: 11 | 12 | ``` 13 | git log --since="2015/10/24" --until="2015/11/21" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 14 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 15 | ``` 16 | 17 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.4.0 18 | 19 | *Please note: the change list above does not contain any TASK commits since they are considered 20 | infrastructure-only and not relevant to end users. The full list includes these!* 21 | 22 | -------------------------------------------------------------------------------- /Documentation/Changelog/4.4.1.md: -------------------------------------------------------------------------------- 1 | ## Release: 4.4.1 (2016/03/02) 2 | 3 | * 2016-01-30 [BUGFIX] Add cache definition also in install tool (Commit af6014b by Claus Due) 4 | * 2016-01-15 [BUGFIX] Fix conflicts between introducing FCEs in common tabs and sanitized elements (Commit 7aefc1b by Juan Manuel Vergés Solanas) 5 | * 2016-01-08 [BUGFIX] Reload content edit form when changing fluid content type (Commit 95a8ec1 by Christian Weiske) 6 | * 2016-01-05 [BUGFIX] Use backend user group white/black lists in new content wizard (Commit 0ecddd4 by Claus Due) 7 | 8 | Generated by: 9 | 10 | ``` 11 | git log --since="2015/11/21" --until="2016/03/02" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 12 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 13 | ``` 14 | 15 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/1.0.0...4.4.1 16 | 17 | *Please note: the change list above does not contain any TASK commits since they are considered 18 | infrastructure-only and not relevant to end users. The full list includes these!* 19 | 20 | -------------------------------------------------------------------------------- /Documentation/Changelog/5.0.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 5.0.0 (2017/01/28) 2 | 3 | * 2017-01-25 [BUGFIX] Fix possible errors with templates that don't contain Form (Commit 9313427 by Claus Due) 4 | * 2017-01-21 [BUGFIX] Respect Fluidcontent.hidden option in Form (Commit e335921 by Claus Due) 5 | * 2017-01-21 [BUGFIX] Fix usage of "common" etc. tabs in new content wizard (Commit b29849b by Claus Due) 6 | * 2017-01-21 [BUGFIX] Avoid translating non-LLL references for content labels (#379) (Commit 9953604 by Claus Due) 7 | * 2017-01-10 [FEATURE] Support Flux 8.0.0+ (Commit ba43777 by Marc Neuhaus) 8 | * 2017-01-09 [FEATURE] Raise TYPO3 and Flux version requirement (Commit 9ec9cdc by Marc Neuhaus) 9 | * 2017-01-09 [REMOVAL] Raise PHP version requirement to 7.0.0+ (Commit a3a9996 by Marc Neuhaus) 10 | * 2016-12-14 [FEATURE] Group content types in content selector (Commit dc9359e by monosize) 11 | * 2016-06-22 [BUGFIX] Cache individual content icons (Commit c644748 by Claus Due) 12 | * 2016-06-17 [BUGFIX] Check availability of cache before access (Commit 3d84a57 by Daniel Neugebauer) 13 | * 2016-03-22 [BUGFIX] Don't resolve symlinks on icon discovery (Commit 8ba1489 by Daniel Neugebauer) 14 | 15 | Generated by: 16 | 17 | ``` 18 | git log --since="2016/03/02" --until="2017/01/28" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 19 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 20 | ``` 21 | 22 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/4.4.1...5.0.0 23 | 24 | *Please note: the change list above does not contain any TASK commits since they are considered 25 | infrastructure-only and not relevant to end users. The full list includes these!* 26 | 27 | -------------------------------------------------------------------------------- /Documentation/Changelog/5.1.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 5.1.0 (2017/03/04) 2 | 3 | * 2017-02-20 [FEATURE] Raise maximum supported TYPO3 version to 8.6 (Commit 3dc3495 by Claus Due) 4 | * 2017-02-20 [BUGFIX] Restrict TS template parsing to root templates (#390) (Commit cabad7f by Franz Kugelmann) 5 | * 2017-02-16 [BUGFIX] Limit scan for content templates to first level only (Commit 1f3f21d by Claus Due) 6 | * 2017-02-12 [BUGFIX] Only scan one level of folders for Content templates (Commit 9e9240b by Claus Due) 7 | * 2017-02-11 [FEATURE] Introduce option Fluidcontent.hidden (#368) (Commit 08add89 by Claus Due) 8 | * 2017-02-11 [BUGFIX] Register tx_fed_fcefile as default-valued column (Commit dfafa27 by Claus Due) 9 | * 2017-02-11 [BUGFIX] Adapt TCA to respect pragma on LTS / 8.x (Commit 6fcb896 by Claus Due) 10 | * 2017-02-11 [BUGFIX] Fix wrong language definitions in labels (#384) (Commit bf0f166 by Frank Rakow) 11 | * 2017-02-11 [BUGFIX] Missing check if 'tx_fed_fcefile' exists (#385) (Commit c09bdf5 by Frank Rakow) 12 | * 2017-02-10 [BUGFIX] Missing frames palette in TCA for tt_content (#383) (Commit 7d83f07 by Frank Rakow) 13 | * 2017-02-06 [BUGFIX] Adopt default TCA from fluid_styled_content (Commit a51e40b by Claus Due) 14 | * 2017-02-03 [FEATURE] Add rowDescription to TCA (#380) (Commit 2562f02 by Frank Rakow) 15 | 16 | Generated by: 17 | 18 | ``` 19 | git log --since="2017/01/28" --until="2017/03/04" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 20 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 21 | ``` 22 | 23 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/5.0.0...5.1.0 24 | 25 | *Please note: the change list above does not contain any TASK commits since they are considered 26 | infrastructure-only and not relevant to end users. The full list includes these!* 27 | 28 | -------------------------------------------------------------------------------- /Documentation/Changelog/5.2.0.md: -------------------------------------------------------------------------------- 1 | ## Release: 5.2.0 (2017/04/26) 2 | 3 | * 2017-04-25 [FEATURE] Support TYPO3 8.7 LTS (#404) (Commit 4f14596 by Cedric Ziel) 4 | * 2017-04-07 [BUGFIX] Support spaces in group name (#403) (Commit 7050c13 by DA COSTA Filipe) 5 | * 2017-04-03 [BUGFIX] Avoid injecting non-singleton class (Commit 56a5b29 by Claus Due) 6 | 7 | Generated by: 8 | 9 | ``` 10 | git log --since="2017/03/04" --until="2017/04/26" --abbrev-commit --pretty='%ad %s (Commit %h by %an)' \ 11 | --date=short | egrep '(\[FEATURE|BUGFIX|REMOVAL\])+'` 12 | ``` 13 | 14 | Full list of changes: https://github.com/FluidTYPO3/fluidcontent/compare/5.1.0...5.2.0 15 | 16 | *Please note: the change list above does not contain any TASK commits since they are considered 17 | infrastructure-only and not relevant to end users. The full list includes these!* 18 | 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### Copyright notice 2 | 3 | > (c) 2014 Claus Due 4 | > All rights reserved 5 | 6 | This repository is part of the TYPO3 project. The TYPO3 project is 7 | free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | The GNU General Public License can be found at 13 | http://www.gnu.org/copyleft/gpl.html. 14 | 15 | This repository is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | This copyright notice MUST APPEAR in all copies of the repository! 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Fluidcontent: Fluid Content Elements 4 | ==================================== 5 | 6 | OBSOLETE! 7 | --------- 8 | 9 | #### Issues and pull requests have been disabled. The extension is no longer supported or maintained. 10 | 11 | *This extension is considered obsolete since Flux (the engine used by this extension) now provides a similar but better method 12 | of using templates as content element types. The most recent release of this extension, version 6.0, should only be used if you 13 | must upgrade an existing site and must avoid migrating templates (at the current time of writing this, automatic migration is not 14 | possible).* 15 | 16 | For new projects you can simply skip installing `fluidcontent` and use the exact same `registerProviderExtensionKey` function 17 | to register your templates. Flux detects that `fluidcontent` isn't installed and takes over. 18 | 19 | Please note the following key differences between `fluidcontent` and `flux` in how they register templates: 20 | 21 | * `fluidcontent` uses a wrapping `fluidcontent_content` CType which behaves like plugins in that it has a sub-type where you 22 | select the Fluid template to be used as content template. 23 | * `flux` directly registers your template as a new, unique CType which behaves like a true content type (but still allows you 24 | to use a ContentController) 25 | * Without `fluidcontent` installed, access restrictions for allowed content types are now configured directly from the standard 26 | content types list. And subsequently you need to target the individual CTypes when configuring `allowedContentTypes` 27 | or `deniedContentTypes` in Flux grid columns and when customising the TCA/TS for your content types. 28 | 29 | The parts that cannot be migrated (yet) are exactly those parts: converting the existing content records' type values and scanning 30 | for possible references to the converted content types (and either reporting or fixing by rewriting those cases). Apart from that 31 | the solutions are compatible in that they consume the exact same type of templates with the same configuration. 32 | -------------------------------------------------------------------------------- /Resources/Private/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /Resources/Private/Language/locallang.xlf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | default 8 | 9 | 10 | Allowed fluidcontent types 11 | 12 | 13 | Denied fluidcontent types 14 | 15 | 16 | No available content types 17 | 18 | 19 | Configuration 20 | 21 | 22 | Content settings 23 | 24 | 25 | Element type 26 | 27 | 28 | Element Configuration 29 | 30 | 31 | Content area 32 | 33 | 34 | Fluid Content type 35 | 36 | 37 | Fluid Content type not selected - edit this element in the TYPO3 backend to fix this! 38 | 39 | 40 | Fluid Content type not selected - edit this element to fix this! 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Resources/Private/Layouts/Content.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Resources/Private/Layouts/FCE.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Resources/Private/Templates/Content/Error.html: -------------------------------------------------------------------------------- 1 | {namespace flux=FluidTYPO3\Flux\ViewHelpers} 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 | 11 | 12 | 13 | 14 |
15 |
16 |

Warning

17 | 18 |
19 | 20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 |
28 | 29 | 30 | 31 |
32 |
33 |
34 | 35 | 36 | 37 | 38 |
39 |
40 |

Warning

41 | 42 |
43 | 44 |
45 |
46 |
47 |
48 | 49 |
50 | 51 | 52 |
53 | 54 |

Content uid: [{record.uid}] 55 |
56 |
-------------------------------------------------------------------------------- /Resources/Public/Icons/Plugin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /Tests/Fixtures/Templates/Content/DisabledContent.html: -------------------------------------------------------------------------------- 1 | {namespace flux=FluidTYPO3\Flux\ViewHelpers} 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Tests/Fixtures/Templates/Content/DummyContent.html: -------------------------------------------------------------------------------- 1 | {namespace flux=FluidTYPO3\Flux\ViewHelpers} 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Tests/Fixtures/Templates/Content/EmptyTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/Unit/Backend/TableConfigurationPostProcessorTest.php: -------------------------------------------------------------------------------- 1 | callInaccessibleMethod($instance, 'getConfigurationService'); 28 | $this->assertInstanceOf(ConfigurationService::class, $result); 29 | } 30 | 31 | /** 32 | * @test 33 | */ 34 | public function testProcessData() 35 | { 36 | $service = $this->getMockBuilder(ConfigurationService::class)->setMethods(['getPageTsConfig'])->getMock(); 37 | $service->expects($this->once())->method('getPageTsConfig')->willReturn(''); 38 | $instance = $this->getMockBuilder(TableConfigurationPostProcessor::class)->setMethods(['getConfigurationService'])->getMock(); 39 | $instance->expects($this->once())->method('getConfigurationService')->willReturn($service); 40 | $instance->processData(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Tests/Unit/Controller/ContentControllerTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder(ContentController::class) 34 | ->setMethods( 35 | [ 36 | 'getRecord', 'initializeProvider', 'initializeSettings', 'initializeOverriddenSettings', 37 | 'initializeViewObject', 'initializeViewVariables', 'initializeViewHelperVariableContainer' 38 | ] 39 | )->getMock(); 40 | $request = $this->getMockBuilder(Request::class)->getMock(); 41 | $viewProperty = new PropertyReflection(ContentController::class, 'request'); 42 | $viewProperty->setAccessible(true); 43 | $viewProperty->setValue($instance, $request); 44 | /** @var ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject $configurationManager */ 45 | $configurationManager = $this->getMockBuilder(ConfigurationManager::class) 46 | ->setMethods(['getContentObject', 'getConfiguration']) 47 | ->getMock(); 48 | $contentObject = new \stdClass(); 49 | $configurationManager->expects($this->once())->method('getContentObject')->willReturn($contentObject); 50 | $configurationManager->expects($this->once())->method('getConfiguration')->willReturn(['foo' => 'bar']); 51 | $instance->expects($this->atLeastOnce())->method('getRecord')->willReturn(['uid' => 0]); 52 | $GLOBALS['TSFE'] = (object) ['page' => 'page', 'fe_user' => (object) ['user' => 'user']]; 53 | 54 | $provider = $this->getMockBuilder(ProviderInterface::class)->getMockForAbstractClass(); 55 | $provider->expects($this->once())->method('getControllerExtensionKeyFromRecord')->willReturn('test'); 56 | 57 | $paths = $this->getMockBuilder(TemplatePaths::class)->setMethods(['fillDefaultsByPackageName'])->getMock(); 58 | $controllerContext = $this->getMockBuilder(ControllerContext::class)->setMethods(['getRequest'])->getMock(); 59 | $context = $this->getMockBuilder(RenderingContext::class)->setMethods(['getTemplatePaths', 'setControllerAction'])->getMock(); 60 | 61 | $controllerContext->expects($this->atLeastOnce())->method('getRequest')->willReturn($request); 62 | 63 | $context->expects($this->once())->method('setControllerAction'); 64 | $context->expects($this->atLeastOnce())->method('getTemplatePaths')->willReturn($paths); 65 | 66 | /** @var ExposedTemplateView|\PHPUnit_Framework_MockObject_MockObject $view */ 67 | $view = $this->getMockBuilder(TemplateView::class)->setMethods(['assign'])->getMock(); 68 | $view->setRenderingContext($context); 69 | $view->expects($this->at(0))->method('assign')->with('page', 'page'); 70 | $view->expects($this->at(1))->method('assign')->with('user', 'user'); 71 | $view->expects($this->at(2))->method('assign')->with('record', ['uid' => 0]); 72 | $view->expects($this->at(3))->method('assign')->with('contentObject', $contentObject); 73 | $view->expects($this->at(4))->method('assign')->with('cookies', $_COOKIE); 74 | $view->expects($this->at(5))->method('assign')->with('session', $_SESSION); 75 | 76 | ObjectAccess::setProperty($instance, 'provider', $provider, true); 77 | ObjectAccess::setProperty($instance, 'controllerContext', $controllerContext, true); 78 | $instance->injectConfigurationManager($configurationManager); 79 | $instance->initializeView($view); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Tests/Unit/Hooks/WizardItemsHookSubscriberTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder(DatabaseConnection::class) 35 | ->setMethods(['prepare_SELECTquery']) 36 | ->disableOriginalConstructor() 37 | ->getMock(); 38 | $preparedStatementMock = $this->getMockBuilder(PreparedStatement::class) 39 | ->setMethods(['execute', 'fetch', 'free']) 40 | ->disableOriginalConstructor() 41 | ->getMock(); 42 | $preparedStatementMock->expects($this->any())->method('execute')->willReturn(false); 43 | $preparedStatementMock->expects($this->any())->method('free'); 44 | $preparedStatementMock->expects($this->any())->method('fetch')->willReturn(false); 45 | ; 46 | $GLOBALS['TYPO3_DB']->expects($this->any())->method('prepare_SELECTquery')->willReturn($preparedStatementMock); 47 | $instance = GeneralUtility::makeInstance(ObjectManager::class)->get(WizardItemsHookSubscriber::class); 48 | $this->assertInstanceOf(WizardItemsHookSubscriber::class, $instance); 49 | } 50 | 51 | /** 52 | * @dataProvider getTestElementsWhiteAndBlackListsAndExpectedList 53 | * @test 54 | * @param array $items 55 | * @param string $whitelist 56 | * @param string $blacklist 57 | * @param array $expectedList 58 | */ 59 | public function processesWizardItems($items, $whitelist, $blacklist, $expectedList) 60 | { 61 | $GLOBALS['LOCAL_LANG'] = new \stdClass(); 62 | $GLOBALS['BE_USER'] = new BackendUserAuthentication(); 63 | $objectManager = GeneralUtility::makeInstance(ObjectManager::class); 64 | /** @var WizardItemsHookSubscriber $instance */ 65 | $instance = $objectManager->get(WizardItemsHookSubscriber::class); 66 | $emulatedPageAndContentRecord = ['uid' => 1, 'tx_flux_column' => 'name']; 67 | $controller = $this->getMockBuilder(NewContentElementController::class)->setMethods(['init'])->disableOriginalConstructor()->getMock(); 68 | $controller->colPos = 0; 69 | $controller->uid_pid = -1; 70 | $grid = new Grid(); 71 | $row = new Row(); 72 | $column = new Column(); 73 | $column->setColumnPosition(0); 74 | $column->setName('name'); 75 | $column->setVariable('Fluidcontent', [ 76 | 'allowedContentTypes' => $whitelist, 77 | 'deniedContentTypes' => $blacklist 78 | ]); 79 | $row->add($column); 80 | $grid->add($row); 81 | /** @var Provider $provider1 */ 82 | $provider1 = $objectManager->get(Provider::class); 83 | $provider1->setTemplatePaths([]); 84 | $provider1->setTemplateVariables([]); 85 | $provider1->setGrid($grid); 86 | $provider2 = $this->getMockBuilder(Provider::class)->setMethods(['getGrid'])->getMock(); 87 | $provider2->expects($this->exactly(1))->method('getGrid')->will($this->returnValue(null)); 88 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $configurationService */ 89 | $configurationService = $this->getMockBuilder(ConfigurationService::class) 90 | ->setMethods(['resolveConfigurationProviders', 'writeCachedConfigurationIfMissing']) 91 | ->getMock(); 92 | $configurationService->expects($this->exactly(1))->method('resolveConfigurationProviders') 93 | ->will($this->returnValue([$provider1, $provider2])); 94 | /** @var WorkspacesAwareRecordService|\PHPUnit_Framework_MockObject_MockObject $recordService */ 95 | $recordService = $this->getMockBuilder(WorkspacesAwareRecordService::class)->setMethods(['getSingle'])->getMock(); 96 | $recordService->expects($this->exactly(2))->method('getSingle')->will($this->returnValue($emulatedPageAndContentRecord)); 97 | $instance->injectConfigurationService($configurationService); 98 | $instance->injectRecordService($recordService); 99 | $instance->manipulateWizardItems($items, $controller); 100 | $this->assertEquals($expectedList, $items); 101 | } 102 | 103 | /** 104 | * @return array 105 | */ 106 | public function getTestElementsWhiteAndBlackListsAndExpectedList() 107 | { 108 | $items = [ 109 | 'plugins' => ['title' => 'Nice header'], 110 | 'plugins_test1' => [ 111 | 'tt_content_defValues' => ['CType' => 'fluidcontent_content', 'tx_fed_fcefile' => 'test1:test1'] 112 | ], 113 | 'plugins_test2' => [ 114 | 'tt_content_defValues' => ['CType' => 'fluidcontent_content', 'tx_fed_fcefile' => 'test2:test2'] 115 | ] 116 | ]; 117 | return [ 118 | [ 119 | $items, 120 | null, 121 | null, 122 | $items, 123 | ], 124 | [ 125 | $items, 126 | 'test1:test1', 127 | null, 128 | [ 129 | 'plugins' => ['title' => 'Nice header'], 130 | 'plugins_test1' => $items['plugins_test1'] 131 | ], 132 | ], 133 | [ 134 | $items, 135 | null, 136 | 'test1:test1', 137 | [ 138 | 'plugins' => ['title' => 'Nice header'], 139 | 'plugins_test2' => $items['plugins_test2'] 140 | ], 141 | ], 142 | [ 143 | $items, 144 | 'test1:test1', 145 | 'test1:test1', 146 | [], 147 | ], 148 | ]; 149 | } 150 | 151 | public function testManipulateWizardItemsCallsExpectedMethodSequenceWithoutProviders() 152 | { 153 | $GLOBALS['BE_USER'] = new BackendUserAuthentication(); 154 | /** @var WizardItemsHookSubscriber $instance */ 155 | $instance = GeneralUtility::makeInstance(ObjectManager::class) 156 | ->get(WizardItemsHookSubscriber::class); 157 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $configurationService */ 158 | $configurationService = $this->getMockBuilder(ConfigurationService::class) 159 | ->setMethods(['writeCachedConfigurationIfMissing', 'resolveConfigurationProviders']) 160 | ->getMock(); 161 | /** @var WorkspacesAwareRecordService|\PHPUnit_Framework_MockObject_MockObject $recordService */ 162 | $recordService = $this->getMockBuilder(WorkspacesAwareRecordService::class)->setMethods(['getSingle'])->getMock(); 163 | $configurationService->expects($this->once())->method('writeCachedConfigurationIfMissing'); 164 | $configurationService->expects($this->once())->method('resolveConfigurationProviders')->willReturn([]); 165 | $recordService->expects($this->once())->method('getSingle')->willReturn(null); 166 | $instance->injectConfigurationService($configurationService); 167 | $instance->injectRecordService($recordService); 168 | $parent = $this->getMockBuilder(NewContentElementController::class) 169 | ->setMethods(['init']) 170 | ->disableOriginalConstructor() 171 | ->getMock(); 172 | $items = []; 173 | $instance->manipulateWizardItems($items, $parent); 174 | } 175 | 176 | public function testManipulateWizardItemsCallsExpectedMethodSequenceWithProvidersWithColPosWithoutRelativeElement() 177 | { 178 | $GLOBALS['BE_USER'] = new BackendUserAuthentication(); 179 | /** @var WizardItemsHookSubscriber $instance */ 180 | $instance = GeneralUtility::makeInstance(ObjectManager::class)->get(WizardItemsHookSubscriber::class); 181 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $configurationService */ 182 | $configurationService = $this->getMockBuilder(ConfigurationService::class) 183 | ->setMethods(['writeCachedConfigurationIfMissing', 'resolveConfigurationProviders']) 184 | ->getMock(); 185 | /** @var WorkspacesAwareRecordService|\PHPUnit_Framework_MockObject_MockObject $recordService */ 186 | $recordService = $this->getMockBuilder(WorkspacesAwareRecordService::class) 187 | ->setMethods(['getSingle']) 188 | ->getMock(); 189 | $record = ['uid' => 0]; 190 | $provider1 = $this->getMockProvider($record); 191 | $provider2 = $this->getMockProvider($record); 192 | $provider3 = $this->getMockProvider($record, false); 193 | $configurationService->expects($this->once())->method('writeCachedConfigurationIfMissing'); 194 | $configurationService->expects($this->once())->method('resolveConfigurationProviders')->willReturn([ 195 | $provider1, $provider2, $provider3 196 | ]); 197 | $recordService->expects($this->once())->method('getSingle')->willReturn($record); 198 | $instance->injectConfigurationService($configurationService); 199 | $instance->injectRecordService($recordService); 200 | $parent = $this->getMockBuilder(NewContentElementController::class) 201 | ->setMethods(['init']) 202 | ->disableOriginalConstructor() 203 | ->getMock(); 204 | $parent->colPos = 1; 205 | $items = []; 206 | $instance->manipulateWizardItems($items, $parent); 207 | } 208 | 209 | /** 210 | * @param array $record 211 | * @param boolean $withGrid 212 | * @return Provider 213 | */ 214 | protected function getMockProvider(array $record, $withGrid = true) 215 | { 216 | $instance = $this->getMockBuilder(Provider::class)->setMethods(['getViewVariables', 'getGrid'])->getMock(); 217 | if (false === $withGrid) { 218 | $instance->expects($this->any())->method('getGrid')->willReturn(null); 219 | } else { 220 | $grid = Grid::create(); 221 | $grid->createContainer('Row', 'row')->createContainer('Column', 'column')->setColumnPosition(1) 222 | ->setVariable('Fluidcontent', ['deniedContentTypes' => 'html', 'allowedContentTypes' => 'text']); 223 | $instance->expects($this->any())->method('getGrid')->willReturn($grid); 224 | } 225 | return $instance; 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /Tests/Unit/Provider/ContentProviderTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder(DatabaseConnection::class) 35 | ->setMethods(['prepare_SELECTquery', 'exec_SELECTgetSingleRow', 'exec_SELECTgetRows', 'exec_SELECTquery']) 36 | ->disableOriginalConstructor() 37 | ->getMock(); 38 | $preparedStatementMock = $this->getMockBuilder(PreparedStatement::class) 39 | ->setMethods(['execute', 'fetch', 'free']) 40 | ->disableOriginalConstructor() 41 | ->getMock(); 42 | $preparedStatementMock->expects($this->any())->method('execute')->willReturn(false); 43 | $preparedStatementMock->expects($this->any())->method('free'); 44 | $preparedStatementMock->expects($this->any())->method('fetch')->willReturn(false); 45 | $GLOBALS['TYPO3_DB']->expects($this->any())->method('prepare_SELECTquery')->willReturn($preparedStatementMock); 46 | $instance = $this->getMockBuilder(ContentProvider::class)->setMethods(['getPreview', 'getTemplatePaths'])->getMock(); 47 | $instance->expects($this->any())->method('getTemplatePaths')->willReturn(['templateRootPaths' => ['EXT:fluidcontent/Resources/Private/Templates/']]); 48 | $instance->expects($this->any())->method('getPreview')->willReturn(['preview', true]); 49 | $configurationServiceMock = $this->getMockBuilder(ConfigurationService::class)->setMethods(['translateLabel', 'getContentConfiguration'])->getMock(); 50 | $configurationServiceMock->expects($this->any())->method('getContentConfiguration')->willReturn([ 51 | 'fluidcontent' => [ 52 | 'templateRootPaths' => [ 53 | 'EXT:fluidcontent/Tests/Fixtures/Templates/' 54 | ] 55 | ] 56 | ]); 57 | $instance->injectConfigurationService($configurationServiceMock); 58 | return $instance; 59 | } 60 | 61 | /** 62 | * @test 63 | */ 64 | public function testPerformsInjections() 65 | { 66 | $instance = GeneralUtility::makeInstance(ObjectManager::class)->get(ContentProvider::class); 67 | $this->assertAttributeInstanceOf( 68 | ConfigurationManagerInterface::class, 69 | 'configurationManager', 70 | $instance 71 | ); 72 | $this->assertAttributeInstanceOf( 73 | ConfigurationService::class, 74 | 'contentConfigurationService', 75 | $instance 76 | ); 77 | } 78 | 79 | /** 80 | * @dataProvider getTemplatePathAndFilenameTestValues 81 | * @param array $record 82 | * @param string $expected 83 | */ 84 | public function testGetTemplatePathAndFilename(array $record, $expected) 85 | { 86 | $GLOBALS['TYPO3_LOADED_EXT'] = []; 87 | $instance = $this->createProviderInstance(); 88 | 89 | $extPath = ExtensionManagementUtility::extPath('fluidcontent'); 90 | $configuration = array( 91 | 'templateRootPaths' => array( 92 | $extPath . 'Resources/Private/Templates/', 93 | $extPath . 'Tests/Fixtures/Templates/' 94 | ), 95 | 'partialRootPaths' => array( 96 | $extPath . 'Resources/Private/Partials/' 97 | ), 98 | 'layoutRootPaths' => array( 99 | $extPath . 'Resources/Private/Layouts/' 100 | ), 101 | ); 102 | $configurationManager = $this->getMockBuilder(ConfigurationManager::class)->setMethods(['getConfiguration'])->getMock(); 103 | $configurationManager->expects($this->once())->method('getConfiguration')->willReturn( 104 | ['module' => ['tx_fluidcontent' => ['view' => $configuration]]] 105 | ); 106 | 107 | $objectManager = $this->getMockBuilder(ObjectManager::class)->setMethods(['get'])->getMock(); 108 | $objectManager->expects($this->atLeastOnce())->method('get')->with(ConfigurationManagerInterface::class)->willReturn($configurationManager); 109 | 110 | GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager); 111 | 112 | $result = $instance->getTemplatePathAndFilename($record); 113 | 114 | GeneralUtility::removeSingletonInstance(ObjectManager::class, $objectManager); 115 | 116 | $this->assertEquals($expected, $result); 117 | } 118 | 119 | /** 120 | * @return array 121 | */ 122 | public function getTemplatePathAndFilenameTestValues() 123 | { 124 | $path = ExtensionManagementUtility::extPath('fluidcontent'); 125 | $file = $path . 'Resources/Private/Templates/Content/Error.html'; 126 | return [ 127 | [['uid' => 0], $file], 128 | [['tx_fed_fcefile' => 'fluidcontent:Error.html'], $file], 129 | ]; 130 | } 131 | 132 | /** 133 | * @dataProvider getTemplatePathAndFilenameOverrideTestValues 134 | * @param string $template 135 | * @param string $expected 136 | */ 137 | public function testGetTemplatePathAndFilenameWithOverride($template, $expected) 138 | { 139 | $instance = $this->createProviderInstance(); 140 | $instance->setTemplatePathAndFilename($template); 141 | $result = $instance->getTemplatePathAndFilename([]); 142 | $this->assertEquals($expected, $result); 143 | } 144 | 145 | /** 146 | * @return array 147 | */ 148 | public function getTemplatePathAndFilenameOverrideTestValues() 149 | { 150 | $path = ExtensionManagementUtility::extPath('fluidcontent'); 151 | return [ 152 | [ 153 | 'EXT:fluidcontent/Resources/Private/Templates/Content/Error.html', 154 | $path . 'Resources/Private/Templates/Content/Error.html', 155 | ], 156 | [ 157 | $path . 'Resources/Private/Templates/Content/Error.html', 158 | $path . 'Resources/Private/Templates/Content/Error.html', 159 | ], 160 | [ 161 | $path . '/Does/Not/Exist.html', 162 | null, 163 | ] 164 | ]; 165 | } 166 | 167 | /** 168 | * @dataProvider getControllerExtensionKeyFromRecordTestValues 169 | * @param array $record 170 | * @param $expected 171 | */ 172 | public function testGetControllerExtensionKeyFromRecord(array $record, $expected) 173 | { 174 | $instance = $this->createProviderInstance(); 175 | $result = $instance->getControllerExtensionKeyFromRecord($record); 176 | $this->assertEquals($expected, $result); 177 | } 178 | 179 | /** 180 | * @return array 181 | */ 182 | public function getControllerExtensionKeyFromRecordTestValues() 183 | { 184 | return [ 185 | [['uid' => 0], 'Fluidcontent'], 186 | [['tx_fed_fcefile' => 'test:test'], 'test'], 187 | ]; 188 | } 189 | 190 | /** 191 | * @dataProvider getControllerActionFromRecordTestValues 192 | * @param array $record 193 | * @param $expected 194 | */ 195 | public function testGetControllerActionFromRecord(array $record, $expected) 196 | { 197 | $instance = $this->createProviderInstance(); 198 | $result = $instance->getControllerActionFromRecord($record); 199 | $this->assertEquals($expected, $result); 200 | } 201 | 202 | /** 203 | * @return array 204 | */ 205 | public function getControllerActionFromRecordTestValues() 206 | { 207 | return [ 208 | [['uid' => 0], 'error'], 209 | [['tx_fed_fcefile' => 'test:test'], 'test'], 210 | ]; 211 | } 212 | 213 | /** 214 | * @dataProvider getPriorityTestValues 215 | * @param array $record 216 | * @param $expected 217 | */ 218 | public function testGetPriority(array $record, $expected) 219 | { 220 | $instance = $this->createProviderInstance(); 221 | $result = $instance->getPriority($record); 222 | $this->assertEquals($expected, $result); 223 | } 224 | 225 | /** 226 | * @return array 227 | */ 228 | public function getPriorityTestValues() 229 | { 230 | return [ 231 | [['uid' => 0], 0], 232 | [['tx_fed_fcefile' => 'test:test'], 0], 233 | [['tx_fed_fcefile' => 'test:test', 'CType' => 'fluidcontent_content'], 100], 234 | ]; 235 | } 236 | 237 | /** 238 | * @test 239 | * @dataProvider getPreviewTestValues 240 | * @param array $record 241 | * 242 | * tests if defaut previews for content elements of different types 243 | * each with a tx_fed_tcefile defined 244 | */ 245 | public function testGetPreviewForTextElement(array $record) 246 | { 247 | $instance = $this->createProviderInstance(); 248 | $recordService = $this->getMockBuilder(WorkspacesAwareRecordService::class)->setMethods(['get'])->getMock(); 249 | $instance->injectRecordService($recordService); 250 | $result = $instance->getPreview($record); 251 | $this->assertEquals(['preview', true], $result); 252 | } 253 | 254 | public function getPreviewTestValues() 255 | { 256 | return [ 257 | [ 258 | [ 259 | 'uid' => 1, 260 | 'CType' => 'text', 261 | 'header' => 'this is a simple text element', 262 | 'tx_fed_tcefile' => 'dummy-fed-file.txt' 263 | ] 264 | ], 265 | [ 266 | [ 267 | 'uid' => 1, 268 | 'CType' => 'fluidcontent_content', 269 | 'header' => 'this is a simple text element', 270 | 'tx_fed_tcefile' => 'dummy-fed-file.txt' 271 | ] 272 | ] 273 | ]; 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /Tests/Unit/Service/ConfigurationServiceTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder(ConfigurationService::class) 40 | ->setMethods(['dummy']) 41 | ->disableOriginalConstructor() 42 | ->getMock(); 43 | 44 | $configuration = array( 45 | 'templateRootPaths' => array( 46 | $extPath . 'Resources/Private/Templates/', 47 | $extPath . 'Tests/Fixtures/Templates/' 48 | ), 49 | 'partialRootPaths' => array( 50 | $extPath . 'Resources/Private/Partials/' 51 | ), 52 | 'layoutRootPaths' => array( 53 | $extPath . 'Resources/Private/Layouts/' 54 | ), 55 | ); 56 | $configurationManager = $this->getMockBuilder(ConfigurationManager::class)->setMethods(['getConfiguration'])->getMock(); 57 | $configurationManager->expects($this->once())->method('getConfiguration')->willReturn( 58 | ['module' => ['tx_fluidcontent' => ['view' => $configuration]]] 59 | ); 60 | 61 | $objectManager = $this->getMockBuilder(ObjectManager::class)->setMethods(['get'])->getMock(); 62 | $objectManager->expects($this->atLeastOnce())->method('get')->with(ConfigurationManagerInterface::class)->willReturn($configurationManager); 63 | 64 | GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager); 65 | 66 | $result = $service->getContentConfiguration(); 67 | 68 | GeneralUtility::removeSingletonInstance(ObjectManager::class, $objectManager); 69 | 70 | 71 | $this->assertEquals(array('FluidTYPO3.Fluidcontent' => $configuration), $result); 72 | } 73 | 74 | public function testWriteCachedConfigurationIfMissing() 75 | { 76 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $service */ 77 | $service = $this->getMockBuilder(ConfigurationService::class) 78 | ->setMethods(array('getPageTsConfig')) 79 | ->disableOriginalConstructor() 80 | ->getMock(); 81 | $service->expects($this->any())->method('getPageTsConfig')->willReturn('test'); 82 | $service->writeCachedConfigurationIfMissing(); 83 | } 84 | 85 | public function testBuildAllWizardTabsPageTsConfig() 86 | { 87 | $tabs = array( 88 | 'tab1' => array( 89 | 'title' => 'Tab 1', 90 | 'key' => 'tab1', 91 | 'elements' => array( 92 | 'a,b,c' 93 | ) 94 | ), 95 | 'tab2' => array( 96 | 'title' => 'Tab 2', 97 | 'key' => 'tab2', 98 | 'elements' => array( 99 | 'a,b,c' 100 | ) 101 | ) 102 | ); 103 | $service = $this->getMockBuilder(ConfigurationService::class)->setMethods(['getExistingNewContentWizardItems'])->getMock(); 104 | $service->expects($this->once())->method('getExistingNewContentWizardItems')->willReturn([]); 105 | $result = $this->callInaccessibleMethod($service, 'buildAllWizardTabsPageTsConfig', $tabs); 106 | foreach ($tabs as $tabId => $tab) { 107 | $this->assertContains($tabId, $result); 108 | $this->assertContains($tab['key'], $result); 109 | } 110 | } 111 | 112 | public function testRenderWizardTabItem() 113 | { 114 | $form = Form::create(); 115 | $form->setLabel('bazlabel'); 116 | $form->setDescription('foobar'); 117 | $service = $this->getMockBuilder(ConfigurationService::class)->disableOriginalConstructor()->getMock(); 118 | $result = $this->callInaccessibleMethod($service, 'buildWizardTabItem', 'tabid', 'id', $form, ''); 119 | $this->assertContains('tabid.elements.id', $result); 120 | $this->assertContains('title = bazlabel', $result); 121 | $this->assertContains('description = foobar', $result); 122 | } 123 | 124 | /** 125 | * @test 126 | * @dataProvider getSanitizeStringTestValues 127 | * @param string $input 128 | * @param string $expected 129 | */ 130 | public function testSanitizeString($input, $expected) 131 | { 132 | $service = $this->getMockBuilder(ConfigurationService::class)->disableOriginalConstructor()->getMock(); 133 | $result = $this->callInaccessibleMethod($service, 'sanitizeString', $input); 134 | $this->assertEquals($expected, $result); 135 | } 136 | 137 | /** 138 | * @return array 139 | */ 140 | public function getSanitizeStringTestValues() 141 | { 142 | return array( 143 | array('foo bar', 'foobar') 144 | ); 145 | } 146 | 147 | /** 148 | * @return void 149 | */ 150 | public function testGetContentElementFormInstances() 151 | { 152 | $class = substr(str_replace('Tests\\Unit\\', '', get_class($this)), 0, -4); 153 | 154 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $mock */ 155 | $mock = $this->getMockBuilder($class)->setMethods(array('getContentConfiguration'))->getMock(); 156 | $provider = new ContentProvider(); 157 | $provider->setForm(Form::create()); 158 | 159 | /** @var ObjectManager $objectManager */ 160 | $objectManager = $this->getMockBuilder(ObjectManager::class)->setMethods(['get'])->getMock(); 161 | $objectManager->method('get')->with(ContentProvider::class)->willReturn($provider); 162 | 163 | $mock->injectObjectManager($objectManager); 164 | 165 | $mock->expects($this->once())->method('getContentConfiguration')->willReturn(array( 166 | 'fluidcontent' => array( 167 | 'templateRootPaths' => [ExtensionManagementUtility::extPath('fluidcontent', 'Tests/Fixtures/Templates/')] 168 | ) 169 | )); 170 | $result = $mock->getContentElementFormInstances(); 171 | $this->assertInstanceOf(Form::class, $result['fluidcontent']['fluidcontent_DummyContent_html']); 172 | } 173 | 174 | /** 175 | * @return void 176 | */ 177 | public function testBuildAllWizardTabGroups() 178 | { 179 | $class = substr(str_replace('Tests\\Unit\\', '', get_class($this)), 0, -4); 180 | 181 | /** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $mock */ 182 | $mock = $this->getMockBuilder($class)->setMethods(array('getContentConfiguration', 'message', 'translateLabel'))->getMock(); 183 | $mock->expects($this->atLeastOnce())->method('translateLabel')->willReturn('translated'); 184 | 185 | $provider = new ContentProvider(); 186 | $provider->setForm(Form::create()); 187 | 188 | /** @var ObjectManager $objectManager */ 189 | $objectManager = $this->getMockBuilder(ObjectManager::class)->setMethods(['get'])->getMock(); 190 | $objectManager->method('get')->with(ContentProvider::class)->willReturn($provider); 191 | $mock->injectObjectManager($objectManager); 192 | $paths = array( 193 | 'fluidcontent' => array( 194 | 'templateRootPaths' => array('EXT:fluidcontent/Tests/Fixtures/Templates/') 195 | ) 196 | ); 197 | $cacheManager = $this->getMockBuilder(CacheManager::class)->setMethods(['hasCache'])->getMock(); 198 | $cacheManager->expects($this->any())->method('hasCache')->with('fluidcontent')->willReturn(false); 199 | ObjectAccess::setProperty($mock, 'manager', $cacheManager, true); 200 | $mock->expects($this->once())->method('getContentConfiguration')->willReturn($paths); 201 | $result = $this->callInaccessibleMethod($mock, 'buildAllWizardTabGroups', $paths); 202 | $this->assertNotEmpty($result['common']['title']); 203 | $this->assertArrayHasKey('fluidcontent_DummyContent_html', $result['common']['elements']); 204 | } 205 | 206 | /** 207 | * @return void 208 | */ 209 | public function testRenderPageTypoScriptForPageUidCreatesExpectedTypoScript() 210 | { 211 | $pageUid = 1; 212 | $class = substr(str_replace('Tests\\Unit\\', '', get_class($this)), 0, -4); 213 | $instance = $this->getMockBuilder($class) 214 | ->setMethods( 215 | array( 216 | 'overrideCurrentPageUidForConfigurationManager', 217 | 'buildAllWizardTabGroups', 218 | 'buildAllWizardTabsPageTsConfig' 219 | ) 220 | )->getMock(); 221 | $instance->expects($this->once())->method('overrideCurrentPageUidForConfigurationManager')->with($pageUid); 222 | $instance->expects($this->once())->method('buildAllWizardTabGroups')->willReturn(array()); 223 | $instance->expects($this->once())->method('buildAllWizardTabsPageTsConfig')->willReturn('targetmarker'); 224 | $result = $this->callInaccessibleMethod($instance, 'renderPageTypoScriptForPageUid', $pageUid); 225 | $this->assertContains('targetmarker', $result); 226 | } 227 | 228 | /** 229 | * @return void 230 | */ 231 | public function testRenderPageTypoScriptForPageUidDelegatesExceptionsToDebug() 232 | { 233 | $class = substr(str_replace('Tests\\Unit\\', '', get_class($this)), 0, -4); 234 | $instance = $this->getMockBuilder($class)->setMethods(array('getContentConfiguration', 'message'))->getMock(); 235 | $instance->expects($this->once())->method('getContentConfiguration') 236 | ->willThrowException(new \RuntimeException('test')); 237 | $instance->expects($this->once())->method('message'); 238 | $this->callInaccessibleMethod($instance, 'renderPageTypoScriptForPageUid', 0, array()); 239 | } 240 | 241 | /** 242 | * @return void 243 | */ 244 | public function testConfigurationManagerOverrides() 245 | { 246 | $instance = new ConfigurationService(); 247 | /** @var ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject $mock */ 248 | $mock = $this->getMockBuilder(\FluidTYPO3\Flux\Configuration\ConfigurationManager::class)->setMethods(array('setCurrentPageUid', 'getCurrentPageId'))->getMock(); 249 | $mock->expects($this->at(0))->method('setCurrentPageUid')->with(1); 250 | $mock->expects($this->at(1))->method('getCurrentPageId')->willReturn(2); 251 | $mock->expects($this->at(2))->method('setCurrentPageUid')->with(2); 252 | $instance->injectConfigurationManager($mock); 253 | $this->callInaccessibleMethod($instance, 'overrideCurrentPageUidForConfigurationManager', 1); 254 | $this->callInaccessibleMethod($instance, 'backupPageUidForConfigurationManager'); 255 | $this->callInaccessibleMethod($instance, 'restorePageUidForConfigurationManager'); 256 | } 257 | 258 | /** 259 | * @test 260 | */ 261 | public function testGetPageTsConfigFetchesAndCachesRootTypoScriptIfNotCached() 262 | { 263 | $expectedValue = 'This will be fetched and cached.'; 264 | $cache = $this->getMockBuilder(VariableFrontend::class)->setMethods(array('has', 'set', 'get'))->disableOriginalConstructor()->getMock(); 265 | $cache->expects($this->once())->method('has')->with($this->equalTo(self::CACHE_KEY_PAGETSCONFIG))->willReturn(false); 266 | $cache->expects($this->once())->method('set')->with($this->equalTo(self::CACHE_KEY_PAGETSCONFIG), $this->equalTo($expectedValue)); 267 | $cache->expects($this->never())->method('get'); 268 | $manager = $this->getMockBuilder(CacheManager::class)->setMethods(array('hasCache', 'getCache'))->getMock(); 269 | $manager->expects($this->once())->method('hasCache')->willReturn(true); 270 | $manager->expects($this->once())->method('getCache')->willReturn($cache); 271 | $service = $this->getMockBuilder(ConfigurationService::class) 272 | ->setMethods(array('getAllRootTypoScriptTemplates', 'renderPageTypoScriptForPageUid', 'getTypoScriptTemplatesInRootline')) 273 | ->disableOriginalConstructor() 274 | ->getMock(); 275 | $service->expects($this->never())->method('getTypoScriptTemplatesInRootline'); 276 | $service->expects($this->once())->method('renderPageTypoScriptForPageUid')->willReturn($expectedValue); 277 | $service->expects($this->once())->method('getAllRootTypoScriptTemplates')->willReturn(array(1)); 278 | 279 | $service->injectConfigurationManager($this->getMockBuilder(ConfigurationManager::class)->getMock()); 280 | $service->injectCacheManager($manager); 281 | $returnedValue = $service->getPageTsConfig(); 282 | 283 | $this->assertEquals($expectedValue, $returnedValue); 284 | } 285 | 286 | /** 287 | * @test 288 | */ 289 | public function testGetPageTsConfigFetchesRootTypoScriptIfCacheUnavailable() 290 | { 291 | $expectedValue = 'This will be fetched.'; 292 | $manager = $this->getMockBuilder(CacheManager::class)->setMethods(array('hasCache', 'getCache'))->getMock(); 293 | $manager->expects($this->once())->method('hasCache')->willReturn(false); 294 | $manager->expects($this->never())->method('getCache')->willThrowException(new NoSuchCacheException()); 295 | $service = $this->getMockBuilder(ConfigurationService::class) 296 | ->setMethods(array('getAllRootTypoScriptTemplates', 'renderPageTypoScriptForPageUid', 'getTypoScriptTemplatesInRootline')) 297 | ->disableOriginalConstructor() 298 | ->getMock(); 299 | $service->expects($this->never())->method('getTypoScriptTemplatesInRootline'); 300 | $service->expects($this->once())->method('renderPageTypoScriptForPageUid')->willReturn($expectedValue); 301 | $service->expects($this->once())->method('getAllRootTypoScriptTemplates')->willReturn(array(1)); 302 | 303 | $service->injectConfigurationManager($this->getMockBuilder(ConfigurationManager::class)->getMock()); 304 | $service->injectCacheManager($manager); 305 | $returnedValue = $service->getPageTsConfig(); 306 | 307 | $this->assertEquals($expectedValue, $returnedValue); 308 | } 309 | 310 | /** 311 | * @test 312 | */ 313 | public function testGetPageTsConfigUsesCachedRootTypoScriptIfAvailable() 314 | { 315 | $cachedValue = 'this has been cached'; 316 | $cache = $this->getMockBuilder(VariableFrontend::class) 317 | ->setMethods(array('has', 'set', 'get', 'getByTag')) 318 | ->disableOriginalConstructor() 319 | ->getMock(); 320 | $cache->expects($this->once())->method('has')->with(self::CACHE_KEY_PAGETSCONFIG)->willReturn(true); 321 | $cache->expects($this->never())->method('set'); 322 | $cache->expects($this->once())->method('get')->with(self::CACHE_KEY_PAGETSCONFIG)->willReturn($cachedValue); 323 | $cache->expects($this->once())->method('getByTag')->with(ConfigurationService::ICON_CACHE_TAG)->willReturn(array()); 324 | $manager = $this->getMockBuilder(CacheManager::class)->setMethods(array('hasCache', 'getCache'))->getMock(); 325 | $manager->expects($this->once())->method('hasCache')->willReturn(true); 326 | $manager->expects($this->once())->method('getCache')->willReturn($cache); 327 | $service = $this->getMockBuilder(ConfigurationService::class) 328 | ->setMethods(array('getAllRootTypoScriptTemplates', 'renderPageTypoScriptForPageUid', 'getTypoScriptTemplatesInRootline')) 329 | ->disableOriginalConstructor() 330 | ->getMock(); 331 | $service->expects($this->never())->method('getTypoScriptTemplatesInRootline'); 332 | $service->expects($this->never())->method('getAllRootTypoScriptTemplates'); 333 | 334 | $service->injectConfigurationManager($this->getMockBuilder(ConfigurationManager::class)->getMock()); 335 | $service->injectCacheManager($manager); 336 | $returnedValue = $service->getPageTsConfig(); 337 | 338 | $this->assertEquals($cachedValue, $returnedValue); 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /Tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | addPsr4('FluidTYPO3\\Fluidcontent\\Tests\\', __DIR__ . '/'); 33 | 34 | \FluidTYPO3\Development\Bootstrap::initialize( 35 | $autoloader, 36 | array( 37 | 'fluid_template' => \FluidTYPO3\Development\Bootstrap::CACHE_PHP_NULL, 38 | 'cache_core' => \FluidTYPO3\Development\Bootstrap::CACHE_PHP_NULL, 39 | 'cache_rootline' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 40 | 'cache_runtime' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 41 | 'extbase_object' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 42 | 'extbase_datamapfactory_datamap' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 43 | 'extbase_typo3dbbackend_tablecolumns' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 44 | 'extbase_typo3dbbackend_queries' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 45 | 'flux' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 46 | 'fluidcontent' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 47 | 'l10n' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL, 48 | ) 49 | ); 50 | 51 | /** @var $extbaseObjectContainer \TYPO3\CMS\Extbase\Object\Container\Container */ 52 | $extbaseObjectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\Container\Container'); 53 | $extbaseObjectContainer->registerImplementation('TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface', 'FluidTYPO3\Flux\Configuration\ConfigurationManager'); 54 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fluidtypo3-fluidcontent", 3 | "homepage": "http://fluidtypo3.org", 4 | "description": "Create Flexible Content elements in pure fluid", 5 | "dependencies": { 6 | "flux": "fluidtypo3-flux#latest" 7 | }, 8 | "keywords": [ 9 | "TYPO3", 10 | "CMS", 11 | "extension", 12 | "templating", 13 | "bootstrap", 14 | "flux", 15 | "fluidcontent", 16 | "fedext", 17 | "fluid" 18 | ], 19 | "authors": [ 20 | "FluidTYPO3 Team" 21 | ], 22 | "license": "GPL-2.0+" 23 | } 24 | -------------------------------------------------------------------------------- /class.ext_update.php: -------------------------------------------------------------------------------- 1 | exec_TRUNCATEquery('cf_extbase_reflection'); 25 | $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cf_extbase_reflection_tags'); 26 | $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cf_extbase_object'); 27 | $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cf_extbase_object_tags'); 28 | $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 29 | 'tt_content', 30 | 'CType = \'fed_fce\'', 31 | ['CType' => 'fluidcontent_content'] 32 | ); 33 | 34 | return $GLOBALS['TYPO3_DB']->sql_affected_rows().' rows have been updated'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fluidtypo3/fluidcontent", 3 | "description": "Create Flexible Content elements in pure fluid", 4 | "require": { 5 | "fluidtypo3/flux": "^7.3|^8.0|dev-development", 6 | "typo3/cms": "^7.6|^8.4", 7 | "php": ">=7.0.0" 8 | }, 9 | "require-dev": { 10 | "fluidtypo3/development": "^3.0", 11 | "fluidtypo3/flux": "dev-development" 12 | }, 13 | "autoload": { 14 | "psr-4": { 15 | "FluidTYPO3\\Fluidcontent\\": "Classes/" 16 | } 17 | }, 18 | "type": "typo3-cms-extension", 19 | "keywords": ["TYPO3 CMS", "templating", "bootstrap", "flux", "fluidcontent", "fedext", "fluid"], 20 | "homepage": "https://fluidtypo3.org", 21 | "license": "GPL-2.0+", 22 | "support": { 23 | "irc": "irc://irc.freenode.org/fedext", 24 | "issues": "https://github.com/FluidTYPO3/fluidcontent/issues" 25 | }, 26 | "suggest": { 27 | "fluidtypo3/fluidpages": "Gives the ability to render Page Templates with pure fluid." 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ext_emconf.php: -------------------------------------------------------------------------------- 1 | 'Fluid Content Engine', 4 | 'description' => 'Fluid Content Element engine - integrates extremely compact and highly dynamic content element templates written in Fluid. See: https://github.com/FluidTYPO3/fluidcontent', 5 | 'category' => 'misc', 6 | 'author' => 'FluidTYPO3 Team', 7 | 'author_email' => 'claus@namelesscoder.net', 8 | 'author_company' => '', 9 | 'shy' => '', 10 | 'dependencies' => 'flux', 11 | 'conflicts' => '', 12 | 'priority' => '', 13 | 'module' => '', 14 | 'state' => 'obsolete', 15 | 'internal' => '', 16 | 'uploadfolder' => 0, 17 | 'createDirs' => '', 18 | 'modify_tables' => '', 19 | 'clearCacheOnLoad' => 1, 20 | 'lockType' => '', 21 | 'version' => '5.2.0', 22 | 'constraints' => 23 | array ( 24 | 'depends' => 25 | array ( 26 | 'php' => '7.0.0-7.1.99', 27 | 'typo3' => '8.7.0-8.7.99', 28 | 'flux' => '8.2.0-9.99.99', 29 | ), 30 | 'conflicts' => 31 | array ( 32 | ), 33 | 'suggests' => 34 | array ( 35 | ), 36 | ), 37 | 'suggests' => 38 | array ( 39 | ), 40 | '_md5_values_when_last_written' => '', 41 | 'autoload' => 42 | array ( 43 | 'psr-4' => 44 | array ( 45 | 'FluidTYPO3\\Fluidcontent\\' => 'Classes/', 46 | ), 47 | ), 48 | 'autoload-dev' => 49 | array ( 50 | 'psr-4' => 51 | array ( 52 | 'FluidTYPO3\\Fluidcontent\\Tests\\' => 'Tests/', 53 | ), 54 | ), 55 | ); 56 | -------------------------------------------------------------------------------- /ext_icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluidTYPO3/fluidcontent/49e5bd3239a74507ebf6fe86fd3ad2ae591b3f50/ext_icon.gif -------------------------------------------------------------------------------- /ext_localconf.php: -------------------------------------------------------------------------------- 1 | 'render', 12 | ], 13 | [], 14 | \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT 15 | ); 16 | 17 | \FluidTYPO3\Flux\Core::registerConfigurationProvider('FluidTYPO3\Fluidcontent\Provider\ContentProvider'); 18 | \FluidTYPO3\Flux\Core::registerConfigurationProvider('FluidTYPO3\Fluidcontent\Provider\BackendUserGroupProvider'); 19 | 20 | if ('BE' === TYPO3_MODE) { 21 | $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook']['fluidcontent'] = 'FluidTYPO3\Fluidcontent\Hooks\WizardItemsHookSubscriber'; 22 | $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroups_postProcessing']['fluidcontent'] = 'FluidTYPO3\Fluidcontent\Hooks\GroupAccessListPostProcessor->addAccessLists'; 23 | $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing']['fluidcontent'] = 'FluidTYPO3\Fluidcontent\Backend\TableConfigurationPostProcessor'; 24 | } 25 | } 26 | 27 | if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['fluidcontent'])) { 28 | $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['fluidcontent'] = [ 29 | 'groups' => ['system'], 30 | ]; 31 | } 32 | -------------------------------------------------------------------------------- /ext_tables.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | Tests 18 | 19 | 20 | 21 | 22 | Classes 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------