diff --git a/Classes/Command/MigrateNewsCommandController.php b/Classes/Command/MigrateNewsCommandController.php index 2947e61e87e60cb7755040c7e6ceb404f2e5ecb0..770eba208348d42ab5a9966c891a6f9bc1c512dc 100644 --- a/Classes/Command/MigrateNewsCommandController.php +++ b/Classes/Command/MigrateNewsCommandController.php @@ -29,6 +29,7 @@ namespace SGalinski\SgNews\Command; use SGalinski\SgNews\Domain\Model\News; use SGalinski\SgNews\Domain\Repository\FileReferenceRepository; use SGalinski\SgNews\Domain\Repository\NewsRepository; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -41,7 +42,6 @@ use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; -use Symfony\Component\Console\Command\Command; use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException; @@ -77,12 +77,15 @@ class MigrateNewsCommandController extends Command { ->addArgument('categoryPid', InputArgument::REQUIRED, 'The page id of the category page') ->addArgument('year', InputArgument::OPTIONAL, 'Only news from that year will be migrated', 2015) ->addArgument( - 'languageMapAsJson', InputArgument::OPTIONAL, + 'languageMapAsJson', + InputArgument::OPTIONAL, 'A json, mapping language ids (old => new). this is needed if the sys_language_uids have changed', '{"3":1,"1":0,"2":2,"0":3}' ) ->addArgument( - 'categoryMapAsJson', InputArgument::OPTIONAL, 'A json, mapping sys_category ids (old => new).', + 'categoryMapAsJson', + InputArgument::OPTIONAL, + 'A json, mapping sys_category ids (old => new).', '{"2":17,"3":16,"4":15,"5":14,"6":14,"7":15,"8":16,"9":17}' ) ->addArgument('pId', InputArgument::OPTIONAL, 'Only news from that pid will be migrated', 52); @@ -93,7 +96,7 @@ class MigrateNewsCommandController extends Command { * * @param InputInterface $input * @param OutputInterface $output - * @return void + * @return int * @throws \JsonException */ public function execute(InputInterface $input, OutputInterface $output) { @@ -121,7 +124,7 @@ class MigrateNewsCommandController extends Command { ->where( $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pId, Connection::PARAM_INT)) ) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); $localDataHandler = GeneralUtility::makeInstance(DataHandler::class); Bootstrap::initializeBackendAuthentication(); $localCommandMap = [ @@ -163,20 +166,26 @@ class MigrateNewsCommandController extends Command { $newsPage->setLastUpdated($date); $this->setMatchingTag($row); - /** @var File $image */ + /** @var File $file */ $file = $this->getMatchingFile($row); if ($file instanceof File) { $teaserImage1 = $fileReferenceRepository->addFileReferenceFromFile( - $file, $this->newsPagesMap[$row['uid']], - $this->newsPagesMap[$row['uid']], 'pages', 'tx_sgnews_teaser1_image' + $file, + $this->newsPagesMap[$row['uid']], + $this->newsPagesMap[$row['uid']], + 'pages', + 'tx_sgnews_teaser1_image' ); if ($teaserImage1) { $newsPage->addTeaser1Image($teaserImage1); $teaserImage2 = $fileReferenceRepository->addFileReferenceFromFile( - $file, $this->newsPagesMap[$row['uid']], - $this->newsPagesMap[$row['uid']], 'pages', 'tx_sgnews_teaser2_image' + $file, + $this->newsPagesMap[$row['uid']], + $this->newsPagesMap[$row['uid']], + 'pages', + 'tx_sgnews_teaser2_image' ); $newsPage->addTeaser2Image($teaserImage2); } @@ -194,12 +203,15 @@ class MigrateNewsCommandController extends Command { ->where( $queryBuilder->expr()->andX( $queryBuilder->expr()->eq( - 'pid', $queryBuilder->createNamedParameter($newPageId, Connection::PARAM_INT) + 'pid', + $queryBuilder->createNamedParameter($newPageId, Connection::PARAM_INT) ), $queryBuilder->expr()->eq( - 'sys_language_uid', $queryBuilder->createNamedParameter( - $this->languageMap[(int) $row['sys_language_uid']], \PDO::PARAM_INT - ) + 'sys_language_uid', + $queryBuilder->createNamedParameter( + $this->languageMap[(int) $row['sys_language_uid']], + \PDO::PARAM_INT + ) ) ) ) @@ -210,6 +222,7 @@ class MigrateNewsCommandController extends Command { $this->updateTranslation($row); } } + return Command::SUCCESS; } /** @@ -230,15 +243,17 @@ class MigrateNewsCommandController extends Command { ->where( $queryBuilder->expr()->andX( $queryBuilder->expr()->eq( - 'tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news') + 'tablenames', + $queryBuilder->createNamedParameter('tx_news_domain_model_news') ), $queryBuilder->expr()->eq('fieldname', $queryBuilder->createNamedParameter('fal_media')), $queryBuilder->expr()->eq( - 'uid_foreign', $queryBuilder->createNamedParameter($row['uid'], Connection::PARAM_INT) + 'uid_foreign', + $queryBuilder->createNamedParameter($row['uid'], Connection::PARAM_INT) ) ) ) - ->execute()->fetch(); + ->execute()->fetchAssociative(); if (!$fileReferenceResult) { return NULL; } @@ -251,10 +266,11 @@ class MigrateNewsCommandController extends Command { ->from('sys_file_news_migration') ->where( $queryBuilder->expr()->eq( - 'uid', $queryBuilder->createNamedParameter($fileReferenceResult['uid_local'], Connection::PARAM_INT) + 'uid', + $queryBuilder->createNamedParameter($fileReferenceResult['uid_local'], Connection::PARAM_INT) ) ) - ->execute()->fetch(); + ->execute()->fetchAssociative(); if (!$fileResult) { return NULL; } @@ -283,10 +299,11 @@ class MigrateNewsCommandController extends Command { ->from('sys_category_record_mm_news_migration') ->where( $queryBuilder->expr()->eq( - 'uid_foreign', $queryBuilder->createNamedParameter($row['uid'], Connection::PARAM_INT) + 'uid_foreign', + $queryBuilder->createNamedParameter($row['uid'], Connection::PARAM_INT) ) ) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); foreach ($mmRows as $mmRow) { $values = [ 'uid_local' => $this->categoryMap[(int) $mmRow['uid_local']], @@ -322,7 +339,8 @@ class MigrateNewsCommandController extends Command { if ((int) $this->languageMap[(int) $row['sys_language_uid'] === 0]) { $queryBuilder->where( $queryBuilder->expr()->eq( - 'uid', $queryBuilder->createNamedParameter($originalContentElement[0], Connection::PARAM_INT) + 'uid', + $queryBuilder->createNamedParameter($originalContentElement[0], Connection::PARAM_INT) ) ); } else { @@ -338,9 +356,11 @@ class MigrateNewsCommandController extends Command { if (isset($this->languageMap[(int) $row['sys_language_uid']])) { $queryBuilder->andWhere( $queryBuilder->expr()->eq( - 'sys_language_uid', $queryBuilder->createNamedParameter( - $this->languageMap[(int) $row['sys_language_uid']], Connection::PARAM_INT - ) + 'sys_language_uid', + $queryBuilder->createNamedParameter( + $this->languageMap[(int) $row['sys_language_uid']], + Connection::PARAM_INT + ) ) ); } else { @@ -362,10 +382,11 @@ class MigrateNewsCommandController extends Command { ->from('pages') ->where( $queryBuilder->expr()->eq( - 'uid', $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) + 'uid', + $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) ) ) - ->execute()->fetch(); + ->execute()->fetchAssociative(); if ($result) { $queryBuilder->where( $queryBuilder->expr()->eq( @@ -390,7 +411,8 @@ class MigrateNewsCommandController extends Command { $queryBuilder->update('pages') ->where( $queryBuilder->expr()->eq( - 'uid', $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) + 'uid', + $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) ) ) ->set('title', $newTitle, TRUE) @@ -402,7 +424,8 @@ class MigrateNewsCommandController extends Command { $queryBuilder->update('pages') ->where( $queryBuilder->expr()->eq( - 'l10n_parent', $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) + 'l10n_parent', + $queryBuilder->createNamedParameter($parentId, Connection::PARAM_INT) ) ); @@ -412,9 +435,11 @@ class MigrateNewsCommandController extends Command { ) { $queryBuilder->andWhere( $queryBuilder->expr()->eq( - 'sys_language_uid', $queryBuilder->createNamedParameter( - $this->languageMap[(int) $row['sys_language_uid']], Connection::PARAM_INT - ) + 'sys_language_uid', + $queryBuilder->createNamedParameter( + $this->languageMap[(int) $row['sys_language_uid']], + Connection::PARAM_INT + ) ) ); } else { diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index d7fc77278262b39e3bdffa00738268ea33e73c24..92a944cd75129a345e6e9ae3f341d7dfdb015c65 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -57,7 +57,7 @@ abstract class AbstractController extends ActionController { * @throws \RuntimeException */ public function errorAction() { - throw new RuntimeException(parent::errorAction()); + throw new RuntimeException($this->getFlattenedValidationErrorMessage()); } /** @@ -75,4 +75,15 @@ abstract class AbstractController extends ActionController { } return $offset; } + + /** + * Build Typo3 11 Response + * @param string|NULL $html + * @return \Psr\Http\Message\ResponseInterface + */ + protected function htmlResponse(string $html = NULL): \Psr\Http\Message\ResponseInterface { + return $this->responseFactory->createResponse() + ->withHeader('Content-Type', 'text/html; charset=utf-8') + ->withBody($this->streamFactory->createStream($html ?? $this->view->render())); + } } diff --git a/Classes/Controller/Ajax/LikeController.php b/Classes/Controller/Ajax/LikeController.php index d2060167e9b959e03bcbc53d1c55a4e3920b3682..647da0d78b5e366d8a2b12e3df8f032f3f41507e 100644 --- a/Classes/Controller/Ajax/LikeController.php +++ b/Classes/Controller/Ajax/LikeController.php @@ -36,7 +36,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * @package SGalinski\SgNews\Controller\Ajax */ class LikeController extends AbstractAjaxController { - /** * This action increases the tx_sgnews_likes field of a given page ($newsPid) by one * @@ -57,9 +56,9 @@ class LikeController extends AbstractAjaxController { ) ->execute(); } catch (\Exception $exception) { - $this->returnData(['success' => false]); + $this->returnData(['success' => FALSE]); } - $this->returnData(['success' => true]); + $this->returnData(['success' => TRUE]); } } diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 3db08d161509b3d0b0b21df28311baa094ad2bb1..fe347a840d22c01c271fae6b27c483fecca02f8a 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -26,14 +26,17 @@ namespace SGalinski\SgNews\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use SGalinski\SgNews\Paginator\QueryBuilderPaginator; use SGalinski\SgNews\Utility\BackendNewsUtility; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\Components\ButtonBar; use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; +use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Pagination\SimplePagination; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; @@ -43,7 +46,6 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; * News Controller */ class BackendController extends ActionController { - /** * The uid of the current page * @@ -79,6 +81,12 @@ class BackendController extends ActionController { */ private $docHeaderComponent; + + /** + * @var ?ModuleTemplate + */ + protected $moduleTemplate = NULL; + /** * Initializes the view before invoking an action method. * @@ -100,7 +108,11 @@ class BackendController extends ActionController { $backendUser = $GLOBALS['BE_USER']; $this->pageInfo = BackendUtility::readPageAccess($this->pageUid, $backendUser->getPagePermsClause(1)); if ($this->pageInfo) { - $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); + } else { + $this->getDocHeaderComponent(); + } if ($this->pageUid) { $this->rootPageUid = BackendNewsUtility::getRootUidByPageUid($this->pageUid); } @@ -114,7 +126,8 @@ class BackendController extends ActionController { } $this->language = $backendUser->getModuleData( - 'tools_beuser/index.php/web_SgNewsNews_language', 'ses' + 'tools_beuser/index.php/web_SgNewsNews_language', + 'ses' ) ?: 0; $languageOptions = BackendNewsUtility::getAvailableLanguages($this->pageUid); $currentLanguageInfo = $languageOptions[$this->language] ?? NULL; @@ -131,16 +144,15 @@ class BackendController extends ActionController { } /** - * @param array $filters - * @throws \InvalidArgumentException - * @throws \UnexpectedValueException + * @param array|null $filters + * @return \Psr\Http\Message\ResponseInterface|null * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ - public function indexAction(array $filters = NULL) { + public function indexAction(array $filters = NULL): ?\Psr\Http\Message\ResponseInterface { $showNewsList = FALSE; if ( ($this->pageUid && $this->pageUid === $this->rootPageUid) || - (int) $this->pageInfo['doktype'] === BackendNewsUtility::CATEGORY_DOKTYPE + (isset($this->pageInfo['doktype']) && (int) $this->pageInfo['doktype'] === BackendNewsUtility::CATEGORY_DOKTYPE) ) { /** @var BackendUserAuthentication $backendUser */ $backendUser = $GLOBALS['BE_USER']; @@ -157,7 +169,13 @@ class BackendController extends ActionController { $filters['categories'] = [$this->pageUid]; } $tags = BackendNewsUtility::getTagsForPage($this->pageUid, $this->language); - $news = BackendNewsUtility::getNewsByFilters($this->rootPageUid, $filters, $this->language); + [$news, $newsQueryBuilder] = BackendNewsUtility::getNewsByFilters($this->rootPageUid, $filters, $this->language); + + $paginator = new QueryBuilderPaginator($newsQueryBuilder); + $pagination = new SimplePagination($paginator); + + $this->view->assign('paginator', $paginator); + $this->view->assign('pagination', $pagination); $this->view->assign('tags', $tags); $this->view->assign('news', $news); @@ -168,6 +186,14 @@ class BackendController extends ActionController { $this->view->assign('alternativePageOptions', $alternativePageOptions); } $this->view->assign('showNewsList', $showNewsList); + + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $this->view->assign('V11', FALSE); + return NULL; + } else { + $this->view->assign('V11', TRUE); + return $this->createBackendResponse(); + } } /** @@ -226,7 +252,8 @@ class BackendController extends ActionController { ->setTitle($language['title']) ->setHref( $uriBuilder->buildUriFromRoute( - 'web_SgNewsNews', ['id' => $this->pageUid, 'SET' => ['language' => $key]] + 'web_SgNewsNews', + ['id' => $this->pageUid, 'SET' => ['language' => $key]] ) ); if ((int) $this->language === (int) $key) { @@ -236,4 +263,39 @@ class BackendController extends ActionController { } $this->docHeaderComponent->getMenuRegistry()->addMenu($languageMenu); } + + + /** + * Use the ModuleTemplateResponse to create a response object for the backend + * + * @return \Psr\Http\Message\ResponseInterface + */ + protected function createBackendResponse(): \Psr\Http\Message\ResponseInterface { + $this->getModuleTemplate(); + $this->moduleTemplate->setContent($this->view->render()); + return $this->htmlResponse($this->moduleTemplate->renderContent()); + } + + /** + * Since we cannot use constructer Injection, we do have to get one Dynamicly. If we want to use + * our ModuleTemplate, call GetModuleTemplate before, which will init one if there is none for some reason + */ + protected function getModuleTemplate() { + if ($this->moduleTemplate === NULL) { + $moduleTemplateFactory = GeneralUtility::makeInstance( + \TYPO3\CMS\Backend\Template\ModuleTemplateFactory::class + ); + $this->moduleTemplate = $moduleTemplateFactory->create($this->request); + } + } + + /** + * Other Helper function, which gets us just the DocHeaderComponent + */ + protected function getDocHeaderComponent() { + if ($this->moduleTemplate === NULL) { + $this->getModuleTemplate(); + } + $this->docHeaderComponent = $this->moduleTemplate->getDocHeaderComponent(); + } } diff --git a/Classes/Controller/LatestController.php b/Classes/Controller/LatestController.php index e5eb3ea0cdeaa830bdf41fca500797a9a4bf9e68..d6b07cc6727ea7061fac078a92a0404360b20bfd 100644 --- a/Classes/Controller/LatestController.php +++ b/Classes/Controller/LatestController.php @@ -64,36 +64,64 @@ class LatestController extends AbstractController { * * @param array $newsMetaData * @param int $offset - * @return void + * @return null|\Psr\Http\Message\ResponseInterface * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException */ - public function indexAction(array $newsMetaData = [], $offset = 0) { - $limit = ((int) $this->settings['limit']); + public function indexAction(array $newsMetaData = [], $offset = 0): ?\Psr\Http\Message\ResponseInterface { + $limit = 0; + if (isset($this->settings['limit'])) { + $limit = ((int) $this->settings['limit']); + } $limit = ($limit < 1 ? 1 : $limit); $configurationService = GeneralUtility::makeInstance(ConfigurationService::class); $sortBy = $configurationService->getConfiguration('sortBy', $this->settings); - $categoryUids = GeneralUtility::intExplode(',', $this->settings['categories'], TRUE); - $tagUids = GeneralUtility::intExplode(',', $this->settings['tags'], TRUE); + $categoryUids = []; + $tagUids = []; + if (isset($this->settings['categories'])) { + $categoryUids = GeneralUtility::intExplode(',', $this->settings['categories'], TRUE); + } + if (isset($this->settings['tags'])) { + $tagUids = GeneralUtility::intExplode(',', $this->settings['tags'], TRUE); + } if ((int) $GLOBALS['TSFE']->page['doktype'] === 117 && !count($categoryUids)) { $categoryUids = [$GLOBALS['TSFE']->id]; } - $startTime = (int) $this->settings['starttime']; - $endTime = (int) $this->settings['endtime']; + $startTime = 0; + $endTime = 0; + if (isset($this->settings['starttime'])) { + $startTime = (int) $this->settings['starttime']; + } + if (isset($this->settings['endtime'])) { + $endTime = (int) $this->settings['endtime']; + } $latestNewsEntries = $this->newsRepository->findLastUpdatedOrHighlightedNewsByCategories( - $limit, FALSE, $categoryUids, $offset, TRUE, $sortBy, $tagUids, $startTime, $endTime + $limit, + FALSE, + $categoryUids, + $offset, + TRUE, + $sortBy, + $tagUids, + $startTime, + $endTime ); $categories = []; + $category = NULL; foreach ($latestNewsEntries as $latestNewsEntry) { /** @var News $latestNewsEntry */ /** @var Category $category */ $categoryUid = $latestNewsEntry->getPid(); - $category = $categories[$categoryUid]; + + if (isset($categories[$categoryUid])) { + $category = $categories[$categoryUid]; + } + if (!$category) { $category = $this->categoryRepository->findByUid($categoryUid); if (!$category) { @@ -110,12 +138,18 @@ class LatestController extends AbstractController { } $this->view->assign('newsMetaData', $newsMetaData); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } /** * @param CategoryRepository $categoryRepository */ - public function injectCategoryRepository(CategoryRepository $categoryRepository + public function injectCategoryRepository( + CategoryRepository $categoryRepository ) { $this->categoryRepository = $categoryRepository; } diff --git a/Classes/Controller/ListByCategoryController.php b/Classes/Controller/ListByCategoryController.php index d4547f514ed26d96f9b0e05c707065975d3db6b4..5dfd1abbc86c4bb0e84e167487a82cb246ea21f8 100644 --- a/Classes/Controller/ListByCategoryController.php +++ b/Classes/Controller/ListByCategoryController.php @@ -33,8 +33,8 @@ use SGalinski\SgNews\Domain\Repository\TagRepository; use SGalinski\SgNews\Domain\Service\NewsService; use SGalinski\SgNews\Service\ConfigurationService; use SGalinski\SgNews\Service\HeaderMetaDataService; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Http\ImmediateResponseException; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Controller\ErrorController; use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons; @@ -66,7 +66,8 @@ class ListByCategoryController extends AbstractController { /** * @param CategoryRepository $categoryRepository */ - public function injectCategoryRepository(CategoryRepository $categoryRepository + public function injectCategoryRepository( + CategoryRepository $categoryRepository ) { $this->categoryRepository = $categoryRepository; } @@ -98,7 +99,9 @@ class ListByCategoryController extends AbstractController { * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException */ public function initializeIndexAction() { - $currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage']; + $currentPageBrowserPage = GeneralUtility::_GP('tx_sgnews_pagebrowser') + ? (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'] + : 0; if ($currentPageBrowserPage > 0) { $this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage); } @@ -109,17 +112,23 @@ class ListByCategoryController extends AbstractController { * * @param array $newsMetaData * @param int $currentPageBrowserPage - * @return void + * @return null|\Psr\Http\Message\ResponseInterface * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException * @throws ImmediateResponseException * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException */ - public function indexAction(array $newsMetaData = [], int $currentPageBrowserPage = 0) { + public function indexAction(array $newsMetaData = [], int $currentPageBrowserPage = 0): ?\Psr\Http\Message\ResponseInterface { $filterByCategories = FALSE; - $categoryUids = GeneralUtility::intExplode(',', $this->settings['categories']); - $tagUids = GeneralUtility::intExplode(',', $this->settings['tags'], TRUE); + $categoryUids = []; + $tagUids = []; + if (isset($this->settings['categories'])) { + $categoryUids = GeneralUtility::intExplode(',', $this->settings['categories'], TRUE); + } + if (isset($this->settings['tags'])) { + $tagUids = GeneralUtility::intExplode(',', $this->settings['tags'], TRUE); + } HeaderMetaDataService::addPageNumberToCanonical($currentPageBrowserPage); @@ -150,8 +159,14 @@ class ListByCategoryController extends AbstractController { } } - $startTime = (int) $this->settings['starttime']; - $endTime = (int) $this->settings['endtime']; + $startTime = 0; + $endTime = 0; + if (isset($this->settings['starttime'])) { + $startTime = (int) $this->settings['starttime']; + } + if (isset($this->settings['endtime'])) { + $endTime = (int) $this->settings['endtime']; + } $newsPerPage = (int) $this->settings['newsLimitPerPage']; $newsCount = $this->newsRepository->newsCountByCategories($categoryUids, $tagUids, $startTime, $endTime); @@ -175,29 +190,30 @@ class ListByCategoryController extends AbstractController { $sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings); $news = $this->newsRepository->findAllSortedNewsByCategories( - $categoryUids, $newsPerPage, $offset, $sortBy, $tagUids, $startTime, $endTime, $sortDirection + $categoryUids, + $newsPerPage, + $offset, + $sortBy, + $tagUids, + $startTime, + $endTime, + $sortDirection )->toArray(); foreach ($news as $newsEntry) { /** @var News $newsEntry */ $data = $this->newsService->getMetaDataForNews($newsEntry, $categories[$newsEntry->getPid()]); $newsMetaData[] = $data; - - if (!$headerSet) { - if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - if ($data['image']) { - HeaderMetaDataService::addOgImageToHeader($data['image']); - $headerSet = TRUE; - } elseif ($data['teaserImage']) { - HeaderMetaDataService::addOgImageToHeader($data['teaserImage']); - $headerSet = TRUE; - } - } - } } $this->view->assign('numberOfPages', $numberOfPages); $this->view->assign('newsMetaData', $newsMetaData); $this->view->assign('categories', $categories); + + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } } diff --git a/Classes/Controller/NewsByAuthorController.php b/Classes/Controller/NewsByAuthorController.php index 217140fc9f465753eee084f7699e37f1d5186e67..1f3db1393ddf42ea209cddfe93c4f85ae27fb094 100644 --- a/Classes/Controller/NewsByAuthorController.php +++ b/Classes/Controller/NewsByAuthorController.php @@ -57,18 +57,22 @@ class NewsByAuthorController extends AbstractController { * Renders the news author list. * * @param int $authorId - * @return void + * @return null|\Psr\Http\Message\ResponseInterface * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \TYPO3\CMS\Core\Package\Exception */ - public function listAction($authorId = 0): void { + public function listAction($authorId = 0): ?\Psr\Http\Message\ResponseInterface { if ($authorId) { $newsAuthorsIds[] = $authorId; } else { $newsAuthorsIds = GeneralUtility::intExplode(',', $this->settings['newsAuthors']); if (\count($newsAuthorsIds) <= 0) { - return; + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } } @@ -81,33 +85,34 @@ class NewsByAuthorController extends AbstractController { continue; } - if (version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - $headTagService = GeneralUtility::makeInstance( - HeadTagService::class, - TRUE, - $author->getName(), - $author->getDescription(), - '&tx_sgnews_newsbyauthor[authorId]=' . $author->getUid() - ); - $headTagService->execute(); - } else { - $GLOBALS['TSFE']->page['titlebyextension'] = $author->getName(); - $GLOBALS['TSFE']->page['description'] = \strip_tags(\substr($author->getDescription(), 0, 200)); - $GLOBALS['TSFE']->page['extensionArgumentsForCanonicalAndHrefLang'] = - '&tx_sgnews_newsbyauthor[authorId]=' . $author->getUid(); - } + $headTagService = GeneralUtility::makeInstance( + HeadTagService::class, + TRUE, + $author->getName(), + $author->getDescription(), + '&tx_sgnews_newsbyauthor[authorId]=' . $author->getUid() + ); + $headTagService->execute(); $authors[] = $author; } if (\count($authors) <= 0) { - return; + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } $newsRepository = $this->objectManager->get(NewsRepository::class); $news = $newsRepository->findAllByNewsAuthor($newsAuthorsIds); if (\count($news) <= 0) { - return; + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } $categories = $newsMetaData = []; @@ -137,5 +142,11 @@ class NewsByAuthorController extends AbstractController { $this->view->assign('newsMetaData', $newsMetaData); $this->view->assign('authors', $authors); + + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } } diff --git a/Classes/Controller/NewsFeedController.php b/Classes/Controller/NewsFeedController.php index c734588689d49f6ee26cb92193a0e8238d65cf83..c986f508423e839097f9e2bbd55a96eac5c3afb7 100644 --- a/Classes/Controller/NewsFeedController.php +++ b/Classes/Controller/NewsFeedController.php @@ -43,16 +43,24 @@ class NewsFeedController extends AbstractController { /** * Renders the news feed * - * @return void + * @return null|\Psr\Http\Message\ResponseInterface * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ - public function indexAction() { + public function indexAction(): ?\Psr\Http\Message\ResponseInterface { $categories = GeneralUtility::intExplode(',', $this->settings['showCategories'], TRUE); $tags = GeneralUtility::intExplode(',', $this->settings['showTags'], TRUE); $startTime = (int) $this->settings['starttime']; $endTime = (int) $this->settings['endtime']; $news = $this->newsRepository->findLastUpdatedOrHighlightedNewsByCategories( - 10, FALSE, $categories, 0, FALSE, 'date', $tags, $startTime, $endTime + 10, + FALSE, + $categories, + 0, + FALSE, + 'date', + $tags, + $startTime, + $endTime ); $newsCategories = []; @@ -74,6 +82,12 @@ class NewsFeedController extends AbstractController { $this->view->assign('news', $news); $this->view->assign('newsCategories', $newsCategories); + + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } /** diff --git a/Classes/Controller/OverviewController.php b/Classes/Controller/OverviewController.php index 93a0d0b702c6e8799ae3b336a15f0bf349cc9eda..5ca9999e7a9eb211065888bfdce07aefea6b2fc9 100644 --- a/Classes/Controller/OverviewController.php +++ b/Classes/Controller/OverviewController.php @@ -70,7 +70,8 @@ class OverviewController extends AbstractController { /** * @param CategoryRepository $categoryRepository */ - public function injectCategoryRepository(CategoryRepository $categoryRepository + public function injectCategoryRepository( + CategoryRepository $categoryRepository ) { $this->categoryRepository = $categoryRepository; } @@ -102,7 +103,7 @@ class OverviewController extends AbstractController { * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException */ public function initializeOverviewAction() { - $currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage']; + $currentPageBrowserPage = (int) (GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'] ?? 0); if ($currentPageBrowserPage > 0) { $this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage); } @@ -119,34 +120,45 @@ class OverviewController extends AbstractController { * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException */ - public function overviewAction(array $newsFilter = [], int $currentPageBrowserPage = 0) { + public function overviewAction(array $newsFilter = [], int $currentPageBrowserPage = 0): ?\Psr\Http\Message\ResponseInterface { if ((int) $this->settings['groupBy'] === 0 && (bool) $this->settings['enableFilter'] === FALSE) { - $this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments()); + if (version_compare( + \TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), + '11.0.0', + '<' + )) { + $this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments()); + } else { + return (new \TYPO3\CMS\Extbase\Http\ForwardResponse( + 'overviewWithoutCategories' + )) + ->withArguments($this->request->getArguments()); + } } // Setup settings - $startTime = (int) $this->settings['starttime']; - $endTime = (int) $this->settings['endtime']; - $newsLimit = (int) $this->settings['newsLimit']; + $startTime = (int) ($this->settings['starttime'] ?? 0); + $endTime = (int) ($this->settings['endtime'] ?? 0); + $newsLimit = (int) ($this->settings['newsLimit'] ?? 0); $offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimit); $configurationService = GeneralUtility::makeInstance(ConfigurationService::class); $sortBy = $configurationService->getConfiguration('sortBy', $this->settings); $sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings); $this->tagRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]); $this->categoryRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]); - $useAllFilters = (bool) $this->settings['enableFilter']; - $isCategoryFiltered = $useAllFilters || (int) $this->settings['groupBy'] === 1; - $isTagFiltered = $useAllFilters || (int) $this->settings['groupBy'] === 2; + $useAllFilters = (bool) ($this->settings['enableFilter'] ?? FALSE); + $isCategoryFiltered = $useAllFilters || $this->settings['groupBy'] === 1 ? 1 : 0; + $isTagFiltered = $useAllFilters || $this->settings['groupBy'] === 2 ? 1 : 0; HeaderMetaDataService::addPageNumberToCanonical($currentPageBrowserPage); // Get tag pid - $tagPid = (int) $this->settings['tagPid']; + $tagPid = (int) ($this->settings['tagPid'] ?? 0); if (!$tagPid) { $tagPid = $GLOBALS['TSFE']->id; } - if ($this->settings['onlyNewsWithinThisPageSection']) { + if ($this->settings['onlyNewsWithinThisPageSection'] ?? FALSE) { $categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id); $tags = $this->tagRepository->findTagsInRootLine($tagPid); } else { @@ -155,7 +167,7 @@ class OverviewController extends AbstractController { } // Apply category restrictions - $categoryRestrictions = GeneralUtility::intExplode(',', $this->settings['categoryRestrictions'], TRUE); + $categoryRestrictions = GeneralUtility::intExplode(',', $this->settings['categoryRestrictions'] ?? '', TRUE); if (!$isCategoryFiltered) { $categoryRestrictions = []; } @@ -181,7 +193,7 @@ class OverviewController extends AbstractController { } // Apply tag restrictions - $tagRestrictions = GeneralUtility::intExplode(',', $this->settings['tagRestrictions'], TRUE); + $tagRestrictions = GeneralUtility::intExplode(',', $this->settings['tagRestrictions'] ?? '', TRUE); if (!$isTagFiltered) { $tagRestrictions = []; } @@ -195,7 +207,7 @@ class OverviewController extends AbstractController { // Get category ids or use the one in the filter $categoryIds = []; - if ($newsFilter['category']) { + if ($newsFilter['category'] ?? FALSE) { $categoryIds = [(int) $newsFilter['category']]; } elseif ($isCategoryFiltered) { foreach ($categories as $category) { @@ -207,7 +219,7 @@ class OverviewController extends AbstractController { // Get tag ids or use the one in the filter $tagIds = []; - if ($newsFilter['tag']) { + if ($newsFilter['tag'] ?? FALSE) { $tagIds = [(int) $newsFilter['tag']]; } elseif ($isTagFiltered) { foreach ($tags as $tag) { @@ -219,7 +231,14 @@ class OverviewController extends AbstractController { // Get all news by category and tag ids $news = $this->newsRepository->findAllSortedNewsByCategories( - $categoryIds, $newsLimit, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection + $categoryIds, + $newsLimit, + $offset, + $sortBy, + $tagIds, + $startTime, + $endTime, + $sortDirection ); // Process news result query based on filters @@ -229,8 +248,8 @@ class OverviewController extends AbstractController { foreach ($news as $newsEntry) { /** @var News $newsEntry */ $newsCategory = $this->categoryRepository->findOriginalLanguageById( - $newsEntry->getPid() - ) ?? $this->categoryRepository->findByUid($newsEntry->getPid()); + $newsEntry->getPid() + ) ?? $this->categoryRepository->findByUid($newsEntry->getPid()); $newsCategoryId = $newsCategory->getUid(); $newsMetaData = $this->newsService->getMetaDataForNews($newsEntry, $newsCategory); @@ -292,8 +311,8 @@ class OverviewController extends AbstractController { } // remember selection of the filter values, if any - $selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']); - $selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']); + $selectedTag = $this->tagRepository->findByUid((int) ($newsFilter['tag'] ?? 0)); + $selectedCategory = $this->categoryRepository->findByUid((int) ($newsFilter['category'] ?? 0)); $this->view->assign('selectedCategory', $selectedCategory); $this->view->assign('selectedTag', $selectedTag); $this->view->assign('tags', $tags); @@ -303,7 +322,7 @@ class OverviewController extends AbstractController { $this->view->assign('allNews', $allNews); $this->setupGridColumns(); - switch ($this->settings['groupBy']) { + switch ($this->settings['groupBy'] ?? '') { case 1: $this->view->assign('groupBy', 'category'); $this->view->assign('categoryTabs', TRUE); @@ -315,6 +334,12 @@ class OverviewController extends AbstractController { default: $this->view->assign('groupBy', 'none'); } + + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } /** @@ -334,10 +359,13 @@ class OverviewController extends AbstractController { switch ($columnAmount) { case 4: $columnClasses .= 'col-lg-3 '; + // no break case 3: $columnClasses .= 'col-md-4 '; + // no break case 2: $columnClasses .= 'col-sm-6 '; + // no break default: $columnClasses .= 'col-xs-12'; } @@ -353,13 +381,21 @@ class OverviewController extends AbstractController { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ protected function highlightBestFitNews(array $categoryIds = NULL, array $tagIds = NULL) { - $startTime = (int) $this->settings['starttime']; - $endTime = (int) $this->settings['endtime']; + $startTime = (int) ($this->settings['starttime'] ?? 0); + $endTime = (int) ($this->settings['endtime'] ?? 0); /** @var News $highlightedNews */ $highlightedNews = $this->newsRepository ->findLastUpdatedOrHighlightedNewsByCategories( - 1, FALSE, $categoryIds, 0, FALSE, $this->settings['sortBy'], $tagIds, $startTime, $endTime + 1, + FALSE, + $categoryIds, + 0, + FALSE, + $this->settings['sortBy'], + $tagIds, + $startTime, + $endTime )->getFirst(); if (!$highlightedNews) { return; @@ -371,14 +407,6 @@ class OverviewController extends AbstractController { if ($category) { $highlightedNewsMetaData = $this->newsService->getMetaDataForNews($highlightedNews, $category); } - - if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - if ($highlightedNewsMetaData['image']) { - HeaderMetaDataService::addOgImageToHeader($highlightedNewsMetaData['image']); - } elseif ($highlightedNewsMetaData['teaserImage']) { - HeaderMetaDataService::addOgImageToHeader($highlightedNewsMetaData['teaserImage']); - } - } } /** @@ -406,7 +434,9 @@ class OverviewController extends AbstractController { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ protected function overviewWithoutCategoriesAction( - array $newsMetaData = [], array $newsFilter = NULL, int $currentPageBrowserPage = 0 + array $newsMetaData = [], + array $newsFilter = NULL, + int $currentPageBrowserPage = 0 ) { // remember selection of the filter values, if any $selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']); @@ -484,7 +514,14 @@ class OverviewController extends AbstractController { } $news = $this->newsRepository->findAllSortedNewsByCategories( - $categoryIds, $newsPerPage, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection + $categoryIds, + $newsPerPage, + $offset, + $sortBy, + $tagIds, + $startTime, + $endTime, + $sortDirection ); foreach ($news as $newsEntry) { /** @var News $newsEntry */ diff --git a/Classes/Controller/SingleViewController.php b/Classes/Controller/SingleViewController.php index a7d929ff11fc51619c7593d661568217c2a553aa..1031ef76ad11abda4607162f4a01c0b01ae3af30 100644 --- a/Classes/Controller/SingleViewController.php +++ b/Classes/Controller/SingleViewController.php @@ -68,44 +68,41 @@ class SingleViewController extends AbstractController { /** * Renders the news single view * - * @return void + * @return null|\Psr\Http\Message\ResponseInterface * @throws \InvalidArgumentException */ - public function singleViewAction() { - /** @var News $news */ + public function singleViewAction(): ?\Psr\Http\Message\ResponseInterface { $currentId = (int) $GLOBALS['TSFE']->id; + /** @var News $news */ $news = $this->newsRepository->findByUid($currentId); if (!$news) { - return; + if (version_compare( + \TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), + '11.0.0', + '<' + )) { + return NULL; + } else { + return $this->htmlResponse(); + } } /** @var Category $newsCategory */ $newsCategory = $this->categoryRepository->findByUid($news->getPid()); if (!$newsCategory) { - return; + if (version_compare( + \TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), + '11.0.0', + '<' + )) { + return NULL; + } else { + return $this->htmlResponse(); + } } -// $similarNewsMetaData = []; -// $similarNews = $this->newsRepository->findRandomNews(3, $news); -// foreach ($similarNews as $similarNewsEntry) { -// /** @var News $similarNewsEntry */ -// /** @var Category $category */ -// $category = $this->categoryRepository->findByUid($similarNewsEntry->getPid()); -// if (!$category) { -// continue; -// } -// -// $similarNewsMetaData[] = $this->getMetaDataForNews($similarNewsEntry, $category); -// } - $newsMetaData = $this->newsService->getMetaDataForNews($news, $newsCategory); - if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - if ($newsMetaData['image']) { - HeaderMetaDataService::addOgImageToHeader($newsMetaData['image']); - } elseif ($newsMetaData['teaserImage']) { - HeaderMetaDataService::addOgImageToHeader($newsMetaData['teaserImage']); - } - } + $previousNews = $this->newsRepository->findPreviousNewsEntryFromCurrentNews($news, $this->settings['sortBy']) ->getFirst(); @@ -121,12 +118,18 @@ class SingleViewController extends AbstractController { 'newsAuthor' => $news->getNewsAuthor(), ] ); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + return NULL; + } else { + return $this->htmlResponse(); + } } /** * @param CategoryRepository $categoryRepository */ - public function injectCategoryRepository(CategoryRepository $categoryRepository + public function injectCategoryRepository( + CategoryRepository $categoryRepository ) { $this->categoryRepository = $categoryRepository; } diff --git a/Classes/Domain/Model/FileReference.php b/Classes/Domain/Model/FileReference.php index 63c7c7d9ee19a751613c6db032cc727f422b54bf..9a51b3dee41ed9b0b1930b0ed036d69c8f6719ad 100644 --- a/Classes/Domain/Model/FileReference.php +++ b/Classes/Domain/Model/FileReference.php @@ -30,5 +30,4 @@ namespace SGalinski\SgNews\Domain\Model; * FileReference */ class FileReference extends \TYPO3\CMS\Extbase\Domain\Model\FileReference { - } diff --git a/Classes/Domain/Model/Tag.php b/Classes/Domain/Model/Tag.php index 1dbb808c4adb7dd2a20923b31876db220f4edea3..96a5fd8e73cb2d1ffd0983c652f3b3216ec21ae9 100644 --- a/Classes/Domain/Model/Tag.php +++ b/Classes/Domain/Model/Tag.php @@ -31,7 +31,6 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; * Tag */ class Tag extends AbstractEntity { - /** * @var string */ diff --git a/Classes/Domain/Repository/AbstractRepository.php b/Classes/Domain/Repository/AbstractRepository.php index 49ad3c22f70749cf4b18fafb57dafea4b36affca..348f5d4fc313cfc00e5e9c2cce50cfd8a3bc8584 100644 --- a/Classes/Domain/Repository/AbstractRepository.php +++ b/Classes/Domain/Repository/AbstractRepository.php @@ -27,6 +27,7 @@ namespace SGalinski\SgNews\Domain\Repository; ***************************************************************/ use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Persistence\Repository; @@ -43,44 +44,17 @@ abstract class AbstractRepository extends Repository { * @return void */ public function initializeObject() { - /** @var $querySettings Typo3QuerySettings */ + /** @var Typo3QuerySettings $querySettings */ $querySettings = $this->objectManager->get(Typo3QuerySettings::class); $querySettings->setRespectStoragePage(FALSE); - if (TYPO3_MODE === 'BE') { + // in Migration wizard it was possible tha $GLOBALS['TYPO3_REQUEST'] was not set + // this should not be the case in any other case + if (!isset($GLOBALS['TYPO3_REQUEST']) || ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { $querySettings->setIgnoreEnableFields(TRUE); } $this->setDefaultQuerySettings($querySettings); } - /** - * Method creates a statement string of the enableFields for the given database table. - * - * @param string $table - * @param string $alias - * @param bool $ignoreEnableFields - * @return string - * @throws \InvalidArgumentException - */ - protected function getEnableFieldsStatement($table, $alias = '', $ignoreEnableFields = FALSE): string { - if (TYPO3_MODE === 'FE' && $GLOBALS['TSFE'] instanceof TypoScriptFrontendController) { - /** @var PageRepository $pageRepository */ - $pageRepository = $GLOBALS['TSFE']->sys_page; - $statement = $pageRepository->enableFields($table); - } else { - $statement = BackendUtility::deleteClause($table); - - if (!$ignoreEnableFields) { - $statement .= BackendUtility::BEenableFields($table); - } - } - - if ($alias !== '') { - $statement = str_replace($table, $alias, $statement); - } - - return $statement; - } - /** * This count returns the right amount of results, in contrast to $query->execute()->count(), which does not respect * the language- nor the workspace overlay. @@ -90,6 +64,6 @@ abstract class AbstractRepository extends Repository { * @return int */ public function getCount(QueryInterface $query) { - return \count($query->execute(true)); + return \count($query->execute(TRUE)); } } diff --git a/Classes/Domain/Repository/AuthorRepository.php b/Classes/Domain/Repository/AuthorRepository.php index f1ac33f72aec678de1133119d79b55c42dd8d2be..7fd9bb8285e14c7e93bc0dd6dd334ac96fd85989 100644 --- a/Classes/Domain/Repository/AuthorRepository.php +++ b/Classes/Domain/Repository/AuthorRepository.php @@ -32,5 +32,4 @@ use SGalinski\SgNews\Domain\Repository\AbstractRepository; * Repository for the Author model. */ class AuthorRepository extends AbstractRepository { - } diff --git a/Classes/Domain/Repository/CategoryRepository.php b/Classes/Domain/Repository/CategoryRepository.php index 83d5324301f1ee784c1b026803ed1a2619b96b06..6fffcc342b15c13d132b77ba1cea9ea4588c8c5d 100644 --- a/Classes/Domain/Repository/CategoryRepository.php +++ b/Classes/Domain/Repository/CategoryRepository.php @@ -37,7 +37,6 @@ use TYPO3\CMS\Extbase\Persistence\QueryInterface; * Category Repository */ class CategoryRepository extends AbstractRepository { - /** * @var array */ @@ -61,7 +60,7 @@ class CategoryRepository extends AbstractRepository { $queryBuilder->expr()->eq('translation.uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) ) ->setMaxResults(1) - ->execute()->fetch(); + ->execute()->fetchAssociative(); if ($row && (int) $row['uid'] !== 0) { return current($dataMapper->map($this->objectType, [$row])); } diff --git a/Classes/Domain/Repository/FileReferenceRepository.php b/Classes/Domain/Repository/FileReferenceRepository.php index b26ff56edfb84d559a68e8a4f1c3e06694411f37..ac8e9612c3bd9ea888526ba601512099cc449c20 100644 --- a/Classes/Domain/Repository/FileReferenceRepository.php +++ b/Classes/Domain/Repository/FileReferenceRepository.php @@ -26,16 +26,15 @@ namespace SGalinski\SgNews\Domain\Repository; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; use SGalinski\SgNews\Domain\Model\FileReference; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * FileReference Repository */ class FileReferenceRepository extends AbstractRepository { - /** * Method creates a file reference entry in the database. This step is necessary because the * extbase can not handle the default TCA for FAL records. Without this method the FAL records will miss @@ -71,7 +70,7 @@ class FileReferenceRepository extends AbstractRepository { * extbase can not handle the default TCA for FAL records. Without this method the FAL records will miss * the uid_foreign, field name and table names. * - * @param $fileId + * @param int $fileId * @param array $reference * @param string $tablename * @param string $fieldname diff --git a/Classes/Domain/Repository/NewsRepository.php b/Classes/Domain/Repository/NewsRepository.php index 7b5f136564ed227a55505911e83fa3e85127a967..9ab663bf11f6bf8d1d1ced9c27cacb8dd2462b97 100644 --- a/Classes/Domain/Repository/NewsRepository.php +++ b/Classes/Domain/Repository/NewsRepository.php @@ -86,8 +86,14 @@ class NewsRepository extends AbstractRepository { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ public function findAllSortedNewsByCategories( - array $categoryIds = NULL, $limit = 0, $offset = 0, $sortBy = 'date', array $tagIds = NULL, - $startTime = 0, $endTime = 0, $sortDirection = 'DESC' + array $categoryIds = NULL, + $limit = 0, + $offset = 0, + $sortBy = 'date', + array $tagIds = NULL, + $startTime = 0, + $endTime = 0, + $sortDirection = 'DESC' ): QueryResultInterface { $query = $this->createQuery(); @@ -171,7 +177,10 @@ class NewsRepository extends AbstractRepository { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ public function newsCountByCategories( - array $categoryIds = NULL, array $tagIds = NULL, $startTime = 0, $endTime = 0 + array $categoryIds = NULL, + array $tagIds = NULL, + $startTime = 0, + $endTime = 0 ): int { $query = $this->createQuery(); @@ -231,13 +240,26 @@ class NewsRepository extends AbstractRepository { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ public function findLastUpdatedOrHighlightedNewsByCategories( - $limit = 1, $onlyHighlighted = FALSE, array $categoryIds = NULL, - $offset = 0, $hideNeverHighlightedNews = FALSE, $sortBy = 'date', array $tagIds = NULL, - $startTime = 0, $endTime = 0 + $limit = 1, + $onlyHighlighted = FALSE, + array $categoryIds = NULL, + $offset = 0, + $hideNeverHighlightedNews = FALSE, + $sortBy = 'date', + array $tagIds = NULL, + $startTime = 0, + $endTime = 0 ): QueryResultInterface { return $this->getQueryForLastUpdatedOrHighlightedNewsByCategories( - $limit, $onlyHighlighted, $categoryIds, $offset, $hideNeverHighlightedNews, $sortBy, $tagIds, - $startTime, $endTime + $limit, + $onlyHighlighted, + $categoryIds, + $offset, + $hideNeverHighlightedNews, + $sortBy, + $tagIds, + $startTime, + $endTime )->execute(); } @@ -257,9 +279,15 @@ class NewsRepository extends AbstractRepository { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ protected function getQueryForLastUpdatedOrHighlightedNewsByCategories( - $limit = 1, $onlyHighlighted = FALSE, array $categoryIds = NULL, - $offset = 0, $hideNeverHighlightedNews = FALSE, $sortBy = 'date', array $tagIds = NULL, - $startTime = 0, $endTime = 0 + $limit = 1, + $onlyHighlighted = FALSE, + array $categoryIds = NULL, + $offset = 0, + $hideNeverHighlightedNews = FALSE, + $sortBy = 'date', + array $tagIds = NULL, + $startTime = 0, + $endTime = 0 ): QueryInterface { $query = $this->createQuery(); $constraints = NULL; @@ -498,7 +526,7 @@ class NewsRepository extends AbstractRepository { */ public function findByUidIgnoreEnableFields($uid) { $query = $this->createQuery(); - /** @var $querySettings \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings */ + /** @var \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings $querySettings */ $querySettings = $query->getQuerySettings(); $querySettings->setIgnoreEnableFields(TRUE); $querySettings->setRespectStoragePage(FALSE); @@ -553,9 +581,9 @@ class NewsRepository extends AbstractRepository { // Here we fetch the lastUpdated of the $limit amount of news with older lastUpdated dates $result = $qb->where( - $qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)), - $qb->expr()->lte('lastUpdated', $news->getLastUpdated()->getTimestamp()) - )->andWhere(...$constraints) + $qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)), + $qb->expr()->lte('lastUpdated', $news->getLastUpdated()->getTimestamp()) + )->andWhere(...$constraints) ->orderBy('lastUpdated', 'asc') ->execute(); $oldest = $result->fetchOne(); diff --git a/Classes/Domain/Service/NewsService.php b/Classes/Domain/Service/NewsService.php index 7ba3ad6d291e7a412b78cf1b3145c203321c4595..ec24fca72e1d16fcc8048187c3aefc2a801bc8da 100644 --- a/Classes/Domain/Service/NewsService.php +++ b/Classes/Domain/Service/NewsService.php @@ -28,10 +28,10 @@ namespace SGalinski\SgNews\Domain\Service; use SGalinski\SgNews\Domain\Model\Category; use SGalinski\SgNews\Domain\Model\News; +use TYPO3\CMS\Core\Resource\FileRepository; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Domain\Model\FileReference; -use TYPO3\CMS\Core\Resource\FileRepository; /** * This service takes care of meta data generation for the news objects diff --git a/Classes/Hooks/EditDocumentController.php b/Classes/Hooks/EditDocumentController.php deleted file mode 100644 index 34b2ef2dfccbea5b3aa949dd7054dc8af7c2c603..0000000000000000000000000000000000000000 --- a/Classes/Hooks/EditDocumentController.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -namespace SGalinski\SgNews\Hooks; - -/*************************************************************** - * Copyright notice - * - * (c) sgalinski Internet Services (https://www.sgalinski.de) - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ - -use SGalinski\SgNews\Utility\BackendNewsUtility; -use TYPO3\CMS\Backend\Controller\EditDocumentController as CoreEditDocumentController; -use TYPO3\CMS\Backend\Utility\BackendUtility; - -/** - * Backend edid form hook - */ -class EditDocumentController { - - /** - * Sets the default value for the pages author field - * to the name of the logged-in user - * - * @param CoreEditDocumentController $controller - * @return void - */ - public function preInitAfter($controller) { - $tables = ['pages']; - if ( - $GLOBALS['BE_USER']->user['realName'] !== '' - && (isset($controller->editconf[$tables[0]]) || isset($controller->editconf[$tables[1]])) - ) { - $doktype = 0; - $userName = $GLOBALS['BE_USER']->user['realName']; - $tableName = isset($controller->editconf[$tables[0]]) ? $tables[0] : $tables[1]; - $command = reset($controller->editconf[$tableName]); - $pageUid = key($controller->editconf[$tableName]); - if ($command === 'edit') { - $pageRow = BackendUtility::getRecord($tableName, (int) $pageUid); - if ($pageRow && isset($pageRow['doktype'])) { - $doktype = (int) $pageRow['doktype']; - } - } elseif ($command === 'new' && isset($controller->overrideVals[$tableName]['doktype'])) { - $doktype = (int) $controller->overrideVals[$tableName]['doktype']; - } - if ($doktype === BackendNewsUtility::NEWS_DOKTYPE) { - $GLOBALS['BE_USER']->userTS['TCAdefaults.'][$tableName . '.']['author'] = $userName; - } - } - } -} diff --git a/Classes/Hooks/PageLayoutController.php b/Classes/Hooks/PageLayoutController.php index 253737b2c6dfe06c70bfcd236e6ded809e40d4ac..aa63564edb36ede9a51492dc7478b6c1e01beb2e 100644 --- a/Classes/Hooks/PageLayoutController.php +++ b/Classes/Hooks/PageLayoutController.php @@ -37,17 +37,15 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; * Backend edid form hook */ class PageLayoutController { - /** - * Sets the default value for the pages author field - * to the name of the logged-in user + * Adds a Button to News-Pages which allows the user to switch to the News module * * @param array $parameters * @param CorePageLayoutController $controller * @return string * @throws \InvalidArgumentException */ - public function addNewsModuleLink(array $parameters = [], $controller): string { + public function addNewsModuleLink(array $parameters = [], CorePageLayoutController $controller = NULL): string { $out = ''; $pageRow = BackendUtility::getRecord('pages', $controller->id); $acceptedDoktypes = [BackendNewsUtility::NEWS_DOKTYPE, BackendNewsUtility::CATEGORY_DOKTYPE]; diff --git a/Classes/Hooks/PageLayoutView/PluginRenderer.php b/Classes/Hooks/PageLayoutView/PluginRenderer.php index 7e94ef789b5461f7baf86b3babbee412bd0fa254..d0bb7e435efd7a06769c48b861cd20ff2b323114 100644 --- a/Classes/Hooks/PageLayoutView/PluginRenderer.php +++ b/Classes/Hooks/PageLayoutView/PluginRenderer.php @@ -20,6 +20,7 @@ namespace SGalinski\SgNews\Hooks\PageLayoutView; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use SGalinski\SgNews\Preview\PreviewService; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\View\PageLayoutView; use TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface; @@ -34,6 +35,11 @@ use TYPO3\CMS\Fluid\View\StandaloneView; * @package SGalinski\SgNews\Hook\PagelayoutView\PluginRenderer */ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { + protected PreviewService $previewService; + + public function init() { + $this->previewService = GeneralUtility::makeInstance(PreviewService::class); + } /** * Preprocesses the preview rendering of an sg_news content element plugin. @@ -46,34 +52,19 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { * @noinspection ReferencingObjectsInspection */ public function preProcess( - PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row + PageLayoutView &$parentObject, + &$drawItem, + &$headerContent, + &$itemContent, + array &$row ): void { + $this->init(); switch ($row['list_type']) { case 'sgnews_overview': $drawItem = FALSE; - - $view = $this->createViewWithTemplate('Overview'); - $view->assign('uid', $row['uid']); - $this->adaptPluginHeaderContent($headerContent, $row); - // Get available plugin settings and their values from flexform - $pluginConfiguration = GeneralUtility::xml2array( - $row['pi_flexform'], 'T3DataStructure' - )['data']['main']['lDEF']; - - $templateData = [ - 'groupBy' => $pluginConfiguration['settings.groupBy']['vDEF'], - 'enableFilter' => $pluginConfiguration['settings.enableFilter']['vDEF'], - 'newsLimit' => $pluginConfiguration['settings.newsLimit']['vDEF'], - 'onlyNewsWithinThisPageSection' => $pluginConfiguration['settings.onlyNewsWithinThisPageSection']['vDEF'], - 'starttime' => $pluginConfiguration['settings.starttime']['vDEF'], - 'endtime' => $pluginConfiguration['settings.endtime']['vDEF'], - 'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF'], - 'sortDirection' => $pluginConfiguration['settings.sortDirection']['vDEF'] - ]; - - $view->assign('data', $templateData); + $view = $this->previewService->getOverviewView($row); $itemContent .= $view->render(); break; @@ -81,32 +72,8 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { case 'sgnews_latest': $drawItem = FALSE; - $view = $this->createViewWithTemplate('Latest'); - $view->assign('uid', $row['uid']); - $this->adaptPluginHeaderContent($headerContent, $row); - - // Get available plugin settings and their values from flexform - $pluginConfiguration = GeneralUtility::xml2array( - $row['pi_flexform'], 'T3DataStructure' - )['data']['main']['lDEF']; - - $categories = $pluginConfiguration['settings.categories']['vDEF']; - $tags = $pluginConfiguration['settings.tags']['vDEF']; - $templateData = [ - 'limit' => $pluginConfiguration['settings.limit']['vDEF'], - 'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList( - 'pages', $categories - ) : '', - 'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList( - 'sys_category', $tags - ) : '', - 'starttime' => $pluginConfiguration['settings.starttime']['vDEF'], - 'endtime' => $pluginConfiguration['settings.endtime']['vDEF'], - 'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF'] - ]; - - $view->assign('data', $templateData); + $view = $this->previewService->getLatestView($row); $itemContent .= $view->render(); break; @@ -114,31 +81,8 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { case 'sgnews_listbycategory': $drawItem = FALSE; - $view = $this->createViewWithTemplate('ListByCategory'); - $view->assign('uid', $row['uid']); - $this->adaptPluginHeaderContent($headerContent, $row); - - // Get available plugin settings and their values from flexform - $pluginConfiguration = GeneralUtility::xml2array( - $row['pi_flexform'], 'T3DataStructure' - )['data']['main']['lDEF']; - - $categories = $pluginConfiguration['settings.categories']['vDEF']; - $tags = $pluginConfiguration['settings.tags']['vDEF']; - $templateData = [ - 'newsLimitPerPage' => $pluginConfiguration['settings.newsLimitPerPage']['vDEF'], - 'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList( - 'pages', $categories - ) : '', - 'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList('sys_category', $tags) : '', - 'starttime' => $pluginConfiguration['settings.starttime']['vDEF'], - 'endtime' => $pluginConfiguration['settings.endtime']['vDEF'], - 'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF'], - 'sortDirection' => $pluginConfiguration['settings.sortDirection']['vDEF'] - ]; - - $view->assign('data', $templateData); + $view = $this->previewService->getListByCategoryView($row); $itemContent .= $view->render(); break; @@ -146,37 +90,9 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { case 'sgnews_newsbyauthor': $drawItem = FALSE; - $view = $this->createViewWithTemplate('NewsByAuthor'); - $view->assign('uid', $row['uid']); - $this->adaptPluginHeaderContent($headerContent, $row); - // Get available plugin settings and their values from flexform - $pluginConfiguration = GeneralUtility::xml2array( - $row['pi_flexform'], 'T3DataStructure' - )['data']['main']['lDEF']; - - $newsAuthors = $pluginConfiguration['settings.newsAuthors']['vDEF']; - $templateData = [ - 'showDetails' => $pluginConfiguration['settings.showDetails']['vDEF'], - 'newsAuthors' => is_string($newsAuthors) ? $this->addFieldContentsToRecordIdList( - 'tx_sgnews_domain_model_author',$newsAuthors,'name' - ) : '' - ]; - - // Not using addFieldContentsToRecordIdList to avoid repetitive imploding and exploding. - $excludedNewsIds = GeneralUtility::intExplode( - ',', $pluginConfiguration['settings.excludedNews']['vDEF'], TRUE - ); - $excludedNewsListWithTitles = []; - foreach ($excludedNewsIds as $excludedNewsId) { - $excludedNewsListWithTitles[] = BackendUtility::getRecord( - 'pages', $excludedNewsId, 'title' - )['title'] . ' [' . $excludedNewsId . ']'; - } - $templateData['excludedNews'] = $excludedNewsListWithTitles; - - $view->assign('data', $templateData); + $view = $this->previewService->getNewsByAuthorView($row); $itemContent .= $view->render(); break; @@ -186,37 +102,18 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { } } - /** - * Creates a new StandaloneView object with template and partial rot paths, - * attaches the template with the given name to it and returns it. - * - * @param string $templateName - * @return StandaloneView - */ - protected - function createViewWithTemplate(string $templateName): StandaloneView { - $view = GeneralUtility::makeInstance(StandaloneView::class); - $view->setTemplateRootPaths(['EXT:sg_news/Resources/Private/Templates/Backend']); - $view->setPartialRootPaths(['EXT:sg_news/Resources/Private/Partials/Backend']); - if (!str_ends_with($templateName, '.html')) { - $templateName .= '.html'; - } - $view->setTemplate($templateName); - return $view; - } - /** * Adapts the given $headerContent. * To be used in all plugin previews so the Header Contents appear similarly. * - * @param $headerContent - * @param $row + * @param string $headerContent + * @param array $row */ - protected - function adaptPluginHeaderContent(&$headerContent, $row): void { + protected function adaptPluginHeaderContent(&$headerContent, $row): void { $headerContent = '<h4>' . $this->getPluginNameForHeaderContent( - (int) $row['pid'], $row['list_type'] - ) . $headerContent . '</h4>'; + (int) $row['pid'], + $row['list_type'] + ) . $headerContent . '</h4>'; } /** @@ -227,39 +124,17 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { * @param string $listType * @return string */ - protected - function getPluginNameForHeaderContent(int $pid, string $listType): string { + protected function getPluginNameForHeaderContent(int $pid, string $listType): string { $languageService = GeneralUtility::makeInstance(LanguageService::class); $pluginName = $languageService->sL( BackendUtility::getLabelFromItemListMerged( - $pid, 'tt_content', 'list_type', $listType + $pid, + 'tt_content', + 'list_type', + $listType ) ); return '<span class="label label-primary">' . $pluginName . '</span> '; } - - /** - * Takes a comma-separated list of record IDs, the corresponding table and optionally the field to look up. - * Returns another comma-space-separated list of the same records with the content of the field added. - * The returned list should look nice enough to be rendered in the backend preview directly. - * - * @param string $table - * @param string $recordIdList - * @param string $field - * @return string - */ - protected function addFieldContentsToRecordIdList( - string $table, string $recordIdList, string $field = 'title' - ): string { - $recordIdsArray = GeneralUtility::intExplode(',', $recordIdList, TRUE); - $recordsWithTitlesArray = []; - - foreach ($recordIdsArray as $recordId) { - $recordsWithTitlesArray[] = BackendUtility::getRecord( - $table, $recordId, $field - )[$field] . ' [' . $recordId . ']'; - } - return implode(', ', $recordsWithTitlesArray); - } } diff --git a/Classes/Hooks/RealUrlAutoConfiguration.php b/Classes/Hooks/RealUrlAutoConfiguration.php index f1b77b7960a7868f62c024416f28979a50ade53b..32ac5369318105bc2243bb1ac54642204af67380 100644 --- a/Classes/Hooks/RealUrlAutoConfiguration.php +++ b/Classes/Hooks/RealUrlAutoConfiguration.php @@ -37,7 +37,8 @@ class RealUrlAutoConfiguration { */ public function addNewsConfig($params): array { return array_merge_recursive( - $params['config'], [ + $params['config'], + [ 'postVarSets' => [ '_DEFAULT' => [ 'page' => [ diff --git a/Classes/Paginator/QueryBuilderPaginator.php b/Classes/Paginator/QueryBuilderPaginator.php new file mode 100644 index 0000000000000000000000000000000000000000..405c8a55495e645a6d6b4a040a5264f35bc5cd5d --- /dev/null +++ b/Classes/Paginator/QueryBuilderPaginator.php @@ -0,0 +1,105 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace SGalinski\SgNews\Paginator; + +use TYPO3\CMS\Core\Pagination\AbstractPaginator; +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; + +/** + * Copied QueryResult Paginator for us to get a raw result returned, + * just like the old Controller used to use, also alot of BE ViewHelpers want an array + */ +final class QueryBuilderPaginator extends AbstractPaginator { + /** + * @var \TYPO3\CMS\Core\Database\Query\QueryBuilder + */ + private $queryBuilder; + + /** + * @var array + */ + private $paginatedQueryResult; + + /** + * @var int + */ + protected int $totalItems = 0; + + public function __construct( + \TYPO3\CMS\Core\Database\Query\QueryBuilder $queryBuilder, + int $currentPageNumber = 1, + int $itemsPerPage = 10 + ) { + $this->queryBuilder = $queryBuilder; + $this->setCurrentPageNumber($currentPageNumber); + $this->setItemsPerPage($itemsPerPage); + + $this->updateInternalState(); + } + + /** + * @return iterable|QueryResultInterface + */ + public function getPaginatedItems(): iterable { + return $this->paginatedQueryResult; + } + + protected function updatePaginatedItems(int $limit, int $offset): void { + $this->paginatedQueryResult = $this->queryBuilder + ->setMaxResults($limit) + ->setFirstResult($offset) + ->execute()->fetchAllAssociative(); + } + + protected function getTotalAmountOfItems(): int { + $countBuilder = clone $this->queryBuilder; + try { + $totalItems = $countBuilder + ->setMaxResults(99999) + ->setFirstResult(0) + ->count('uid') + ->execute()->fetchOne(); + } catch (\Exception $e) { + $totalItems = $countBuilder + ->setMaxResults(99999) + ->setFirstResult(0) + ->count('p.uid') + ->execute()->fetchOne(); + } + $this->setTotalItems($totalItems ?: 0); + return $totalItems ?: 0; + } + + protected function getAmountOfItemsOnCurrentPage(): int { + return count($this->paginatedQueryResult); + } + + /** + * @return int + */ + public function getTotalItems(): int { + return $this->totalItems; + } + + /** + * @param int $totalItems + */ + public function setTotalItems(int $totalItems): void { + $this->totalItems = $totalItems; + } +} diff --git a/Classes/Preview/PreviewRenderer.php b/Classes/Preview/PreviewRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..efbe5c8c1f141b09109a810e5ab73f403ddbcf69 --- /dev/null +++ b/Classes/Preview/PreviewRenderer.php @@ -0,0 +1,118 @@ +<?php + +/*************************************************************** + * Copyright notice + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * All rights reserved + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +namespace SGalinski\SgNews\Preview; + +use TYPO3\CMS\Backend\Preview\PreviewRendererInterface; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; + +/** + * + */ +class PreviewRenderer implements PreviewRendererInterface { + /** + * @var LanguageService $languageService + */ + protected LanguageService $languageService; + + protected PreviewService $previewService; + + public function __construct(LanguageService $languageService, PreviewService $previewService) { + $this->previewService = $previewService; + $this->languageService = $languageService; + } + + /** + * Dedicated method for rendering preview header HTML for + * the page module only. Receives $item which is an instance of + * GridColumnItem which has a getter method to return the record. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewHeader(GridColumnItem $item): string { + $label = BackendUtility::getLabelFromItemListMerged( + $item->getRecord()['pid'], + 'tt_content', + 'list_type', + $item->getRecord()['list_type'] + ); + return '<h4><span class="label label-primary">' . $this->languageService->sL($label) . '</span> </h4>'; + } + + /** + * Dedicated method for rendering preview body HTML for + * the page module only. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewContent(GridColumnItem $item): string { + $row = $item->getRecord(); + switch ($row['list_type']) { + case 'sgnews_overview': + $view = $this->previewService->getOverviewView($row); + return $view->render(); + + case 'sgnews_latest': + $view = $this->previewService->getLatestView($row); + return $view->render(); + + case 'sgnews_listbycategory': + $view = $this->previewService->getListByCategoryView($row); + return $view->render(); + + case 'sgnews_newsbyauthor': + $view = $this->previewService->getNewsByAuthorView($row); + return $view->render(); + + default: + // No need to do anything + } + return ''; + } + + /** + * Render a footer for the record to display in page module below + * the body of the item's preview. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewFooter(GridColumnItem $item): string { + return ''; + } + + /** + * Dedicated method for wrapping a preview header and body HTML. + * + * @param string $previewHeader + * @param string $previewContent + * @param GridColumnItem $item + * @return string + */ + public function wrapPageModulePreview(string $previewHeader, string $previewContent, GridColumnItem $item): string { + return $previewHeader . $previewContent; + } +} diff --git a/Classes/Preview/PreviewService.php b/Classes/Preview/PreviewService.php new file mode 100644 index 0000000000000000000000000000000000000000..8161f2be0b6980a5e0da44d90a5d25f8b80e8493 --- /dev/null +++ b/Classes/Preview/PreviewService.php @@ -0,0 +1,250 @@ +<?php + +/*************************************************************** + * Copyright notice + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * All rights reserved + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ +namespace SGalinski\SgNews\Preview; + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; + +/** + * small helper class, aslong as we use PageLayout hook + Previewrenderer.... + */ +class PreviewService { + public const RETURNTYPE_ARR = 'array'; + + /** + * returns a Standalone view for SgNews Overview Plugin + * + * @param array $row + * @return StandaloneView + */ + public function getOverviewView(array $row): StandaloneView { + $view = $this->createViewWithTemplate('Overview'); + $view->assign('uid', $row['uid']); + + // Get available plugin settings and their values from flexform + $pluginConfiguration = GeneralUtility::xml2array( + $row['pi_flexform'], + 'T3DataStructure' + )['data']['main']['lDEF']; + + $templateData = [ + 'groupBy' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.groupBy'), + 'enableFilter' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.enableFilter'), + 'newsLimit' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.newsLimit'), + 'onlyNewsWithinThisPageSection' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.onlyNewsWithinThisPageSection'), + 'starttime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.starttime'), + 'endtime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.endtime'), + 'sortBy' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.sortBy'), + 'sortDirection' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.sortDirection'), + ]; + + $view->assign('data', $templateData); + return $view; + } + + /** + * Returns LatestView for Previews of sg_news + * + * @param array $row + * @return StandaloneView + */ + public function getLatestView(array $row): StandaloneView { + $view = $this->createViewWithTemplate('Latest'); + $view->assign('uid', $row['uid']); + + // Get available plugin settings and their values from flexform + $pluginConfiguration = GeneralUtility::xml2array( + $row['pi_flexform'], + 'T3DataStructure' + )['data']['main']['lDEF']; + + $categories = $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.categories'); + $tags = $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.tags'); + $templateData = [ + 'limit' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.limit'), + 'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList( + 'pages', + $categories + ) : '', + 'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList( + 'sys_category', + $tags + ) : '', + 'starttime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.starttime'), + 'endtime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.endtime'), + 'sortBy' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.sortBy'), + ]; + + $view->assign('data', $templateData); + return $view; + } + + /** + * Returns ListByCategory View for Previews of sg_news + * + * @param array $row + * @return StandaloneView + */ + public function getListByCategoryView(array $row): StandaloneView { + $view = $this->createViewWithTemplate('ListByCategory'); + $view->assign('uid', $row['uid']); + + + // Get available plugin settings and their values from flexform + $pluginConfiguration = GeneralUtility::xml2array( + $row['pi_flexform'], + 'T3DataStructure' + )['data']['main']['lDEF']; + + $categories = $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.categories'); + $tags = $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.tags'); + $templateData = [ + 'newsLimitPerPage' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.newsLimitPerPage'), + 'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList( + 'pages', + $categories + ) : '', + 'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList( + 'sys_category', + $tags + ) : '', + + 'starttime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.starttime'), + 'endtime' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.endtime'), + 'sortBy' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.sortBy'), + 'sortDirection' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.sortDirection') + ]; + + $view->assign('data', $templateData); + return $view; + } + + /** + * Returns News by author View for Previews of sg_news + * + * @param array $row + * @return StandaloneView + */ + public function getNewsByAuthorView(array $row): StandaloneView { + $view = $this->createViewWithTemplate('NewsByAuthor'); + $view->assign('uid', $row['uid']); + + // Get available plugin settings and their values from flexform + $pluginConfiguration = GeneralUtility::xml2array( + $row['pi_flexform'], + 'T3DataStructure' + )['data']['main']['lDEF']; + + $newsAuthors = $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.newsAuthors'); + $templateData = [ + 'showDetails' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.showDetails'), + 'newsAuthors' => is_string($newsAuthors) ? $this->addFieldContentsToRecordIdList( + 'tx_sgnews_domain_model_author', + $newsAuthors, + 'name' + ) : '' + ]; + + // Not using addFieldContentsToRecordIdList to avoid repetitive imploding and exploding. + $excludedNewsIds = GeneralUtility::intExplode( + ',', + $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.excludedNews'), + TRUE + ); + $excludedNewsListWithTitles = []; + foreach ($excludedNewsIds as $excludedNewsId) { + $excludedNewsListWithTitles[] = BackendUtility::getRecord( + 'pages', + $excludedNewsId, + 'title' + )['title'] . ' [' . $excludedNewsId . ']'; + } + $templateData['excludedNews'] = $excludedNewsListWithTitles; + + $view->assign('data', $templateData); + return $view; + } + + /** + * @param array $conf + * @param string $key + * @param string $returnType + * @return array|mixed|string + */ + private function passVDefOnKeyToTemplate(array $conf, string $key, string $returnType = '') { + if (isset($conf[$key])) { + return $conf[$key]['vDEF']; + } + + // check if we got a possible returntype: + if ($returnType === self::RETURNTYPE_ARR) { + return []; + } + + return ''; + } + + /** + * Creates a new StandaloneView object with template and partial root paths, + * attaches the template with the given name to it and returns it. + * + * @param string $templateName + * @return StandaloneView + */ + protected function createViewWithTemplate(string $templateName): StandaloneView { + $view = GeneralUtility::makeInstance(StandaloneView::class); + $view->setTemplateRootPaths(['EXT:sg_news/Resources/Private/Templates/Backend']); + $view->setPartialRootPaths(['EXT:sg_news/Resources/Private/Partials/Backend']); + if (!str_ends_with($templateName, '.html')) { + $templateName .= '.html'; + } + $view->setTemplate($templateName); + return $view; + } + + /** + * Takes a comma-separated list of record IDs, the corresponding table and optionally the field to look up. + * Returns another comma-space-separated list of the same records with the content of the field added. + * The returned list should look nice enough to be rendered in the backend preview directly. + * + * @param string $table + * @param string $recordIdList + * @param string $field + * @return string + */ + protected function addFieldContentsToRecordIdList( + string $table, + string $recordIdList, + string $field = 'title' + ): string { + $recordIdsArray = GeneralUtility::intExplode(',', $recordIdList, TRUE); + $recordsWithTitlesArray = []; + + foreach ($recordIdsArray as $recordId) { + $recordsWithTitlesArray[] = BackendUtility::getRecord( + $table, + $recordId, + $field + )[$field] . ' [' . $recordId . ']'; + } + return implode(', ', $recordsWithTitlesArray); + } +} diff --git a/Classes/Service/ConfigurationService.php b/Classes/Service/ConfigurationService.php index 4ee488f46b88b3388009592d9128ddf413d3125c..e2cdd4683ba7ebc560bc6f83ab5cbb2ffd9df269 100644 --- a/Classes/Service/ConfigurationService.php +++ b/Classes/Service/ConfigurationService.php @@ -36,7 +36,6 @@ use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException; * This service provides helper function for dealing with plugin configuration */ class ConfigurationService implements SingletonInterface { - /** * @var array */ diff --git a/Classes/Service/HeaderMetaDataService.php b/Classes/Service/HeaderMetaDataService.php index aa686892aa0dd5eda059acb9dfb9e2429c1aba5a..f3c4e52bca8940334bdb657a155b6a0d7dc9eb64 100644 --- a/Classes/Service/HeaderMetaDataService.php +++ b/Classes/Service/HeaderMetaDataService.php @@ -44,11 +44,23 @@ class HeaderMetaDataService { * @return void */ public static function addOgImageToHeader($path): void { - /** @var $typoScriptController TypoScriptFrontendController */ + /** @var TypoScriptFrontendController $typoScriptController */ $typoScriptController = $GLOBALS['TSFE']; $typoScriptController->page['og_image_path_by_extension'] = $path; } + /** + * Sets the data for the og:image meta data header tag. + * + * @param FileReference $file + * @return void + */ + public static function addOgImageObjectToHeader($file): void { + /** @var TypoScriptFrontendController $typoScriptController */ + $typoScriptController = $GLOBALS['TSFE']; + $typoScriptController->page['og_image_path_by_extension'] = $file; + } + /** * Adds the page number to the canonical * @@ -61,18 +73,13 @@ class HeaderMetaDataService { return; } - if (version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - $headTagService = GeneralUtility::makeInstance( - HeadTagService::class, - FALSE, - '', - '', - '&tx_sgnews_pagebrowser[currentPage]=' . $currentPage - ); - $headTagService->execute(); - } else { - $GLOBALS['TSFE']->page['extensionArgumentsForCanonicalAndHrefLang'] = - '&tx_sgnews_pagebrowser[currentPage]=' . $currentPage; - } + $headTagService = GeneralUtility::makeInstance( + HeadTagService::class, + FALSE, + '', + '', + '&tx_sgnews_pagebrowser[currentPage]=' . $currentPage + ); + $headTagService->execute(); } } diff --git a/Classes/Service/ImageService.php b/Classes/Service/ImageService.php index 67aa6736192b1e92ee796fb9e65c29e019043ca0..0438bb314fed6558d4385ec3d1e477a5b24a9717 100644 --- a/Classes/Service/ImageService.php +++ b/Classes/Service/ImageService.php @@ -61,7 +61,10 @@ class ImageService implements SingletonInterface { * @throws \InvalidArgumentException */ public function cropFirstMediaImage( - FileReference $image, array $coordinates, $path = 'typo3temp/sg_news/', $prefix = '' + FileReference $image, + array $coordinates, + $path = 'typo3temp/sg_news/', + $prefix = '' ): string { $originalResource = $image->getOriginalResource(); $extension = strtolower($originalResource->getExtension()); diff --git a/Classes/TCA/TcaProvider.php b/Classes/TCA/TcaProvider.php index c0ace7acee23cbd3f5eccfe44d7652ab4a88a3de..6594390e175eb86cb00e73a3aef592a15e86c889 100644 --- a/Classes/TCA/TcaProvider.php +++ b/Classes/TCA/TcaProvider.php @@ -35,7 +35,6 @@ use TYPO3\CMS\Extbase\Object\ObjectManager; * This class contains methods for usage within the TCA forms. */ class TcaProvider implements SingletonInterface { - /** * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface */ @@ -79,13 +78,13 @@ class TcaProvider implements SingletonInterface { ->where( $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($pagesIdentity, \PDO::PARAM_INT)) ) - ->execute()->fetch(); + ->execute()->fetchAssociative(); $workspaceOriginalId = (int) $row['t3ver_oid']; if ($workspaceOriginalId > 0) { $row = $queryBuilder->where( - $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($workspaceOriginalId, \PDO::PARAM_INT)) - )->execute()->fetch(); + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($workspaceOriginalId, \PDO::PARAM_INT)) + )->execute()->fetchAssociative(); } // only articles diff --git a/Classes/Updates/MigrateSchedulerTasks.php b/Classes/Updates/MigrateSchedulerTasks.php index b7af223e9e09c4d4b1dbcb770aad118f23eda876..00381f8e2658c2e6b5ae22b5bffbb255041c4b5a 100644 --- a/Classes/Updates/MigrateSchedulerTasks.php +++ b/Classes/Updates/MigrateSchedulerTasks.php @@ -41,7 +41,7 @@ class MigrateSchedulerTasks implements UpgradeWizardInterface { /** * Identifier of the upgrade */ - const IDENTIFIER = 'tx_sgnews_migrateschedulertasks'; + public const IDENTIFIER = 'tx_sgnews_migrateschedulertasks'; /** * @inheritDoc @@ -75,11 +75,11 @@ class MigrateSchedulerTasks implements UpgradeWizardInterface { ->from('tx_scheduler_task') ->where( $queryBuilder->expr()->eq('disable', 0) - )->execute()->fetchAll(); + )->execute()->fetchAllAssociative(); foreach ($tasks as $_task) { $task = unserialize($_task['serialized_task_object'], [\__PHP_Incomplete_Class::class]); $taskVars = $this->cleanArrayKeys((array)$task); - $identifier = $taskVars['*commandIdentifier']; + $identifier = $taskVars['*commandIdentifier'] ?? ''; if ( $identifier === 'sg_news:migratenews:runmigratenews' ) { @@ -131,11 +131,11 @@ class MigrateSchedulerTasks implements UpgradeWizardInterface { ->from('tx_scheduler_task') ->where( $queryBuilder->expr()->eq('disable', 0) - )->execute()->fetchAll(); + )->execute()->fetchAllAssociative(); foreach ($tasks as $_task) { $task = unserialize($_task['serialized_task_object'], [\__PHP_Incomplete_Class::class]); $taskVars = $this->cleanArrayKeys((array)$task); - $identifier = $taskVars['*commandIdentifier']; + $identifier = $taskVars['*commandIdentifier'] ?? ''; if ( $identifier === 'sg_news:migratenews:runmigratenews' ) { @@ -153,7 +153,7 @@ class MigrateSchedulerTasks implements UpgradeWizardInterface { */ protected function cleanArrayKeys(array $array) { $newArray = []; - foreach($array as $key => $value) { + foreach ($array as $key => $value) { $newArray[str_replace("\0", '', $key)] = $value; } return $newArray; diff --git a/Classes/Updates/UpdateAuthors.php b/Classes/Updates/UpdateAuthors.php index eb56fa715436765a2e45b831a0edc1f0f1a7b655..f87a04db977da9150056f55a3d2cf51b7e9608bc 100644 --- a/Classes/Updates/UpdateAuthors.php +++ b/Classes/Updates/UpdateAuthors.php @@ -41,7 +41,7 @@ class UpdateAuthors implements UpgradeWizardInterface { /** * The wizard identifier */ - const IDENTIFIER = 'tx_sgnews_update_authors'; + public const IDENTIFIER = 'tx_sgnews_update_authors'; /** * Retrieves the next site root in the page hierarchy from the current page @@ -86,6 +86,8 @@ class UpdateAuthors implements UpgradeWizardInterface { /** * @return bool + * @throws \Doctrine\DBAL\DBALException + * @throws \Doctrine\DBAL\Driver\Exception */ public function executeUpdate(): bool { $newsQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); @@ -98,7 +100,7 @@ class UpdateAuthors implements UpgradeWizardInterface { $newsQueryBuilder->expr()->neq('author', $newsQueryBuilder->quote('')) ) ) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); if (count($newsEntries) <= 0) { return TRUE; } @@ -122,7 +124,7 @@ class UpdateAuthors implements UpgradeWizardInterface { ) ) ->setMaxResults(1) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); if (!$author) { $authorQueryBuilder->insert('tx_sgnews_domain_model_author') ->values([ diff --git a/Classes/UserFunction/AddAdditionalMailRecipients.php b/Classes/UserFunction/AddAdditionalMailRecipients.php index 08d4644fa28e998289454620c85f50d792ae036d..dd1d5bf8c0a58c09b75095c786365a3a4eacc114 100644 --- a/Classes/UserFunction/AddAdditionalMailRecipients.php +++ b/Classes/UserFunction/AddAdditionalMailRecipients.php @@ -38,7 +38,7 @@ class AddAdditionalMailRecipients implements SingletonInterface { /** * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer */ - public $cObj; + protected $cObj; /** * Adds the news authors to the additional mail recipients. @@ -69,4 +69,8 @@ class AddAdditionalMailRecipients implements SingletonInterface { return $authorEmail; } + + public function setContentObjectRenderer(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $cObj): void { + $this->cObj = $cObj; + } } diff --git a/Classes/Utility/BackendNewsUtility.php b/Classes/Utility/BackendNewsUtility.php index 4cb2354ff3afcc609df0fd6a15987630a4ff7ad9..47de86a49364d0ed542aa1190092b94803a4156d 100644 --- a/Classes/Utility/BackendNewsUtility.php +++ b/Classes/Utility/BackendNewsUtility.php @@ -50,16 +50,15 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; * Class Utility */ class BackendNewsUtility { - /** * @var int The category page doktype */ - const CATEGORY_DOKTYPE = 117; + public const CATEGORY_DOKTYPE = 117; /** * @var int The news page doktype */ - const NEWS_DOKTYPE = 116; + public const NEWS_DOKTYPE = 116; /** * Retrieves the next site root in the page hierarchy from the current page @@ -92,7 +91,12 @@ class BackendNewsUtility { $andWhere = ' AND sys_language_uid IN (0,-1)'; /** @var array $rootOptionRows */ $rootOptionRows = self::getRecordsByField( - 'pages', 'is_siteroot', 1, $andWhere, '', 'sorting' + 'pages', + 'is_siteroot', + 1, + $andWhere, + '', + 'sorting' ); if ($rootOptionRows) { foreach ($rootOptionRows as $row) { @@ -106,7 +110,8 @@ class BackendNewsUtility { foreach ($categories as $categoryUid => $categoryTitle) { if ((int) $pageInfo['uid'] !== $categoryUid) { $categoryPageInfo = BackendUtility::readPageAccess( - $categoryUid, $GLOBALS['BE_USER']->getPagePermsClause(1) + $categoryUid, + $GLOBALS['BE_USER']->getPagePermsClause(1) ); if ($categoryPageInfo) { $options[] = self::getOptionPageInfo($categoryPageInfo); @@ -154,7 +159,10 @@ class BackendNewsUtility { // get all pageids below the given siteroot $queryGenerator = GeneralUtility::makeInstance(QueryGenerator::class); $childPids = $queryGenerator->getTreeList( - $siteRootUid, PHP_INT_MAX, 0, $GLOBALS['BE_USER']->getPagePermsClause(1) + $siteRootUid, + PHP_INT_MAX, + 0, + $GLOBALS['BE_USER']->getPagePermsClause(1) ); $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); @@ -167,11 +175,12 @@ class BackendNewsUtility { $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter(explode(',', $childPids), Connection::PARAM_INT_ARRAY)) ) ) - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); $categories = []; foreach ($result as $page) { $categoryPageInfo = BackendUtility::readPageAccess( - (int) $page['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1) + (int) $page['uid'], + $GLOBALS['BE_USER']->getPagePermsClause(1) ); if ($categoryPageInfo) { $categories[(int) $page['uid']] = $page['title']; @@ -207,11 +216,14 @@ class BackendNewsUtility { $querySettings = $query->getQuerySettings(); $querySettings->setLanguageUid($languageUid); $querySettings->setLanguageOverlayMode(TRUE); - $querySettings->setLanguageMode('content_fallback'); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $querySettings->setLanguageMode('content_fallback'); + } + $query->setQuerySettings($querySettings); if ($pageUid) { $rootline = BackendUtility::BEgetRootLine($pageUid, '', TRUE); - $pageTS = BackendUtility::getPagesTSconfig($pageUid, $rootline); + $pageTS = BackendUtility::getPagesTSconfig($pageUid); $tagsPid = 0; if (isset($pageTS['TCEFORM.']['pages.']['tx_sgnews_tags.']['PAGE_TSCONFIG_ID'])) { @@ -262,7 +274,9 @@ class BackendNewsUtility { $querySettings = $query->getQuerySettings(); $querySettings->setLanguageUid($languageUid); $querySettings->setLanguageOverlayMode(TRUE); - $querySettings->setLanguageMode('content_fallback'); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $querySettings->setLanguageMode('content_fallback'); + } $query->setQuerySettings($querySettings); if ($newsItemUid) { $query->matching($query->equals('uid', $newsItemUid)); @@ -293,7 +307,7 @@ class BackendNewsUtility { * @return array * @throws \InvalidArgumentException */ - public static function getNewsByFilters($rootPageUid = 0, array $filters = [], $languageUid = 0): array { + public static function getNewsByFilters($rootPageUid = 0, array $filters = [], $languageUid = 0, $limit = 0): array { $out = []; $rootPageUid = (int) $rootPageUid; $languageUid = (int) $languageUid; @@ -312,7 +326,8 @@ class BackendNewsUtility { $filterCategories = $filters['categories']; foreach ($filterCategories as $categoryUid) { $categoryPageInfo = BackendUtility::readPageAccess( - (int) $categoryUid, $GLOBALS['BE_USER']->getPagePermsClause(1) + (int) $categoryUid, + $GLOBALS['BE_USER']->getPagePermsClause(1) ); if ($categoryPageInfo) { $categories[] = (int) $categoryUid; @@ -328,9 +343,14 @@ class BackendNewsUtility { $allowedUids = []; foreach ($categories as $categoryUid) { $allowedUidsTemp = GeneralUtility::intExplode( - ',', $queryGenerator->getTreeList( - $categoryUid, 1, 0, $GLOBALS['BE_USER']->getPagePermsClause(1) - ), TRUE + ',', + $queryGenerator->getTreeList( + $categoryUid, + 1, + 0, + $GLOBALS['BE_USER']->getPagePermsClause(1) + ), + TRUE ); $allowedUids = array_unique(array_merge($allowedUids, $allowedUidsTemp)); } @@ -343,13 +363,20 @@ class BackendNewsUtility { $deletedRestriction = GeneralUtility::makeInstance(DeletedRestriction::class); $queryBuilder = $connectionPool->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions()->removeAll()->add($deletedRestriction); - $queryBuilder->select('p.uid', - 'p.pid', - 'p.hidden', - 'p.sorting', - 'p.doktype', - 'p.title' - )->from('pages', 'p') + $queryBuilder->select( + 'p.uid', + 'p.pid', + 'p.hidden', + 'p.sorting', + 'p.doktype', + 'p.nav_hide', + 'p.t3ver_state', + 'p.starttime', + 'p.endtime', + 'p.fe_group', + 'p.l10n_parent', + 'p.title' + )->from('pages', 'p') ->where( $queryBuilder->expr()->andX( $queryBuilder->expr()->in('p.uid', $queryBuilder->createNamedParameter($allowedUids, Connection::PARAM_INT_ARRAY)), @@ -359,7 +386,10 @@ class BackendNewsUtility { ->groupBy('p.uid') ->orderBy('p.sorting'); if ($languageUid) { - $queryBuilder->leftJoin('p', 'pages', 'translation', + $queryBuilder->leftJoin( + 'p', + 'pages', + 'translation', $queryBuilder->expr()->andX( $queryBuilder->expr()->eq('translation.l10n_parent', 'p.uid'), $queryBuilder->expr()->eq('translation.sys_language_uid', $queryBuilder->createNamedParameter($languageUid, \PDO::PARAM_INT)) @@ -368,7 +398,10 @@ class BackendNewsUtility { } if (isset($filters['tags']) && is_array($filters['tags']) && count($filters['tags'])) { - $queryBuilder->innerJoin('p', 'sys_category_record_mm', 'tag', + $queryBuilder->innerJoin( + 'p', + 'sys_category_record_mm', + 'tag', $queryBuilder->expr()->andX( $queryBuilder->expr()->eq('tag.tablenames', $queryBuilder->createNamedParameter('pages')), $queryBuilder->expr()->eq('tag.fieldname', $queryBuilder->createNamedParameter('tx_sgnews_tags')), @@ -400,7 +433,7 @@ class BackendNewsUtility { $authorQueryBuilder->expr()->like('author.name', $authorSearchParameter), $authorQueryBuilder->expr()->like('author.email', $authorSearchParameter) ) - )->execute()->fetchAll(); + )->execute()->fetchAllAssociative(); if (count($authors) > 0) { foreach (array_column($authors, 'uid') as $authorUid) { @@ -414,8 +447,11 @@ class BackendNewsUtility { ) ); } + if ($limit > 0) { + $queryBuilder->setMaxResults($limit); + } - return $queryBuilder->execute()->fetchAll(); + return [$queryBuilder->execute()->fetchAllAssociative(), $queryBuilder]; } /** @@ -429,7 +465,7 @@ class BackendNewsUtility { $pageUid = (int) $pageUid; $rootline = BackendUtility::BEgetRootLine($pageUid, '', TRUE); $defaultLanguage = LocalizationUtility::translate('backend.language.default', 'SgNews'); - $pageTS = BackendUtility::getPagesTSconfig($pageUid, $rootline); + $pageTS = BackendUtility::getPagesTSconfig($pageUid); if (isset($pageTS['mod.']['SHARED.']['defaultLanguageLabel'])) { $defaultLanguage = $pageTS['mod.']['SHARED.']['defaultLanguageLabel'] . ' (' . $defaultLanguage . ')'; } @@ -446,7 +482,7 @@ class BackendNewsUtility { $languageRows = $queryBuilder->select('uid', 'title', 'flag') ->from('sys_language') ->orderBy('sorting') - ->execute()->fetchAll(); + ->execute()->fetchAllAssociative(); if ($languageRows) { /** @var BackendUserAuthentication $backendUser */ $backendUser = $GLOBALS['BE_USER']; @@ -479,12 +515,19 @@ class BackendNewsUtility { * @return mixed Multidimensional array with selected records (if any is selected) */ public static function getRecordsByField( - $theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '', + $theTable, + $theField, + $theValue, + $whereClause = '', + $groupBy = '', + $orderBy = '', + $limit = '', $useDeleteClause = TRUE ) { if (is_array($GLOBALS['TCA'][$theTable])) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($theTable); - $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));; + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); + ; if ($useDeleteClause) { $queryBuilder->getRestrictions() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); @@ -508,7 +551,7 @@ class BackendNewsUtility { // order by if ($orderBy !== '') { foreach (QueryHelper::parseOrderBy($orderBy) as $orderPair) { - list($fieldName, $order) = $orderPair; + [$fieldName, $order] = $orderPair; $queryBuilder->addOrderBy($fieldName, $order); } } @@ -524,7 +567,7 @@ class BackendNewsUtility { } } - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder->execute()->fetchAllAssociative(); } return NULL; diff --git a/Classes/ViewHelpers/AbstractViewHelper.php b/Classes/ViewHelpers/AbstractViewHelper.php index 87cb14a7473934b6d3414e683dd487ae198d2c70..740f8f26da8241cd413f59437c516d78ca202a13 100644 --- a/Classes/ViewHelpers/AbstractViewHelper.php +++ b/Classes/ViewHelpers/AbstractViewHelper.php @@ -32,7 +32,6 @@ use TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper; * Abstract view helper */ class AbstractViewHelper extends AbstractBackendViewHelper { - /** * @var boolean */ diff --git a/Classes/ViewHelpers/Backend/ControlViewHelper.php b/Classes/ViewHelpers/Backend/ControlViewHelper.php index 9ec52630991bc5cd0841d9dcf47903d301c01cc7..807864ce1102c69dd4f97161143bf749f80dc035 100644 --- a/Classes/ViewHelpers/Backend/ControlViewHelper.php +++ b/Classes/ViewHelpers/Backend/ControlViewHelper.php @@ -39,7 +39,6 @@ use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList; * Class ControlViewHelper **/ class ControlViewHelper extends AbstractViewHelper { - /** * Initialize the ViewHelper arguments */ @@ -66,9 +65,22 @@ class ControlViewHelper extends AbstractViewHelper { } $databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class); + if ($table === 'pages') { + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $databaseRecordList->searchlevels = 1; + } else { + // searchLevels is Init with 0 and can only be set by using ->start + $databaseRecordList->start($row['uid'], $table, 0, '', 1, 1); + } + } + $backendUser = $GLOBALS['BE_USER']; $pageInfo = BackendUtility::readPageAccess($row['pid'], $backendUser->getPagePermsClause(1)); - $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); + if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) { + $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); + } else { + $databaseRecordList->calcPerms = new \TYPO3\CMS\Core\Type\Bitmask\Permission($GLOBALS['BE_USER']->calcPerms($pageInfo)); + } $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler'); $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); @@ -76,9 +88,7 @@ class ControlViewHelper extends AbstractViewHelper { $languageService->includeLLFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'); $databaseRecordList->currentTable = $sortingData; - if ($table === 'pages') { - $databaseRecordList->searchLevels = 1; - } + $out = $databaseRecordList->makeControl($table, $row); if ($table === 'pages') { diff --git a/Classes/ViewHelpers/Backend/IconViewHelper.php b/Classes/ViewHelpers/Backend/IconViewHelper.php index 5788ca4d81acf229368e7c31b2566c411188b021..981acef8eca1db5ebbcd56aeaca3de07ed76a840 100644 --- a/Classes/ViewHelpers/Backend/IconViewHelper.php +++ b/Classes/ViewHelpers/Backend/IconViewHelper.php @@ -35,7 +35,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * Class IconViewHelper **/ class IconViewHelper extends AbstractViewHelper { - /** * Initialize the ViewHelper arguments */ @@ -58,13 +57,13 @@ class IconViewHelper extends AbstractViewHelper { $size = trim($this->arguments['size']); $overlayId = $this->arguments['overlayId']; switch ($size) { - case 'small' : + case 'small': $size = Icon::SIZE_SMALL; break; - case 'large' : + case 'large': $size = Icon::SIZE_LARGE; break; - default : + default: $size = Icon::SIZE_DEFAULT; break; } diff --git a/Classes/ViewHelpers/Backend/Link/NewRecordViewHelper.php b/Classes/ViewHelpers/Backend/Link/NewRecordViewHelper.php index 6fce666ac733b9091d855fbfb781ee0d8ff3678e..a496db6999c9771a5fd883cfca32663b54a6388b 100644 --- a/Classes/ViewHelpers/Backend/Link/NewRecordViewHelper.php +++ b/Classes/ViewHelpers/Backend/Link/NewRecordViewHelper.php @@ -78,45 +78,42 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper; * * <be:link.newRecord table="a_table" returnUrl="{f:be.uri(route: 'web_MyextensionList')}" pid="17"> */ -class NewRecordViewHelper extends AbstractTagBasedViewHelper -{ - /** - * @var string - */ - protected $tagName = 'a'; +class NewRecordViewHelper extends AbstractTagBasedViewHelper { + /** + * @var string + */ + protected $tagName = 'a'; - public function initializeArguments() - { - parent::initializeArguments(); - $this->registerUniversalTagAttributes(); - $this->registerArgument('uid', 'int', 'uid < 0 will insert the record after the given uid', false); - $this->registerArgument('pid', 'int', 'the page id where the record will be created', false); - $this->registerArgument('table', 'string', 'target database table', true); - $this->registerArgument('type', 'string', 'The type of the news', true); - $this->registerArgument('returnUrl', 'string', 'return to this URL after closing the edit dialog', false, ''); - } + public function initializeArguments() { + parent::initializeArguments(); + $this->registerUniversalTagAttributes(); + $this->registerArgument('uid', 'int', 'uid < 0 will insert the record after the given uid', FALSE); + $this->registerArgument('pid', 'int', 'the page id where the record will be created', FALSE); + $this->registerArgument('table', 'string', 'target database table', TRUE); + $this->registerArgument('type', 'string', 'The type of the news', TRUE); + $this->registerArgument('returnUrl', 'string', 'return to this URL after closing the edit dialog', FALSE, ''); + } - /** - * @return string - * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException - */ - public function render(): string - { - if ($this->arguments['uid'] && $this->arguments['pid']) { - throw new \InvalidArgumentException('Can\'t handle both uid and pid for new records', 1526129969); - } - if (isset($this->arguments['uid']) && $this->arguments['uid'] >= 0) { - throw new \InvalidArgumentException('Uid must be negative integer, ' . $this->arguments['uid'] . ' given', 1526134901); - } + /** + * @return string + * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException + */ + public function render(): string { + if ($this->arguments['uid'] && $this->arguments['pid']) { + throw new \InvalidArgumentException('Can\'t handle both uid and pid for new records', 1526129969); + } + if (isset($this->arguments['uid']) && $this->arguments['uid'] >= 0) { + throw new \InvalidArgumentException('Uid must be negative integer, ' . $this->arguments['uid'] . ' given', 1526134901); + } - if (empty($this->arguments['returnUrl'])) { - $this->arguments['returnUrl'] = GeneralUtility::getIndpEnv('REQUEST_URI'); - } + if (empty($this->arguments['returnUrl'])) { + $this->arguments['returnUrl'] = GeneralUtility::getIndpEnv('REQUEST_URI'); + } - $params = [ - 'edit' => [$this->arguments['table'] => [$this->arguments['uid'] ?? $this->arguments['pid'] ?? 0 => 'new']], - 'returnUrl' => $this->arguments['returnUrl'] - ]; + $params = [ + 'edit' => [$this->arguments['table'] => [$this->arguments['uid'] ?? $this->arguments['pid'] ?? 0 => 'new']], + 'returnUrl' => $this->arguments['returnUrl'] + ]; if ($this->arguments['table'] === 'pages' && in_array($this->arguments['type'], ['news', 'category'], TRUE)) { $params['overrideVals'] = [ 'pages' => [ @@ -125,11 +122,11 @@ class NewRecordViewHelper extends AbstractTagBasedViewHelper ]; } - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $uri = (string)$uriBuilder->buildUriFromRoute('record_edit', $params); - $this->tag->addAttribute('href', $uri); - $this->tag->setContent($this->renderChildren()); - $this->tag->forceClosingTag(true); - return $this->tag->render(); - } + $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); + $uri = (string)$uriBuilder->buildUriFromRoute('record_edit', $params); + $this->tag->addAttribute('href', $uri); + $this->tag->setContent($this->renderChildren()); + $this->tag->forceClosingTag(TRUE); + return $this->tag->render(); + } } diff --git a/Classes/ViewHelpers/Backend/NewsItemTagsViewHelper.php b/Classes/ViewHelpers/Backend/NewsItemTagsViewHelper.php index ebaa2980d917bcea4fd960c176381ac16a32fb95..d8ba9a15d3c44eeb6c551290bcc50d5874f7eaa2 100644 --- a/Classes/ViewHelpers/Backend/NewsItemTagsViewHelper.php +++ b/Classes/ViewHelpers/Backend/NewsItemTagsViewHelper.php @@ -33,7 +33,6 @@ use SGalinski\SgNews\ViewHelpers\AbstractViewHelper; * Class EditOnClickViewHelper **/ class NewsItemTagsViewHelper extends AbstractViewHelper { - /** * Initialize the ViewHelper arguments */ diff --git a/Classes/ViewHelpers/Backend/RecordIconViewHelper.php b/Classes/ViewHelpers/Backend/RecordIconViewHelper.php index 20f18b705713daa8d7002da845edd6eb01f511f3..d7d6be0a2cc21d60eb3958283a0354fc49ba4588 100644 --- a/Classes/ViewHelpers/Backend/RecordIconViewHelper.php +++ b/Classes/ViewHelpers/Backend/RecordIconViewHelper.php @@ -36,7 +36,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * Class IconViewHelper **/ class RecordIconViewHelper extends AbstractViewHelper { - /** * Initialize the ViewHelper arguments */ diff --git a/Classes/ViewHelpers/Backend/TranslationLinksViewHelper.php b/Classes/ViewHelpers/Backend/TranslationLinksViewHelper.php index 56e190c67ee06cc7e394718159f450b8792bd630..c7f08571b077d168cc9210ada42847da4dd140af 100644 --- a/Classes/ViewHelpers/Backend/TranslationLinksViewHelper.php +++ b/Classes/ViewHelpers/Backend/TranslationLinksViewHelper.php @@ -40,7 +40,6 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; * Class EditOnClickViewHelper **/ class TranslationLinksViewHelper extends AbstractViewHelper { - /** * Register the ViewHelp0er arguments */ @@ -115,13 +114,14 @@ class TranslationLinksViewHelper extends AbstractViewHelper { 'returnUrl' => (string) $returnUrl ]); - $out .= ' <a href="' . $link . '" title="'. $language['title'] . ' [' . $editLabel . ']" >' + $out .= ' <a href="' . $link . '" title="' . $language['title'] . ' [' . $editLabel . ']" >' . $iconFactory->getIcon($language['flag'], Icon::SIZE_SMALL)->render() . '</a>'; } else { $out .= ' <a href="' . BackendUtility::getLinkToDataHandlerAction( - sprintf($translationParameters, $languageUid), $returnUrl + sprintf($translationParameters, $languageUid), + $returnUrl ) . '" title="' . $language['title'] . ' [' . $newLabel . ']" >' . $iconFactory->getIcon( diff --git a/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php b/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php deleted file mode 100644 index 3b1f2ea17ce7fd1b4656de6f6ed279dcd29bdd47..0000000000000000000000000000000000000000 --- a/Classes/ViewHelpers/Backend/Widget/Controller/PaginateController.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace SGalinski\SgNews\ViewHelpers\Backend\Widget\Controller; - -/*************************************************************** - * Copyright notice - * - * (c) sgalinski Internet Services (https://www.sgalinski.de) - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ - -use TYPO3\CMS\Extbase\Persistence\Generic\Query; -use TYPO3\CMS\Fluid\ViewHelpers\Be\Widget\Controller\PaginateController as FluidPaginateController; - -/** - * Class PaginateController - */ -class PaginateController extends FluidPaginateController { - - /** - * @var mixed - */ - protected $objects; - - /** - * Renders the paginator - * - * @param int $currentPage - * @return void - * @throws \InvalidArgumentException - */ - public function indexAction($currentPage = 1) { - // set current page - $this->currentPage = (int) $currentPage; - if ($this->currentPage < 1) { - $this->currentPage = 1; - } - if ($this->currentPage > $this->numberOfPages) { - // set $modifiedObjects to NULL if the page does not exist - $modifiedObjects = NULL; - } else { - // modify query - $this->itemsPerPage = (int) $this->configuration['itemsPerPage']; - $this->offset = $this->itemsPerPage * ($this->currentPage - 1); - if (is_array($this->objects)) { - $modifiedObjects = []; - for ($index = $this->offset; $index < $this->offset + $this->itemsPerPage; $index++) { - if (isset($this->objects[$index])) { - $modifiedObjects[] = $this->objects[$index]; - } else { - break; - } - } - } else { - /** @var Query $query */ - $query = $this->objects->getQuery(); - $query->setLimit($this->itemsPerPage); - if ($this->currentPage > 1) { - $query->setOffset($this->offset); - } - $modifiedObjects = $query->execute(); - } - } - $this->view->assign( - 'contentArguments', [ - $this->widgetConfiguration['as'] => $modifiedObjects - ] - ); - $this->view->assign('configuration', $this->configuration); - $this->view->assign('pagination', $this->buildPagination()); - } - - /** - * Returns an array with the keys "pages", "current", "numberOfPages", - * "nextPage" & "previousPage" - * - * @return array - */ - protected function buildPagination(): array { - $pagination = parent::buildPagination(); - $pagination['totalObjects'] = count($this->objects); - return $pagination; - } -} diff --git a/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php b/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php deleted file mode 100644 index 644806b9d8baa9ed11e7c0288846750fd119d2c6..0000000000000000000000000000000000000000 --- a/Classes/ViewHelpers/Backend/Widget/PaginateViewHelper.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace SGalinski\SgNews\ViewHelpers\Backend\Widget; - -/*************************************************************** - * Copyright notice - * - * (c) sgalinski Internet Services (https://www.sgalinski.de) - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ -use SGalinski\SgNews\ViewHelpers\Backend\Widget\Controller\PaginateController; -use TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetViewHelper; - -/** - * Class PaginateViewHelper - */ -class PaginateViewHelper extends AbstractWidgetViewHelper { - /** - * @var PaginateController - */ - protected $controller; - - /** - * Initializes the controller - * - * @param PaginateController $controller - */ - public function injectPaginateController(PaginateController $controller) { - $this->controller = $controller; - } - - /** - * Initialize the ViewHelper arguments - */ - public function initializeArguments() { - parent::initializeArguments(); - $this->registerArgument('objects', 'mixed', 'The objects to paginate', TRUE); - $this->registerArgument('as', 'string', 'The name of the variable inside the pagination', TRUE); - $this->registerArgument( - 'configuration', - 'array', - 'The configuration of the pagination', - FALSE, - [ - 'itemsPerPage' => 10, - 'insertAbove' => FALSE, - 'insertBelow' => TRUE, - 'recordsLabel' => '' - ] - ); - } - - /** - * Renders the paginator - * - * @return string - * @throws \TYPO3\CMS\Fluid\Core\Widget\Exception\MissingControllerException - */ - public function render(): string { - return $this->initiateSubRequest(); - } -} diff --git a/Classes/ViewHelpers/GetReadingTimeViewHelper.php b/Classes/ViewHelpers/GetReadingTimeViewHelper.php index eb601920b7563f7c97099834374ab3c6279a9cfd..bb11302bc3557ee17cbc4d8735465de03dd08411 100644 --- a/Classes/ViewHelpers/GetReadingTimeViewHelper.php +++ b/Classes/ViewHelpers/GetReadingTimeViewHelper.php @@ -36,7 +36,6 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; * <sg:getReadingTime content="" /> */ class GetReadingTimeViewHelper extends AbstractViewHelper { - /** * Register the ViewHelper arguments */ diff --git a/Classes/ViewHelpers/RelatedViewHelper.php b/Classes/ViewHelpers/RelatedViewHelper.php index 69b8e781d353728940d593b4788c082e934de247..3be86fcc2b3790134b21996350e11ae802a970ce 100644 --- a/Classes/ViewHelpers/RelatedViewHelper.php +++ b/Classes/ViewHelpers/RelatedViewHelper.php @@ -19,7 +19,7 @@ class RelatedViewHelper extends AbstractViewHelper { /** * @var bool */ - protected $escapeOutput = false; + protected $escapeOutput = FALSE; /** * Initialize the view helper arguments @@ -45,7 +45,8 @@ class RelatedViewHelper extends AbstractViewHelper { TRUE ); $this->registerArgument( - 'iteration', 'string', + 'iteration', + 'string', 'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)' ); $this->registerArgument( @@ -68,7 +69,9 @@ class RelatedViewHelper extends AbstractViewHelper { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ public static function renderStatic( - array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext + array $arguments, + \Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext ) { $newsService = GeneralUtility::makeInstance(NewsService::class); $categoryRepository = GeneralUtility::makeInstance(CategoryRepository::class); diff --git a/Classes/ViewHelpers/RenderAuthorNewsViewHelper.php b/Classes/ViewHelpers/RenderAuthorNewsViewHelper.php index 8a6bccd56ec0fd1d6fa516bc6cb36fcee265f244..07643323d37017d2c595025cdfd6a130a5e584d9 100644 --- a/Classes/ViewHelpers/RenderAuthorNewsViewHelper.php +++ b/Classes/ViewHelpers/RenderAuthorNewsViewHelper.php @@ -61,7 +61,7 @@ class RenderAuthorNewsViewHelper extends AbstractViewHelper { /** * Initialize arguments. * - * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception + * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception * @return void * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception */ diff --git a/Classes/Xclass/PageRenderer.php b/Classes/Xclass/PageRenderer.php index 2a26a5b62c792ac2239ee778b14980b2eb76865d..84583eb353686619902f1de1ab07f5415045b5f2 100755 --- a/Classes/Xclass/PageRenderer.php +++ b/Classes/Xclass/PageRenderer.php @@ -58,7 +58,9 @@ class PageRenderer extends \TYPO3\CMS\Core\Page\PageRenderer { if (is_array($this->headerDataRegex)) { foreach ($this->headerDataRegex as $regex) { $this->headerData = preg_replace( - '/' . $regex['pattern'] . '/is', $regex['replacement'], $this->headerData + '/' . $regex['pattern'] . '/is', + $regex['replacement'], + $this->headerData ); } } @@ -72,7 +74,9 @@ class PageRenderer extends \TYPO3\CMS\Core\Page\PageRenderer { * @param string $substituteHash * @return string */ - public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash + public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects( + $cachedPageContent, + $substituteHash ): string { $this->executeHeaderRegularExpressions(); return parent::renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash); diff --git a/Configuration/Commands.php b/Configuration/Commands.php deleted file mode 100644 index 813f2eed18af07382c22a5a6c20bad8a1c1a2ecd..0000000000000000000000000000000000000000 --- a/Configuration/Commands.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php -return [ - 'sg_news:migrateNews' => [ - 'class' => \SGalinski\SgNews\Command\MigrateNewsCommandController::class - ] -]; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index bd14047d646e2916741aab1b5792740200bbc634..8513d90f04b09ad8247980b88ed4fcf15c2cb14b 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -1,4 +1,5 @@ <?php + declare(strict_types=1); // if you need to change this, keep in mind the changes need to be done in diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 9afc78e3bafed7f16ff66441ba06742b01bbbb21..3c0cb4eb296d3f3af857a2d25f8cf085b274211c 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,8 +1,17 @@ services: - _defaults: - autowire: true - autoconfigure: true - public: true + _defaults: + autowire: true + autoconfigure: true + public: false - SGalinski\SgNews\: - resource: '../Classes/*' + SGalinski\SgNews\: + resource: '../Classes/*' + + SGalinski\SgNews\Preview\PreviewRenderer: + public: true + +# Commands + SGalinski\SgNews\Command\MigrateNewsCommandController: + tags: + - name: 'console.command' + command: 'sg_news:migrateNews' diff --git a/Configuration/TCA/Overrides/pages.php b/Configuration/TCA/Overrides/pages.php index 89fe28395137c140dcd5645668a8ae94ba8d72f2..d67c9e9cb2bbf2654233b55cb2677642943263c5 100644 --- a/Configuration/TCA/Overrides/pages.php +++ b/Configuration/TCA/Overrides/pages.php @@ -1,5 +1,6 @@ <?php +defined('TYPO3') or die(); /** * * Copyright notice @@ -56,121 +57,68 @@ foreach ( ]; } -if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - $GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::NEWS_DOKTYPE] = [ - 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, - --palette--;;standard, - --palette--;;titleDescriptionAndHighlightFlag, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.editorial;editorialWithNewsAuthor, - tx_sgnews_content_from_another_page, tx_sgnews_related_news, tx_sgnews_tags, - --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.seo, - --palette--;;seo, - --palette--;;robots, - --palette--;;canonical, - --palette--;;sitemap, - --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.socialmedia, - --palette--;;opengraph, - --palette--;;twittercards, - --div--;' . $localLangDbPath . 'pages.tabs.images, - tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, - --palette--;;media, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, - --palette--;;language - ' - ]; -} else { - $GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::NEWS_DOKTYPE] = [ - 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, - --palette--;;standard, - --palette--;;titleDescriptionAndHighlightFlag, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.editorial;editorialWithNewsAuthor, - tx_sgnews_content_from_another_page, tx_sgnews_related_news, tx_sgnews_tags, - --div--;' . $localLangDbPath . 'pages.tabs.images, - tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, - --palette--;;media, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, - tx_projectbase_devnullrobots_flags, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, - tx_projectbase_seo_titletag,tx_projectbase_seo_canonicaltag, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, - --palette--;;language - ' - ]; -} -if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - $GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::CATEGORY_DOKTYPE] = [ - 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, - --palette--;;standard, - title, slug, tx_projectbase_path_segment, tx_projectbase_excludefromsluggeneration, tx_realurl_pathsegment, tx_realurl_exclude, - --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.seo, - --palette--;;seo, - --palette--;;robots, - --palette--;;canonical, - --palette--;;sitemap, - --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.socialmedia, - --palette--;;opengraph, - --palette--;;twittercards, - --div--;' . $localLangDbPath . 'pages.tabs.images, - tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, - --palette--;;media, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, - seo_title,canonical_link, ' . (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('yoast_seo') || \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('seo') ? '':'description,') . ' - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, - --palette--;;language - ' - ]; -} else { - $GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::CATEGORY_DOKTYPE] = [ - 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, - --palette--;;standard, - title, slug, tx_projectbase_path_segment, tx_projectbase_excludefromsluggeneration, tx_realurl_pathsegment, tx_realurl_exclude, - --div--;' . $localLangDbPath . 'pages.tabs.images, - tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, - --palette--;;media, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, - tx_projectbase_devnullrobots_flags, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, - tx_projectbase_seo_titletag,tx_projectbase_seo_canonicaltag, ' . (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('yoast_seo') || \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('seo') ? '':'description,') . ' - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, - --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, - --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, - --palette--;;language - ' - ]; -} +$GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::NEWS_DOKTYPE] = [ + 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, + --palette--;;standard, + --palette--;;titleDescriptionAndHighlightFlag, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.editorial;editorialWithNewsAuthor, + tx_sgnews_content_from_another_page, tx_sgnews_related_news, tx_sgnews_tags, + --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.seo, + --palette--;;seo, + --palette--;;robots, + --palette--;;canonical, + --palette--;;sitemap, + --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.socialmedia, + --palette--;;opengraph, + --palette--;;twittercards, + --div--;' . $localLangDbPath . 'pages.tabs.images, + tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, + --palette--;;media, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, + --palette--;;language + ' +]; + +$GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::CATEGORY_DOKTYPE] = [ + 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, + --palette--;;standard, + title, slug, tx_projectbase_path_segment, tx_projectbase_excludefromsluggeneration, tx_realurl_pathsegment, tx_realurl_exclude, + --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.seo, + --palette--;;seo, + --palette--;;robots, + --palette--;;canonical, + --palette--;;sitemap, + --div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.socialmedia, + --palette--;;opengraph, + --palette--;;twittercards, + --div--;' . $localLangDbPath . 'pages.tabs.images, + tx_sgnews_teaser2_image, tx_sgnews_teaser1_image, + --palette--;;media, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.metadata, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.abstract;abstract, + seo_title,canonical_link, ' . (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('yoast_seo') || \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('seo') ? '' : 'description,') . ' + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.appearance, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.layout;layout, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.visibility;visibility, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:pages.palettes.access;access, + --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tabs.behaviour, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.caching;caching, + --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.palettes.miscellaneous;miscellaneous, + --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, + --palette--;;language + ' +]; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns( 'pages', @@ -178,11 +126,7 @@ if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExten 'tx_sgnews_teaser1_image' => [ 'exclude' => TRUE, 'label' => $localLangDbPath . 'pages.tx_sgnews_teaser1_image', - 'description' => (version_compare( - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sg_seo'), - '5.0.0', - '>=') - ) ? 'LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:teaser_description' : null, + 'description' => 'LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:teaser_description', 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( 'tx_sgnews_teaser1_image', [ @@ -190,32 +134,32 @@ if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExten 'foreign_types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ], @@ -232,11 +176,7 @@ if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExten 'tx_sgnews_teaser2_image' => [ 'exclude' => TRUE, 'label' => $localLangDbPath . 'pages.tx_sgnews_teaser2_image', - 'description' => (version_compare( - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sg_seo'), - '5.0.0', - '>=') - ) ? 'LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:teaser_description' : null, + 'description' => 'LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:teaser_description', 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( 'tx_sgnews_teaser2_image', [ @@ -244,32 +184,32 @@ if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExten 'foreign_types' => [ '0' => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ], \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [ 'showitem' => ' - --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette' ] ], @@ -460,7 +400,7 @@ if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExten $GLOBALS['TCA']['pages']['palettes']['titleDescriptionAndHighlightFlag'] = [ 'showitem' => 'subtitle;' . $localLangDbPath . 'pages.subtitle.inPalette, --linebreak--, title, - ' . (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('yoast_seo') || \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('seo') ? '':'--linebreak--, description,') . ' + ' . (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('yoast_seo') || \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('seo') ? '' : '--linebreak--, description,') . ' --linebreak--, slug, --linebreak--, tx_projectbase_path_segment, tx_projectbase_excludefromsluggeneration, --linebreak--, tx_realurl_pathsegment, tx_realurl_exclude, @@ -478,64 +418,38 @@ $GLOBALS['TCA']['pages']['palettes']['editorialWithNewsAuthor'] = [ ]; foreach ($GLOBALS['TCA']['pages']['columns'] as $languageExcludeField => $_) { - if (version_compare(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) { - $fieldNames = [ - 'doktype', - 'title', - 'subtitle', - 'description', - 'slug', - 'tx_projectbase_path_segment', - 'tx_projectbase_excludefromsluggeneration', - 'tx_sgnews_location', - 'tx_sgnews_teaser1_image', - 'tx_sgnews_teaser2_image', - 'tx_sgnews_tags', - 'abstract', - 'seo_title', - 'canonical_link', - 'hidden', - 'sys_language_uid', - 'tx_languagevisibility_visibility', - 'lastUpdated', - 'tx_sgnews_date_end', - 'tx_sgnews_highlighted', - 'tx_sgnews_never_highlighted', - 'tx_sgnews_comments_enable', - 'og_title', - 'og_description', - 'og_image', - 'twitter_title', - 'twitter_description', - 'twitter_image', - 'twitter_card' - ]; - } else { - $fieldNames = [ - 'doktype', - 'title', - 'subtitle', - 'description', - 'slug', - 'tx_projectbase_path_segment', - 'tx_projectbase_excludefromsluggeneration', - 'tx_sgnews_location', - 'tx_sgnews_teaser1_image', - 'tx_sgnews_teaser2_image', - 'tx_sgnews_tags', - 'abstract', - 'tx_projectbase_seo_titletag', - 'tx_projectbase_seo_canonicaltag', - 'hidden', - 'sys_language_uid', - 'tx_languagevisibility_visibility', - 'lastUpdated', - 'tx_sgnews_date_end', - 'tx_sgnews_highlighted', - 'tx_sgnews_never_highlighted', - 'tx_sgnews_comments_enable' - ]; - } + $fieldNames = [ + 'doktype', + 'title', + 'subtitle', + 'description', + 'slug', + 'tx_projectbase_path_segment', + 'tx_projectbase_excludefromsluggeneration', + 'tx_sgnews_location', + 'tx_sgnews_teaser1_image', + 'tx_sgnews_teaser2_image', + 'tx_sgnews_tags', + 'abstract', + 'seo_title', + 'canonical_link', + 'hidden', + 'sys_language_uid', + 'tx_languagevisibility_visibility', + 'lastUpdated', + 'tx_sgnews_date_end', + 'tx_sgnews_highlighted', + 'tx_sgnews_never_highlighted', + 'tx_sgnews_comments_enable', + 'og_title', + 'og_description', + 'og_image', + 'twitter_title', + 'twitter_description', + 'twitter_image', + 'twitter_card' + ]; + if (!in_array($languageExcludeField, $fieldNames)) { $GLOBALS['TCA']['pages']['types'][\SGalinski\SgNews\Utility\BackendNewsUtility::NEWS_DOKTYPE]['columnsOverrides'][$languageExcludeField]['l10n_mode'] = 'exclude'; } diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index 866956e45ad81c53aa88d3ddb71febc934353263..e68202faf0645ab8f8451d2ea11fad57c5b2c41b 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,4 +1,6 @@ <?php + +defined('TYPO3') or die(); /** * * Copyright notice @@ -25,5 +27,7 @@ */ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile( - 'sg_news', 'Configuration/TypoScript/Frontend', 'News System' + 'sg_news', + 'Configuration/TypoScript/Frontend', + 'News System' ); diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index 849be5b17a03744908929d18d717026c6c856c38..eb86f04f405069b444799b7d5d054a0ffe3743ce 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -1,4 +1,6 @@ <?php + +defined('TYPO3') or die(); /** * * Copyright notice @@ -58,20 +60,29 @@ $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['sgnews_n // Flex form assignment $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgnews_overview'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( - 'sgnews_overview', 'FILE:EXT:sg_news/Configuration/FlexForms/Overview.xml' + 'sgnews_overview', + 'FILE:EXT:sg_news/Configuration/FlexForms/Overview.xml' ); $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgnews_listbycategory'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( - 'sgnews_listbycategory', 'FILE:EXT:sg_news/Configuration/FlexForms/ListByCategory.xml' + 'sgnews_listbycategory', + 'FILE:EXT:sg_news/Configuration/FlexForms/ListByCategory.xml' ); $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgnews_latest'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( - 'sgnews_latest', 'FILE:EXT:sg_news/Configuration/FlexForms/Latest.xml' + 'sgnews_latest', + 'FILE:EXT:sg_news/Configuration/FlexForms/Latest.xml' ); $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgnews_newsbyauthor'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( - 'sgnews_newsbyauthor', 'FILE:EXT:sg_news/Configuration/FlexForms/NewsByAuthor.xml' + 'sgnews_newsbyauthor', + 'FILE:EXT:sg_news/Configuration/FlexForms/NewsByAuthor.xml' ); + +$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_overview'] = \SGalinski\SgNews\Preview\PreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_listbycategory'] = \SGalinski\SgNews\Preview\PreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_latest'] = \SGalinski\SgNews\Preview\PreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_newsbyauthor'] = \SGalinski\SgNews\Preview\PreviewRenderer::class; diff --git a/Configuration/TCA/tx_sgnews_domain_model_author.php b/Configuration/TCA/tx_sgnews_domain_model_author.php index 779d63e3e171a46ba7a99acbc3bfe4add5880e7a..173e05f2a70d1a8a3df3c9edaf24cc7e3cd2f498 100644 --- a/Configuration/TCA/tx_sgnews_domain_model_author.php +++ b/Configuration/TCA/tx_sgnews_domain_model_author.php @@ -34,7 +34,6 @@ $configuration = [ 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', 'searchFields' => 'name, email, description, website', - 'dividers2tabs' => TRUE, 'delete' => 'deleted', 'enablecolumns' => [ 'disabled' => 'hidden', @@ -48,7 +47,7 @@ $configuration = [ 'interface' => [], 'types' => [ '1' => [ - 'showitem' => 'hidden;;1, --palette--;;authorInfos, path_segment, description' + 'showitem' => 'hidden,--palette--;;1,--palette--;;authorInfos,path_segment,description' ], ], 'palettes' => [ @@ -164,7 +163,8 @@ $configuration = [ 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:tx_sgnews_domain_model_author.image', 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( - 'files', [ + 'files', + [ 'appearance' => [ 'useSortable' => TRUE, ], @@ -192,8 +192,5 @@ $configuration = [ ], ] ]; -if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '10.3.0', '<')) { - $configuration['interface']['showRecordFieldList'] = 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, crdate, name, email, description, website, image, path_segment'; -} return $configuration; diff --git a/Configuration/TypoScript/Common/setup.typoscript b/Configuration/TypoScript/Common/setup.typoscript index 1223a9805550ed76981e5ea357b34c112095d4f1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/Configuration/TypoScript/Common/setup.typoscript +++ b/Configuration/TypoScript/Common/setup.typoscript @@ -1,50 +0,0 @@ -config.tx_extbase { - persistence { - classes { - # @deprecated This configuration does not work in TYPO3 10 at all, you need to also change - # Configuration/Extbase/Persistence/Classes.php - SGalinski\SgNews\Domain\Model\News { - mapping { - tableName = pages - recordType = 116 - columns { - tx_sgnews_highlighted.mapOnProperty = highlighted - tx_sgnews_never_highlighted.mapOnProperty = neverHighlighted - tx_sgnews_related_news.mapOnProperty = relatedNews - tx_sgnews_news_author.mapOnProperty = newsAuthor - lastUpdated.mapOnProperty = lastUpdated - crdate.mapOnProperty = creationDate - tx_sgnews_teaser1_image.mapOnProperty = teaser1Image - tx_sgnews_teaser2_image.mapOnProperty = teaser2Image - tx_sgnews_tags.mapOnProperty = tags - tx_sgnews_likes.mapOnProperty = likes - tx_sgnews_content_from_another_page.mapOnProperty = contentFromAnotherPage - tx_sgnews_location.mapOnProperty = location - tx_sgnews_date_end.mapOnProperty = dateEnd - } - } - } - SGalinski\SgNews\Domain\Model\Category { - mapping { - tableName = pages - recordType = 117 - columns { - tx_sgnews_teaser1_image.mapOnProperty = teaser1Image - tx_sgnews_teaser2_image.mapOnProperty = teaser2Image - } - } - } - SGalinski\SgNews\Domain\Model\Tag { - mapping { - tableName = sys_category - } - } - - SGalinski\SgNews\Domain\Model\FileReference { - mapping { - tableName = sys_file_reference - } - } - } - } -} diff --git a/Configuration/TypoScript/Frontend/constants.typoscript b/Configuration/TypoScript/Frontend/constants.typoscript index 58f8138af09e551c7aec4fbb1efd6f6b9db7ca00..056a6f06563356824bebc02b2bd764d182a6d6d9 100644 --- a/Configuration/TypoScript/Frontend/constants.typoscript +++ b/Configuration/TypoScript/Frontend/constants.typoscript @@ -21,6 +21,6 @@ plugin.tx_sgnews { sortDirection = DESC # This enables the output of related news in regards to the news category or tags - enableAutomaticRelatedNews = 0 + enableAutomaticRelatedNews = 1 } } diff --git a/README.md b/README.md index 09323fcaa0349055ac13b4b94239da470a30c5ef..6e56e2faff35e87a5ac42e23a5015799929e5b20 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Repository: https://gitlab.sgalinski.de/typo3/sg_news Please report bugs here: https://gitlab.sgalinski.de/typo3/sg_news -TYPO3 version: >=9.5 +TYPO3 version: >=10.4 ## About diff --git a/Resources/Private/Layouts/Backend.html b/Resources/Private/Layouts/Backend.html index 11777dd28bf8a4a54fe506d87525c293a6f8f951..73ae87a2fdbf1b53bcc8580a0fa8225f38b2ffe5 100644 --- a/Resources/Private/Layouts/Backend.html +++ b/Resources/Private/Layouts/Backend.html @@ -1,52 +1,68 @@ {namespace core = TYPO3\CMS\Core\ViewHelpers} {namespace sg=SGalinski\SgNews\ViewHelpers} -<f:be.container - includeRequireJsModules="{ - 0: 'TYPO3/CMS/Backend/ContextMenu', - 1: 'TYPO3/CMS/Backend/Tooltip', - 2: 'TYPO3/CMS/SgNews/Backend'}"> - <div class="module" data-module-id="" data-module-name=""> - <div class="module-docheader t3js-module-docheader"> - <div class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation"> - <div class="module-docheader-bar-column-left"> - <f:for each="{docHeader.menus}" as="menu"> - <f:be.menus.actionMenu additionalAttributes="{name: menu.identifier}"> - <f:for each="{menu.menuItems}" as="menuItem"> - <option value="{menuItem.href}" {f:if(condition: '{menuItem.active}', then: 'selected="selected"')}>{menuItem.title}</option> +<f:if condition="{V11}"> + <f:then> + <f:be.pageRenderer includeRequireJsModules="{ + 0: 'TYPO3/CMS/Backend/ContextMenu', + 1: 'TYPO3/CMS/Backend/Tooltip', + 2: 'TYPO3/CMS/SgNews/Backend'}" + /> + + <h1> + <f:render section="headline" /> + </h1> + <f:render section="content" /> + </f:then> + <f:else> + <f:be.container + includeRequireJsModules="{ + 0: 'TYPO3/CMS/Backend/ContextMenu', + 1: 'TYPO3/CMS/Backend/Tooltip', + 2: 'TYPO3/CMS/SgNews/Backend'}"> + <div class="module" data-module-id="" data-module-name=""> + <div class="module-docheader t3js-module-docheader"> + <div class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation"> + <div class="module-docheader-bar-column-left"> + <f:for each="{docHeader.menus}" as="menu"> + <f:be.menus.actionMenu additionalAttributes="{name: menu.identifier}"> + <f:for each="{menu.menuItems}" as="menuItem"> + <option value="{menuItem.href}" {f:if(condition: '{menuItem.active}', then: 'selected="selected"')}>{menuItem.title}</option> + </f:for> + </f:be.menus.actionMenu> </f:for> - </f:be.menus.actionMenu> - </f:for> - </div> - <div class="module-docheader-bar-column-right"> - <span class="typo3-docheader-pagePath"> - <f:if condition="{typo3Version} < 9000000"> - <f:then> - <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> - </f:then> - <f:else> - <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> - </f:else> - </f:if> - </span> - <f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw> + </div> + <div class="module-docheader-bar-column-right"> + <span class="typo3-docheader-pagePath"> + <f:if condition="{typo3Version} < 9000000"> + <f:then> + <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> + </f:then> + <f:else> + <f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw> + </f:else> + </f:if> + </span> + <f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw> + </div> + </div> + <div class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons"> + <div class="module-docheader-bar-column-left"> + </div> + <div class="module-docheader-bar-column-right"> + <f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" /> + </div> + </div> </div> </div> - <div class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons"> - <div class="module-docheader-bar-column-left"> - </div> - <div class="module-docheader-bar-column-right"> - <f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" /> + <div id="typo3-docbody"> + <div id="typo3-inner-docbody"> + <h1> + <f:render section="headline" /> + </h1> + <f:render section="content" /> </div> </div> - </div> - </div> - <div id="typo3-docbody"> - <div id="typo3-inner-docbody"> - <h1> - <f:render section="headline" /> - </h1> - <f:render section="content" /> - </div> - </div> -</f:be.container> + </f:be.container> + </f:else> +</f:if> diff --git a/Resources/Private/Partials/Backend/Filter.html b/Resources/Private/Partials/Backend/Filter.html index 256ca3dcdc31e4799c53d90940fde5b4943317cd..2837aa7324fee73005c5405bff29574dde43e189 100644 --- a/Resources/Private/Partials/Backend/Filter.html +++ b/Resources/Private/Partials/Backend/Filter.html @@ -1,7 +1,7 @@ <f:form action="index" controller="Backend" method="post" objectName="filters" object="{filters}"> <div class="row"> <f:if condition="{showCategoryFilter}"> - <div class="col-xs-4"> + <div class="col-sm-4"> <div class="form-group"> <label for="filter-categories"> <f:translate key="backend.filters.categories" /> @@ -11,7 +11,7 @@ </div> </div> </f:if> - <div class="col-xs-{f:if(condition: showCategoryFilter, then: '4', else: '6')}"> + <div class="col-sm-{f:if(condition: showCategoryFilter, then: '4', else: '6')}"> <div class="form-group"> <label for="filter-tags"> <f:translate key="backend.filters.tags" /> @@ -20,16 +20,16 @@ <small><f:format.raw><f:translate key="backend.filters.tags.description" /></f:format.raw></small> </div> </div> - <div class="col-xs-{f:if(condition: showCategoryFilter, then: '4', else: '6')}"> + <div class="col-sm-{f:if(condition: showCategoryFilter, then: '4', else: '6')}"> <div class="form-group"> <label for="filter-search"><f:translate key="backend.filters.search" /></label> <f:form.textfield class="form-control" property="search" id="filter-search" /> </div> - <div class="media"> + <div class="media-buttons"> <div class="pull-right divider"> <f:form.button class="btn btn-success form-control" type="submit"><f:translate key="backend.filter" /></f:form.button> </div> - <div class="pull-right divider"> + <div class="pull-right divider" style="margin-right: 15px"> <f:form.button id="filter-reset-btn" class="btn btn-danger form-control" type="reset"><f:translate key="backend.filter.reset" /></f:form.button> </div> </div> diff --git a/Resources/Private/Partials/Backend/Pagination.html b/Resources/Private/Partials/Backend/Pagination.html new file mode 100644 index 0000000000000000000000000000000000000000..242dff918ccb9d5ff8faae1bf0644db8e67a23b0 --- /dev/null +++ b/Resources/Private/Partials/Backend/Pagination.html @@ -0,0 +1,103 @@ +{namespace core=TYPO3\CMS\Core\ViewHelpers} +{namespace sg=SGalinski\SgMail\ViewHelpers} + +<nav class="pagination-wrap"> + <ul class="pagination pagination-block"> + <f:if condition="{pagination.previousPageNumber} && {pagination.previousPageNumber} >= {pagination.firstPageNumber}"> + <f:then> + <li class="page-item"> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: 1})}" title="{f:translate(key:'widget.pagination.first')}" class="page-link"> + <core:icon identifier="actions-view-paging-first" /> + </a> + </li> + <li class="page-item"> + <a href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.previousPageNumber})}" title="{f:translate(key:'widget.pagination.previous')}" class="page-link"> + <core:icon identifier="actions-view-paging-previous" /> + </a> + </li> + </f:then> + <f:else> + <li class="page-item disabled"> + <span class="page-link"> + <core:icon identifier="actions-view-paging-first" /> + </span> + </li> + <li class="page-item disabled"> + <span class="page-link"> + <core:icon identifier="actions-view-paging-previous" /> + </span> + </li> + </f:else> + </f:if> + <li class="page-item"> + <span class="page-link"> + <f:if condition="{recordsLabel}"> + <f:then> + {recordsLabel} + </f:then> + <f:else> + <f:translate key="widget.pagination.records" /> + </f:else> + </f:if> + {pagination.startRecordNumber} - {pagination.endRecordNumber} / {paginator.totalItems} + </span> + </li> + <li class="page-item"> + <span class="page-link"> + <f:translate key="widget.pagination.page" /> + <form id="paginator-form-{position}" onsubmit="goToPage{position}(this); return false;" style="display:inline;"> + <script type="text/javascript"> + function goToPage{position}(formObject) { + var page = formObject.elements['paginator-target-page'].value; + var url = '{f:uri.action(action:actionName, arguments:{currentPage: 987654321}) -> f:format.raw()}'; + + if (page > {pagination.lastPageNumber}) { + page = {pagination.lastPageNumber}; + } + else + if (page < 1) { + page = 1; + } + url = url.replace('987654321', page); + self.location.href = url; + } + </script> + <f:form.textfield id="paginator-{position}" name="paginator-target-page" additionalAttributes="{min: '1'}" class="form-control input-sm paginator-input" size="5" value="{currentPage}" type="number" /> + </form> + + / {pagination.lastPageNumber} + </span> + </li> + <f:if condition="{pagination.nextPageNumber} && {pagination.nextPageNumber} <= {pagination.lastPageNumber}"> + <f:then> + <li class="page-item"> + <a class="page-link" href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.nextPageNumber})}" title="{f:translate(key:'widget.pagination.next')}"> + <core:icon identifier="actions-view-paging-next" /> + </a> + </li> + <li class="page-item"> + <a class="page-link" href="{f:uri.action(action:actionName, arguments:{currentPage: pagination.lastPageNumber})}" title="{f:translate(key:'widget.pagination.last')}"> + <core:icon identifier="actions-view-paging-last" /> + </a> + </li> + </f:then> + <f:else> + <li class="page-item disabled"> + <span class="page-link"> + <core:icon identifier="actions-view-paging-next" /> + </span> + </li> + <li class="page-item disabled"> + <span class="page-link"> + <core:icon identifier="actions-view-paging-last" /> + </span> + </li> + </f:else> + </f:if> + <li class="page-item"> + <a class="page-link" href="{f:uri.action(action:actionName, arguments:{currentPage: currentPage})}" title="{f:translate(key:'widget.pagination.refresh')}"> + <core:icon identifier="actions-refresh" /> + </a> + </li> + </ul> +</nav> diff --git a/Resources/Private/Templates/Backend/Index.html b/Resources/Private/Templates/Backend/Index.html index 164b931cd4f72f930dde5780cecb47611254e9f0..e511a05940a4939154947b45746d86df1e3f19af 100644 --- a/Resources/Private/Templates/Backend/Index.html +++ b/Resources/Private/Templates/Backend/Index.html @@ -45,55 +45,54 @@ <div class="panel panel-default recordlist"> <div class="table-fit"> <table data-table="pages" class="table table-striped table-hover"> - <sg:backend.widget.paginate objects="{news}" as="paginatedNews" configuration="{insertAbove: 1, itemsPerPage: 20}"> - <tbody> - <f:for each="{paginatedNews}" as="singleNews"> - <tr data-uid="{singleNews.uid}"> - <td nowrap="nowrap" class="col-icon"> - <f:format.raw> - <sg:backend.recordIcon table="pages" row="{singleNews}" /> - </f:format.raw> - </td> - <td nowrap="nowrap"> - <f:alias map="{newsItemTags: '{sg:backend.newsItemTags(uid: singleNews.uid, languageUid: language)}'}"> - <f:if condition="{singleNews.translation_uid}"> - <f:then> - <be:link.editRecord uid="{singleNews.translation_uid}" table="pages"> - <span> - <f:if condition="{singleNews.translation_title}"> - <f:then> - {singleNews.translation_title} - </f:then> - <f:else> - {singleNews.title} - </f:else> - </f:if> - <f:if condition="{newsItemTags}">({newsItemTags})</f:if> - </span> - </be:link.editRecord> - </f:then> - <f:else> - <be:link.editRecord uid="{singleNews.uid}" table="pages"> - <span> - {singleNews.title} - <f:if condition="{newsItemTags}">({newsItemTags})</f:if> - </span> - </be:link.editRecord> - </f:else> - </f:if> - </f:alias> - <br /> - <sg:backend.translationLinks pageUid="{pageUid}" table="pages" uid="{singleNews.uid}" /> - </td> - <td nowrap="nowrap" class="col-control"> - <f:format.raw> - <sg:backend.control table="pages" row="{singleNews}" /> - </f:format.raw> - </td> - </tr> - </f:for> - </tbody> - </sg:backend.widget.paginate> + <f:render partial="Backend/Pagination" arguments="{pagination: pagination, paginator: paginator, actionName: 'index', currentPage: currentPage}"/> + <tbody> + <f:for each="{paginator.paginatedItems}" as="singleNews"> + <tr data-uid="{singleNews.uid}"> + <td nowrap="nowrap" class="col-icon"> + <f:format.raw> + <sg:backend.recordIcon table="pages" row="{singleNews}" /> + </f:format.raw> + </td> + <td nowrap="nowrap"> + <f:alias map="{newsItemTags: '{sg:backend.newsItemTags(uid: singleNews.uid, languageUid: language)}'}"> + <f:if condition="{singleNews.translation_uid}"> + <f:then> + <be:link.editRecord uid="{singleNews.translation_uid}" table="pages"> + <span> + <f:if condition="{singleNews.translation_title}"> + <f:then> + {singleNews.translation_title} + </f:then> + <f:else> + {singleNews.title} + </f:else> + </f:if> + <f:if condition="{newsItemTags}">({newsItemTags})</f:if> + </span> + </be:link.editRecord> + </f:then> + <f:else> + <be:link.editRecord uid="{singleNews.uid}" table="pages"> + <span> + {singleNews.title} + <f:if condition="{newsItemTags}">({newsItemTags})</f:if> + </span> + </be:link.editRecord> + </f:else> + </f:if> + </f:alias> + <br /> + <sg:backend.translationLinks pageUid="{pageUid}" table="pages" uid="{singleNews.uid}" /> + </td> + <td nowrap="nowrap" class="col-control"> + <f:format.raw> + <sg:backend.control table="pages" row="{singleNews}" /> + </f:format.raw> + </td> + </tr> + </f:for> + </tbody> </table> </div> </div> diff --git a/Resources/Public/Icons/Extension.png b/Resources/Public/Icons/Extension.png new file mode 100644 index 0000000000000000000000000000000000000000..67fda8fec210ccf660363ff30c10f19513b4bfb2 Binary files /dev/null and b/Resources/Public/Icons/Extension.png differ diff --git a/Resources/Public/JavaScript/Backend.js b/Resources/Public/JavaScript/Backend.js index 8a23a1f3793986483424c1a028a0decb234f66ec..37d69d2f0250f0a433d9ad8287a8a492aeda49d5 100644 --- a/Resources/Public/JavaScript/Backend.js +++ b/Resources/Public/JavaScript/Backend.js @@ -39,8 +39,10 @@ define([ this.form.submit(); }); $('.sg-news_pageswitch').on('click', function(event) { - event.preventDefault(); - SgNewsModule.goTo('web_SgNewsNews', event.target.dataset.page, event.target.dataset.path); + if(Viewport.NavigationContainer.PageTree !== undefined) { + event.preventDefault(); + SgNewsModule.goTo('web_SgNewsNews', event.target.dataset.page, event.target.dataset.path); + } }); }, diff --git a/Upgrade.md b/Upgrade.md index 140b41e2afea0854efbd877c96159f33c16d1ad2..eaa76f6b7b65f214d046ae1d4cdc7636182942c9 100644 --- a/Upgrade.md +++ b/Upgrade.md @@ -1,3 +1,10 @@ +# Upgrade from ```9.x.x``` to ```10.x.x``` + +- Dropped TYPO3 9 support +- Dropped php 7.3 support +- Dropped sg_seo < 6.0 support +- enableAutomaticRelatedNews defaults now to 1 instead of 0 + ## Upgrade from ```9.5.x``` to ```9.6.x``` - Filters are now visible when using the option ```settings.enableFilter``` in the **Overview** plugin. diff --git a/composer.json b/composer.json index 9b0413761978d7f07744c337b58191d616448db0..e8c2b0590cee23d9a49b8e1483db420282777ae8 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ } ], "require": { - "typo3/cms-core": "^9.5.0 || ^10.4.0" + "typo3/cms-core": "^10.4.0 || ^11.5.0", + "sgalinski/sg-seo": ">=6.0.0" }, "suggest": { "sgalinski/sg-ajax": "Required for the like feature", diff --git a/ext_emconf.php b/ext_emconf.php index 45ec25ffa3886211f7878a53fa1e94afccc4649a..7e98f8f9620800ab974e18f607fe07700cf8ac16 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -22,13 +22,13 @@ $EM_CONF['sg_news'] = [ 'version' => '9.8.6', 'constraints' => [ 'depends' => [ - 'typo3' => '9.5.0-10.4.99', - 'php' => '7.3.0-7.4.99', + 'typo3' => '10.4.0-11.5.99', + 'php' => '7.4.0-8.1.99', ], 'conflicts' => [], 'suggests' => [ - 'sg_comments' => '5.0.0', - 'sg_ajax' => '3.0.0' + 'sg_comments' => '6.0.0', + 'sg_ajax' => '4.0.0' ], ], 'suggests' => [], diff --git a/ext_localconf.php b/ext_localconf.php index 050de5bb24d54bb615a436ea248bdc11858932f4..eea75eda0d6ef416d213abfd9c9dfcd306acc84a 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,4 +1,6 @@ <?php + +defined('TYPO3') or die(); /** * * Copyright notice @@ -33,86 +35,75 @@ call_user_func( // plugin configurations \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'Overview', - ['Overview' => 'overview',], - ['Overview' => 'overview',] + [\SGalinski\SgNews\Controller\OverviewController::class => 'overview', ], + [\SGalinski\SgNews\Controller\OverviewController::class => 'overview', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'ListByCategory', - ['ListByCategory' => 'index',], - ['ListByCategory' => '',] + [\SGalinski\SgNews\Controller\ListByCategoryController::class => 'index', ], + [\SGalinski\SgNews\Controller\ListByCategoryController::class => '', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'SingleView', - ['SingleView' => 'singleView',], - ['SingleView' => '',] + [\SGalinski\SgNews\Controller\SingleViewController::class => 'singleView', ], + [\SGalinski\SgNews\Controller\SingleViewController::class => '', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'NewsFeed', - ['NewsFeed' => 'index',], - ['NewsFeed' => '',] + [\SGalinski\SgNews\Controller\NewsFeedController::class => 'index', ], + [\SGalinski\SgNews\Controller\NewsFeedController::class => '', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'Latest', - ['Latest' => 'index',], - ['Latest' => '',] + [\SGalinski\SgNews\Controller\LatestController::class => 'index', ], + [\SGalinski\SgNews\Controller\LatestController::class => '', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'ListByCategory', - ['ListByCategory' => 'index',], - ['ListByCategory' => '',] + [\SGalinski\SgNews\Controller\ListByCategoryController::class => 'index', ], + [\SGalinski\SgNews\Controller\ListByCategoryController::class => '', ] ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_news', + 'SgNews', 'NewsByAuthor', - ['NewsByAuthor' => 'list',], - ['NewsByAuthor' => '',] + [\SGalinski\SgNews\Controller\NewsByAuthorController::class => 'list', ], + [\SGalinski\SgNews\Controller\NewsByAuthorController::class => '', ] ); if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('sg_ajax')) { \SGalinski\SgAjax\Service\AjaxRegistration::configureAjaxFrontendPlugin( 'sg_news', [ - 'Ajax\Like' => 'addLike', + \SGalinski\SgNews\Controller\Ajax\LikeController::class => 'addLike', ] ); } // hook registration $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = - 'SGalinski\SgNews\TCA\TcaProvider'; + \SGalinski\SgNews\TCA\TcaProvider::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']['sg_news'] = \SGalinski\SgNews\Hooks\PageLayoutView\PluginRenderer::class; // Xclasses - $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\CMS\Core\Page\PageRenderer'] = - ['className' => 'SGalinski\SgNews\Xclass\PageRenderer']; - - /** @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */ - $signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class - ); - - $signalSlotDispatcher->connect( - \TYPO3\CMS\Backend\Controller\EditDocumentController::class, - 'preInitAfter', - \SGalinski\SgNews\Hooks\EditDocumentController::class, - 'preInitAfter' - ); + $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Core\Page\PageRenderer::class] = + ['className' => \SGalinski\SgNews\Xclass\PageRenderer::class]; - if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'])) { + # Hook to add the "go to News Module Button + if (!isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'])) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'] = []; } $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawHeaderHook'][] = diff --git a/ext_tables.php b/ext_tables.php index acb4c72e9b86ef2d85bc4f94e9f24ab3c0d703a1..bdd99ffb4c5bee55e04fb0e6f06174bbbe510cf8 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -1,4 +1,6 @@ <?php + +defined('TYPO3') or die(); /** * * Copyright notice @@ -30,23 +32,21 @@ call_user_func( 'tx_sgnews_domain_model_author' ); - if (TYPO3_MODE === 'BE') { - $navigationComponentId = 'TYPO3/CMS/Backend/PageTree/PageTreeElement'; - \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule( - 'SGalinski.sg_news', - 'web', - 'News', - '', - [ - 'Backend' => 'index', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:sg_news/Resources/Public/Icons/module-sgnews.svg', - 'labels' => 'LLL:EXT:sg_news/Resources/Private/Language/locallang.xlf', - 'navigationComponentId' => $navigationComponentId - ] - ); - } + $navigationComponentId = 'TYPO3/CMS/Backend/PageTree/PageTreeElement'; + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule( + 'SgNews', + 'web', + 'News', + '', + [ + \SGalinski\SgNews\Controller\BackendController::class => 'index', + ], + [ + 'access' => 'user,group', + 'icon' => 'EXT:sg_news/Resources/Public/Icons/module-sgnews.svg', + 'labels' => 'LLL:EXT:sg_news/Resources/Private/Language/locallang.xlf', + 'navigationComponentId' => $navigationComponentId + ] + ); } );