From abd08429f5d7781acf1c9b11f9262da799d43122 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Fri, 25 Sep 2020 01:09:36 +0200 Subject: [PATCH] Migrate DB logic from TS to new Data Processor This way multiple joins are possible. As multiple joins are possible, TYPO3 can add pages to the query and therefore respect the enable fields. Hidden pages will therefore not be part of the result, fixing inaccurate count for none published pages with assigned categories. Also the TypoScript communicates what should happen. --- .../DataProcessing/CategoriesCounts.php | 110 ++++++++++++++++++ Configuration/Services.yaml | 13 +++ .../TypoScript/Setup/Page.typoscript | 11 +- 3 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 Classes/Frontend/DataProcessing/CategoriesCounts.php diff --git a/Classes/Frontend/DataProcessing/CategoriesCounts.php b/Classes/Frontend/DataProcessing/CategoriesCounts.php new file mode 100644 index 0000000..d4ec288 --- /dev/null +++ b/Classes/Frontend/DataProcessing/CategoriesCounts.php @@ -0,0 +1,110 @@ + + * + * This program 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. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Database\Query\QueryHelper; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface; + +class CategoriesCounts implements DataProcessorInterface +{ + /** + * @var QueryBuilder + */ + private $queryBuilder; + + public function __construct(QueryBuilder $queryBuilder) + { + $this->queryBuilder = $queryBuilder; + } + + public function process( + ContentObjectRenderer $cObj, + array $contentObjectConfiguration, + array $processorConfiguration, + array $processedData + ) { + $as = $cObj->stdWrapValue('as', $processorConfiguration, 'categories'); + $parent = $cObj->stdWrapValue('parent', $processorConfiguration, ''); + $orderBy = $cObj->stdWrapValue('orderBy', $processorConfiguration, 'count desc'); + [$orderByField, $orderByDirection] = QueryHelper::parseOrderBy($orderBy)[0]; + + if ($parent === '') { + throw new \InvalidArgumentException('No "parent" given.', 1600988668); + } + if ($orderByField === null || $orderByDirection === null) { + throw new \Exception('Non correct "orderBy" given. Needs field and "asc" or "desc".', 1600988713); + } + + $processedData[$as] = $this->getCategoriesCount( + $parent, + $orderByField, + $orderByDirection + ); + + return $processedData; + } + + private function getCategoriesCount( + int $parentId, + string $orderByField, + string $orderByDirection + ): array { + $queryBuilder = clone $this->queryBuilder; + + $queryBuilder->select('category.*'); + $queryBuilder->addSelectLiteral('count(mm.uid_foreign) as count'); + $queryBuilder->from('pages'); + $queryBuilder->leftJoin( + 'pages', + 'sys_category_record_mm', + 'mm', + 'pages.uid = mm.uid_foreign', + ); + $queryBuilder->leftJoin( + 'mm', + 'sys_category', + 'category', + 'mm.uid_local = category.uid', + ); + $queryBuilder->where( + $queryBuilder->expr()->eq( + 'category.parent', + $queryBuilder->createNamedParameter($parentId) + ) + ); + $queryBuilder->groupBy('category.uid'); + $queryBuilder->orderBy($orderByField, $orderByDirection); + + $statement = $queryBuilder->execute(); + + $categories = []; + while ($category = $statement->fetch()) { + $categories[] = [ + 'data' => $category, + ]; + } + + return $categories; + } +} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 1a056a3..64457bb 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -10,6 +10,19 @@ services: DanielSiepmann\DsSite\: resource: '../Classes/*' + querybuilder.pages: + class: 'TYPO3\CMS\Core\Database\Query\QueryBuilder' + factory: + - '@TYPO3\CMS\Core\Database\ConnectionPool' + - 'getQueryBuilderForTable' + arguments: + - 'pages' + + DanielSiepmann\DsSite\Frontend\DataProcessing\CategoriesCounts: + public: true + arguments: + $queryBuilder: '@querybuilder.pages' + # Widgets dashboard.widget.site_ownrss: class: 'TYPO3\CMS\Dashboard\Widgets\RssWidget' diff --git a/Configuration/TypoScript/Setup/Page.typoscript b/Configuration/TypoScript/Setup/Page.typoscript index b3a1c96..cabaf01 100644 --- a/Configuration/TypoScript/Setup/Page.typoscript +++ b/Configuration/TypoScript/Setup/Page.typoscript @@ -81,18 +81,17 @@ page { orderBy = colPos, sorting } - 100 < .10 + 100 = DanielSiepmann\DsSite\Frontend\DataProcessing\CategoriesCounts 100 { as = allTopics - selectFields = sys_category.*, count(sys_category_record_mm.uid_foreign) as count - where = sys_category.parent = 1 AND sys_category_record_mm.uid_foreign IS NOT NULL - groupBy = sys_category.uid + orderBy = count desc + parent = 1 } 101 < .100 101 { as = allTypo3Compatible - where = sys_category.parent = 2 AND sys_category_record_mm.uid_foreign IS NOT NULL - orderBy = sorting + orderBy = title asc + parent = 2 } 500 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor