From b4dbb87c1ee353be103f46334d0c7611dd732c74 Mon Sep 17 00:00:00 2001 From: Helmut Hackbarth Date: Wed, 5 Apr 2023 10:15:49 +0200 Subject: [PATCH] New release v5.2.9 --- .../Backend/Preview/T3sbPreviewRenderer.php | 90 +-- Classes/Command/CdnToLocal.php | 3 +- Classes/Command/CustomScss.php | 5 +- Classes/Components/Card.php | 15 +- Classes/Components/Carousel.php | 25 +- .../AbstractCompatibilityController.php | 533 -------------- Classes/Controller/AbstractController.php | 33 +- Classes/Controller/ConfigController.php | 276 ++++++- Classes/Controller/ConsentController.php | 4 +- Classes/DataProcessing/BootstrapProcessor.php | 9 +- Classes/DataProcessing/ConfigProcessor.php | 16 +- Classes/DataProcessing/GalleryProcessor.php | 685 +++++++----------- .../DataProcessing/LastModifiedProcessor.php | 4 +- Classes/Domain/Model/Config.php | 80 +- Classes/EventListener/TCA/TcaCompilation.php | 111 +++ Classes/Helper/ClassHelper.php | 11 +- Classes/Helper/GalleryHelper.php | 4 +- Classes/Helper/MediaElementHelper.php | 17 +- Classes/Hooks/PageRenderer/PreProcessHook.php | 3 +- Classes/Parser/AbstractParser.php | 3 +- Classes/Updates/T3sbCardsUpdateWizard.php | 6 +- Classes/Updates/T3sbMigrateUpdateWizard.php | 34 +- Classes/UserFunction/TcaMatcher.php | 25 +- Classes/Utility/ResponsiveImagesUtility.php | 24 +- Classes/ViewHelpers/MediaViewHelper.php | 51 +- Classes/Wrapper/BackgroundWrapper.php | 9 +- Classes/Wrapper/CardWrapper.php | 63 +- Classes/Wrapper/CarouselContainer.php | 2 +- Classes/Wrapper/CollapsibleContainer.php | 2 +- Classes/Wrapper/SwiperContainer.php | 9 +- .../FlexForms/Container/BackgroundWrapper.xml | 14 + .../FlexForms/Container/CardWrapper.xml | 19 +- .../FlexForms/Container/ThreeColumns.xml | 23 +- Configuration/RTE/Default.yaml | 1 + Configuration/Services.yaml | 8 + Configuration/TCA/Overrides/pages.php | 19 +- Configuration/TCA/Overrides/tt_content.php | 148 +++- .../tx_t3sbootstrap_domain_model_config.php | 30 +- Configuration/TSConfig/Page.tsconfig | 5 +- .../ContentElement/Bootstrap.typoscript | 12 +- .../ContentElement/Container.typoscript | 2 +- .../ContentElement/Default.typoscript | 9 +- .../TypoScript/Lib/ContentElement.typoscript | 8 +- Configuration/TypoScript/Lib/_main.typoscript | 48 +- .../TypoScript/Page/BodyTag.typoscript | 15 +- .../TypoScript/Page/IncludeDefault.typoscript | 27 +- .../TypoScript/Page/IncludeLocal.typoscript | 3 - .../Page/JS/CookieConsent.typoscript | 5 +- .../TypoScript/Page/Print.typoscript | 31 +- .../TypoScript/Page/Register.typoscript | 2 +- .../TypoScript/Page/Template.typoscript | 19 +- .../TypoScript/Page/_main.typoscript | 12 +- Configuration/TypoScript/constants.typoscript | 12 +- Configuration/TypoScript/setup.typoscript | 4 +- .../Private/Backend/Layouts/Default.html | 2 +- .../Backend/Partials/Config/Accordion.html | 15 + .../Backend/Templates/Config/Dashboard.html | 1 + .../Backend/Templates/Config/List.html | 13 +- .../TSconfig/templateLayouts.tsconfig | 11 + .../Configuration/TypoScript/setup.typoscript | 14 +- .../Private/Partials/{ => T3SB}/CalDate.html | 0 .../Private/Partials/T3SB/Filters.html | 16 + .../Partials/{ => T3SB}/Filters/Checkbox.html | 8 +- .../Partials/{ => T3SB}/ResultRow.html | 8 +- .../Partials/{ => T3SB}/ResultRows.html | 6 +- .../Private/Partials/{ => T3SB}/Sorting.html | 0 .../Private/Templates/ResultList.html | 53 +- .../Private/Templates/SearchForm.html | 90 ++- .../Partials/Detail/T3sbMediaContainer.html | 7 + .../Private/Templates/Category/List.html | 12 +- .../Partials/Content/Card/FlipCard.html | 2 + .../Partials/Content/Media/Gallery.html | 34 +- .../Partials/Content/Media/RawGallery.html | 2 +- .../Content/Media/Rendering/Image.html | 92 ++- .../Content/Media/Rendering/Video.html | 29 +- .../Private/Partials/Content/Media/Type.html | 2 +- .../Partials/Content/Media/Type/Image.html | 14 +- .../Private/Partials/FunctionAssets.html | 127 +++- Resources/Private/Partials/Page/Assets.html | 88 ++- .../Private/Partials/Page/Jumbotron.html | 5 + .../Partials/Page/Navbar/DarkModeToggler.html | 31 + .../Partials/Page/Navbar/Language.html | 5 +- .../Partials/Page/Navbar/MenuRight.html | 50 ++ .../Private/Partials/Page/Navbar/Navbar.html | 71 +- .../Partials/Page/Navbar/Plusicon.html | 18 +- .../Private/Partials/Page/Searchbox.html | 17 +- Resources/Private/Partials/Page/Section.html | 6 +- .../Container/BackgroundWrapper.html | 14 +- .../Templates/Container/CardWrapper.html | 90 +-- .../Templates/Container/ParallaxWrapper.html | 6 +- .../Private/Templates/Content/Button.html | 2 +- .../Private/Templates/Content/Carousel.html | 13 +- .../Templates/Content/ImageGallery.html | 6 +- .../Templates/Content/MenuSection.html | 2 +- Resources/Private/Templates/Main.html | 11 +- Resources/Private/Templates/Print/Button.html | 2 +- Resources/Private/Templates/Print/Page.html | 19 +- Resources/Public/Backend/bestyles-v10.css | 307 -------- .../{bestyles-v11.css => bestyles.css} | 14 +- .../BootstrapIsons/bootstrap-icons.css | 25 + .../BootstrapIsons/brightness-high-fill.svg | 3 + .../Contrib/BootstrapIsons/circle-half.svg | 3 + .../BootstrapIsons/fonts/bootstrap-icons.woff | Bin 0 -> 164352 bytes .../fonts/bootstrap-icons.woff2 | Bin 0 -> 121296 bytes .../BootstrapIsons/moon-stars-fill.svg | 4 + Resources/Public/Styles/t3sbootstrap.css | 2 +- Resources/Public/Styles/t3sprint.css | 2 +- composer.json | 8 +- ext_conf_template.txt | 17 + ext_emconf.php | 13 +- ext_localconf.php | 24 +- ext_tables.sql | 7 +- 112 files changed, 2038 insertions(+), 2033 deletions(-) delete mode 100644 Classes/Controller/AbstractCompatibilityController.php create mode 100644 Classes/EventListener/TCA/TcaCompilation.php create mode 100644 Resources/Private/Extensions/ke_search/Configuration/TSconfig/templateLayouts.tsconfig rename Resources/Private/Extensions/ke_search/Resources/Private/Partials/{ => T3SB}/CalDate.html (100%) create mode 100644 Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters.html rename Resources/Private/Extensions/ke_search/Resources/Private/Partials/{ => T3SB}/Filters/Checkbox.html (68%) rename Resources/Private/Extensions/ke_search/Resources/Private/Partials/{ => T3SB}/ResultRow.html (87%) rename Resources/Private/Extensions/ke_search/Resources/Private/Partials/{ => T3SB}/ResultRows.html (74%) rename Resources/Private/Extensions/ke_search/Resources/Private/Partials/{ => T3SB}/Sorting.html (100%) create mode 100644 Resources/Private/Partials/Page/Navbar/DarkModeToggler.html create mode 100644 Resources/Private/Partials/Page/Navbar/MenuRight.html delete mode 100644 Resources/Public/Backend/bestyles-v10.css rename Resources/Public/Backend/{bestyles-v11.css => bestyles.css} (97%) create mode 100644 Resources/Public/Contrib/BootstrapIsons/bootstrap-icons.css create mode 100644 Resources/Public/Contrib/BootstrapIsons/brightness-high-fill.svg create mode 100644 Resources/Public/Contrib/BootstrapIsons/circle-half.svg create mode 100644 Resources/Public/Contrib/BootstrapIsons/fonts/bootstrap-icons.woff create mode 100644 Resources/Public/Contrib/BootstrapIsons/fonts/bootstrap-icons.woff2 create mode 100644 Resources/Public/Contrib/BootstrapIsons/moon-stars-fill.svg diff --git a/Classes/Backend/Preview/T3sbPreviewRenderer.php b/Classes/Backend/Preview/T3sbPreviewRenderer.php index e69dfab3..97151962 100644 --- a/Classes/Backend/Preview/T3sbPreviewRenderer.php +++ b/Classes/Backend/Preview/T3sbPreviewRenderer.php @@ -19,7 +19,6 @@ use TYPO3\CMS\Fluid\View\StandaloneView; use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; /* @@ -31,25 +30,25 @@ class T3sbPreviewRenderer extends StandardContentPreviewRenderer { - /** - * @var Registry - */ - protected $tcaRegistry; + /** + * @var Registry + */ + protected $tcaRegistry; - /** - * @var ContainerFactory - */ - protected $containerFactory; + /** + * @var ContainerFactory + */ + protected $containerFactory; - /** - * @var ContainerColumnConfigurationService - */ - protected $containerColumnConfigurationService; + /** + * @var ContainerColumnConfigurationService + */ + protected $containerColumnConfigurationService; - /** - * @var ContainerService - */ - protected $containerService; + /** + * @var ContainerService + */ + protected $containerService; public function __construct( @@ -117,17 +116,13 @@ public function renderPageModulePreviewHeader(GridColumnItem $item): string public function renderPageModulePreviewContent(GridColumnItem $item): string { - $typo3Version = new Typo3Version(); $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - if ($typo3Version->getMajorVersion() === 11) { - $pageRenderer->loadRequireJsModule( - 'TYPO3/CMS/T3sbootstrap/Bootstrap', - 'function() { console.log("Loaded bootstrap.js by t3sbootstrap!"); }' - ); - $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles-v11.css'); - } else { - $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles-v10.css'); - } + $pageRenderer->loadRequireJsModule( + 'TYPO3/CMS/T3sbootstrap/Bootstrap', + 'function() { console.log("Loaded bootstrap.js by t3sbootstrap!"); }' + ); + $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles.css'); + $content = parent::renderPageModulePreviewContent($item); $context = $item->getContext(); $record = $item->getRecord(); @@ -241,7 +236,9 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string if (!empty($flexconf['card_wrapper']) && $record['CType'] == 'card_wrapper') { $out .= '
- Wrapper: Card '.$flexconf['card_wrapper']; if ( !empty($flexconf['visibleCards']) ) { - $out .= '
- Visible Cards: '.$flexconf['visibleCards']; + if ($flexconf['card_wrapper'] !== 'flipper' && $flexconf['card_wrapper'] !== 'columns') { + $out .= '
- Visible Cards: '.$flexconf['visibleCards']; + } } if ( !empty($flexconf['interval']) ) { $out .= '
- Interval: '.$flexconf['interval']; @@ -355,11 +352,11 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string $rowObject = GeneralUtility::makeInstance(GridRow::class, $context); foreach ($cols as $col) { $newContentElementAtTopTarget = $this->containerService->getNewContentElementAtTopTargetInColumn($container, $col['colPos']); - if ($this->containerColumnConfigurationService->isMaxitemsReached($container, $col['colPos'])) { - $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $newContentElementAtTopTarget, false); - } else { - $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $newContentElementAtTopTarget); - } + if ($this->containerColumnConfigurationService->isMaxitemsReached($container, $col['colPos'])) { + $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $newContentElementAtTopTarget, false); + } else { + $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $newContentElementAtTopTarget); + } $rowObject->addColumn($columnObject); if (!empty($col['colPos'])) { $records = $container->getChildrenByColPos($col['colPos']); @@ -383,7 +380,7 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string $view->assign('newContentTitleShort', parent::getLanguageService()->getLL('content')); $view->assign('allowEditContent', parent::getBackendUser()->check('tables_modify', 'tt_content')); $view->assign('containerGrid', $grid); - $view->assign('defaultRecordDirectory', $this->hasDefaultDirectory() ? 'RecordDefault' : 'Record'); + $view->assign('defaultRecordDirectory', 'Record'); $rendered = $view->render(); @@ -394,15 +391,13 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string } $extconf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('t3sbootstrap'); - $typo3Version = new Typo3Version(); - $show = $typo3Version->getMajorVersion() == 10 ? 'in' : 'show'; if ($extconf['previewClosedCollapsible']) { $newContent = '

'.$rendered.'
'; } else { $newContent = '

-
'.$rendered.'
'; +
'.$rendered.'
'; } return $flexconfOut.$newContent; @@ -422,25 +417,4 @@ public function wrapPageModulePreview(string $previewHeader, string $previewCont return $content; } - - /** - * Check TYPO3 version to see whether the default record templates - * are located in RecordDefault/ instead of Record/. - * See: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69769 - */ - protected function hasDefaultDirectory(): bool - { - $typo3Version = new Typo3Version(); - - if ($typo3Version->getMajorVersion() === 10) { - return version_compare((new Typo3Version())->getVersion(), '10.4.17', '>'); - } - - if ($typo3Version->getMajorVersion() === 11) { - return version_compare((new Typo3Version())->getVersion(), '11.3.0', '>'); - } - - return false; - } - } diff --git a/Classes/Command/CdnToLocal.php b/Classes/Command/CdnToLocal.php index 1d8c72db..3c0634a7 100644 --- a/Classes/Command/CdnToLocal.php +++ b/Classes/Command/CdnToLocal.php @@ -3,6 +3,7 @@ namespace T3SBS\T3sbootstrap\Command; +use TYPO3\CMS\Core\Http\RequestFactory; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -320,7 +321,7 @@ private function getGoogleFonts($googleFonts, $preloadGooleFonts, $gooleFontsWei foreach ( explode(',', $gooleFontsWeights) as $style ) { $style = trim($style); $zipFilename = strtolower($font).'?download=zip&subsets=latin&variants='.$style; - $zipContent = GeneralUtility::getURL(self::zipFilePath . $zipFilename); + $zipContent = GeneralUtility::makeInstance(RequestFactory::class)->request(self::zipFilePath . $zipFilename)->getBody()->getContents(); $fontArr[$fontFamily] = self::getGoogleFiles($zipContent, $localZipFile, $localZipPath); } } diff --git a/Classes/Command/CustomScss.php b/Classes/Command/CustomScss.php index 5d297128..8ebc5568 100644 --- a/Classes/Command/CustomScss.php +++ b/Classes/Command/CustomScss.php @@ -3,6 +3,7 @@ namespace T3SBS\T3sbootstrap\Command; +use TYPO3\CMS\Core\Http\RequestFactory; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -90,7 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $queryBuilder->expr()->eq('sys_language_uid', 0), $queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $siteroots = $result->fetchAll(); foreach ($siteroots as $key=>$siteroot) { @@ -246,7 +247,7 @@ public function getBootstrapFiles($bootstrapVersion): void mkdir($localZipPath, 0777, true); $localZipFile = GeneralUtility::getFileAbsFileName(self::localZipPath.self::localZipFile); $zipFilename = 'v'.$bootstrapVersion.'.zip'; - $zipContent = GeneralUtility::getURL(self::zipFilePath . $zipFilename); + $zipContent = GeneralUtility::makeInstance(RequestFactory::class)->request(self::zipFilePath . $zipFilename)->getBody()->getContents(); if ($zipContent) { GeneralUtility::writeFile($localZipFile, $zipContent); $extractTo = $localZipPath; diff --git a/Classes/Components/Card.php b/Classes/Components/Card.php index a61f1476..fbb60e45 100644 --- a/Classes/Components/Card.php +++ b/Classes/Components/Card.php @@ -3,6 +3,7 @@ namespace T3SBS\T3sbootstrap\Components; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Service\FlexFormService; @@ -97,7 +98,8 @@ public function getProcessedData(array $processedData, array $flexconf, array $p } } // block - if ( empty($processedData['data']['bodytext']) && empty($processedData['data']['tx_t3sbootstrap_bodytext']) && empty($processedData['data']['header']) && empty($processedData['data']['subheader']) ) { + if ( empty($processedData['data']['bodytext']) && empty($processedData['data']['tx_t3sbootstrap_bodytext']) + && empty($processedData['data']['header']) && empty($processedData['data']['subheader']) ) { $cardData['block']['enable'] = FALSE; } else { $cardData['block']['enable'] = TRUE; @@ -127,8 +129,7 @@ public function getProcessedData(array $processedData, array $flexconf, array $p // list group $cardData['list'] = []; if (!empty($processedData['data']['tx_t3sbootstrap_list_item'])) { - - $connectionPool = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class); + $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_t3sbootstrap_list_item_inline'); $listGroup = $queryBuilder ->select('listitem') @@ -136,10 +137,10 @@ public function getProcessedData(array $processedData, array $flexconf, array $p ->where( $queryBuilder->expr()->eq('parentid', $queryBuilder->createNamedParameter($processedData['data']['uid'], \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchAll(); - - $cardData['list'] = $listGroup; + + $cardData['list'] = $listGroup; } // profile card @@ -179,7 +180,7 @@ public function getProcessedData(array $processedData, array $flexconf, array $p $cardClass .= ' border-'.$cardData['cardborderstyle']; } // parent equal Height - if ( !empty($parentflexconf['equalHeight']) ) { + if ( !empty($parentflexconf['equalHeight']) && isset($parentflexconf['card_wrapper']) && $parentflexconf['card_wrapper'] !== 'group' ) { $cardClass .= ' h-100'; } diff --git a/Classes/Components/Carousel.php b/Classes/Components/Carousel.php index fc3da1ed..ed9f7c4d 100644 --- a/Classes/Components/Carousel.php +++ b/Classes/Components/Carousel.php @@ -100,12 +100,25 @@ public function getProcessedData(array $processedData, array $flexconf, array $p $processedData['controls'] = $flexconf['controls']; } } + + $processedData['ratioCalc'] = ''; + if ($parentflexconf['ratio']) { $ratioArr = explode(':', $parentflexconf['ratio']); - $processedData['ratioCalc'] = $ratioArr[1] / $ratioArr[0]; + $x = str_replace(':', 'x', $parentflexconf['ratio']); + $y = $ratioArr[1].' / '.$ratioArr[0].' * 100%'; + $processedData['ratioCalc'] .= '.ratio-'.$x.'{--bs-aspect-ratio:calc('.$y.');}'; + $processedData['videoRatio'] = str_replace(':', 'x', $parentflexconf['ratio']); + $processedData['videoStyle'] = ''; + if ( $parentflexconf['ratio'] !== '16:9') { + $processedData['videoStyle'] .= 'object-fit: cover;'; + } } else { $processedData['ratioCalc'] = 1; + $processedData['videRatio'] = ''; + $processedData['videoStyle'] = ''; } + if ( empty($processedData['files']) && !$processedData['localVideoPath'] ) { $ratio = $parentflexconf['ratio'] ? $parentflexconf['ratio'] : '16:9'; $noImgHeight = explode(':', (string) $ratio); @@ -124,12 +137,18 @@ public function getProcessedData(array $processedData, array $flexconf, array $p } $processedData['shift'] = ''; $processedData['videoShift'] = ''; + if (!empty($flexconf['shift'])){ + $processedData['videoStyle'] .= 'transform: translateY('.(int)$flexconf['shift'].'%);'; + $negShift = (int)$flexconf['shift'] * -1; + $processedData['videoStyle'] .= 'top: '.$negShift.'% !important;'; $processedData['shift'] = (int)$flexconf['shift'] / 100; $breakWidth = '576'; - $processedData['videoShift'] = '@media(min-width: '.$breakWidth.'px){.carousel-item-'.$processedData['data']['uid'].' figure{margin-top:'.(int)$flexconf['shift'].'% !important}}'; - } + + $videoStyle = $processedData['videoStyle']; + $processedData['videoStyle'] = ' style="'.$videoStyle.'"'; + if ( !empty($parentflexconf['swiperJs']) ) { $processedData['swiper'] = TRUE; } diff --git a/Classes/Controller/AbstractCompatibilityController.php b/Classes/Controller/AbstractCompatibilityController.php deleted file mode 100644 index c88580f1..00000000 --- a/Classes/Controller/AbstractCompatibilityController.php +++ /dev/null @@ -1,533 +0,0 @@ -getMajorVersion() > 10) { - - // TYPO3 v11 - abstract class AbstractCompatibilityController extends AbstractController - { - protected ModuleTemplateFactory $moduleTemplateFactory; - - public function __construct( - ConfigRepository $configRepository, - PersistenceManager $persistenceManager, - ModuleTemplateFactory $moduleTemplateFactory - ) - { - $this->configRepository = $configRepository ?? GeneralUtility::makeInstance(ConfigRepository::class); - $this->persistenceManager = $persistenceManager ?? GeneralUtility::makeInstance(PersistenceManager::class); - $this->moduleTemplateFactory = $moduleTemplateFactory; - } - - /** - * Init all actions. - */ - public function initializeAction() - { - parent::initializeAction(); - } - - /** - * action list - */ - public function listAction(bool $deleted = FALSE, bool $created = FALSE, bool $updateSss = FALSE): ResponseInterface - { - if ( $this->isSiteroot && $this->rootPageId ) { - $pidList = $this->getTreeList($this->rootPageId, 999999, 0, '1'); - $allConfig = []; - foreach ( $this->configRepository->findAll() as $config ) { - if (GeneralUtility::inList($pidList, $config->getPid())) { - $page = BackendUtility::getRecord('pages',$config->getPid(),'uid,title'); - $allConfig[$page['uid']]['confUid'] = $config->getUid(); - $allConfig[$page['uid']]['title'] = $page['title']; - $allConfig[$page['uid']]['uid'] = $page['uid']; - $assignedOptions['compress'] = $config->getCompress(); - } - } - - $assignedOptions['isSiteroot'] = TRUE; - $assignedOptions['allConfig'] = $allConfig; - } - - $assignedOptions['rootTemplate'] = TRUE; - if (count($this->rootTemplates) === 0) { - $assignedOptions['rootTemplate'] = FALSE; - } - $assignedOptions['t3version'] = $this->version; - $assignedOptions['rootConfig'] = $this->rootConfig ? TRUE : FALSE; - $assignedOptions['config'] = $this->configRepository->findOneByPid($this->currentUid); - $assignedOptions['admin'] = $this->isAdmin; - $assignedOptions['customScss'] = FALSE; - $assignedOptions['scss'] = ''; - $assignedOptions['action'] = 'list'; - $assignedOptions['updateScss'] = $updateSss; - $assignedOptions['deleted'] = $deleted; - $assignedOptions['created'] = $created; - - if ( !empty($this->settings['customScss']) && (int)$this->settings['customScss'] === 1 ) { - $customScss = parent::getCustomScss('custom-variables'); - $assignedOptions['custom-variables'] = !empty($customScss['custom-variables']) ? $customScss['custom-variables'] : ''; - $customScss = parent::getCustomScss('custom'); - $assignedOptions['custom'] = !empty($customScss['custom']) ? $customScss['custom'] : ''; - $assignedOptions['customScss'] = !empty($customScss['customScss']) ? $customScss['customScss'] : ''; - if ( !empty($this->settings['enableUtilityColors']) ) { - $assignedOptions['utilColors'] = parent::getUtilityColors(); - } - } - - if ( !empty($this->settings['pages']['override']) ) { - foreach ($this->settings['pages']['override'] as $field=>$override) { - if (!empty($override)) { - $assignedOptions['pagesOverride'][$field] = $override; - } - } - } - - $this->view->assignMultiple($assignedOptions); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action new - * - * @return void - */ - public function newAction(): ResponseInterface - { - $assignedOptions = parent::getFieldsOptions(); - $assignedOptions['pid'] = $this->currentUid; - $assignedOptions['tcaColumns'] = parent::getTcaColumns(); - $assignedOptions['t3version'] = $this->version; - - if ( $this->rootConfig ) { - // config from rootline - if ( $this->rootConfig->getGeneralRootline() ) { - $rootLineArray = GeneralUtility::makeInstance(RootlineUtility::class, $this->currentUid)->get(); - // unset current page - if (count($rootLineArray) > 1) - unset($rootLineArray[count($rootLineArray)-1]); - foreach ($rootLineArray as $rootline) { - $rootlineConfig = $this->configRepository->findOneByPid((int)$rootline['uid']); - if ( !empty($rootlineConfig) ) break; - } - $assignedOptions['newConfig'] = parent::getNewConfig($rootlineConfig); - // config from rootpage - } else { - $assignedOptions['newConfig'] = parent::getNewConfig($this->rootConfig); - } - - } else { - $newConfig = new Config(); - // some defaults - $newConfig = parent::setDefaults($newConfig); - - #$assignedOptions['pid'] = $this->getCurrentUid; - $assignedOptions['newConfig'] = $newConfig; - } - - $this->view->assignMultiple($assignedOptions); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action create - */ - public function createAction(Config $newConfig): ResponseInterface - { - $newConfig->setHomepageUid($this->rootPageId); - $newConfig->setPid($this->currentUid); - $this->configRepository->add($newConfig); - parent::writeConstants(); - parent::redirect('list',NULL,Null,array('created' => TRUE)); - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action edit - */ - public function editAction(Config $config, bool $updated = FALSE): ResponseInterface - { - $assignedOptions = parent::getFieldsOptions(); - $assignedOptions['t3version'] = $this->version; - $assignedOptions['config'] = $config; - $assignedOptions['pid'] = $this->currentUid; - $assignedOptions['admin'] = $this->isAdmin; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['updated'] = $updated; - $assignedOptions['override'] = parent::overrideConfig(); - $assignedOptions['tcaColumns'] = parent::getTcaColumns(); - $assignedOptions['action'] = 'edit'; - if ( !$this->isSiteroot ) { - $assignedOptions['compare'] = parent::compareConfig($config); - } - - $this->view->assignMultiple($assignedOptions); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action update - */ - public function updateAction(Config $config): ResponseInterface - { - $config->setHomepageUid($this->rootPageId); - $this->configRepository->update($config); - parent::writeConstants(); - - parent::redirect('edit',NULL,Null,array('config' => $config, 'updated' => TRUE)); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action delete - */ - public function deleteAction(Config $config): ResponseInterface - { - $this->configRepository->remove($config); - parent::writeConstants(); - - parent::redirect('list',NULL,Null,array('deleted' => TRUE)); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action dashboard - */ - public function dashboardAction(): ResponseInterface - { - if ( $this->isSiteroot ) { - $assignedOptions['extconf'] = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('t3sbootstrap'); - } - - $assignedOptions['t3version'] = $this->version; - $assignedOptions['action'] = 'dashboard'; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['admin'] = $this->isAdmin; - - $this->view->assignMultiple($assignedOptions); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - - /** - * action constants - */ - public function constantsAction(): ResponseInterface - { - if ( $this->isSiteroot ) { - $constantPath = GeneralUtility::getFileAbsFileName('fileadmin/T3SB/Configuration/TypoScript/t3sbconstants.typoscript'); - if ( file_exists($constantPath) ) { - $fileGetContents = file_get_contents($constantPath); - $outsourcedConstantsArr = explode('[END]', trim($fileGetContents)); - $toEnd = count($outsourcedConstantsArr); - $filecontent = ''; - foreach ($outsourcedConstantsArr as $outsourcedConstants) { - if (0 === --$toEnd) { - $filecontent .= trim($outsourcedConstants).PHP_EOL.PHP_EOL; - } else { - $filecontent .= trim($outsourcedConstants).PHP_EOL . '[END]'.PHP_EOL.PHP_EOL; - } - } - $assignedOptions['filecontent'] = $filecontent; - } - } - - $assignedOptions['t3version'] = $this->version; - $assignedOptions['action'] = 'constants'; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['admin'] = $this->isAdmin; - - $this->view->assignMultiple($assignedOptions); - - $moduleTemplate = $this->moduleTemplateFactory->create($this->request); - // Adding title, menus, buttons, etc. using $moduleTemplate ... - $moduleTemplate->setContent($this->view->render()); - return $this->htmlResponse($moduleTemplate->renderContent()); - } - - } -} else { - - // TYPO3 v10 - abstract class AbstractCompatibilityController extends AbstractController - { - - protected $defaultViewObjectName = \TYPO3\CMS\Backend\View\BackendTemplateView::class; - - public function __construct( - ConfigRepository $configRepository, - PersistenceManager $persistenceManager - ) - { - $this->configRepository = $configRepository ?? GeneralUtility::makeInstance(ConfigRepository::class); - $this->persistenceManager = $persistenceManager ?? GeneralUtility::makeInstance(PersistenceManager::class); - } - - - /** - * action list - */ - public function listAction(bool $deleted = FALSE, bool $created = FALSE, bool $updateSss = FALSE): void - { - if ( $this->isSiteroot && $this->rootPageId ) { - $pidList = $this->getTreeList($this->rootPageId, 999999, 0, '1'); - $allConfig = []; - foreach ( $this->configRepository->findAll() as $config ) { - if (GeneralUtility::inList($pidList, $config->getPid())) { - $page = BackendUtility::getRecord('pages',$config->getPid(),'uid,title'); - $allConfig[$page['uid']]['confUid'] = $config->getUid(); - $allConfig[$page['uid']]['title'] = $page['title']; - $allConfig[$page['uid']]['uid'] = $page['uid']; - $assignedOptions['compress'] = $config->getCompress(); - } - } - $assignedOptions['isSiteroot'] = TRUE; - $assignedOptions['allConfig'] = $allConfig; - } - - $assignedOptions['rootTemplate'] = TRUE; - if (count($this->rootTemplates) === 0) { - $assignedOptions['rootTemplate'] = FALSE; - } - $assignedOptions['t3version'] = $this->version; - $assignedOptions['rootConfig'] = $this->rootConfig ? TRUE : FALSE; - $assignedOptions['config'] = $this->configRepository->findOneByPid($this->currentUid); - $assignedOptions['admin'] = $this->isAdmin; - $assignedOptions['customScss'] = FALSE; - $assignedOptions['scss'] = ''; - $assignedOptions['action'] = 'list'; - $assignedOptions['updateScss'] = $updateSss; - $assignedOptions['deleted'] = $deleted; - $assignedOptions['created'] = $created; - - if ( (int)$this->settings['customScss'] === 1 ) { - $customScss = parent::getCustomScss('custom-variables'); - $assignedOptions['custom-variables'] = !empty($customScss['custom-variables']) ? $customScss['custom-variables'] : ''; - $customScss = parent::getCustomScss('custom'); - $assignedOptions['custom'] = !empty($customScss['custom']) ? $customScss['custom'] : ''; - $assignedOptions['customScss'] = !empty($customScss['customScss']) ? $customScss['customScss'] : ''; - if ( !empty($this->settings['enableUtilityColors']) ) { - $assignedOptions['utilColors'] = parent::getUtilityColors(); - } - } - - - if ( !empty($this->settings['pages']['override']) ) { - foreach ($this->settings['pages']['override'] as $field=>$override) { - if (!empty($override)) { - $assignedOptions['pagesOverride'][$field] = $override; - } - } - } - - $this->view->assignMultiple($assignedOptions); - } - - - /** - * action new - * - * @return void - */ - public function newAction(): void - { - $assignedOptions = parent::getFieldsOptions(); - $assignedOptions['pid'] = $this->currentUid; - $assignedOptions['tcaColumns'] = parent::getTcaColumns(); - $assignedOptions['t3version'] = $this->version; - - if ( $this->rootConfig ) { - // config from rootline - if ( $this->rootConfig->getGeneralRootline() ) { - $rootLineArray = GeneralUtility::makeInstance(RootlineUtility::class, $this->currentUid)->get(); - // unset current page - if (count($rootLineArray) > 1) - unset($rootLineArray[count($rootLineArray)-1]); - foreach ($rootLineArray as $rootline) { - $rootlineConfig = $this->configRepository->findOneByPid((int)$rootline['uid']); - if ( !empty($rootlineConfig) ) break; - } - $assignedOptions['newConfig'] = parent::getNewConfig($rootlineConfig); - // config from rootpage - } else { - $assignedOptions['newConfig'] = parent::getNewConfig($this->rootConfig); - } - - } else { - $newConfig = new Config(); - // some defaults - $newConfig = parent::setDefaults($newConfig); - - #$assignedOptions['pid'] = $this->getCurrentUid; - $assignedOptions['newConfig'] = $newConfig; - } - - $this->view->assignMultiple($assignedOptions); - } - - - /** - * action create - */ - public function createAction(Config $newConfig): void - { - $newConfig->setHomepageUid($this->rootPageId); - $newConfig->setPid($this->currentUid); - $this->configRepository->add($newConfig); - parent::writeConstants(); - - parent::redirect('list',NULL,Null,array('created' => TRUE)); - } - - - /** - * action edit - */ - public function editAction(Config $config, bool $updated = FALSE): void - { - $assignedOptions = parent::getFieldsOptions(); - $assignedOptions['t3version'] = $this->version; - $assignedOptions['config'] = $config; - $assignedOptions['pid'] = $this->currentUid; - $assignedOptions['admin'] = $this->isAdmin; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['updated'] = $updated; - $assignedOptions['override'] = parent::overrideConfig(); - $assignedOptions['tcaColumns'] = parent::getTcaColumns(); - $assignedOptions['action'] = 'edit'; - if ( !$this->isSiteroot ) { - $assignedOptions['compare'] = parent::compareConfig($config); - } - - $this->view->assignMultiple($assignedOptions); - } - - - /** - * action update - */ - public function updateAction(Config $config): void - { - $config->setHomepageUid($this->rootPageId); - $this->configRepository->update($config); - parent::writeConstants(); - - parent::redirect('edit',NULL,Null,array('config' => $config, 'updated' => TRUE)); - } - - - /** - * action delete - */ - public function deleteAction(Config $config): void - { - $this->configRepository->remove($config); - parent::writeConstants(); - - parent::redirect('list',NULL,Null,array('deleted' => TRUE)); - } - - - /** - * action dashboard - */ - public function dashboardAction(): void - { - if ( $this->isSiteroot ) { - $assignedOptions['extconf'] = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('t3sbootstrap'); - } - - $assignedOptions['t3version'] = $this->version; - $assignedOptions['action'] = 'dashboard'; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['admin'] = $this->isAdmin; - - $this->view->assignMultiple($assignedOptions); - } - - - /** - * action constants - */ - public function constantsAction(): void - { - if ( $this->isSiteroot ) { - $constantPath = GeneralUtility::getFileAbsFileName('fileadmin/T3SB/Configuration/TypoScript/t3sbconstants.typoscript'); - if ( file_exists($constantPath) ) { - $fileGetContents = file_get_contents($constantPath); - $outsourcedConstantsArr = explode('[END]', trim($fileGetContents)); - $toEnd = count($outsourcedConstantsArr); - $filecontent = ''; - foreach ($outsourcedConstantsArr as $outsourcedConstants) { - if (0 === --$toEnd) { - $filecontent .= trim($outsourcedConstants).PHP_EOL.PHP_EOL; - } else { - $filecontent .= trim($outsourcedConstants).PHP_EOL . '[END]'.PHP_EOL.PHP_EOL; - } - } - $assignedOptions['filecontent'] = $filecontent; - } - } - - $assignedOptions['t3version'] = $this->version; - $assignedOptions['action'] = 'constants'; - $assignedOptions['isSiteroot'] = $this->isSiteroot; - $assignedOptions['admin'] = $this->isAdmin; - - $this->view->assignMultiple($assignedOptions); - } - } - -} diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index 9a2c666b..e177e0eb 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -11,7 +11,6 @@ use TYPO3\CMS\Core\Routing\SiteMatcher; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\Database\Query\QueryHelper; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; @@ -19,12 +18,14 @@ use T3SBS\T3sbootstrap\Domain\Repository\ConfigRepository; use T3SBS\T3sbootstrap\Domain\Model\Config; -/** - * Abstract controller. +/* + * This file is part of the TYPO3 extension t3sbootstrap. + * + * For the full copyright and license information, please read the + * LICENSE file that was distributed with this source code. */ abstract class AbstractController extends ActionController { - protected $configRepository; protected $isSiteroot; protected $rootPageId; @@ -32,12 +33,11 @@ abstract class AbstractController extends ActionController protected $tcaColumns; protected $isAdmin; protected $rootConfig; - protected $version; protected $rootTemplates; protected $persistenceManager; /** - * Init all actions. + * init all actions */ public function initializeAction() { @@ -48,8 +48,7 @@ public function initializeAction() $this->tcaColumns = $GLOBALS['TCA']['tx_t3sbootstrap_domain_model_config']['columns']; $this->isAdmin = $GLOBALS['BE_USER']->isAdmin(); $this->rootConfig = $this->configRepository->findOneByPid($this->rootPageId); - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - $this->version = (int)$typo3Version->getVersion(); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_template'); $this->rootTemplates = $queryBuilder ->select('uid','pid', 'constants') @@ -57,14 +56,10 @@ public function initializeAction() ->where( $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) ) - ->execute()->fetchAll(); + ->executeQuery()->fetchAll(); $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - if ($typo3Version->getMajorVersion() === 11) { - $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles-v11.css'); - } else { - $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles-v10.css'); - } + $pageRenderer->addCssFile('EXT:t3sbootstrap/Resources/Public/Backend/bestyles.css'); $pageRenderer->loadRequireJsModule( 'TYPO3/CMS/T3sbootstrap/Bootstrap', 'function() { console.log("Loaded bootstrap.js by t3sbootstrap!"); }' @@ -88,7 +83,7 @@ protected function getCustomScss( string $file ): array $queryBuilder->expr()->eq('sys_language_uid', 0), $queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $siteroots = $result->fetchAll(); $customScssFileName = ''; @@ -184,7 +179,7 @@ protected function getNewConfig(Config $rootConfig): Config /** - * Compare config with rootconfig + * compare config with rootconfig */ protected function compareConfig(Config $config): array { @@ -275,7 +270,6 @@ protected function writeConstants(): void $breakpointWidth = $navbarBreakpoint == 'no' ? '' : $this->settings['breakpoint'][$navbarBreakpoint]; $siteroots = []; $filecontent = ''; - foreach( $this->configRepository->findAll() as $config ) { $page = GeneralUtility::makeInstance(PageRepository::class)->getPage($config->getPid()); if ( $page['hidden'] === 0 && $page['deleted'] === 0 ) { @@ -548,9 +542,10 @@ protected function setDefaults(Config $newConfig): Config $newConfig->setSubheaderColor( 'secondary' ); $newConfig->setFaLinkIcons(1); $newConfig->setSectionmenuAnchorOffset(29); - $newConfig->setSectionmenuScrollspyOffset(130); $newConfig->setSectionmenuScrollspy(1); $newConfig->setNavbarLangFlags(1); + $newConfig->setSectionmenuScrollspyThreshold('0.1, 0.5, 1'); + $newConfig->setSectionmenuScrollspyRootMargin('0px 0px -75%'); return $newConfig; } @@ -589,7 +584,7 @@ protected function getTreeList($id, $depth, $begin = 0, $permsClause = ''): stri $queryBuilder->expr()->eq('sys_language_uid', 0), QueryHelper::stripLogicalOperatorPrefix($permsClause) ) - ->execute(); + ->executeQuery(); while ($row = $statement->fetch()) { if ($begin <= 0) { $theList .= ',' . $row['uid']; diff --git a/Classes/Controller/ConfigController.php b/Classes/Controller/ConfigController.php index 4d78ebb1..385ed480 100644 --- a/Classes/Controller/ConfigController.php +++ b/Classes/Controller/ConfigController.php @@ -3,17 +3,287 @@ namespace T3SBS\T3sbootstrap\Controller; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\RootlineUtility; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use T3SBS\T3sbootstrap\Domain\Repository\ConfigRepository; +use T3SBS\T3sbootstrap\Domain\Model\Config; +use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; +use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; +use Psr\Http\Message\ResponseInterface; + /* * This file is part of the TYPO3 extension t3sbootstrap. * * For the full copyright and license information, please read the * LICENSE file that was distributed with this source code. */ -class ConfigController extends AbstractCompatibilityController +class ConfigController extends AbstractController { - public function initializeAction() + protected ModuleTemplateFactory $moduleTemplateFactory; + + public function __construct( + ConfigRepository $configRepository, + PersistenceManager $persistenceManager, + ModuleTemplateFactory $moduleTemplateFactory + ) + { + $this->configRepository = $configRepository ?? GeneralUtility::makeInstance(ConfigRepository::class); + $this->persistenceManager = $persistenceManager ?? GeneralUtility::makeInstance(PersistenceManager::class); + $this->moduleTemplateFactory = $moduleTemplateFactory; + } + + /** + * Init all actions. + */ + public function initializeAction() + { + parent::initializeAction(); + } + + /** + * action list + */ + public function listAction(bool $deleted = FALSE, bool $created = FALSE, bool $updateSss = FALSE): ResponseInterface + { + if ( $this->isSiteroot && $this->rootPageId ) { + $pidList = $this->getTreeList($this->rootPageId, 999999, 0, '1'); + $allConfig = []; + foreach ( $this->configRepository->findAll() as $config ) { + if (GeneralUtility::inList($pidList, $config->getPid())) { + $page = BackendUtility::getRecord('pages',$config->getPid(),'uid,title'); + $allConfig[$page['uid']]['confUid'] = $config->getUid(); + $allConfig[$page['uid']]['title'] = $page['title']; + $allConfig[$page['uid']]['uid'] = $page['uid']; + $assignedOptions['compress'] = $config->getCompress(); + } + } + + $assignedOptions['isSiteroot'] = TRUE; + $assignedOptions['allConfig'] = $allConfig; + } + + $assignedOptions['rootTemplate'] = TRUE; + if (count($this->rootTemplates) === 0) { + $assignedOptions['rootTemplate'] = FALSE; + } + $assignedOptions['rootConfig'] = $this->rootConfig ? TRUE : FALSE; + $assignedOptions['config'] = $this->configRepository->findOneByPid($this->currentUid); + $assignedOptions['admin'] = $this->isAdmin; + $assignedOptions['customScss'] = FALSE; + $assignedOptions['scss'] = ''; + $assignedOptions['action'] = 'list'; + $assignedOptions['updateScss'] = $updateSss; + $assignedOptions['deleted'] = $deleted; + $assignedOptions['created'] = $created; + + if ( !empty($this->settings['customScss']) && (int)$this->settings['customScss'] === 1 ) { + $customScss = parent::getCustomScss('custom-variables'); + $assignedOptions['custom-variables'] = !empty($customScss['custom-variables']) ? $customScss['custom-variables'] : ''; + $customScss = parent::getCustomScss('custom'); + $assignedOptions['custom'] = !empty($customScss['custom']) ? $customScss['custom'] : ''; + $assignedOptions['customScss'] = !empty($customScss['customScss']) ? $customScss['customScss'] : ''; + if ( !empty($this->settings['enableUtilityColors']) ) { + $assignedOptions['utilColors'] = parent::getUtilityColors(); + } + } + + if ( !empty($this->settings['pages']['override']) ) { + foreach ($this->settings['pages']['override'] as $field=>$override) { + if (!empty($override)) { + $assignedOptions['pagesOverride'][$field] = $override; + } + } + } + + $assignedOptions['webpIsLoaded'] = false; + if ( \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('webp') ) { + $assignedOptions['webpIsLoaded'] = true; + } + + $this->view->assignMultiple($assignedOptions); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action new + * + * @return void + */ + public function newAction(): ResponseInterface { - parent::initializeAction(); + $assignedOptions = parent::getFieldsOptions(); + $assignedOptions['pid'] = $this->currentUid; + $assignedOptions['tcaColumns'] = parent::getTcaColumns(); + + if ( $this->rootConfig ) { + // config from rootline + if ( $this->rootConfig->getGeneralRootline() ) { + $rootLineArray = GeneralUtility::makeInstance(RootlineUtility::class, $this->currentUid)->get(); + // unset current page + if (count($rootLineArray) > 1) + unset($rootLineArray[count($rootLineArray)-1]); + foreach ($rootLineArray as $rootline) { + $rootlineConfig = $this->configRepository->findOneByPid((int)$rootline['uid']); + if ( !empty($rootlineConfig) ) break; + } + $assignedOptions['newConfig'] = parent::getNewConfig($rootlineConfig); + // config from rootpage + } else { + $assignedOptions['newConfig'] = parent::getNewConfig($this->rootConfig); + } + + } else { + $newConfig = new Config(); + // some defaults + $newConfig = parent::setDefaults($newConfig); + + #$assignedOptions['pid'] = $this->getCurrentUid; + $assignedOptions['newConfig'] = $newConfig; + } + + $this->view->assignMultiple($assignedOptions); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); } + + + /** + * action create + */ + public function createAction(Config $newConfig): ResponseInterface + { + $newConfig->setHomepageUid($this->rootPageId); + $newConfig->setPid($this->currentUid); + $this->configRepository->add($newConfig); + parent::writeConstants(); + parent::redirect('list',NULL,Null,array('created' => TRUE)); + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action edit + */ + public function editAction(Config $config, bool $updated = FALSE): ResponseInterface + { + $assignedOptions = parent::getFieldsOptions(); + $assignedOptions['config'] = $config; + $assignedOptions['pid'] = $this->currentUid; + $assignedOptions['admin'] = $this->isAdmin; + $assignedOptions['isSiteroot'] = $this->isSiteroot; + $assignedOptions['updated'] = $updated; + $assignedOptions['override'] = parent::overrideConfig(); + $assignedOptions['tcaColumns'] = parent::getTcaColumns(); + $assignedOptions['action'] = 'edit'; + if ( !$this->isSiteroot ) { + $assignedOptions['compare'] = parent::compareConfig($config); + } + + $this->view->assignMultiple($assignedOptions); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action update + */ + public function updateAction(Config $config): ResponseInterface + { + $config->setHomepageUid($this->rootPageId); + $this->configRepository->update($config); + parent::writeConstants(); + + parent::redirect('edit',NULL,Null,array('config' => $config, 'updated' => TRUE)); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action delete + */ + public function deleteAction(Config $config): ResponseInterface + { + $this->configRepository->remove($config); + parent::writeConstants(); + + parent::redirect('list',NULL,Null,array('deleted' => TRUE)); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action dashboard + */ + public function dashboardAction(): ResponseInterface + { + if ( $this->isSiteroot ) { + $assignedOptions['extconf'] = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('t3sbootstrap'); + } + + $assignedOptions['action'] = 'dashboard'; + $assignedOptions['isSiteroot'] = $this->isSiteroot; + $assignedOptions['admin'] = $this->isAdmin; + + $this->view->assignMultiple($assignedOptions); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + + + /** + * action constants + */ + public function constantsAction(): ResponseInterface + { + if ( $this->isSiteroot ) { + $constantPath = GeneralUtility::getFileAbsFileName('fileadmin/T3SB/Configuration/TypoScript/t3sbconstants.typoscript'); + if ( file_exists($constantPath) ) { + $fileGetContents = file_get_contents($constantPath); + $outsourcedConstantsArr = explode('[END]', trim($fileGetContents)); + $toEnd = count($outsourcedConstantsArr); + $filecontent = ''; + foreach ($outsourcedConstantsArr as $outsourcedConstants) { + if (0 === --$toEnd) { + $filecontent .= trim($outsourcedConstants).PHP_EOL.PHP_EOL; + } else { + $filecontent .= trim($outsourcedConstants).PHP_EOL . '[END]'.PHP_EOL.PHP_EOL; + } + } + $assignedOptions['filecontent'] = $filecontent; + } + } + + $assignedOptions['action'] = 'constants'; + $assignedOptions['isSiteroot'] = $this->isSiteroot; + $assignedOptions['admin'] = $this->isAdmin; + + $this->view->assignMultiple($assignedOptions); + + $moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($moduleTemplate->renderContent()); + } + } diff --git a/Classes/Controller/ConsentController.php b/Classes/Controller/ConsentController.php index 2689f456..0bc7a9be 100644 --- a/Classes/Controller/ConsentController.php +++ b/Classes/Controller/ConsentController.php @@ -3,6 +3,7 @@ namespace T3SBS\T3sbootstrap\Controller; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Resource\FileRepository; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; @@ -22,7 +23,7 @@ class ConsentController extends ActionController * * @return void */ - public function indexAction(): void + public function indexAction(): ResponseInterface { $consentRecordUid = (int)$this->settings['consent']['contentByUid']; $fileRepository = GeneralUtility::makeInstance(FileRepository::class); @@ -63,6 +64,7 @@ public function indexAction(): void } $this->view->assignMultiple($assignedValues); + return $this->htmlResponse(); } } diff --git a/Classes/DataProcessing/BootstrapProcessor.php b/Classes/DataProcessing/BootstrapProcessor.php index 1ecf3292..1d71fab9 100644 --- a/Classes/DataProcessing/BootstrapProcessor.php +++ b/Classes/DataProcessing/BootstrapProcessor.php @@ -64,7 +64,13 @@ class BootstrapProcessor implements DataProcessorInterface */ public function process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData) { + + if ( empty($processedData['data']['CType']) ) { + return $processedData; + } + $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('t3sbootstrap'); + $cType = $processedData['data']['CType']; $parentCType = ''; $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); @@ -225,6 +231,7 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu $processedData = GeneralUtility::makeInstance(MasonryWrapper::class) ->getProcessedData($processedData, $flexconf); } + if ( $cType == 'swiper_container' ) { $processedData = GeneralUtility::makeInstance(SwiperContainer::class) ->getProcessedData($processedData, $flexconf); @@ -258,7 +265,7 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu // media if ( $processedData['data']['assets'] || $processedData['data']['image'] || $processedData['data']['media'] ) { $mediaElementHelper = GeneralUtility::makeInstance(MediaElementHelper::class); - $processedData = $mediaElementHelper->getProcessedData($processedData, $extConf, $contentObjectConfiguration['settings.']['breakpoint']); + $processedData = $mediaElementHelper->getProcessedData($processedData, $extConf, $contentObjectConfiguration['settings.']['breakpoint'], $parentflexconf); $fileRepository = GeneralUtility::makeInstance(FileRepository::class); $fileObjects = $fileRepository->findByRelation('tt_content ', 'assets', 875); $fileParts = []; diff --git a/Classes/DataProcessing/ConfigProcessor.php b/Classes/DataProcessing/ConfigProcessor.php index daedeab4..ec2fd49e 100644 --- a/Classes/DataProcessing/ConfigProcessor.php +++ b/Classes/DataProcessing/ConfigProcessor.php @@ -62,8 +62,9 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu $company = $processedRecordVariables['company']; $companyArr = GeneralUtility::trimExplode('|', $company); $sysLanguageUid = $processedData['data']['sys_language_uid']; + if ( $sysLanguageUid && $company ) { - $company = $companyArr[$sysLanguageUid] ?: $company; + $company = !empty($companyArr[$sysLanguageUid]) ? $companyArr[$sysLanguageUid] : $company; } else { $company = $companyArr[0] ?: $company; } @@ -475,6 +476,10 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu if ($hasBgImages && !empty($processedRecordVariables['jumbotronBgimageratio'])) { $processedData['config']['jumbotron']['noBgRatio'] = FALSE; $processedData['config']['jumbotron']['class'] .= ' ratio ratio-'.$processedRecordVariables['jumbotronBgimageratio']; + $ratioArr = explode('x', $processedRecordVariables['jumbotronBgimageratio']); + $x = $processedRecordVariables['jumbotronBgimageratio']; + $y = $ratioArr[1].' / '.$ratioArr[0].' * 100%'; + $processedData['ratioCalcCss'] = '.ratio-'.$x.'{--bs-aspect-ratio:calc('.$y.');}'; } } @@ -525,7 +530,6 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu $processedData['config']['sidebar']['stickTopClass'] = $processedRecordVariables['sectionmenuStickyTop'] ? ' sticky-top': ''; $topOffset = (int)$processedRecordVariables['sectionmenuAnchorOffset'] + (int)$processedRecordVariables['navbarHeight']; $processedData['config']['sidebar']['stickTopOffset'] = $topOffset ? $topOffset.'px' : 0; - $processedData['config']['sidebar']['scrollspyOffset'] = $processedRecordVariables['sectionmenuScrollspyOffset']; $processedData['config']['sidebar']['scrollspy'] = $processedRecordVariables['sectionmenuScrollspy']; } else { if (!empty($processedData['subNavigation']) && is_array($processedData['subNavigation'])) { @@ -567,7 +571,7 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu ->where( $queryBuilder->expr()->eq('colPos', $queryBuilder->createNamedParameter(20, \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchColumn(); $processedData['config']['expandedcontentTop']['enable'] = $numberOfTop ? $processedRecordVariables['expandedcontentEnabletop'] : 0; $processedData['config']['expandedcontentTop']['slide'] = $processedRecordVariables['expandedcontentSlidetop']; @@ -584,7 +588,7 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu ->where( $queryBuilder->expr()->eq('colPos', $queryBuilder->createNamedParameter(21, \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchColumn(); $processedData['config']['expandedcontentBottom']['enable'] = $numberOfBottom ? $processedRecordVariables['expandedcontentEnablebottom'] : 0; $processedData['config']['expandedcontentBottom']['slide'] = $processedRecordVariables['expandedcontentSlidebottom']; @@ -626,7 +630,7 @@ protected function getNavigationColor(int $languageUid): string ->andWhere( $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($languageUid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $navbarColors = $result->fetchAll(); $navbarColorCSS = ''; @@ -699,7 +703,7 @@ protected function getTreeList(int $id, int $depth, int $begin = 0, string $perm $queryBuilder->expr()->eq('sys_language_uid', 0), QueryHelper::stripLogicalOperatorPrefix($permsClause) ) - ->execute(); + ->executeQuery(); while ($row = $statement->fetch()) { if ($begin <= 0) { $theList .= ',' . $row['uid']; diff --git a/Classes/DataProcessing/GalleryProcessor.php b/Classes/DataProcessing/GalleryProcessor.php index 72384b98..2858a12a 100644 --- a/Classes/DataProcessing/GalleryProcessor.php +++ b/Classes/DataProcessing/GalleryProcessor.php @@ -15,7 +15,6 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3\CMS\Backend\Utility\BackendUtility; - /* * This file is part of the TYPO3 extension t3sbootstrap. * @@ -24,25 +23,41 @@ */ class GalleryProcessor implements DataProcessorInterface { - /** - * The content object renderer - * - * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer - */ - protected $contentObjectRenderer; - /** - * The processor configuration - * - * @var array - */ - protected $processorConfiguration; + const bsMaxGridWidth = 1320; + const maxGalleryWidth = 1296; + const minimumWidth = 575; + const gridColumns = 12; + const gridGutterWidth = 24; // default 1.5rem => 24px - /** - * Matching the tt_content field towards the imageOrient option - * - * @var array - */ + protected $contentObjectRenderer; + protected $contentObjectConfiguration; + protected $processorConfiguration; + protected $numberOfColumns; + protected $mediaOrientation; + protected $maxGalleryWidth; + protected $equalMediaHeight; + protected $equalMediaWidth; + protected $cropVariant = 'default'; + protected $fileObjects = []; + protected $mediaDimensions = []; + protected $beLayout = 'OneCol'; + protected $colPos; + protected $parentgridColPos; + protected $minimumWidth; + protected $ratioWithHeight; + protected $pageContainer; + protected $rowWidth; + protected $columns; + protected $cType; + protected $bodytext; + protected $maxWidthMediaObject; + protected $maxWidthToast; + protected $disableAutoRow; + protected $parentflexconf; + protected $processedData; + protected $processedParentData; + protected $cardWrapper; protected $availableGalleryPositions = [ 'horizontal' => [ 'center' => [0, 8], @@ -55,12 +70,6 @@ class GalleryProcessor implements DataProcessorInterface 'below' => [8, 9, 10] ] ]; - - /** - * Storage for processed data - * - * @var array - */ protected $galleryData = [ 'position' => [ 'horizontal' => '', @@ -81,135 +90,6 @@ class GalleryProcessor implements DataProcessorInterface 'rows' => [] ]; - /** - * @var int - */ - protected $numberOfColumns; - - /** - * @var int - */ - protected $mediaOrientation; - - /** - * @var int - */ - protected $maxGalleryWidth; - - /** - * @var int - */ - protected $equalMediaHeight; - - /** - * @var int - */ - protected $equalMediaWidth; - - /** - * @var string - */ - protected $cropVariant = 'default'; - - /** - * The (filtered) media files to be used in the gallery - * - * @var FileInterface[] - */ - protected $fileObjects = []; - - /** - * The calculated dimensions for each media element - * - * @var array - */ - protected $mediaDimensions = []; - - /** - * @var string - */ - protected $beLayout = 'OneCol'; - - /** - * @var int - */ - protected $colPos; - - /** - * @var int - */ - protected $parentgridColPos; - - /** - * @var boolean - */ - protected $minimumWidth; - - /** - * @var boolean - */ - protected $ratioWithHeight; - - /** - * @var string - */ - protected $pageContainer; - - /** - * @var string - */ - protected $rowWidth; - - /** - * @var string - */ - protected $columns; - - /** - * @var string - */ - protected $cType; - - /** - * @var string - */ - protected $bodytext; - - /** - * @var int - */ - protected $maxWidthMediaObject; - - /** - * @var int - */ - protected $maxWidthToast; - - /** - * @var boolean - */ - protected $disableAutoRow; - - /** - * @var string - */ - protected $parentflexconf; - - /** - * @var array - */ - protected $processedData; - - /** - * @var array - */ - protected $processedParentData; - - /** - * @var string - */ - protected $cardWrapper; - /** * Process data for a gallery, for instance the CType "textmedia" @@ -226,8 +106,8 @@ public function process( array $contentObjectConfiguration, array $processorConfiguration, array $processedData - ) { - + ): array + { if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) { return $processedData; } @@ -237,23 +117,21 @@ public function process( $this->processedData = $processedData; $this->contentObjectConfiguration = $contentObjectConfiguration; - if (!empty($processedData['data']['tx_container_parent'])) { - $parentRecord = self::getContentRecord($processedData['data']['tx_container_parent']); - $this->processedParentData = !empty($parentRecord) ? $parentRecord : []; + if (!empty($this->processedData['data']['tx_container_parent'])) { + $this->processedParentData = self::getContentRecord($this->processedData['data']['tx_container_parent']); } else { $this->processedParentData = []; } - $this->processedParentData = !empty($processedData['data']['tx_container_parent']) ? $parentRecord : []; - - $filesProcessedDataKey = (string)$cObj->stdWrapValue( 'filesProcessedDataKey', $processorConfiguration, 'files' ); - if (isset($processedData[$filesProcessedDataKey]) && is_array($processedData[$filesProcessedDataKey])) { - $this->fileObjects = $processedData[$filesProcessedDataKey]; + + if (isset($this->processedData[$filesProcessedDataKey]) && is_array($this->processedData[$filesProcessedDataKey])) { + $this->fileObjects = $this->processedData[$filesProcessedDataKey]; + if ( !empty($this->fileObjects[0]) ) { $fileObjects = []; // image gallery @@ -268,7 +146,7 @@ public function process( } if (empty($this->fileObjects)) { - return $processedData; + return $this->processedData; } $this->ratioWithHeight = $this->getConfigurationValue('ratioWithHeight'); @@ -276,25 +154,24 @@ public function process( $this->equalMediaHeight = (int)$this->getConfigurationValue('equalMediaHeight', 'imageheight'); $this->equalMediaWidth = (int)$this->getConfigurationValue('equalMediaWidth', 'imagewidth'); $this->numberOfColumns = (int)$this->getConfigurationValue('numberOfColumns', 'imagecols'); - $this->maxGalleryWidth = (int)$this->getConfigurationValue('maxGalleryWidth') ?: 1110; + $this->maxGalleryWidth = (int)$this->getConfigurationValue('maxGalleryWidth') ?: self::maxGalleryWidth; $this->mediaOrientation = (int)$this->getConfigurationValue('mediaOrientation', 'imageorient'); - $this->beLayout = $processedData['be_layout']; - $this->colPos = (int)$processedData['data']['colPos']; + $this->beLayout = $this->processedData['be_layout']; + $this->colPos = (int)$this->processedData['data']['colPos']; $this->minimumWidth = $this->getConfigurationValue('minimumWidth'); - $this->bodytext = $processedData['data']['bodytext']; - $this->cType = $processedData['data']['CType']; - $this->rowWidth = $processedData['data']['tx_t3sbootstrap_inTextImgRowWidth']; + $this->bodytext = $this->processedData['data']['bodytext']; + $this->cType = $this->processedData['data']['CType']; + $this->rowWidth = $this->processedData['data']['tx_t3sbootstrap_inTextImgRowWidth']; $this->maxWidthMediaObject = $this->getConfigurationValue('maxWidthMediaObject'); $this->maxWidthToast = $this->getConfigurationValue('maxWidthToast'); $this->disableAutoRow = $this->getConfigurationValue('disableAutoRow'); $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); - $this->parentflexconf = !empty($this->processedParentData['tx_t3sbootstrap_flexform']) ? $flexFormService->convertFlexFormContentToArray($this->processedParentData['tx_t3sbootstrap_flexform']) : []; $pageContainer = self::getFrontendController()->page['tx_t3sbootstrap_container']; - $contentContainer = $processedData['data']['tx_t3sbootstrap_container']; + $contentContainer = $this->processedData['data']['tx_t3sbootstrap_container']; if ( $pageContainer ) { $this->pageContainer = $pageContainer; } elseif ( $contentContainer ) { @@ -315,9 +192,9 @@ public function process( 'gallery' ); - $processedData[$targetFieldName] = $this->galleryData; + $this->processedData[$targetFieldName] = $this->galleryData; - return $processedData; + return $this->processedData; } /** @@ -328,7 +205,7 @@ public function process( * @param string|NULL $dataArrayKey * @return string */ - protected function getConfigurationValue($key, $dataArrayKey = null) + protected function getConfigurationValue(string $key, string|NULL $dataArrayKey = null): string { $defaultValue = ''; if ($dataArrayKey && isset($this->contentObjectRenderer->data[$dataArrayKey])) { @@ -360,6 +237,7 @@ protected function determineGalleryPosition() if ($this->mediaOrientation === 25 || $this->mediaOrientation === 26) { $this->galleryData['position']['noWrap'] = true; } + $this->galleryData['position']['alignCenter'] = false; if ($this->mediaOrientation === 66 || $this->mediaOrientation === 77) { $this->galleryData['position']['alignCenter'] = true; } @@ -369,7 +247,7 @@ protected function determineGalleryPosition() /** * Get the gallery width if 'tx_t3sbootstrap_inTextImgRowWidth' is set to 'auto' */ - protected function determineMaximumGalleryWidth() + protected function determineMaximumGalleryWidth(): void { if ( $this->rowWidth == 'auto' && $this->disableAutoRow ) { $this->rowWidth = 'none'; @@ -388,6 +266,9 @@ protected function determineMaximumGalleryWidth() // above or below $this->rowWidth = 66; } + if ( $this->galleryData['position']['vertical'] == 'above' || $this->galleryData['position']['vertical'] == 'below' ) { + $this->rowWidth = 100; + } } else { $this->rowWidth = 100; } @@ -395,25 +276,7 @@ protected function determineMaximumGalleryWidth() // Cards inside a card-wrapper } elseif ( $this->cType == 't3sbs_card' && $this->processedData['data']['tx_container_parent'] && $this->processedParentData['CType'] == 'card_wrapper') { - $countChildren = self::countContentRecord($this->processedData['data']['tx_container_parent'], 'tt_content', 'tx_container_parent'); - $this->galleryData['count']['columns'] = $countChildren; $this->rowWidth = 100; - - $this->cardWrapper = $this->parentflexconf['card_wrapper']; - - if ($this->parentflexconf['card_wrapper'] == 'columns' ) { - - $this->galleryData['count']['columns'] = 4; - - } elseif ($this->parentflexconf['card_wrapper'] == 'slider' ) { - - $this->galleryData['count']['columns'] = 3; - - } elseif ($this->parentflexconf['card_wrapper'] == 'flipper' ) { - - $this->galleryData['count']['columns'] = 4; - } - } else { $this->rowWidth = 100; } @@ -424,7 +287,7 @@ protected function determineMaximumGalleryWidth() /** * Calculate the amount of rows and columns */ - protected function calculateRowsAndColumns() + protected function calculateRowsAndColumns(): void { // If no columns defined, set it to 1 $columns = max((int)$this->numberOfColumns, 1); @@ -434,7 +297,9 @@ protected function calculateRowsAndColumns() } else { // When more columns than media elements, set the columns to the amount of media elements if ($columns > $this->galleryData['count']['files']) { - $columns = $this->galleryData['count']['files']; + if ( $this->processedData['data']['CType'] !== 't3sbs_gallery' ) { + $columns = $this->galleryData['count']['files']; + } } } @@ -444,7 +309,6 @@ protected function calculateRowsAndColumns() // Calculate the rows from the amount of files and the columns $rows = ceil($this->galleryData['count']['files'] / $columns); - $this->galleryData['count']['columns'] = $columns; $this->galleryData['count']['rows'] = (int)$rows; } @@ -460,63 +324,26 @@ protected function calculateRowsAndColumns() */ protected function calculateMediaWidthsAndHeights() { + if ( $this->equalMediaWidth == 0 && $this->equalMediaHeight == 0 ) { + // container $pageContainer = self::getPageContainer($this->pageContainer); - // if a cookie with the name 'windowWidth' has a value - $windowWidth = !empty($_COOKIE['windowWidth']) ? (int)$_COOKIE['windowWidth'] : ''; - - $correction = FALSE; - // nested container - if ($this->colPos > 199 && $this->processedParentData['colPos'] > 199 ) { - $grandParent = []; - $greatGrandParent = []; - if ( $this->processedParentData['tx_container_parent'] ) { - $grandParent = self::getContentRecord($this->processedParentData['tx_container_parent']); - if ( $grandParent['tx_container_parent'] ) { - $greatGrandParent = self::getContentRecord($grandParent['tx_container_parent']); - } - } - if ( $this->processedParentData['colPos'] < 200 ) { - $this->colPos = $this->processedParentData['colPos']; - - } elseif ( $grandParent['colPos'] < 200 ) { - $this->colPos = $grandParent['colPos']; - if ( $grandParent['CType'] == 'collapsible_container' ) $correction = 'collapsible_container'; - if ( $grandParent['CType'] == 'tabs_container' ) $correction = 'tabs_container'; - if ( $grandParent['CType'] == 'background_wrapper' ) $correction = 'background_wrapper'; - if ( $grandParent['CType'] == 'container' && !$pageContainer ) { - $pageContainer = $grandParent['tx_t3sbootstrap_container']; - } - } elseif ( $greatGrandParent['colPos'] < 200 ) { - - $this->colPos = $greatGrandParent['colPos']; - if ( $greatGrandParent['CType'] == 'collapsible_container' ) $correction = 'collapsible_container'; - if ( $greatGrandParent['CType'] == 'tabs_container' ) $correction = 'tabs_container'; - if ( $greatGrandParent['CType'] == 'background_wrapper' ) $correction = 'background_wrapper'; - if ( $greatGrandParent['CType'] == 'container' && !$pageContainer ) { - $pageContainer = $greatGrandParent['tx_t3sbootstrap_container']; - } - } - } - - if ( $pageContainer == 'container-fluid' ) { - $bsMaxGridWidth = $windowWidth ?: $this->maxGalleryWidth; - } elseif ( $pageContainer == 'container-fluid px-0' ) { - $bsMaxGridWidth = $windowWidth ?: $this->maxGalleryWidth; + if ( str_contains($pageContainer, 'container-fluid') ) { + $bsMaxGridWidth = !empty($_COOKIE['viewportWidth']) ? (int)$_COOKIE['viewportWidth'] : 1920; + $bsMaxGridWidth = $bsMaxGridWidth - self::gridGutterWidth; } else { - $bsMaxGridWidth = 1320; + $bsMaxGridWidth = self::maxGalleryWidth; } + // row width if ( is_int($this->rowWidth) ) { $rowWidth = $this->rowWidth; } elseif ( $this->rowWidth != 'none' && is_string($this->rowWidth) ) { $rowWidth = (int) end(explode('-', $this->rowWidth)); - } else { $rowWidth = 100; } - if ( $this->cType == 't3sbs_gallery' ) { $rowWidth = 100; } @@ -532,7 +359,6 @@ protected function calculateMediaWidthsAndHeights() } else { $defaultSmallColumns = 0; } - $smallColumns = $defaultSmallColumns ?: self::getFrontendController()->page['tx_t3sbootstrap_smallColumns']; if ($this->beLayout == 'OneCol') { @@ -541,7 +367,9 @@ protected function calculateMediaWidthsAndHeights() } elseif ($this->beLayout == 'ThreeCol') { - $bsAsideGridWidth = $bsMaxGridWidth / 12 * (int) $smallColumns; + // Three columns + $bsMaxGridWidth = $bsMaxGridWidth + self::gridGutterWidth; + $bsAsideGridWidth = $bsMaxGridWidth / self::gridColumns * (int) $smallColumns; $bsMainGridWidth = $bsMaxGridWidth - $bsAsideGridWidth * 2; // Main @@ -555,8 +383,10 @@ protected function calculateMediaWidthsAndHeights() } } else { + // Two columns - $bsAsideGridWidth = $bsMaxGridWidth / 12 * (int) $smallColumns; + $bsMaxGridWidth = $bsMaxGridWidth + self::gridGutterWidth; + $bsAsideGridWidth = $bsMaxGridWidth / self::gridColumns * (int) $smallColumns; $bsMainGridWidth = $bsMaxGridWidth - $bsAsideGridWidth; // Main @@ -582,29 +412,26 @@ protected function calculateMediaWidthsAndHeights() $bsGridWidth = $bsMaxGridWidth; } - // Modal - if ( $this->processedData['data']['CType'] == 'modal' ) { - + // Modal - INFO: https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes + if ( isset($this->processedParentData['CType']) && $this->processedParentData['CType'] == 'modal' ) { $size = $this->parentflexconf['size']; - if ( $size == 'modal-lg' ) { - // 798 - 2 * 16 - $bsGridWidth = 796; + if ( $size == 'modal-fullscreen' ) { + $bsGridWidth = $bsMaxGridWidth; + } elseif ( $size == 'modal-xl' ) { + $bsGridWidth = 1140; + } elseif ($size == 'modal-lg') { + $bsGridWidth = 800; } elseif ($size == 'modal-sm') { - // 298 - 2 * 16 - $bsGridWidth = 296; + $bsGridWidth = 300; } else { - // Default: 498 - 2 * 16 - $bsGridWidth = 496; + $bsGridWidth = 500; } - } - if ( $correction == 'background_wrapper' ) { - $bsGridWidth = $bsGridWidth - 36; } - if ( $correction == 'collapsible_container' ) { - $bsGridWidth = $bsGridWidth - 42; + if ( isset($this->processedParentData['CType']) && $this->processedParentData['CType'] == 'collapsible_accordion' ) { + $bsGridWidth = $bsGridWidth - self::gridGutterWidth - 17; } // Child of grid container @@ -612,16 +439,55 @@ protected function calculateMediaWidthsAndHeights() || $this->processedParentData['CType'] == 'three_columns' || $this->processedParentData['CType'] == 'four_columns' || $this->processedParentData['CType'] == 'six_columns') ) { + $bsGridWidth = $bsGridWidth + self::gridGutterWidth; $bsGridWidth = self::getCalculatedGridWidth($bsGridWidth); + } else { + if ($this->beLayout == 'OneCol') { + $bsGridWidth = $bsGridWidth + self::gridGutterWidth; + } } + $rowWidth = $rowWidth ? $rowWidth : 100; + $galleryWidth = $bsGridWidth / 100 * $rowWidth; - $imagePadding = self::getImagePadding($bsGridWidth); - $mediaWidth = ($galleryWidth - $imagePadding ) / $this->galleryData['count']['columns']; + // Card Wrapper + if ( $this->cType == 't3sbs_card' && $this->processedData['data']['tx_container_parent'] + && $this->processedParentData['CType'] == 'card_wrapper') { + $galleryWidth = $galleryWidth - self::gridGutterWidth; + if ($this->parentflexconf['card_wrapper'] === 'group' || $this->parentflexconf['card_wrapper'] === 'columns') { + $this->processedData['data']['tx_t3sbootstrap_gutters'] = ''; + $this->galleryData['count']['columns'] = -1; + // Masonry (columns) + if ($this->parentflexconf['card_wrapper'] === 'columns' && str_contains($this->parentflexconf['colclass'], 'col-lg-')) { + foreach ( explode(' ', $this->parentflexconf['colclass']) as $class) { + if (str_contains($class, 'col-lg-')) { + $countChildren = 12 / (int)end(explode('-', $class)); + } + } + $galleryWidth = $galleryWidth + self::gridGutterWidth - self::gridGutterWidth * $countChildren; + } else { + // Group + $countChildren = self::countContentRecord($this->processedData['data']['tx_container_parent'], 'tt_content', 'tx_container_parent'); + } + $galleryWidth = $galleryWidth / $countChildren; + } elseif ($this->parentflexconf['card_wrapper'] === 'slider') { + // Slider + $this->galleryData['count']['columns'] = -1; + $this->processedData['data']['tx_t3sbootstrap_gutters'] = ''; + } elseif ($this->parentflexconf['card_wrapper'] === 'flipper') { + // Flipper + $this->galleryData['count']['columns'] = -1; + $this->processedData['data']['tx_t3sbootstrap_gutters'] = ''; + } else { + $this->processedData['data']['tx_t3sbootstrap_gutters'] = 'gx-'.$this->parentflexconf['gutter']; + $this->galleryData['count']['columns'] = $this->parentflexconf['visibleCards']; + } + } } + // User entered a predefined width if ( $this->equalMediaWidth ) { @@ -635,7 +501,6 @@ protected function calculateMediaWidthsAndHeights() if ( $this->ratioWithHeight ) { $ratio = $this->equalMediaWidth .':'. $this->equalMediaHeight; $mediaHeight = ''; - } else { $ratio = ''; $mediaHeight = $this->getCroppedDimensionalProperty($fileObject, 'height') @@ -677,7 +542,7 @@ protected function calculateMediaWidthsAndHeights() foreach ($this->fileObjects as $key => $fileObject) { $mediaHeight = $this->equalMediaHeight; if (is_array($fileObject)) { - $fileObject = $fileObject[0]; + $fileObject = $fileObject[0]; } $mediaWidth = $this->getCroppedDimensionalProperty($fileObject, 'width') * ($mediaHeight / max($this->getCroppedDimensionalProperty($fileObject, 'height'), 1)); @@ -693,7 +558,84 @@ protected function calculateMediaWidthsAndHeights() // Automatic setting of width and height } else { + $gutterWidth = 0; + $ratio = 0; + + if (!empty($this->processedData['data']['tx_t3sbootstrap_gutters'])) { + // margin rem in px (base 16px) + $gx = [ 'gx-0' => 0, 'gx-1' => 4, 'gx-2' => 8, 'gx-3' => 16, 'gx-4' => 24, 'gx-5' => 48 ]; + $gutterWidth = $gx[$this->processedData['data']['tx_t3sbootstrap_gutters']]; + if ( !empty($this->parentflexconf['noGutters']) ) { + $gutterWidth = 0; + } + } + + if ( $this->processedData['data']['CType'] === 't3sbs_gallery' ) { + + $galleryWidth = $galleryWidth - self::gridGutterWidth + $gutterWidth; + $gutterWidth = $gutterWidth * $this->galleryData['count']['columns']; + $mediaWidth = ceil(($galleryWidth - $gutterWidth) / $this->galleryData['count']['columns']); + + } else { + + if ( $this->galleryData['count']['columns'] > 1 ) { + + if ($this->galleryData['position']['noWrap']) { + # imageorient 25 & 26 + if ( $this->processedData['data']['tx_t3sbootstrap_gutters'] == 'gx-0') { + $galleryWidth = $galleryWidth - self::gridGutterWidth; + } else { + $galleryWidth = $galleryWidth - $gutterWidth * $this->galleryData['count']['columns']; + } + $mediaWidth = ceil($galleryWidth / $this->galleryData['count']['columns']); + } else { + if ( $this->galleryData['position']['alignCenter'] ) { + # imageorient 66 & 77 + if ( $this->processedData['data']['tx_t3sbootstrap_gutters'] == 'gx-0') { + $galleryWidth = $galleryWidth - self::gridGutterWidth; + } else { + $galleryWidth = $galleryWidth + self::gridGutterWidth; + } + $gutterWidth = $gutterWidth * $this->galleryData['count']['columns']; + $mediaWidth = ceil(($galleryWidth - $gutterWidth) / $this->galleryData['count']['columns']); + } else { + if ( $this->galleryData['position']['vertical'] === 'above' || $this->galleryData['position']['vertical'] === 'below' ) { + # imageorient 0 - 10 + $galleryWidth = $galleryWidth - self::gridGutterWidth + $gutterWidth; + $gutterWidth = $gutterWidth * $this->galleryData['count']['columns']; + $mediaWidth = ceil(($galleryWidth - $gutterWidth) / $this->galleryData['count']['columns']); + } else { + # imageorient 17 & 18 + if ( $this->processedData['data']['tx_t3sbootstrap_gutters'] == 'gx-0') { + $galleryWidth = $galleryWidth - self::gridGutterWidth / 2; + $mediaWidth = ceil($galleryWidth / $this->galleryData['count']['columns']); + } else { + $galleryWidth = $galleryWidth - self::gridGutterWidth / 2 + $gutterWidth; + $gutterWidth = $gutterWidth * $this->galleryData['count']['columns']; + $mediaWidth = ceil(($galleryWidth - $gutterWidth) / $this->galleryData['count']['columns']); + } + } + } + } + + } else { + + if ($this->galleryData['count']['columns'] === -1 && $this->parentflexconf['card_wrapper'] !== 'slider') { + $mediaWidth = $galleryWidth; + } elseif ($this->mediaOrientation === 17 || $this->mediaOrientation === 18) { + // workaround + $mediaWidth = $galleryWidth - 7; + } elseif (!empty($this->parentflexconf) && isset($this->parentflexconf['card_wrapper']) && $this->parentflexconf['card_wrapper'] === 'slider') { + $mediaWidth = ($galleryWidth - (int)$this->parentflexconf['spaceBetween']) / (int)$this->parentflexconf['breakpoints992']; + $ratio = $this->parentflexconf['ratio']; + } else { + $mediaWidth = $galleryWidth - self::gridGutterWidth; + } + } + } + $mediaWidth = self::checkMediaWidth($mediaWidth); + // Set the corrected dimensions for each media element foreach ($this->fileObjects as $key => $fileObject) { if (is_array($fileObject)) { @@ -701,17 +643,16 @@ protected function calculateMediaWidthsAndHeights() } $mediaHeight = $this->getCroppedDimensionalProperty($fileObject, 'height') * ($mediaWidth / max($this->getCroppedDimensionalProperty($fileObject, 'width'), 1)); - $mediaHeight = !empty($mediaHeight) ? floor($mediaHeight) : ''; $this->mediaDimensions[$key] = [ 'width' => floor($mediaWidth), 'height' => $mediaHeight, - 'ratio' => '' + 'ratio' => $ratio ]; } } - $this->galleryData['width'] = floor($mediaWidth); + $this->galleryData['width'] = (int) ceil($mediaWidth); } @@ -719,7 +660,7 @@ protected function calculateMediaWidthsAndHeights() * When retrieving the height or width for a media file * a possible cropping needs to be taken into account. */ - protected function getCroppedDimensionalProperty(FileInterface $fileObject, string $dimensionalProperty): int + protected function getCroppedDimensionalProperty(FileInterface $fileObject, string $dimensionalProperty): int|array { if (!$fileObject->hasProperty('crop') || empty($fileObject->getProperty('crop'))) { return $fileObject->getProperty($dimensionalProperty); @@ -736,9 +677,10 @@ protected function getCroppedDimensionalProperty(FileInterface $fileObject, stri * * Make an array for rows, columns and configuration */ - protected function prepareGalleryData() + protected function prepareGalleryData(): void { for ($row = 1; $row <= $this->galleryData['count']['rows']; $row++) { + $this->galleryData['count']['columns'] = $this->galleryData['count']['columns'] === -1 ? 3 : $this->galleryData['count']['columns']; for ($column = 1; $column <= $this->galleryData['count']['columns']; $column++) { $fileKey = (($row - 1) * $this->galleryData['count']['columns']) + $column - 1; $this->galleryData['rows'][$row]['columns'][$column] = [ @@ -760,7 +702,7 @@ protected function prepareGalleryData() * @param string $pageContainer * @return string */ - protected function getPageContainer($pageContainer) + protected function getPageContainer($pageContainer): string { if ( $this->processedData['data']['tx_container_parent'] && !$pageContainer ) { if ( $this->processedParentData['tx_t3sbootstrap_container'] ) { @@ -826,7 +768,7 @@ protected function getPageContainer($pageContainer) } } - return $pageContainer; + return !empty($this->processorConfiguration['overrideContainer']) ? $this->processorConfiguration['overrideContainer'] : $pageContainer; } @@ -839,7 +781,7 @@ protected function getPageContainer($pageContainer) * * @return array $result */ - protected function getContentRecord($uid, $table='tt_content', $equal='uid') + protected function getContentRecord($uid, $table='tt_content', $equal='uid'): array { return BackendUtility::getRecord($table, $uid, '*'); } @@ -852,9 +794,9 @@ protected function getContentRecord($uid, $table='tt_content', $equal='uid') * @param string $table * @param string $equal * - * @return array $result + * @return int $result */ - protected function countContentRecord($uid, $table='tt_content', $equal='uid') + protected function countContentRecord($uid, $table='tt_content', $equal='uid'): int { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $result = $queryBuilder @@ -863,7 +805,7 @@ protected function countContentRecord($uid, $table='tt_content', $equal='uid') ->where( $queryBuilder->expr()->eq($equal, $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute()->fetchColumn(); + ->executeQuery()->fetchColumn(); return $result; } @@ -874,56 +816,57 @@ protected function countContentRecord($uid, $table='tt_content', $equal='uid') * * @param int $bsGridWidth * - * @return int $mediaWidth + * @return int $gridWidth */ - protected function getCalculatedGridWidth($bsGridWidth) + protected function getCalculatedGridWidth($bsGridWidth): int { switch ($this->processedParentData['CType']) { case 'two_columns': if ( $this->processedData['data']['colPos'] === 221 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'one'); + $gridWidth = self::getGridWidth($bsGridWidth, 'one'); } else { - $mediaWidth = self::getGridWidth($bsGridWidth, 'two'); + $gridWidth = self::getGridWidth($bsGridWidth, 'two'); } break; case 'three_columns': if ( $this->processedData['data']['colPos'] === 231 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'one'); + $gridWidth = self::getGridWidth($bsGridWidth, 'one'); } elseif ( $this->processedData['data']['colPos'] === 232 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'two'); + + $gridWidth = self::getGridWidth($bsGridWidth, 'two'); } else { - $mediaWidth = self::getGridWidth($bsGridWidth, 'three'); + $gridWidth = self::getGridWidth($bsGridWidth, 'three'); } break; case 'four_columns': if ( $this->processedData['data']['colPos'] === 241 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'one'); + $gridWidth = self::getGridWidth($bsGridWidth, 'one'); } elseif ( $this->processedData['data']['colPos'] === 242 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'two'); + $gridWidth = self::getGridWidth($bsGridWidth, 'two'); } elseif ( $this->processedData['data']['colPos'] === 243 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'three'); + $gridWidth = self::getGridWidth($bsGridWidth, 'three'); } else { - $mediaWidth = self::getGridWidth($bsGridWidth, 'four'); + $gridWidth = self::getGridWidth($bsGridWidth, 'four'); } break; case 'six_columns': if ( $this->processedData['data']['colPos'] === 261 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'one'); + $gridWidth = self::getGridWidth($bsGridWidth, 'one'); } elseif ( $this->processedData['data']['colPos'] === 262 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'two'); + $gridWidth = self::getGridWidth($bsGridWidth, 'two'); } elseif ( $this->processedData['data']['colPos'] === 263 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'three'); + $gridWidth = self::getGridWidth($bsGridWidth, 'three'); } elseif ( $this->processedData['data']['colPos'] === 264 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'four'); + $gridWidth = self::getGridWidth($bsGridWidth, 'four'); } elseif ( $this->processedData['data']['colPos'] === 265 ) { - $mediaWidth = self::getGridWidth($bsGridWidth, 'five'); + $gridWidth = self::getGridWidth($bsGridWidth, 'five'); } else { - $mediaWidth = self::getGridWidth($bsGridWidth, 'six'); + $gridWidth = self::getGridWidth($bsGridWidth, 'six'); } break; } - return $mediaWidth; + return $gridWidth; } @@ -933,110 +876,25 @@ protected function getCalculatedGridWidth($bsGridWidth) * @param int $bsGridWidth * @param string $suffix * - * @return int $mediaWidth + * @return int $gridWidth */ - protected function getGridWidth($bsGridWidth, $suffix) + protected function getGridWidth($bsGridWidth, $suffix): int { - // # of Bootstrap columns - $columns = 12; - // Bootstrap gutter width - $gutterWidth = 24; - - if ( !empty($this->parentflexconf['noGutters']) ) { - $gutterWidth = 0; - } - - if ($this->parentflexconf['md_'.$suffix] != 0) { - $mediaWidth = $bsGridWidth / $columns * $this->parentflexconf['md_'.$suffix] - $gutterWidth; - } elseif ($this->parentflexconf['lg_'.$suffix] != 0) { - $mediaWidth = $bsGridWidth / $columns * $this->parentflexconf['lg_'.$suffix] - $gutterWidth; - } elseif ($this->parentflexconf['xl_'.$suffix] != 0) { - $mediaWidth = $bsGridWidth / $columns * $this->parentflexconf['xl_'.$suffix] - $gutterWidth; - } elseif ($this->parentflexconf['xxl_'.$suffix] != 0) { - $mediaWidth = $bsGridWidth / $columns * $this->parentflexconf['xxl_'.$suffix] - $gutterWidth; + if (!empty($this->parentflexconf['sm_'.$suffix])) { + $gridWidth = $bsGridWidth / self::gridColumns * (int) $this->parentflexconf['sm_'.$suffix]; + } elseif (!empty($this->parentflexconf['md_'.$suffix])) { + $gridWidth = $bsGridWidth / self::gridColumns * (int) $this->parentflexconf['md_'.$suffix]; + } elseif (!empty($this->parentflexconf['lg_'.$suffix])) { + $gridWidth = $bsGridWidth / self::gridColumns * (int) $this->parentflexconf['lg_'.$suffix]; + } elseif (!empty($this->parentflexconf['xl_'.$suffix])) { + $gridWidth = $bsGridWidth / self::gridColumns * (int) $this->parentflexconf['xl_'.$suffix]; + } elseif (!empty($this->parentflexconf['xxl_'.$suffix])) { + $gridWidth = $bsGridWidth / self::gridColumns * (int) $this->parentflexconf['xxl_'.$suffix]; } else { - $mediaWidth = $bsGridWidth / $columns * ($columns-1) - $gutterWidth; + $gridWidth = $bsGridWidth / self::gridColumns * ($columns-1); } - return $mediaWidth; - } - - - /** - * Returns $imagepadding - * - * @param int $bsGridWidth - * - * @return int $imagepadding - */ - protected function getImagePadding($bsGridWidth) - { - - if ( $this->cType == 't3sbs_card' && $this->processedData['data']['tx_container_parent'] - && $this->processedData['data']['CType'] == 'card_wrapper') { - if ( $this->cardWrapper == 'flipper' ) { - $imagePadding = 30 * ($this->galleryData['count']['columns'] - 1); - } else { - $imagePadding = $bsGridWidth / 100 * $this->galleryData['count']['columns'] + $this->galleryData['count']['columns']; - } - } else { - - if ( !empty($this->galleryData['position']['noWrap']) ) { - // beside the text - if ( $this->galleryData['count']['columns'] == 1 ) { - $imagePadding = 22; - } else { - $imagePadding = 16 * ($this->galleryData['count']['columns']); - } - } else { - - if ( $this->galleryData['position']['vertical'] === 'intext' ) { - - if ( !empty($this->galleryData['position']['alignCenter']) ) { - - if ( $this->galleryData['count']['columns'] == 1 ) { - $imagePadding = 20 * ($this->galleryData['count']['columns']); - } elseif ( $this->galleryData['count']['columns'] == 2 ) { - $imagePadding = 16 * ($this->galleryData['count']['columns']); - } else { - $imagePadding = 20 * ($this->galleryData['count']['columns']); - } - - } else { - - if ( $this->galleryData['count']['columns'] == 1 ) { - $imagePadding = 0; - } elseif ( $this->galleryData['count']['columns'] == 2 ) { - - $imagePadding = 8 * ($this->galleryData['count']['columns']); - - } else { - - $imagePadding = 12 * ($this->galleryData['count']['columns']); - } - } - - } else { - - if ( $this->galleryData['count']['columns'] == 1 ) { - $imagePadding = 0; - } elseif ( $this->galleryData['count']['columns'] == 2 ) { - - $imagePadding = 8 * ($this->galleryData['count']['columns']); - - } else { - - $imagePadding = 12 * ($this->galleryData['count']['columns']); - } - } - } - } - - if ( $this->processedData['data']['CType'] == 'modal' ) { - $imagePadding = 0; - } - - return $imagePadding; + return $gridWidth; } @@ -1047,23 +905,26 @@ protected function getImagePadding($bsGridWidth) * * @return int $mediaWidth */ - protected function checkMediaWidth($mediaWidth) + protected function checkMediaWidth($mediaWidth): int { - if ( $this->minimumWidth && $mediaWidth < 575 ) { + if ( $this->minimumWidth && $mediaWidth < self::minimumWidth ) { // set to 575px and therefore 100% wide on mobile (constant: minimumWidth=1) - $mediaWidth = 575; + $mediaWidth = self::minimumWidth; } - + // t3sbs_mediaobject if ( $this->cType == 't3sbs_mediaobject' && $this->maxWidthMediaObject < $mediaWidth ) { $mediaWidth = $this->maxWidthMediaObject; } - + // t3sbs_toast if ( $this->cType == 't3sbs_toast' && $this->maxWidthToast < $mediaWidth ) { $mediaWidth = $this->maxWidthToast; } - + // card slider + if ( !empty($this->parentflexconf['width']) && !empty($this->parentflexconf['card_wrapper']) && $this->parentflexconf['card_wrapper'] === 'slider') { + $mediaWidth = (int)$this->parentflexconf['width']; + } + // masonry_wrapper if ( !empty($this->processedParentData['CType']) && $this->processedParentData['CType'] == 'masonry_wrapper' ) { - $classPrefix = 'col-lg-'; $mediaWidth = $this->getMansoryColumns($classPrefix); if (!$mediaWidth) { @@ -1079,7 +940,7 @@ protected function checkMediaWidth($mediaWidth) $mediaWidth = $this->getMansoryColumns($classPrefix); } if (!$mediaWidth) { - $mediaWidth = 1320 / 2; + $mediaWidth = self::bsMaxGridWidth / 2; } } @@ -1094,35 +955,27 @@ protected function checkMediaWidth($mediaWidth) * * @return int $mediaWidth */ - protected function getMansoryColumns($classPrefix) + protected function getMansoryColumns($classPrefix): int { # 2 columns $pos = strpos($this->parentflexconf['colclass'], $classPrefix.'6'); - if ($pos === false) { - // do nothing - } else { - $mediaWidth = 1320 / 2; + if ($pos !== false) { + $mediaWidth = self::bsMaxGridWidth / 2 - self::gridGutterWidth; } # 3 columns $pos = strpos($this->parentflexconf['colclass'], $classPrefix.'4'); - if ($pos === false) { - // do nothing - } else { - $mediaWidth = 1320 / 3; + if ($pos !== false) { + $mediaWidth = self::bsMaxGridWidth / 3 - self::gridGutterWidth; } # 4 columns $pos = strpos($this->parentflexconf['colclass'], $classPrefix.'3'); - if ($pos === false) { - // do nothing - } else { - $mediaWidth = 1320 / 4; + if ($pos !== false) { + $mediaWidth = self::bsMaxGridWidth / 4 - self::gridGutterWidth; } # 6 columns $pos = strpos($this->parentflexconf['colclass'], $classPrefix.'2'); - if ($pos === false) { - // do nothing - } else { - $mediaWidth = 1320 / 6; + if ($pos !== false) { + $mediaWidth = self::bsMaxGridWidth / 6 - self::gridGutterWidth; } return (int) $mediaWidth; diff --git a/Classes/DataProcessing/LastModifiedProcessor.php b/Classes/DataProcessing/LastModifiedProcessor.php index 16c99561..0070cdb9 100644 --- a/Classes/DataProcessing/LastModifiedProcessor.php +++ b/Classes/DataProcessing/LastModifiedProcessor.php @@ -105,7 +105,7 @@ protected function getRecentlyUpdated($setMaxResults): array $queryBuilder->expr()->neq('pid', $queryBuilder->createNamedParameter(self::getCurrentUid(), \PDO::PARAM_INT)) ) ->setMaxResults($setMaxResults) - ->execute() + ->executeQuery() ->fetchAll(); $mdtm = []; @@ -142,7 +142,7 @@ protected function getPageTitle($uid): string $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)), $queryBuilder->expr()->eq('doktype', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetch(); $pageTitle = !empty($result['nav_title']) ? $result['nav_title'] : $result['title']; diff --git a/Classes/Domain/Model/Config.php b/Classes/Domain/Model/Config.php index 70d6c8a7..a9528e38 100644 --- a/Classes/Domain/Model/Config.php +++ b/Classes/Domain/Model/Config.php @@ -172,6 +172,13 @@ class Config extends AbstractEntity */ protected $navbarDropdownAnimate = ''; + /** + * navbarDarkMode + * + * @var string + */ + protected $navbarDarkMode = ''; + /** * navbarBrand @@ -810,12 +817,17 @@ class Config extends AbstractEntity protected $sectionmenuAnchorOffset = 0; /** - * sectionmenuScrollspyOffset + * sectionmenuScrollspyThreshold * - * @var int + * @var string */ - protected $sectionmenuScrollspyOffset = 0; - + protected $sectionmenuScrollspyThreshold = ''; + /** + * sectionmenuScrollspyRootMargin + * + * @var string + */ + protected $sectionmenuScrollspyRootMargin = ''; /** * sectionmenuStickyTop * @@ -3606,24 +3618,45 @@ public function setSectionmenuAnchorOffset($sectionmenuAnchorOffset) } /** - * Returns the sectionmenuScrollspyOffset + * Returns the sectionmenuScrollspyThreshold * - * @return int $sectionmenuScrollspyOffset + * @return string sectionmenuScrollspyThreshold */ - public function getSectionmenuScrollspyOffset() + public function getSectionmenuScrollspyThreshold() { - return $this->sectionmenuScrollspyOffset; + return $this->sectionmenuScrollspyThreshold; + } + + /** + * Sets the sectionmenuScrollspyThreshold + * + * @param string $sectionmenuScrollspyThreshold + * @return void + */ + public function setSectionmenuScrollspyThreshold($sectionmenuScrollspyThreshold) + { + $this->sectionmenuScrollspyThreshold = $sectionmenuScrollspyThreshold; } /** - * Sets the sectionmenuScrollspyOffset + * Returns the sectionmenuScrollspyRootMargin * - * @param int $sectionmenuScrollspyOffset + * @return string sectionmenuScrollspyRootMargin + */ + public function getSectionmenuScrollspyRootMargin() + { + return $this->sectionmenuScrollspyRootMargin; + } + + /** + * Sets the sectionmenuScrollspyRootMargin + * + * @param string $sectionmenuScrollspyRootMargin * @return void */ - public function setSectionmenuScrollspyOffset($sectionmenuScrollspyOffset) + public function setSectionmenuScrollspyRootMargin($sectionmenuScrollspyRootMargin) { - $this->sectionmenuScrollspyOffset = $sectionmenuScrollspyOffset; + $this->sectionmenuScrollspyRootMargin = $sectionmenuScrollspyRootMargin; } /** @@ -4005,4 +4038,27 @@ public function setSectionmenuIcons($sectionmenuIcons) } + + /** + * Returns the navbarDarkMode + * + * @return string $navbarDarkMode + */ + public function getNavbarDarkMode() + { + return $this->navbarDarkMode; + } + + /** + * Sets the navbarDarkMode + * + * @param string $navbarDarkMode + * @return void + */ + public function setNavbarDarkMode($navbarDarkMode) + { + $this->navbarDarkMode = $navbarDarkMode; + } + + } diff --git a/Classes/EventListener/TCA/TcaCompilation.php b/Classes/EventListener/TCA/TcaCompilation.php new file mode 100644 index 00000000..62a5bf3c --- /dev/null +++ b/Classes/EventListener/TCA/TcaCompilation.php @@ -0,0 +1,111 @@ +get('t3sbootstrap'); + + // tt_content + + if (!empty($extconf['customFaIcons'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['customFaIcons']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['tt_content']['columns']['tx_t3sbootstrap_header_fontawesome']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } else { + $tca = $event->getTca(); + $defaultTCA = $tca['tt_content']['columns']['tx_t3sbootstrap_header_fontawesome']['config']['valuePicker']['items']; + $tca = $defaultTCA; + } + + if (!empty($extconf['customHeaderClass'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['customHeaderClass']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['tt_content']['columns']['tx_t3sbootstrap_header_class']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + + // pages + + if (!empty($extconf['customFaIconsPages'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['customFaIconsPages']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['pages']['columns']['tx_t3sbootstrap_fontawesome_icon']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + + if (!empty($extconf['customTitleColor'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['customTitleColor']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['pages']['columns']['tx_t3sbootstrap_titlecolor']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + + if (!empty($extconf['customSubtitleColor'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['customSubtitleColor']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['pages']['columns']['tx_t3sbootstrap_subtitlecolor']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + + // sys_file_reference + + if (!empty($extconf['figureClass'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['figureClass']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['sys_file_reference']['columns']['tx_t3sbootstrap_extra_class']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + + if (!empty($extconf['imageClass'])) { + $tca = $event->getTca(); + $newItems = []; + foreach ( explode(',',$extconf['imageClass']) as $custom) { + $key = trim(end(explode(' ', $custom))); + $newItems[] = [0 => $key, 1 => $custom]; + } + $tca['sys_file_reference']['columns']['tx_t3sbootstrap_extra_imgclass']['config']['valuePicker']['items'] = $newItems; + $event->setTca($tca); + } + } + +} diff --git a/Classes/Helper/ClassHelper.php b/Classes/Helper/ClassHelper.php index 4dd839b8..0770d17b 100644 --- a/Classes/Helper/ClassHelper.php +++ b/Classes/Helper/ClassHelper.php @@ -70,11 +70,16 @@ public function getDefaultClass(array $data, array $flexconf, string $cTypeClass $layoutClasses = ''; $layoutAltLabels = ''; - if (!empty($pagesTSconfig['TCEFORM.']['tt_content.']['layout.'])) { + if (!empty($pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['addItems.'])) { $layoutAddItems = $pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['addItems.']; + } + if (!empty($pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['classes.'])) { $layoutClasses = $pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['classes.']; + } + if (!empty($pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['altLabels.'])) { $layoutAltLabels = $pagesTSconfig['TCEFORM.']['tt_content.']['layout.']['altLabels.']; } + if (isset($layoutAddItems) && isset($layoutAddItems) === $layout) { $class .= ' layout-'.$layout; } elseif (isset($layoutAltLabels) && !empty($layoutAltLabels[$layout])) { @@ -140,6 +145,10 @@ public function getDefaultClass(array $data, array $flexconf, string $cTypeClass } } + if ($data['sectionIndex']) { + $class .= ' section-index'; + } + return ' '.trim($class); } diff --git a/Classes/Helper/GalleryHelper.php b/Classes/Helper/GalleryHelper.php index 0af87fd3..53fa47f4 100644 --- a/Classes/Helper/GalleryHelper.php +++ b/Classes/Helper/GalleryHelper.php @@ -121,8 +121,8 @@ public function getGalleryClasses(array $processedData, string $breakpoint): arr // In Text right or left (17,18) if ( $imageorient == 17 || $imageorient == 18 ) { $inTextImgColumns = empty($processedData['data']['tx_t3sbootstrap_inTextImgColumns']) ? 4 : $processedData['data']['tx_t3sbootstrap_inTextImgColumns']; - $galleryClass .= $imageorient == 17 ? ' col-md-'.$inTextImgColumns.' float-md-end mb-3 ms-md-3' - : ' col-md-'.$inTextImgColumns.' float-md-start mb-3 me-md-3'; + $galleryClass .= $imageorient == 17 ? ' col-md-'.$inTextImgColumns.' float-md-end ms-md-3' + : ' col-md-'.$inTextImgColumns.' float-md-start me-md-3'; $galleryClass .= ' '.$rowwidth; } // Beside Text right or left (nowrap) (25,26) diff --git a/Classes/Helper/MediaElementHelper.php b/Classes/Helper/MediaElementHelper.php index e100b708..c258b6e5 100644 --- a/Classes/Helper/MediaElementHelper.php +++ b/Classes/Helper/MediaElementHelper.php @@ -19,7 +19,7 @@ class MediaElementHelper implements SingletonInterface /** * Returns the $processedData */ - public function getProcessedData(array $processedData, array $extConf, $breakpoint): array + public function getProcessedData(array $processedData, array $extConf, $breakpoint, $parentflexconf): array { $cType = $processedData['data']['CType']; @@ -27,11 +27,17 @@ public function getProcessedData(array $processedData, array $extConf, $breakpoi $processedData['addmedia']['imgclass'] .= $processedData['data']['imageborder'] ? ' border' :''; $processedData['addmedia']['imgclass'] .= $processedData['data']['tx_t3sbootstrap_bordercolor'] && $processedData['data']['imageborder'] ? ' border-'.$processedData['data']['tx_t3sbootstrap_bordercolor'] : ''; + // lazyload - if ( $extConf['lazyLoad'] ) { - $processedData['addmedia']['imgclass'] .= $extConf['lazyLoad'] == 1 ? ' lazy' : ''; - $processedData['addmedia']['lazyload'] = $extConf['lazyLoad']; - $processedData['lazyload'] = $extConf['lazyLoad']; + if ( $extConf['lazyLoad']) { + if (!empty($parentflexconf) && isset($parentflexconf['card_wrapper']) && $parentflexconf['card_wrapper'] === 'slider' ) { + $processedData['addmedia']['lazyload'] = 0; + $processedData['lazyload'] = 0; + } else { + $processedData['addmedia']['imgclass'] .= $extConf['lazyLoad'] == 1 ? ' lazy' : ''; + $processedData['addmedia']['lazyload'] = $extConf['lazyLoad']; + $processedData['lazyload'] = $extConf['lazyLoad']; + } } $processedData['addmedia']['figureclass'] = !empty($processedData['addmedia']['figureclass']) ? ' '.trim($processedData['addmedia']['figureclass']) : ''; @@ -67,5 +73,4 @@ public function getProcessedData(array $processedData, array $extConf, $breakpoi return $processedData; } - } diff --git a/Classes/Hooks/PageRenderer/PreProcessHook.php b/Classes/Hooks/PageRenderer/PreProcessHook.php index 94c9b089..7db4f26a 100644 --- a/Classes/Hooks/PageRenderer/PreProcessHook.php +++ b/Classes/Hooks/PageRenderer/PreProcessHook.php @@ -4,6 +4,7 @@ namespace T3SBS\T3sbootstrap\Hooks\PageRenderer; +use TYPO3\CMS\Core\Page\PageRenderer; use T3SBS\T3sbootstrap\Service\CompileService; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\ApplicationType; @@ -24,7 +25,7 @@ class PreProcessHook /** * @param array $params - * @param \TYPO3\CMS\Core\Page\PageRenderer $pagerenderer + * @param PageRenderer $pagerenderer */ public function execute(&$params, &$pagerenderer): void { diff --git a/Classes/Parser/AbstractParser.php b/Classes/Parser/AbstractParser.php index c0bb022c..318d098d 100644 --- a/Classes/Parser/AbstractParser.php +++ b/Classes/Parser/AbstractParser.php @@ -3,6 +3,7 @@ namespace T3SBS\T3sbootstrap\Parser; +use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException; use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -121,7 +122,7 @@ protected function getPathSite(): string /** * Clear all page caches - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException + * @throws NoSuchCacheGroupException */ protected function clearPageCaches(): void { diff --git a/Classes/Updates/T3sbCardsUpdateWizard.php b/Classes/Updates/T3sbCardsUpdateWizard.php index b1f1126a..5b9a7949 100644 --- a/Classes/Updates/T3sbCardsUpdateWizard.php +++ b/Classes/Updates/T3sbCardsUpdateWizard.php @@ -66,7 +66,7 @@ protected function upgradeCards(): void ->where( $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('t3sbs_card')) ) - ->execute() + ->executeQuery() ->fetchAll(); if (!empty($statements)) { @@ -128,7 +128,7 @@ protected function upgradeCards(): void ->set('tx_t3sbootstrap_bodytext', $flexconf['text']['bottom']) ->set('tx_t3sbootstrap_cardfooter', $flexconf['footer']['text']) ->set('tx_t3sbootstrap_list_item', $count) - ->execute(); + ->executeQuery(); } } @@ -183,7 +183,7 @@ protected function checkIfWizardIsRequired(): bool ->where( $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('t3sbs_card')) ) - ->execute() + ->executeQuery() ->fetchAll(); if (!empty($statements)) { diff --git a/Classes/Updates/T3sbMigrateUpdateWizard.php b/Classes/Updates/T3sbMigrateUpdateWizard.php index 042fc115..8bba5fa2 100644 --- a/Classes/Updates/T3sbMigrateUpdateWizard.php +++ b/Classes/Updates/T3sbMigrateUpdateWizard.php @@ -69,7 +69,7 @@ protected function upgradeColumns(): void $statements = $queryBuilder ->select('uid', $field) ->from('tx_t3sbootstrap_domain_model_config') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $recordId = (int)$statement['uid']; @@ -83,7 +83,7 @@ protected function upgradeColumns(): void $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($recordId, \PDO::PARAM_INT)) ) ->set($field, str_replace($rename, $renameTo[$key], $statement[$field])) - ->execute(); + ->executeQuery(); } } } @@ -98,7 +98,7 @@ protected function upgradeColumns(): void $statements = $queryBuilder ->select('uid', $field) ->from('sys_file_reference') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $recordId = (int)$statement['uid']; @@ -112,7 +112,7 @@ protected function upgradeColumns(): void $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($recordId, \PDO::PARAM_INT)) ) ->set($field, str_replace($rename, $renameTo[$key], $statement[$field])) - ->execute(); + ->executeQuery(); } } } @@ -127,7 +127,7 @@ protected function upgradeColumns(): void $statements = $queryBuilder ->select('uid', $field) ->from('tt_content') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $recordId = (int)$statement['uid']; @@ -141,7 +141,7 @@ protected function upgradeColumns(): void $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($recordId, \PDO::PARAM_INT)) ) ->set($field, str_replace($rename, $renameTo[$key], $statement[$field])) - ->execute(); + ->executeQuery(); } } } @@ -158,7 +158,7 @@ protected function upgradeColumns(): void $statements = $queryBuilder ->select('uid', $field) ->from('pages') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $recordId = (int)$statement['uid']; @@ -173,7 +173,7 @@ protected function upgradeColumns(): void $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($recordId, \PDO::PARAM_INT)) ) ->set($field, str_replace($rename, $renameTo[$key], $statement[$field])) - ->execute(); + ->executeQuery(); } } } @@ -188,7 +188,7 @@ protected function upgradeColumns(): void ->where( $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('t3sbs_carousel')) ) - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { @@ -204,7 +204,7 @@ protected function upgradeColumns(): void ) ->set('assets', $imageAmount) ->set('image', 0) - ->execute(); + ->executeQuery(); $queryBuilderSFR = $connectionPool->getQueryBuilderForTable('sys_file_reference'); $fileStatements = $queryBuilderSFR @@ -213,7 +213,7 @@ protected function upgradeColumns(): void ->where( $queryBuilderSFR->expr()->eq('uid_foreign', $queryBuilderSFR->createNamedParameter($recordId, \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchAll(); foreach ($fileStatements as $fileStatement) { @@ -224,7 +224,7 @@ protected function upgradeColumns(): void $queryBuilderSFR->expr()->eq('uid', $queryBuilderSFR->createNamedParameter($fileId, \PDO::PARAM_INT)) ) ->set('fieldname', 'assets') - ->execute(); + ->executeQuery(); } } } @@ -285,7 +285,7 @@ protected function checkIfWizardIsRequired(): bool $statements = $queryBuilder ->select('uid', $field) ->from('tx_t3sbootstrap_domain_model_config') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { @@ -311,7 +311,7 @@ protected function checkIfWizardIsRequired(): bool $statements = $queryBuilder ->select('uid', $field) ->from('sys_file_reference') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $pos = strpos((string)$statement[$field], $rename); @@ -336,7 +336,7 @@ protected function checkIfWizardIsRequired(): bool $statements = $queryBuilder ->select('uid', $field) ->from('pages') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $check = strpos((string)$statement[$field], 'var(--bs-'); @@ -362,7 +362,7 @@ protected function checkIfWizardIsRequired(): bool $statements = $queryBuilder ->select('uid', $field) ->from('tt_content') - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { $pos = strpos((string)$statement[$field], $rename); @@ -384,7 +384,7 @@ protected function checkIfWizardIsRequired(): bool ->where( $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('t3sbs_carousel')) ) - ->execute() + ->executeQuery() ->fetchAll(); foreach ($statements as $statement) { diff --git a/Classes/UserFunction/TcaMatcher.php b/Classes/UserFunction/TcaMatcher.php index 0acc093e..1319e643 100644 --- a/Classes/UserFunction/TcaMatcher.php +++ b/Classes/UserFunction/TcaMatcher.php @@ -34,7 +34,7 @@ public function autoLayoutParent(array $arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetch(); if ( !empty($parent_rec['CType']) && $parent_rec['CType'] == 'autoLayout_row' ) { @@ -60,7 +60,7 @@ public function buttonParent(array $arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetch(); if ( !empty($parent_rec['CType']) && $parent_rec['CType'] == 'button_group' ) { @@ -99,7 +99,7 @@ public function cardWrapperParent(array $arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetch(); if ( !empty($parent_rec['CType']) && $parent_rec['CType'] == 'card_wrapper' ) { @@ -165,11 +165,16 @@ public function spacing_0(array $arguments): bool */ public function color_1(array $arguments): bool { - if ( $arguments['record']['CType'][0] == 'parallax_wrapper' ) { - return false; + if (!empty($arguments['record']['CType']) && !empty($arguments['record']['CType'][0])) { + if ( $arguments['record']['CType'][0] == 'parallax_wrapper' ) { + return false; + } else { + return true; + } } else { - return true; + return true; } + } /** @@ -198,7 +203,7 @@ public function flexContainerParent(array $arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetch(); if (!empty($parent_rec)) { @@ -230,7 +235,7 @@ public function isButton(array $arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetchAll(); if (!empty($parent_rec)) { $flexconf = $flexformService->convertFlexFormContentToArray($parent_rec[0]['tx_t3sbootstrap_flexform']); @@ -249,7 +254,7 @@ public function isButton(array $arguments): bool public function isMenu(array $arguments): bool { $menu = false; - if ($arguments['record']['CType'][0]) { + if (!empty($arguments['record']['CType']) && !empty($arguments['record']['CType'][0])) { if ( substr($arguments['record']['CType'][0], 0, 4) == 'menu' ) { $menu = true; } @@ -425,7 +430,7 @@ public function toastContainerParent($arguments): bool ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) - ->execute(); + ->executeQuery(); $parent_rec = $result->fetch(); if ( $parent_rec['CType'] == 'toast_container' ) { $parent = false; diff --git a/Classes/Utility/ResponsiveImagesUtility.php b/Classes/Utility/ResponsiveImagesUtility.php index ce0169db..bab10178 100644 --- a/Classes/Utility/ResponsiveImagesUtility.php +++ b/Classes/Utility/ResponsiveImagesUtility.php @@ -7,11 +7,12 @@ use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection; use TYPO3\CMS\Core\Imaging\ImageManipulation\Area; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; use TYPO3Fluid\Fluid\Core\ViewHelper\TagBuilder; use TYPO3\CMS\Extbase\Service\ImageService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; /* * This file is part of the TYPO3 extension t3sbootstrap. @@ -28,6 +29,7 @@ class ResponsiveImagesUtility implements SingletonInterface */ protected $imageService; + /** * Configuration Manager * @@ -35,6 +37,7 @@ class ResponsiveImagesUtility implements SingletonInterface */ protected $configurationManager; + /** * Default media breakpoint configuration * @@ -47,13 +50,17 @@ class ResponsiveImagesUtility implements SingletonInterface 'srcset' => [] ]; + /** * @param ImageService $imageService */ - public function __construct(ImageService $imageService, ConfigurationManager $configurationManager) + public function __construct( + ImageService $imageService, + ConfigurationManager $configurationManager + ) { - $this->imageService = $imageService; - $this->configurationManager = $configurationManager; + $this->imageService = $imageService; + $this->configurationManager = $configurationManager; } @@ -94,7 +101,7 @@ public function createPictureTag( $tag = $tag ?: GeneralUtility::makeInstance(TagBuilder::class, 'picture'); $fallbackTag = $fallbackTag ?: GeneralUtility::makeInstance(TagBuilder::class, 'img'); - $settings = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); + $settings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); $webpIsLoaded = (bool)$settings['page.']['10.']['settings.']['webp']; // Deal with file formats that can't be cropped separately @@ -298,7 +305,8 @@ public function createSimpleImageTag( $fallbackImage = ($fallbackImage) ?: $originalImage; // if lazyload enabled add data- prefix - $attributePrefix = $lazyload ? 'data-' : ''; + #$attributePrefix = $lazyload ? 'data-' : ''; + $attributePrefix = ''; // Set image source $tag->addAttribute($attributePrefix . 'src', $this->imageService->getImageUri($originalImage, $absoluteUri)); @@ -397,7 +405,6 @@ public function generateSrcsetImages( $srcset = GeneralUtility::trimExplode(',', $srcset); } - $images = []; foreach ($srcset as $widthDescriptor) { // Determine image width @@ -514,7 +521,6 @@ public function generateSrcsetAttribute(array $srcsetImages): string $srcsetString[] = $this->sanitizeSrcsetUrl($imageCandidate) . ' ' . $widthDescriptor; } } - return implode(', ', $srcsetString); } @@ -533,7 +539,6 @@ public function normalizeImageBreakpoints(array $breakpoints): array $breakpoint = [$breakpoint]; } $breakpoint = array_replace($this->breakpointPrototype, $breakpoint); - } ksort($breakpoints); @@ -574,4 +579,3 @@ public function sanitizeSrcsetUrl(string $url): string } } - diff --git a/Classes/ViewHelpers/MediaViewHelper.php b/Classes/ViewHelpers/MediaViewHelper.php index d67d600b..52aadc29 100644 --- a/Classes/ViewHelpers/MediaViewHelper.php +++ b/Classes/ViewHelpers/MediaViewHelper.php @@ -1,4 +1,6 @@ responsiveImagesUtility = $responsiveImagesUtility; } + /** * @param ConfigurationManager $configurationManager */ @@ -148,7 +155,7 @@ protected function renderPicture(FileInterface $image, $width, $height) $lazyload = 1; } elseif ($this->arguments['lazyload'] == 3) { $lazyload = 3; - $this->tag->addAttribute('loading', 'auto'); + $this->tag->addAttribute('loading', 'auto'); } else { if ($this->arguments['lazyload'] == 2 && $image->getProperty('tx_t3sbootstrap_lazy_load')) { $lazyload = 2; @@ -162,10 +169,10 @@ protected function renderPicture(FileInterface $image, $width, $height) } $placeholderSize = 0; - $placeholderInline = 0; + $placeholderInline = false; if ($lazyload) { - $placeholderSize = $this->arguments['placeholderSize'] ?: 60; - $placeholderInline = $this->arguments['placeholderInline'] ?: 1; + $placeholderSize = !empty($this->arguments['placeholderSize']) ? $this->arguments['placeholderSize']: 60; + $placeholderInline = !empty($this->arguments['placeholderInline']) ? $this->arguments['placeholderInline'] : TRUE; } foreach( $this->arguments['breakpoints'] as $bpKey=>$breakpoint ) { @@ -177,7 +184,7 @@ protected function renderPicture(FileInterface $image, $width, $height) $breakpointArr[$bpKey]['srcset'] .= $srcset.','; } else { $breakpointArr[$bpKey]['srcset'] .= $srcset; - break; + break; } } } @@ -253,32 +260,32 @@ protected function renderImageTag(FileInterface $image, $width, $height, $fileEx } } - $cropVariantCollection = CropVariantCollection::create((string)$cropString); - $cropArea = $cropVariantCollection->getCropArea($cropVariant); + $cropVariantCollection = CropVariantCollection::create((string)$cropString); + $cropArea = $cropVariantCollection->getCropArea($cropVariant); if ( $this->arguments['ratio'] ) { $m = $cropArea->getHeight() / $cropArea->getWidth(); $height = ceil((float)$height * (float)$m); } - $processingInstructions = [ - 'width' => $width, - 'height' => $height, - 'crop' => $cropArea->isEmpty() ? null : $cropArea->makeAbsoluteBasedOnFile($image), - ]; + $processingInstructions = [ + 'width' => $width, + 'height' => $height, + 'crop' => $cropArea->isEmpty() ? null : $cropArea->makeAbsoluteBasedOnFile($image), + ]; - if (!empty($fileExtension)) { - $processingInstructions['fileExtension'] = $fileExtension; - } - $imageService = $this->getImageService(); - $processedImage = $imageService->applyProcessingInstructions($image, $processingInstructions); + if (!empty($fileExtension)) { + $processingInstructions['fileExtension'] = $fileExtension; + } + $imageService = $this->getImageService(); + $processedImage = $imageService->applyProcessingInstructions($image, $processingInstructions); - $settings = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); + $settings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); $webpIsLoaded = (bool)$settings['page.']['10.']['settings.']['webp']; + if ( $webpIsLoaded ) { $webpIdentifier = $processedImage->getIdentifier().'.webp'; $processedImage->setIdentifier($webpIdentifier); } - $imageUri = $imageService->getImageUri($processedImage); if (!$this->tag->hasAttribute('data-focus-area')) { @@ -336,7 +343,7 @@ protected function getCropString($image, $cropString) $cropObject->$cropVariant->cropArea->height = $cHeight; } else { $cHeight = $image->getProperties()['height'] / $pxHeight; - + $pxWidth = $cropedHeight / $rArr[1] * $rArr[0]; $cWidth = $pxWidth / $image->getProperties()['width']; $cropObject->$cropVariant->cropArea->width = $cWidth; diff --git a/Classes/Wrapper/BackgroundWrapper.php b/Classes/Wrapper/BackgroundWrapper.php index e9489e11..13108f6d 100644 --- a/Classes/Wrapper/BackgroundWrapper.php +++ b/Classes/Wrapper/BackgroundWrapper.php @@ -80,7 +80,7 @@ public function getProcessedData(array $processedData, array $flexconf, bool $we $queryBuilder->expr()->eq('sys_language_uid', $processedData['data']['sys_language_uid']), $queryBuilder->expr()->eq('tx_container_parent', $queryBuilder->createNamedParameter($processedData['data']['uid'], \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchColumn(0); $autoplay = $file->getProperties()['autoplay']; @@ -93,6 +93,10 @@ public function getProcessedData(array $processedData, array $flexconf, bool $we $processedData['localVideo']['inlineCSS'] = '@media (max-width:768px){#s-'.$processedData['data']['uid']. ' figure.video{width:'.$mobileWidth.'%; max-height:'.$mobileHeight.'px; margin-left:'.$processedData['horizontalShift'].'%}}'; $ratio = end(explode('/', $flexconf['aspectRatio'])).'x9'; + $ratioArr = explode('x', $ratio); + $x = $ratio; + $y = $ratioArr[1].' / '.$ratioArr[0].' * 100%'; + $processedData['ratioCalcCss'] = '.ratio-'.$x.'{--bs-aspect-ratio:calc('.$y.');}'; $processedData['localVideo']['class'] = ' ratio ratio-'.$ratio; $processedData['localVideo']['overlayChild'] = $overlayChild; $processedData['localVideo']['autoplay'] = $autoplay; @@ -107,6 +111,7 @@ public function getProcessedData(array $processedData, array $flexconf, bool $we // orig. image option in flexform if ($flexconf['origImage']) { $processedData['file'] = $file; + $processedData['ingWidth'] = $flexconf['width'] ? $flexconf['width'] : 1296; } else { $bgImage = GeneralUtility::makeInstance(BackgroundImageUtility::class) ->getBgImage($processedData['data']['uid'], 'tt_content', FALSE, TRUE, $flexconf, FALSE, 0, $webp, $bgMediaQueries); @@ -156,7 +161,7 @@ public function getProcessedData(array $processedData, array $flexconf, bool $we $processedData['controlStyle'] = ''; } else { $processedData['controlStyle'] = ' pointer-events:none;'; - } + } if ( !empty($processedData['videoId']) && $processedData['youtube'] ) { $params = '?autoplay='.$processedData['videoAutoPlay'].'&loop='.$flexconf['videoLoop'].'&playlist='. $processedData['videoId'].'&mute='.$mute.'&rel=0&showinfo=0&controls='.$flexconf['videoControls'].'&modestbranding='.$flexconf['videoControls']; diff --git a/Classes/Wrapper/CardWrapper.php b/Classes/Wrapper/CardWrapper.php index 5d4c67c0..04f1c6a0 100644 --- a/Classes/Wrapper/CardWrapper.php +++ b/Classes/Wrapper/CardWrapper.php @@ -38,20 +38,54 @@ public function getProcessedData(array $processedData, array $flexconf): array $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($processedData['data']['sys_language_uid'], \PDO::PARAM_INT)) ) ->orderBy('sorting') - ->execute() + ->executeQuery() ->fetchAll(); $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); - + $processedData['colclass'] = $flexconf['colclass']; $processedData['cropMaxCharacters'] = $flexconf['cropMaxCharacters']; if (count($children)) { $fileRepository = GeneralUtility::makeInstance(FileRepository::class); + // Flipper defaults + if ($flexconf['card_wrapper'] == 'flipper') { + switch ( count($children) ) { + case 1: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-12 col-md-12'; + $processedData['flipper']['width'] = 1294; + break; + case 2: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-6'; + $processedData['flipper']['width'] = 634; + break; + case 3: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-4'; + $processedData['flipper']['width'] = 414; + break; + case 4: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-3'; + $processedData['flipper']['width'] = 304; + break; + case 6: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-2'; + $processedData['flipper']['width'] = 175; + break; + default: + $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-4'; + $processedData['flipper']['width'] = 576; + } + } + foreach ( $children as $key=>$child ) { $fileObjects = $fileRepository->findByRelation('tt_content', 'assets', $child['uid']); - $children[$key]['imgwidth'] = $child['imagewidth'] ?: 576; + if (!empty($processedData['flipper']) && isset($processedData['flipper']['width'])) { + $flipperWidth = $processedData['flipper']['width']; + } else { + $flipperWidth = 0; + } + $children[$key]['imgwidth'] = !empty($child['imagewidth']) ? $child['imagewidth'] : $flipperWidth; if (!empty($fileObjects)) { if ($flexconf['card_wrapper'] == 'flipper'){ $children[$key]['hFa'] = $child['tx_t3sbootstrap_header_fontawesome'] @@ -66,7 +100,6 @@ public function getProcessedData(array $processedData, array $flexconf): array } $children[$key]['ratio'] = $child['tx_t3sbootstrap_image_ratio'] ?: '0'; $children[$key]['uid'] = $child['uid']; - $children[$key]['subheader'] = $child['subheader']; $children[$key]['header_link'] = $child['header_link']; $children[$key]['header_position'] = $child['header_position'] ? ' text-'.$child['header_position'] :''; @@ -79,28 +112,6 @@ public function getProcessedData(array $processedData, array $flexconf): array } $processedData['cards'] = $children; - if ($flexconf['card_wrapper'] == 'flipper') { - - switch ( count($children) ) { - case 1: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-12 col-md-12'; - break; - case 2: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-6'; - break; - case 3: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-4'; - break; - case 4: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-3'; - break; - case 6: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-2'; - break; - default: - $processedData['flipper']['class'] = 'col-xs-12 col-sm-6 col-md-4'; - } - } // swiperjs if ($flexconf['card_wrapper'] == 'slider') { $processedData['visibleCards'] = (int)$flexconf['visibleCards'] ?: 3; diff --git a/Classes/Wrapper/CarouselContainer.php b/Classes/Wrapper/CarouselContainer.php index e15cbe0e..e35bf9bb 100644 --- a/Classes/Wrapper/CarouselContainer.php +++ b/Classes/Wrapper/CarouselContainer.php @@ -38,7 +38,7 @@ public function getProcessedData(array $processedData, array $flexconf): array ->where( $queryBuilder->expr()->eq('tx_container_parent', $queryBuilder->createNamedParameter($processedData['data']['uid'], \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchAll(); $fileRepository = GeneralUtility::makeInstance(FileRepository::class); diff --git a/Classes/Wrapper/CollapsibleContainer.php b/Classes/Wrapper/CollapsibleContainer.php index be043bca..5362160f 100644 --- a/Classes/Wrapper/CollapsibleContainer.php +++ b/Classes/Wrapper/CollapsibleContainer.php @@ -36,7 +36,7 @@ public function getProcessedData(array $processedData, array $flexconf): array ->where( $queryBuilder->expr()->eq('tx_container_parent', $queryBuilder->createNamedParameter($processedData['data']['uid'], \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchAll(); $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); diff --git a/Classes/Wrapper/SwiperContainer.php b/Classes/Wrapper/SwiperContainer.php index 2b548302..6a1103af 100644 --- a/Classes/Wrapper/SwiperContainer.php +++ b/Classes/Wrapper/SwiperContainer.php @@ -22,7 +22,6 @@ class SwiperContainer implements SingletonInterface */ public function getProcessedData(array $processedData, array $flexconf): array { - $filesFromRepository = []; $processedData['swiperCss'] = !empty($flexconf['swiperCss']) ? $flexconf['swiperCss'] : ''; @@ -42,10 +41,7 @@ public function getProcessedData(array $processedData, array $flexconf): array $processedData['pagination'] = (int)$flexconf['pagination']; $processedData['autoplay'] = (int)$flexconf['autoplay']; $processedData['delay'] = !empty($flexconf['autoplay']) ? (int)$flexconf['delay'] : 99999999; - - -$processedData['origImage'] = $flexconf['origImage'] ?? ''; - + $processedData['origImage'] = $flexconf['origImage'] ? $flexconf['origImage'] : ''; $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); $queryBuilder = $connectionPool->getQueryBuilderForTable('tt_content'); @@ -55,8 +51,9 @@ public function getProcessedData(array $processedData, array $flexconf): array ->where( $queryBuilder->expr()->eq('tx_container_parent', $queryBuilder->createNamedParameter($processedData['data']['uid'], \PDO::PARAM_INT)) ) - ->execute() + ->executeQuery() ->fetchAll(); + $fileRepository = GeneralUtility::makeInstance(FileRepository::class); foreach($statement as $element) { $filesFromRepository[$element['uid']] = $fileRepository->findByRelation('tt_content', 'assets', $element['uid']); diff --git a/Configuration/FlexForms/Container/BackgroundWrapper.xml b/Configuration/FlexForms/Container/BackgroundWrapper.xml index 2fdb4c7e..38b60611 100644 --- a/Configuration/FlexForms/Container/BackgroundWrapper.xml +++ b/Configuration/FlexForms/Container/BackgroundWrapper.xml @@ -90,6 +90,20 @@ + + + + USER:T3SBS\T3sbootstrap\UserFunction\TcaMatcher->isImage + + input + 4 + 4 + 1296 + int + 0 + + + diff --git a/Configuration/FlexForms/Container/CardWrapper.xml b/Configuration/FlexForms/Container/CardWrapper.xml index 962cf0a1..e10925ed 100644 --- a/Configuration/FlexForms/Container/CardWrapper.xml +++ b/Configuration/FlexForms/Container/CardWrapper.xml @@ -95,6 +95,21 @@ + + + + FIELD:sDEF.card_wrapper:=:columns + default - 3 columns: "col-sm-6 col-lg-4 mb-4" + + input + 40 + col-sm-6 col-lg-4 mb-4 + trim + + + + + @@ -174,6 +189,7 @@ + if "0" the cards width is used - or auto-width if the cards width is also empty (best practies) FIELD:sDEF.card_wrapper:=:slider input @@ -315,7 +331,7 @@ - + @@ -334,7 +350,6 @@ - diff --git a/Configuration/FlexForms/Container/ThreeColumns.xml b/Configuration/FlexForms/Container/ThreeColumns.xml index 825e3c21..30a8decc 100644 --- a/Configuration/FlexForms/Container/ThreeColumns.xml +++ b/Configuration/FlexForms/Container/ThreeColumns.xml @@ -28,7 +28,7 @@ - INFO: https://getbootstrap.com/docs/5.1/layout/gutters/#horizontal-gutters + INFO: https://getbootstrap.com/docs/5.3/layout/gutters/#horizontal-gutters select selectSingle @@ -65,7 +65,7 @@ - INFO: https://getbootstrap.com/docs/5.1/layout/gutters/#vertical-gutters + INFO: https://getbootstrap.com/docs/5.3/layout/gutters/#vertical-gutters select selectSingle @@ -139,7 +139,7 @@ - Col-xl-* + Col-xxl-* @@ -236,7 +236,6 @@ 3 3 - 4 4 @@ -306,7 +305,6 @@ 3 3 - 4 4 @@ -385,7 +383,6 @@ 3 3 - 4 4 @@ -455,7 +452,6 @@ 3 3 - 4 4 @@ -525,7 +521,6 @@ 3 3 - 4 4 @@ -604,7 +599,6 @@ 3 3 - 4 4 @@ -674,7 +668,6 @@ 3 3 - 4 4 @@ -744,7 +737,6 @@ 3 3 - 4 4 @@ -823,7 +815,6 @@ 3 3 - 4 4 @@ -893,7 +884,6 @@ 3 3 - 4 4 @@ -963,7 +953,6 @@ 3 3 - 4 4 @@ -1042,7 +1031,6 @@ 3 3 - 4 4 @@ -1112,7 +1100,6 @@ 3 3 - 4 4 @@ -1182,7 +1169,6 @@ 3 3 - 4 4 @@ -1261,7 +1247,6 @@ 3 3 - 4 4 @@ -1331,7 +1316,6 @@ 3 3 - 4 4 @@ -1401,7 +1385,6 @@ 3 3 - 4 4 diff --git a/Configuration/RTE/Default.yaml b/Configuration/RTE/Default.yaml index d33bab01..98e08a27 100644 --- a/Configuration/RTE/Default.yaml +++ b/Configuration/RTE/Default.yaml @@ -208,3 +208,4 @@ editor: HTMLparser_db: noAttrib: + diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 20cba922..3a85e440 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -27,3 +27,11 @@ services: - name: event.listener identifier: 't3sbootstrap/AssetPostProcessing' event: TYPO3\CMS\Core\Page\Event\BeforeJavaScriptsRenderingEvent + + + T3SBS\T3sbootstrap\EventListener\TCA\TcaCompilation: + tags: + - name: event.listener + identifier: 't3sbootstrap/TcaPostProcessing' + event: TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent + \ No newline at end of file diff --git a/Configuration/TCA/Overrides/pages.php b/Configuration/TCA/Overrides/pages.php index 682926db..b6cb66aa 100644 --- a/Configuration/TCA/Overrides/pages.php +++ b/Configuration/TCA/Overrides/pages.php @@ -106,6 +106,21 @@ 'config' => [ 'type' => 'input', 'size' => 20, + 'eval' => 'trim', + 'valuePicker' => [ + 'items' => [ + ['typo3', 'fab fa-typo3'], + ['envelope', 'far fa-envelope'], + ['info-circle', 'fas fa-info-circle'], + ['exclamation-circle', 'fas fa-exclamation-circle'], + ['question-circle', 'fas fa-question-circle'], + ['check-circle', 'fas fa-check-circle'], + ['chevron-circle-left', 'fas fa-chevron-circle-left'], + ['chevron-circle-right', 'fas fa-chevron-circle-right'], + ['youtube', 'fab fa-youtube'], + ['vimeo', 'fab fa-vimeo-square'], + ], + ], ] ], 'tx_t3sbootstrap_icon_only' => [ @@ -329,7 +344,6 @@ } if (array_key_exists('fontawesome', $extconf) && $extconf['fontawesome'] === '1') { - $GLOBALS['TCA']['pages']['palettes']['fontawesome'] = [ 'showitem' => 'tx_t3sbootstrap_fontawesome_icon, tx_t3sbootstrap_icon_only', @@ -340,7 +354,7 @@ 'pages', '--palette--;Fontawesome Icon;fontawesome', '', - 'after:layout' + 'after:title' ); } @@ -376,6 +390,7 @@ ], ] ); + /*************** * Register PageTSConfig Files diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index 79b41c04..e9b63906 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -1,5 +1,4 @@ 4 ] ], - 'tx_t3sbootstrap_galleryGutters' => [ - 'label' => 'Gallery gutters', - 'exclude' => 1, - 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'items' => [ - [1,1], - [2,2], - [3,3], - [4,4], - [5,5] - ], - 'default' => 4 - ] - ], 'tx_t3sbootstrap_bgopacity' => [ 'label' => 'Opacity for Background color only', 'exclude' => 1, @@ -944,6 +927,16 @@ 'tx_t3sbootstrap_inTextImgRowWidth' => [ 'label' => 'Gallery row width in %', 'exclude' => 1, + 'displayCond' => [ + 'AND' => [ + 'FIELD:CType:=:textpic', + 'FIELD:CType:=:textmedia', + 'FIELD:CType:=:t3sbs_mediaobject', + 'FIELD:CType:=:t3sbs_card', + 'FIELD:CType:=:t3sbs_toast', + 'FIELD:CType:=:t3sbs_gallery', + ], + ], 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', @@ -960,6 +953,58 @@ 'default' => 'auto' ] ], + 'tx_t3sbootstrap_gutters' => [ + 'label' => 'Horizontal gutters', + 'exclude' => 1, + 'description' => 'INFO: https://getbootstrap.com/docs/5.3/layout/gutters/#horizontal-gutters', + 'displayCond' => [ + 'OR' => [ + 'FIELD:CType:=:image', + 'FIELD:CType:=:textpic', + 'FIELD:CType:=:textmedia', + 'FIELD:CType:=:t3sbs_gallery', + ], + ], + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['gx-0 (no gutters)','gx-0'], + ['gx-1','gx-1'], + ['gx-2','gx-2'], + ['gx-3','gx-3'], + ['gx-4 (default)','gx-4'], + ['gx-5','gx-5'], + ], + 'default' => 'gx-4' + ] + ], + 'tx_t3sbootstrap_verticalgutters' => [ + 'label' => 'Vertical gutters', + 'exclude' => 1, + 'description' => 'INFO: https://getbootstrap.com/docs/5.3/layout/gutters/#vertical-gutters', + 'displayCond' => [ + 'OR' => [ + 'FIELD:CType:=:image', + 'FIELD:CType:=:textpic', + 'FIELD:CType:=:textmedia', + 'FIELD:CType:=:t3sbs_gallery', + ], + ], + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['gy-0 (no gutters)','mb-0'], + ['gy-1','mb-1'], + ['gy-2','mb-2'], + ['gy-3','mb-3'], + ['gy-4 (default)','mb-4'], + ['gy-5','mb-5'], + ], + 'default' => 'mb-4' + ] + ], 'tx_t3sbootstrap_bordercolor' => [ 'label' => 'Border color', 'exclude' => 1, @@ -985,7 +1030,19 @@ 'tx_t3sbootstrap_image_ratio' => [ 'label' => 'Image Ratio', 'exclude' => 1, - 'displayCond' => 'USER:T3SBS\T3sbootstrap\UserFunction\TcaMatcher->ratio_'.$extconf['ratio'], + 'displayCond' => [ + 'AND' => [ + 'USER:T3SBS\T3sbootstrap\UserFunction\TcaMatcher->ratio_'.$extconf['ratio'], + 'OR' => [ + 'FIELD:CType:=:textpic', + 'FIELD:CType:=:textmedia', + 'FIELD:CType:=:t3sbs_mediaobject', + 'FIELD:CType:=:t3sbs_card', + 'FIELD:CType:=:t3sbs_toast', + 'FIELD:CType:=:t3sbs_gallery', + ] + ] + ], 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', @@ -1001,16 +1058,26 @@ 'default' => '' ] ], - 'tx_t3sbootstrap_image_orig' => [ 'exclude' => 1, 'label' => 'Use Original Image', - 'displayCond' => 'USER:T3SBS\T3sbootstrap\UserFunction\TcaMatcher->ratio_'.$extconf['origimage'], + 'displayCond' => [ + 'AND' => [ + 'USER:T3SBS\T3sbootstrap\UserFunction\TcaMatcher->ratio_'.$extconf['ratio'], + 'OR' => [ + 'FIELD:CType:=:textpic', + 'FIELD:CType:=:textmedia', + 'FIELD:CType:=:t3sbs_mediaobject', + 'FIELD:CType:=:t3sbs_card', + 'FIELD:CType:=:t3sbs_toast', + 'FIELD:CType:=:t3sbs_gallery', + ] + ] + ], 'config' => [ 'type' => 'check' ] ], - 'tx_t3sbootstrap_animateCss' => [ 'exclude' => 1, 'l10n_display' => 'hideDiff', @@ -1405,23 +1472,35 @@ ); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( 'tt_content', - 'mediaAdjustments', + 'imageSettings', 'tx_t3sbootstrap_image_ratio', 'after:tx_t3sbootstrap_bordercolor' ); + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( 'tt_content', - 'mediaAdjustments', + 'imageSettings', 'tx_t3sbootstrap_image_orig', 'before:tx_t3sbootstrap_image_ratio' ); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( 'tt_content', - 'mediaAdjustments', + 'imageSettings', 'tx_t3sbootstrap_inTextImgRowWidth', 'after:tx_t3sbootstrap_bordercolor' ); +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( + 'tt_content', + 'imageGutters', + 'tx_t3sbootstrap_gutters', + 'after:tx_t3sbootstrap_image_ratio' +); +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette( + 'tt_content', + 'imageGutters', + 'tx_t3sbootstrap_verticalgutters', + 'after:tx_t3sbootstrap_gutters' +); # add palette bootstrap etc \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( @@ -1448,6 +1527,21 @@ '', 'after:layout' ); + +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( + 'tt_content', + '--palette--;T3SB Image Settings;imageSettings', + '', + 'after:mediaAdjustments' +); +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( + 'tt_content', + '--palette--;T3SB Image Gutters;imageGutters', + '', + 'after:mediaAdjustments' +); + + # add palette animate if EXT:content_animations is not loaded if ( !\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('content_animations') ) { \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( @@ -1458,10 +1552,6 @@ ); } -$GLOBALS['TCA']['tt_content']['palettes']['bsRowWidth'] = [ - 'showitem' => 'tx_t3sbootstrap_image_ratio, tx_t3sbootstrap_inTextImgColumns, tx_t3sbootstrap_galleryGutters' -]; - $GLOBALS['TCA']['tt_content']['palettes']['bsHeaderExtra'] = [ 'showitem' => 'tx_t3sbootstrap_header_display, tx_t3sbootstrap_header_position, --linebreak--, tx_t3sbootstrap_header_class, tx_t3sbootstrap_header_fontawesome' diff --git a/Configuration/TCA/tx_t3sbootstrap_domain_model_config.php b/Configuration/TCA/tx_t3sbootstrap_domain_model_config.php index 585a1ece..d83cc050 100644 --- a/Configuration/TCA/tx_t3sbootstrap_domain_model_config.php +++ b/Configuration/TCA/tx_t3sbootstrap_domain_model_config.php @@ -249,12 +249,22 @@ 'type' => 'input' ] ], - 'sectionmenu_scrollspy_offset' => [ + 'sectionmenu_scrollspy_threshold' => [ 'exclude' => false, - 'label' => 'Scrollspy offset (int)', + 'label' => 'Scrollspy threshold (string)', 'accordion_id' => 1, 'accordion_sub' => '1-5', - 'info' => 'in px - to activate the menu item - (default 130)', + 'info' => 'https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#threshold - (default: 0.1, 0.5, 1)', + 'config' => [ + 'type' => 'input' + ] + ], + 'sectionmenu_scrollspy_root_margin' => [ + 'exclude' => false, + 'label' => 'Scrollspy rootMargin (string)', + 'accordion_id' => 1, + 'accordion_sub' => '1-5', + 'info' => 'https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin - (default: 0px 0px -25%)', 'config' => [ 'type' => 'input' ] @@ -551,6 +561,20 @@ 'type' => 'input' ] ], + 'navbar_dark_mode' => [ + 'exclude' => false, + 'label' => 'Color mode toggler', + 'info' => 'To allow visitors or users to toggle color modes.', + 'accordion_id' => 3, + 'config' => [ + 'type' => 'check', + 'items' => [ + '1' => [ + '0' => 'Enable as right menu dropdown' + ] + ] + ] + ], 'navbar_sectionmenu' => [ 'exclude' => false, 'label' => 'Sectionmenu', diff --git a/Configuration/TSConfig/Page.tsconfig b/Configuration/TSConfig/Page.tsconfig index 881421f8..5f25c645 100644 --- a/Configuration/TSConfig/Page.tsconfig +++ b/Configuration/TSConfig/Page.tsconfig @@ -27,13 +27,13 @@ TCEFORM.tt_content { linkToTop.disabled = 1 table_class.disabled = 1 space_before_class.disabled = 1 - space_after_class.disabled = 1 - + space_after_class.disabled = 1 tx_t3sbootstrap_header_celink { types { t3sbs_button.disabled = 1 t3sbs_toast.disabled = 1 t3sbs_carousel.disabled = 1 + t3sbs_gallery.disabled = 1 two_columns.disabled = 1 three_columns.disabled = 1 four_columns.disabled = 1 @@ -234,7 +234,6 @@ TCEFORM.tt_content { tx_t3sbootstrap_image_ratio { types { t3sbs_toast.disabled = 1 - t3sbs_mediaobject.disabled = 1 two_columns.disabled = 1 three_columns.disabled = 1 four_columns.disabled = 1 diff --git a/Configuration/TypoScript/ContentElement/Bootstrap.typoscript b/Configuration/TypoScript/ContentElement/Bootstrap.typoscript index d3382e47..e5d8a797 100644 --- a/Configuration/TypoScript/ContentElement/Bootstrap.typoscript +++ b/Configuration/TypoScript/ContentElement/Bootstrap.typoscript @@ -28,7 +28,8 @@ tt_content { ratioWithHeight = {$bootstrap.image.ratioWithHeight} maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } } @@ -70,7 +71,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } } @@ -101,7 +103,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } @@ -129,7 +132,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } diff --git a/Configuration/TypoScript/ContentElement/Container.typoscript b/Configuration/TypoScript/ContentElement/Container.typoscript index 718024a7..db6ab3e1 100644 --- a/Configuration/TypoScript/ContentElement/Container.typoscript +++ b/Configuration/TypoScript/ContentElement/Container.typoscript @@ -406,5 +406,5 @@ tt_content { as = col_310 } } - } + } } diff --git a/Configuration/TypoScript/ContentElement/Default.typoscript b/Configuration/TypoScript/ContentElement/Default.typoscript index 8d8d6f18..ed93dd2b 100644 --- a/Configuration/TypoScript/ContentElement/Default.typoscript +++ b/Configuration/TypoScript/ContentElement/Default.typoscript @@ -18,7 +18,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } } @@ -38,7 +39,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } } @@ -58,7 +60,8 @@ tt_content { maxWidthMediaObject = {$bootstrap.image.maxWidthMediaObject} maxWidthToast = {$bootstrap.image.maxWidthToast} disableAutoRow = {$bootstrap.image.disableAutoRow} - overrideSmallColumns = {$pages.override.smallColumns} + overrideSmallColumns = {$bootstrap.pages.override.smallColumns} + overrideContainer = {$bootstrap.pages.override.container} configuid = {$bootstrap.config.uid} } } diff --git a/Configuration/TypoScript/Lib/ContentElement.typoscript b/Configuration/TypoScript/Lib/ContentElement.typoscript index 603d8858..3ce0ac8f 100644 --- a/Configuration/TypoScript/Lib/ContentElement.typoscript +++ b/Configuration/TypoScript/Lib/ContentElement.typoscript @@ -85,7 +85,6 @@ lib.contentElement { cdnEnable = {$bootstrap.cdn.enable} containerError = {$bootstrap.config.containerError} sectionmenuAnchorOffset = {$bootstrap.config.sectionmenuAnchorOffset} - sectionmenuScrollspyOffset = {$bootstrap.config.sectionmenuScrollspyOffset} sectionmenuScrollspy = {$bootstrap.config.sectionmenuScrollspy} sidebarSectionMobile = {$bootstrap.config.sidebarSectionMobile} breakpoint = {$bootstrap.config.navbarBreakpoint} @@ -99,7 +98,10 @@ lib.contentElement { // used also with config config { sectionmenuAnchorOffset = {$bootstrap.config.sectionmenuAnchorOffset} - sectionmenuScrollspyOffset = {$bootstrap.config.sectionmenuScrollspyOffset} + sectionmenuScrollspyRootMargin = {$bootstrap.config.sectionmenuScrollspyRootMargin} + sectionmenuScrollspyThreshold = {$bootstrap.config.sectionmenuScrollspyThreshold} + sidebarSectionMobile = {$bootstrap.config.sidebarSectionMobile} + navbarBreakpointWidth = {$bootstrap.config.navbarBreakpointWidth} } navbarEnable = {$bootstrap.config.navbarEnable} navbar { @@ -108,7 +110,7 @@ lib.contentElement { lg = {$bootstrap.navbar.breakpoint.lg} xl = {$bootstrap.navbar.breakpoint.xl} xxl = {$bootstrap.navbar.breakpoint.xxl} - } + } } variables { be_layout = TEXT diff --git a/Configuration/TypoScript/Lib/_main.typoscript b/Configuration/TypoScript/Lib/_main.typoscript index d1193ee1..66afc800 100644 --- a/Configuration/TypoScript/Lib/_main.typoscript +++ b/Configuration/TypoScript/Lib/_main.typoscript @@ -92,30 +92,30 @@ lib.printButton { 10 = TEXT 10.value = &no_cache=1 - 20 = TEXT - 20.data = GP:L - 20.wrap = &L=| - 20.required = 1 - - 30 = TEXT - 30.data = GP:tx_news_pi1 | news - 30.wrap = &tx_news_pi1[news]=| - 30.required = 1 - - 40 = TEXT - 40.data = GP:tx_news_pi1 | controller - 40.wrap = &tx_news_pi1[controller]=| - 40.required = 1 - - 50 = TEXT - 50.data = GP:tx_news_pi1 | action - 50.wrap = &tx_news_pi1[action]=| - 50.required = 1 - - 60 = TEXT - 60.data = GP:cHash - 60.wrap = &cHash=| - 60.required = 1 + 20 = TEXT + 20.data = GP:L + 20.wrap = &L=| + 20.required = 1 + + 30 = TEXT + 30.data = GP:tx_news_pi1 | news + 30.wrap = &tx_news_pi1[news]=| + 30.required = 1 + + 40 = TEXT + 40.data = GP:tx_news_pi1 | controller + 40.wrap = &tx_news_pi1[controller]=| + 40.required = 1 + + 50 = TEXT + 50.data = GP:tx_news_pi1 | action + 50.wrap = &tx_news_pi1[action]=| + 50.required = 1 + + 60 = TEXT + 60.data = GP:cHash + 60.wrap = &cHash=| + 60.required = 1 70 = TEXT 70.value = &type=98 diff --git a/Configuration/TypoScript/Page/BodyTag.typoscript b/Configuration/TypoScript/Page/BodyTag.typoscript index 4d47a089..edc37e7a 100644 --- a/Configuration/TypoScript/Page/BodyTag.typoscript +++ b/Configuration/TypoScript/Page/BodyTag.typoscript @@ -48,9 +48,9 @@ page { 10.wrap = padding-top:|px; if.isTrue = {$bootstrap.config.navbarHeight} - 20 = TEXT - 20.value = position:relative; - 20.if.isTrue = {$bootstrap.config.navbarSectionmenu} +# 20 = TEXT +# 20.value = position:relative; +# 20.if.isTrue = {$bootstrap.config.navbarSectionmenu} } 40 = TEXT 40.value = {$bootstrap.config.navbarBreakpoint} @@ -61,10 +61,15 @@ page { 50.if.isTrue = {$bootstrap.config.navbarBreakpointWidth} 60 = TEXT - 60.value = {$bootstrap.config.sectionmenuScrollspyOffset} - 60.noTrimWrap = | data-bs-spy="scroll" data-bs-target="#main-navbar" data-bs-offset="|" tabindex="0"| + 60.value = {$bootstrap.config.sectionmenuScrollspyThreshold} + 60.noTrimWrap = | data-bs-spy="scroll" data-bs-target="#main-navbar" data-bs-threshold="[|]" data-bs-smooth-scroll="true" tabindex="0"| 60.if.isTrue = {$bootstrap.config.navbarSectionmenu} + 61 = TEXT + 61.value = {$bootstrap.config.sectionmenuScrollspyRootMargin} + 61.noTrimWrap = | data-bs-root-margin="|"| + 61.if.isTrue = {$bootstrap.config.navbarSectionmenu} + 70 = TEXT 70.value = true 70.noTrimWrap = | data-bs-no-jquery="|"| diff --git a/Configuration/TypoScript/Page/IncludeDefault.typoscript b/Configuration/TypoScript/Page/IncludeDefault.typoscript index cdee6f44..0f51ebfd 100644 --- a/Configuration/TypoScript/Page/IncludeDefault.typoscript +++ b/Configuration/TypoScript/Page/IncludeDefault.typoscript @@ -48,7 +48,7 @@ temp.jsCookieConsent > // preload GOOGLE FONTS [{$bootstrap.preloadGooleFonts} == 1] @import 'fileadmin/T3SB/Configuration/TypoScript/preloadGooleFonts.typoscript' -[END] +[global] # Bugfix for Safari browser if using webp with lazyload [browser('Safari') && {$bootstrap.extconf.webp} == 1 && {$bootstrap.extconf.lazyLoad} > 0] @@ -56,7 +56,7 @@ page.cssInline { 124 = TEXT 124.value = picture img.lazy {opacity:1 !important;} } -[END] +[global] # Background Image [{$bootstrap.config.backgroundImageEnable} == 1] @@ -64,7 +64,7 @@ page.cssInline { 5 = TEXT 5.value = body {background-repeat:no-repeat;background-position: center center;background-size: cover;background-attachment: fixed} } -[END] +[global] # load jquery into the header [{$bootstrap.config.jqueryHeader} == 1 && {$bootstrap.cdn.enable} == 1] @@ -75,7 +75,7 @@ page.includeJSLibs { jqueryCDN.forceOnTop = 1 jqueryCDN.if.isFalse = {$bootstrap.disable.jquery} } -[END] +[global] [{$bootstrap.config.jqueryHeader} == 1 && {$bootstrap.cdn.enable} == 0] page.includeJSFooterlibs.jquery > @@ -84,7 +84,12 @@ page.includeJSLibs { jquery.forceOnTop = 1 jquery.if.isFalse = {$bootstrap.disable.jquery} } -[END] +[global] + +# Bootstrap color mode toggler in navbar +[{$bootstrap.config.navbarDarkMode} == 1] +page.includeCSS.bsicons = EXT:t3sbootstrap/Resources/Public/Contrib/BootstrapIsons/bootstrap-icons.css +[global] ########################################################################################################## # @@ -93,20 +98,20 @@ page.includeJSLibs { ########################################################################################################## [{$bootstrap.config.faLinkIcons} == 1 && {$bootstrap.extconf.fontawesomeCss} == 0] page.includeCSS.t3sfontawesomeMinLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesomeMinLink.css -[END] +[global] [{$bootstrap.config.faLinkIcons} == 1 && {$bootstrap.extconf.fontawesomeCss} == 1] page.includeCSS.t3sfontawesomeLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesomeLink.css -[END] +[global] [{$bootstrap.config.faLinkIcons} == 1 && {$bootstrap.extconf.fontawesomeCss} == 2] page.includeCSS.t3sfontawesomeProLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesomeProLink.css -[END] +[global] [{$bootstrap.config.faLinkIcons} == 1 && {$bootstrap.extconf.fontawesomeCss} == 3] page.includeCSS.t3sfontawesomeLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesome6Link.css -[END] +[global] [{$bootstrap.config.faLinkIcons} == 1 && {$bootstrap.extconf.fontawesomeCss} == 4] page.includeCSS.t3sfontawesomeProLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesome6ProLink.css -[END] +[global] [{$bootstrap.config.faLinkIcons} == 0] page.includeCSS.t3sfontawesomeMin = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesomeMin.css page.includeCSS.t3sfontawesomeMin.if.isFalse = {$bootstrap.extconf.fontawesomeCss} -[END] +[global] diff --git a/Configuration/TypoScript/Page/IncludeLocal.typoscript b/Configuration/TypoScript/Page/IncludeLocal.typoscript index d6ee5d44..74d0aebb 100644 --- a/Configuration/TypoScript/Page/IncludeLocal.typoscript +++ b/Configuration/TypoScript/Page/IncludeLocal.typoscript @@ -77,6 +77,3 @@ page { } } - - - diff --git a/Configuration/TypoScript/Page/JS/CookieConsent.typoscript b/Configuration/TypoScript/Page/JS/CookieConsent.typoscript index 389bedbd..ebcac1e3 100644 --- a/Configuration/TypoScript/Page/JS/CookieConsent.typoscript +++ b/Configuration/TypoScript/Page/JS/CookieConsent.typoscript @@ -79,7 +79,6 @@ temp.jsCookieConsent { }; } - }); - + }); ) -} \ No newline at end of file +} diff --git a/Configuration/TypoScript/Page/Print.typoscript b/Configuration/TypoScript/Page/Print.typoscript index e2ec4dcb..94d64f31 100644 --- a/Configuration/TypoScript/Page/Print.typoscript +++ b/Configuration/TypoScript/Page/Print.typoscript @@ -2,7 +2,7 @@ print = PAGE print { typeNum = 98 - bodyTag = + bodyTag = config.index_enable = 0 headerData.123 = TEXT headerData.123.value = @@ -13,24 +13,13 @@ print { } includeCSS { - - bootstrapCDN = https://stackpath.bootstrapcdn.com/bootstrap/{$bootstrap.cdn.bootstrap}/css/bootstrap.min.css + bootstrapCDN = https://cdn.jsdelivr.net/npm/bootstrap@{$bootstrap.cdn.bootstrap}/dist/css/bootstrap.min.css + bootstrapCDN.integrity = sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65 bootstrapCDN.external = 1 bootstrapCDN.forceOnTop = 1 - bootstrapCDN.if { - isFalse = {$bootstrap.cdn.bootswatch} - isTrue = {$bootstrap.cdn.enable} - } - - t3sfontawesomeCDN = https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css - t3sfontawesomeCDN.external = 1 - t3sfontawesomeLink = EXT:t3sbootstrap/Resources/Public/Contrib/Fontawesome/css/fontawesomeLink.css - t3sbootstrap = EXT:t3sbootstrap/Resources/Public/Styles/t3sbootstrap.css - t3sprint = EXT:t3sbootstrap/Resources/Public/Styles/t3sprint.css - } includeJSFooterlibs { @@ -60,6 +49,8 @@ print { be_layout = TEXT be_layout.value < temp.pagelayout } + + settings { // EM config expandedContent = {$bootstrap.extconf.expandedContent} @@ -196,7 +187,6 @@ print { lightboxSelection = {$bootstrap.config.lightboxSelection} magnifying = {$bootstrap.config.magnifying} sectionmenuAnchorOffset = {$bootstrap.config.sectionmenuAnchorOffset} - sectionmenuScrollspyOffset = {$bootstrap.config.sectionmenuScrollspyOffset} sectionmenuStickyTop = {$bootstrap.config.sectionmenuStickyTop} backgroundImageEnable = {$bootstrap.config.backgroundImageEnable} backgroundImageSlide = {$bootstrap.config.backgroundImageSlide} @@ -213,10 +203,11 @@ print { } lazyLoad = 0 } - dataProcessing.90 = T3SBS\T3sbootstrap\DataProcessing\ConfigProcessor - dataProcessing.90 { - navbarExtraRow = {$bootstrap.config.navbarExtraRow} - rootline = {$bootstrap.config.generalRootline} - } + +# dataProcessing.90 = T3SBS\T3sbootstrap\DataProcessing\ConfigProcessor +# dataProcessing.90 { +# navbarExtraRow = {$bootstrap.config.navbarExtraRow} +# rootline = {$bootstrap.config.generalRootline} +# } } } diff --git a/Configuration/TypoScript/Page/Register.typoscript b/Configuration/TypoScript/Page/Register.typoscript index e55aa0ed..e20e277d 100644 --- a/Configuration/TypoScript/Page/Register.typoscript +++ b/Configuration/TypoScript/Page/Register.typoscript @@ -10,7 +10,7 @@ page.1.newsTitle.cObject { conf.tx_news_domain_model_news = TEXT conf.tx_news_domain_model_news.field = title } -[END] +[global] diff --git a/Configuration/TypoScript/Page/Template.typoscript b/Configuration/TypoScript/Page/Template.typoscript index e6cf718f..49b3a5f9 100644 --- a/Configuration/TypoScript/Page/Template.typoscript +++ b/Configuration/TypoScript/Page/Template.typoscript @@ -35,12 +35,14 @@ page { fontawesome.6latest = {$bootstrap.cdn.fontawesome6latest} fontawesome.pagetitle = {$bootstrap.extconf.fontawesomepagetitle} fontawesome.fontawesomeCss = {$bootstrap.extconf.fontawesomeCss} - fontawesome.faLinkIcons = {$bootstrap.config.faLinkIcons} + fontawesome.faLinkIcons = {$bootstrap.config.faLinkIcons} disableDefaultCss = {$bootstrap.config.disableDefaultCss} codesnippet = {$bootstrap.extconf.codesnippet} lazyLoad = {$bootstrap.extconf.lazyLoad} lazyLoadThreshold = {$bootstrap.image.lazyLoadThreshold} webp = {$bootstrap.extconf.webp} + indexedsearch.loaded = {$bootstrap.ext.indexedsearch} + kesearch.loaded = {$bootstrap.ext.kesearch} cookieconsent = {$bootstrap.extconf.cookieconsent} cdn = {$bootstrap.cdn.enable} googlefonts = {$bootstrap.cdn.googlefonts} @@ -53,6 +55,7 @@ page { bgMediaQueries = {$bootstrap.image.bgMediaQueries} sectionmenuIcons = {$bootstrap.config.sectionmenuIcons} submenu.styleOne = {$bootstrap.submenu.styleOne} + viewportWidthCookie = {$bootstrap.image.viewportWidthCookie} navbar { image.defaultPath = {$bootstrap.navbar.image.defaultPath} image.width = {$bootstrap.navbar.image.width} @@ -89,7 +92,6 @@ page { } } config { - darkMode = {$bootstrap.config.darkMode} jqueryHeader = {$bootstrap.config.jqueryHeader} navbarPlusicon = {$bootstrap.config.navbarPlusicon} } @@ -251,7 +253,6 @@ page { excludeUidList.cObject.value = {$bootstrap.config.homepageUid} levels = 1 as = metaNavigation - } 50.if.isTrue = {$bootstrap.config.metaEnable} @@ -333,7 +334,7 @@ page { } # prevent error: Undefined array key "breadcrumb." -config.pageTitleProviders.breadcrumb.provider = +config.pageTitleProviders.breadcrumb.provider = # Language in Toast lib.t3sbs.close = TEXT @@ -342,13 +343,9 @@ lib.t3sbs.close.value = Schließen lib.t3sbs.dispose = TEXT lib.t3sbs.dispose.value = Nicht mehr anzeigen - [loaded('indexed_search')] page.10.settings.indexedsearch.targetPid = {$plugin.tx_indexedsearch.settings.targetPid} -[ELSE] -page.10.settings.indexedsearch.targetPid = 0 -[END] - +[global] plugin.tx_felogin_login { view { @@ -360,3 +357,7 @@ plugin.tx_felogin_login { // import outsourced setup @import 'fileadmin/T3SB/Configuration/TypoScript/t3sbsetup.typoscript' + +['{$bootstrap.cdn.bootstrap}' < '5.3'] +page.10.settings.config.navbarDarkMode = 0 +[global] diff --git a/Configuration/TypoScript/Page/_main.typoscript b/Configuration/TypoScript/Page/_main.typoscript index 439ea19c..8faca0cc 100644 --- a/Configuration/TypoScript/Page/_main.typoscript +++ b/Configuration/TypoScript/Page/_main.typoscript @@ -4,31 +4,31 @@ [{$bootstrap.extconf.cookieconsent} == 1] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/JS/CookieConsent.typoscript' -[END] +[global] [{$bootstrap.extconf.customScss} == 1 && {$bootstrap.cdn.enable} == 0] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeBootstrapScss.typoscript' @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeLocal.typoscript' -[END] +[global] [{$bootstrap.extconf.customScss} == 1 && {$bootstrap.cdn.enable} == 1] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeBootstrapScss.typoscript' @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeCdn.typoscript' -[END] +[global] [{$bootstrap.extconf.customScss} == 0 && {$bootstrap.cdn.enable} == 1] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeBootstrapCss.typoscript' @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeCdn.typoscript' -[END] +[global] [{$bootstrap.extconf.customScss} == 0 && {$bootstrap.cdn.enable} == 0] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeBootstrapCss.typoscript' @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeLocal.typoscript' -[END] +[global] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/IncludeDefault.typoscript' @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/Template.typoscript' [{$bootstrap.print.enable} == 1] @import 'EXT:t3sbootstrap/Configuration/TypoScript/Page/Print.typoscript' -[END] +[global] diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript index a8c1e84d..fd651ab6 100644 --- a/Configuration/TypoScript/constants.typoscript +++ b/Configuration/TypoScript/constants.typoscript @@ -17,7 +17,7 @@ plugin.tx_t3sbootstrap { bootstrap.cdn.bootstraplatest = 5.2.3 bootstrap.cdn.noZip = 0 bootstrap.cdn.fontawesome5latest = 5.15.4 -bootstrap.cdn.fontawesome6latest = 6.2.1 +bootstrap.cdn.fontawesome6latest = 6.4.0 #------------------------------------------------------------------------------- # Constant Editor @@ -41,8 +41,8 @@ bootstrap.cdn { popperjs = 2.11.6 # cat=bootstrap-cdn/b-version/13; type=small; label=Masonry js: masonry = 4.2.2 - # cat=bootstrap-cdn/b-version/12; type=small; label=Fontawesome: e.g. 5.15.4 or 6.2.1 - fontawesome = 6.2.1 + # cat=bootstrap-cdn/b-version/12; type=small; label=Fontawesome: e.g. 5.15.4 or 6.4.0 + fontawesome = 6.4.0 # cat=bootstrap-cdn/b-version/20; type=small; label=jQuery library: jquery = 3.6.1 # cat=bootstrap-cdn/b-version/22; type=small; label=jQuery Easing: @@ -104,6 +104,8 @@ bootstrap.cdn { # customsubcategory=c-image=Lazyloading Threshold # customsubcategory=d-image=Picturefill bootstrap.image { + # cat=bootstrap-image/a-image/10; type=boolean; label=Set Cookie with viewport width: usefull if using container "fluid-container" and auto image width. + viewportWidthCookie = 0 # cat=bootstrap-image/a-image/30; type=boolean; label=Min. width: if enabled the minimum "equalMediaWidth" is set to 575px and therefore 100% wide on mobile. minimumWidth = 0 # cat=bootstrap-image/a-image/40; type=boolean; label=Ratio: if enabled use width and height for ratio in textmedia, textpic, image, card and media object. @@ -225,8 +227,6 @@ bootstrap.pagebrowser.entryLevel = 1 bootstrap.config.enableUtilityColors = 1 # hints to increase the website speed in the BE Modul bootstrap.config.enableInfo = 1 -# enable the Dark Mode - if "prefers-color-scheme" (iOS and Android) is "dark" -> the body tag gets the class "dark-mode" -bootstrap.config.darkMode = 0 # include print template bootstrap.print.enable = 0 @@ -323,7 +323,7 @@ styles.content.textmedia.borderColor = styles.content.textmedia.borderWidth = styles.content.textmedia.borderPadding = -# pages override +# pages override - deprecated pages.override { # 1,2,3,4 or 6 (only) smallColumns = diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript index f2057798..5849d333 100644 --- a/Configuration/TypoScript/setup.typoscript +++ b/Configuration/TypoScript/setup.typoscript @@ -147,7 +147,7 @@ page.jsInline.1.value ( })(window,document,'script','dataLayer','{$bootstrap.gtm}'); ) page.jsInline.1.if.isTrue = {$bootstrap.gtm} -[END] +[global] [applicationContext == "Development"] @@ -159,4 +159,4 @@ config { concatenateCss = 0 contentObjectExceptionHandler = 0 } -[END] +[global] diff --git a/Resources/Private/Backend/Layouts/Default.html b/Resources/Private/Backend/Layouts/Default.html index 22498b28..006cf180 100644 --- a/Resources/Private/Backend/Layouts/Default.html +++ b/Resources/Private/Backend/Layouts/Default.html @@ -1,6 +1,6 @@
- +
diff --git a/Resources/Private/Backend/Templates/Config/Dashboard.html b/Resources/Private/Backend/Templates/Config/Dashboard.html index 25f8d5ce..14bbed6f 100644 --- a/Resources/Private/Backend/Templates/Config/Dashboard.html +++ b/Resources/Private/Backend/Templates/Config/Dashboard.html @@ -2,6 +2,7 @@ +
diff --git a/Resources/Private/Backend/Templates/Config/List.html b/Resources/Private/Backend/Templates/Config/List.html index 305b9425..dcaae02d 100644 --- a/Resources/Private/Backend/Templates/Config/List.html +++ b/Resources/Private/Backend/Templates/Config/List.html @@ -227,9 +227,18 @@

Global pages override is set in Constant Editor:

- + -

WebP Support is enabled

+ + +

WebP Support is enabled

+
+ +

+ WebP Support is enabled for use the default EXT:webp .htaccess configuration +

+
+

WebP Support is disabled

diff --git a/Resources/Private/Extensions/ke_search/Configuration/TSconfig/templateLayouts.tsconfig b/Resources/Private/Extensions/ke_search/Configuration/TSconfig/templateLayouts.tsconfig new file mode 100644 index 00000000..41872d2e --- /dev/null +++ b/Resources/Private/Extensions/ke_search/Configuration/TSconfig/templateLayouts.tsconfig @@ -0,0 +1,11 @@ +# ********************************************************** +# EXT:ke_search +# ********************************************************** + +TCEFORM { + tt_content { + pi_flexform.ke_search_pi1.view.templateLayout.addItems { + 20 = T3S Bootstrap Template + } + } +} diff --git a/Resources/Private/Extensions/ke_search/Configuration/TypoScript/setup.typoscript b/Resources/Private/Extensions/ke_search/Configuration/TypoScript/setup.typoscript index e4f034a3..ccbf77f8 100644 --- a/Resources/Private/Extensions/ke_search/Configuration/TypoScript/setup.typoscript +++ b/Resources/Private/Extensions/ke_search/Configuration/TypoScript/setup.typoscript @@ -2,16 +2,24 @@ plugin.tx_kesearch_pi1 { view { templateRootPaths { - 5 = EXT:t3sbootstrap/Resources/Private/Extensions/ke_search/Resources/Private/Templates/ + 55 = EXT:t3sbootstrap/Resources/Private/Extensions/ke_search/Resources/Private/Templates/ } partialRootPaths { - 5 = EXT:t3sbootstrap/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ + 55 = EXT:t3sbootstrap/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ } } } plugin.tx_kesearch_pi1.cssFile = plugin.tx_kesearch_pi2.cssFile = - plugin.tx_kesearch_pi2.includeFilters = 1 +lib.searchbox_html = TEXT +lib.searchbox_html.value ( +
+ +
+) + +// The action “/suchen/” ist the slug of the page you created with your result list plugin. + diff --git a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/CalDate.html b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/CalDate.html similarity index 100% rename from Resources/Private/Extensions/ke_search/Resources/Private/Partials/CalDate.html rename to Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/CalDate.html diff --git a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters.html b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters.html new file mode 100644 index 00000000..57253c8c --- /dev/null +++ b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters.html @@ -0,0 +1,16 @@ + +

Filter

+ + + + + + + + + {filter.rawHtmlContent} + + diff --git a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/Filters/Checkbox.html b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters/Checkbox.html similarity index 68% rename from Resources/Private/Extensions/ke_search/Resources/Private/Partials/Filters/Checkbox.html rename to Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters/Checkbox.html index 08ac71a4..962c1710 100644 --- a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/Filters/Checkbox.html +++ b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/Filters/Checkbox.html @@ -4,13 +4,13 @@ modified by EXT:t3sbootstrap --> - -
-

{filter.title}

+
- +
diff --git a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRow.html b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRow.html similarity index 87% rename from Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRow.html rename to Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRow.html index 9f3c90ab..b6feebe2 100644 --- a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRow.html +++ b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRow.html @@ -5,7 +5,6 @@ modified by EXT:t3sbootstrap --> - .card { border-radius: 0; @@ -36,7 +35,7 @@ - + @@ -55,12 +54,9 @@
{resultrow.teaser -> f:format.raw()}
-
diff --git a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRows.html b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRows.html similarity index 74% rename from Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRows.html rename to Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRows.html index 4c8968da..2ca52b72 100644 --- a/Resources/Private/Extensions/ke_search/Resources/Private/Partials/ResultRows.html +++ b/Resources/Private/Extensions/ke_search/Resources/Private/Partials/T3SB/ResultRows.html @@ -5,13 +5,13 @@ modified by EXT:t3sbootstrap --> - +
-