Initial commit - Typo3 11.5.41
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
use GeorgRinger\News\Domain\Model\DemandInterface;
|
||||
use TYPO3\CMS\Core\Information\Typo3Version;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\Storage\BackendInterface;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser;
|
||||
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract demanded repository
|
||||
*/
|
||||
abstract class AbstractDemandedRepository extends Repository implements DemandedRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Persistence\Generic\Storage\BackendInterface
|
||||
*/
|
||||
protected $storageBackend;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Persistence\Generic\Storage\BackendInterface $storageBackend
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function injectStorageBackend(
|
||||
BackendInterface $storageBackend
|
||||
): void {
|
||||
$this->storageBackend = $storageBackend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of constraints created from a given demand object.
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
|
||||
* @param DemandInterface $demand
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface[]
|
||||
* @abstract
|
||||
*/
|
||||
abstract protected function createConstraintsFromDemand(
|
||||
QueryInterface $query,
|
||||
DemandInterface $demand
|
||||
): array;
|
||||
|
||||
/**
|
||||
* Returns an array of orderings created from a given demand object.
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface[]
|
||||
* @abstract
|
||||
*/
|
||||
abstract protected function createOrderingsFromDemand(DemandInterface $demand): array;
|
||||
|
||||
/**
|
||||
* Returns the objects of this repository matching the demand.
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
* @param bool $respectEnableFields
|
||||
* @param bool $disableLanguageOverlayMode
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
|
||||
*/
|
||||
public function findDemanded(DemandInterface $demand, $respectEnableFields = true, $disableLanguageOverlayMode = false)
|
||||
{
|
||||
$query = $this->generateQuery($demand, $respectEnableFields, $disableLanguageOverlayMode);
|
||||
|
||||
return $query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database query to get the matching result
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
* @param bool $respectEnableFields
|
||||
* @param bool $disableLanguageOverlayMode
|
||||
* @return string
|
||||
*/
|
||||
public function findDemandedRaw(DemandInterface $demand, $respectEnableFields = true, $disableLanguageOverlayMode = false): string
|
||||
{
|
||||
$query = $this->generateQuery($demand, $respectEnableFields, $disableLanguageOverlayMode);
|
||||
$versionInformation = GeneralUtility::makeInstance(Typo3Version::class);
|
||||
if ($versionInformation->getMajorVersion() >= 11) {
|
||||
$queryParser = GeneralUtility::makeInstance(Typo3DbQueryParser::class);
|
||||
} else {
|
||||
$queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
|
||||
}
|
||||
|
||||
$queryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
|
||||
$queryParameters = $queryBuilder->getParameters();
|
||||
$params = [];
|
||||
foreach ($queryParameters as $key => $value) {
|
||||
// prefix array keys with ':'
|
||||
$params[':' . $key] = (is_numeric($value)) ? $value : "'" . $value . "'"; //all non numeric values have to be quoted
|
||||
unset($params[$key]);
|
||||
}
|
||||
// replace placeholders with real values
|
||||
$query = strtr($queryBuilder->getSQL(), $params);
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DemandInterface $demand
|
||||
* @param bool $respectEnableFields
|
||||
* @param bool $disableLanguageOverlayMode
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryInterface
|
||||
*/
|
||||
protected function generateQuery(DemandInterface $demand, $respectEnableFields = true, $disableLanguageOverlayMode = false): \TYPO3\CMS\Extbase\Persistence\QueryInterface
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
|
||||
if ($disableLanguageOverlayMode) {
|
||||
$query->getQuerySettings()->setLanguageOverlayMode(false);
|
||||
}
|
||||
|
||||
$constraints = $this->createConstraintsFromDemand($query, $demand);
|
||||
|
||||
// Call hook functions for additional constraints
|
||||
if ($hooks = $GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Domain/Repository/AbstractDemandedRepository.php']['findDemanded'] ?? []) {
|
||||
$params = [
|
||||
'demand' => $demand,
|
||||
'respectEnableFields' => &$respectEnableFields,
|
||||
'query' => $query,
|
||||
'constraints' => &$constraints,
|
||||
];
|
||||
foreach ($hooks as $reference) {
|
||||
GeneralUtility::callUserFunction($reference, $params, $this);
|
||||
}
|
||||
}
|
||||
|
||||
if ($respectEnableFields === false) {
|
||||
$query->getQuerySettings()->setIgnoreEnableFields(true);
|
||||
|
||||
$constraints[] = $query->equals('deleted', 0);
|
||||
}
|
||||
|
||||
if (!empty($constraints)) {
|
||||
$query->matching(
|
||||
$query->logicalAnd($constraints)
|
||||
);
|
||||
}
|
||||
|
||||
if ($orderings = $this->createOrderingsFromDemand($demand)) {
|
||||
$query->setOrderings($orderings);
|
||||
}
|
||||
|
||||
// @todo consider moving this to a separate function as well
|
||||
if ($demand->getLimit() != null) {
|
||||
$query->setLimit((int)$demand->getLimit());
|
||||
}
|
||||
|
||||
// @todo consider moving this to a separate function as well
|
||||
if ($demand->getOffset() != null) {
|
||||
if (!$query->getLimit()) {
|
||||
$query->setLimit(PHP_INT_MAX);
|
||||
}
|
||||
$query->setOffset((int)$demand->getOffset());
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number objects of this repository matching the demand.
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
* @return int
|
||||
*/
|
||||
public function countDemanded(DemandInterface $demand, $respectEnableFields = true, $disableLanguageOverlayMode = false): int
|
||||
{
|
||||
$query = $this->generateQuery($demand, $respectEnableFields, $disableLanguageOverlayMode);
|
||||
|
||||
if ($constraints = $this->createConstraintsFromDemand($query, $demand)) {
|
||||
$query->matching(
|
||||
$query->logicalAnd($constraints)
|
||||
);
|
||||
}
|
||||
|
||||
$result = $query->execute();
|
||||
return $result->count();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Get data used in the administration view
|
||||
*/
|
||||
class AdministrationRepository
|
||||
{
|
||||
public function getTotalCounts(): array
|
||||
{
|
||||
$count = [];
|
||||
|
||||
$queryBuilder = $this->getQueryBuilder('tx_news_domain_model_news');
|
||||
$queryBuilder->getRestrictions()->removeAll();
|
||||
|
||||
$count['tx_news_domain_model_news'] = $queryBuilder
|
||||
->count('*')
|
||||
->from('tx_news_domain_model_news')
|
||||
->execute()->fetchColumn(0);
|
||||
|
||||
$queryBuilder = $this->getQueryBuilder('sys_category_record_mm');
|
||||
$count['category_relations'] = $queryBuilder
|
||||
->count('*')
|
||||
->from('sys_category_record_mm')
|
||||
->where($queryBuilder->expr()->like(
|
||||
'tablenames',
|
||||
$queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)
|
||||
))
|
||||
->execute()->fetchColumn(0);
|
||||
|
||||
if ($count['tx_news_domain_model_news'] > 0 && $count['category_relations']) {
|
||||
$count['_both'] = true;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function getConnection(string $table): Connection
|
||||
{
|
||||
return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
}
|
||||
|
||||
private function getQueryBuilder(string $table): QueryBuilder
|
||||
{
|
||||
return $this->getConnection($table)->createQueryBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
use Doctrine\DBAL\Connection;
|
||||
use GeorgRinger\News\Domain\Model\Category;
|
||||
use GeorgRinger\News\Domain\Model\DemandInterface;
|
||||
use GeorgRinger\News\Service\CategoryService;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Information\Typo3Version;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||
|
||||
/**
|
||||
* Category repository with all callable functionality
|
||||
*/
|
||||
class CategoryRepository extends AbstractDemandedRepository
|
||||
{
|
||||
protected function createConstraintsFromDemand(QueryInterface $query, DemandInterface $demand): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function createOrderingsFromDemand(DemandInterface $demand): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find category by import source and import id
|
||||
*
|
||||
* @param string $importSource import source
|
||||
* @param int $importId import id
|
||||
* @param bool $asArray return result as array
|
||||
* @return Category|array
|
||||
*/
|
||||
public function findOneByImportSourceAndImportId($importSource, $importId, $asArray = false)
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
$query->getQuerySettings()->setIgnoreEnableFields(true);
|
||||
|
||||
$result = $query->matching(
|
||||
$query->logicalAnd(
|
||||
$query->equals('importSource', $importSource),
|
||||
$query->equals('importId', $importId)
|
||||
)
|
||||
)->execute($asArray);
|
||||
if ($asArray) {
|
||||
if (isset($result[0])) {
|
||||
return $result[0];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
return $result->getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find categories by a given pid
|
||||
*
|
||||
* @param int $pid pid
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
|
||||
*/
|
||||
public function findParentCategoriesByPid($pid)
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
return $query->matching(
|
||||
$query->logicalAnd(
|
||||
$query->equals('pid', (int)$pid),
|
||||
$query->equals('parentcategory', 0)
|
||||
)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find category tree
|
||||
*
|
||||
* @param array $rootIdList list of id s
|
||||
* @return QueryInterface|array
|
||||
*/
|
||||
public function findTree(array $rootIdList, $startingPoint = null)
|
||||
{
|
||||
$subCategories = CategoryService::getChildrenCategories(implode(',', $rootIdList));
|
||||
|
||||
$idList = explode(',', $subCategories);
|
||||
if (empty($idList)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$ordering = ['sorting' => QueryInterface::ORDER_ASCENDING];
|
||||
$categories = $this->findByIdList($idList, $ordering, $startingPoint);
|
||||
$flatCategories = [];
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$flatCategories[$category->getUid()] = [
|
||||
'item' => $category,
|
||||
'parent' => ($category->getParentcategory()) ? $category->getParentcategory()->getUid() : null
|
||||
];
|
||||
}
|
||||
|
||||
$tree = [];
|
||||
|
||||
// If leaves are selected without its parents selected, those are shown as parent
|
||||
foreach ($flatCategories as $id => &$flatCategory) {
|
||||
if (!isset($flatCategories[$flatCategory['parent']])) {
|
||||
$flatCategory['parent'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($flatCategories as $id => &$node) {
|
||||
if ($node['parent'] === null) {
|
||||
$tree[$id] = &$node;
|
||||
} else {
|
||||
$flatCategories[$node['parent']]['children'][$id] = &$node;
|
||||
}
|
||||
}
|
||||
|
||||
return $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find categories by a given pid
|
||||
*
|
||||
* @param array $idList list of id s
|
||||
* @param array $ordering ordering
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
|
||||
*/
|
||||
public function findByIdList(array $idList, array $ordering = [], $startingPoint = null)
|
||||
{
|
||||
if (empty($idList)) {
|
||||
throw new \InvalidArgumentException('The given id list is empty.', 1484823597);
|
||||
}
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
$query->getQuerySettings()->setRespectSysLanguage(true);
|
||||
|
||||
if (count($ordering) > 0) {
|
||||
$query->setOrderings($ordering);
|
||||
}
|
||||
$this->overlayTranslatedCategoryIds($idList);
|
||||
|
||||
$conditions = [];
|
||||
$conditions[] = $query->in('uid', $idList);
|
||||
|
||||
if (is_null($startingPoint) === false) {
|
||||
$conditions[] = $query->in('pid', GeneralUtility::trimExplode(',', $startingPoint, true));
|
||||
}
|
||||
|
||||
return $query->matching(
|
||||
$query->logicalAnd(
|
||||
$conditions
|
||||
)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find categories by a given parent
|
||||
*
|
||||
* @param int $parent parent
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
|
||||
*/
|
||||
public function findChildren($parent)
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
return $query->matching(
|
||||
$query->logicalAnd(
|
||||
$query->equals('parentcategory', (int)$parent)
|
||||
)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay the category ids with the ones from current language
|
||||
*
|
||||
* @param array $idList
|
||||
* return void
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function overlayTranslatedCategoryIds(array &$idList): void
|
||||
{
|
||||
$language = $this->getSysLanguageUid();
|
||||
if ($language > 0 && !empty($idList)) {
|
||||
if (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TSFE'])) {
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category');
|
||||
$rows = $queryBuilder
|
||||
->select('l10n_parent', 'uid', 'sys_language_uid')
|
||||
->from('sys_category')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)),
|
||||
$queryBuilder->expr()->in('l10n_parent', $queryBuilder->createNamedParameter($idList, Connection::PARAM_INT_ARRAY))
|
||||
)
|
||||
->execute()->fetchAll();
|
||||
|
||||
$idList = $this->replaceCategoryIds($idList, $rows);
|
||||
}
|
||||
// @todo currently only implemented for the frontend
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sys language uid
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getSysLanguageUid(): int
|
||||
{
|
||||
$sysLanguage = 0;
|
||||
|
||||
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() === 10) {
|
||||
$sysLanguage = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id');
|
||||
} elseif (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TSFE'])) {
|
||||
$sysLanguage = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'contentId');
|
||||
} elseif ((int)GeneralUtility::_GP('L')) {
|
||||
$sysLanguage = (int)GeneralUtility::_GP('L');
|
||||
}
|
||||
|
||||
return $sysLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace ids in array by the given ones
|
||||
*
|
||||
* @param array $idList
|
||||
* @param array $rows
|
||||
* @return array
|
||||
*/
|
||||
protected function replaceCategoryIds(array $idList, array $rows): array
|
||||
{
|
||||
foreach ($rows as $row) {
|
||||
$pos = array_search($row['l10n_parent'], $idList);
|
||||
if ($pos !== false) {
|
||||
$idList[$pos] = (int)$row['uid'];
|
||||
}
|
||||
}
|
||||
|
||||
return $idList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
use GeorgRinger\News\Domain\Model\DemandInterface;
|
||||
|
||||
/**
|
||||
* Demand domain model interface
|
||||
*/
|
||||
interface DemandedRepositoryInterface
|
||||
{
|
||||
public function findDemanded(DemandInterface $demand, $respectEnableFields = true);
|
||||
|
||||
public function countDemanded(DemandInterface $demand);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
/**
|
||||
* Repository for file objects
|
||||
*/
|
||||
class FileRepository extends Repository
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
/**
|
||||
* Repository for link objects
|
||||
*/
|
||||
class LinkRepository extends Repository
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
/**
|
||||
* Repository for media objects
|
||||
*/
|
||||
class MediaRepository extends Repository
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* News repository with all the callable functionality
|
||||
*/
|
||||
class NewsDefaultRepository extends NewsRepository
|
||||
{
|
||||
}
|
||||
519
typo3conf/ext/news/Classes/Domain/Repository/NewsRepository.php
Normal file
519
typo3conf/ext/news/Classes/Domain/Repository/NewsRepository.php
Normal file
@@ -0,0 +1,519 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
use GeorgRinger\News\Domain\Model\DemandInterface;
|
||||
use GeorgRinger\News\Domain\Model\Dto\NewsDemand;
|
||||
use GeorgRinger\News\Service\CategoryService;
|
||||
use GeorgRinger\News\Utility\ConstraintHelper;
|
||||
use GeorgRinger\News\Utility\Validation;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||
|
||||
/**
|
||||
* News repository with all the callable functionality
|
||||
*/
|
||||
class NewsRepository extends AbstractDemandedRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a category constraint created by
|
||||
* a given list of categories and a junction string
|
||||
*
|
||||
* @param QueryInterface $query
|
||||
* @param array $categories
|
||||
* @param string $conjunction
|
||||
* @param bool $includeSubCategories
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface|null
|
||||
*/
|
||||
protected function createCategoryConstraint(
|
||||
QueryInterface $query,
|
||||
$categories,
|
||||
$conjunction,
|
||||
$includeSubCategories = false
|
||||
): ?\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface {
|
||||
$constraint = null;
|
||||
$categoryConstraints = [];
|
||||
|
||||
// If "ignore category selection" is used, nothing needs to be done
|
||||
if (empty($conjunction)) {
|
||||
return $constraint;
|
||||
}
|
||||
|
||||
if (!is_array($categories)) {
|
||||
$categories = GeneralUtility::intExplode(',', $categories, true);
|
||||
}
|
||||
foreach ($categories as $category) {
|
||||
if ($includeSubCategories) {
|
||||
$subCategories = GeneralUtility::trimExplode(
|
||||
',',
|
||||
CategoryService::getChildrenCategories($category, 0, '', true),
|
||||
true
|
||||
);
|
||||
$subCategoryConstraint = [];
|
||||
$subCategoryConstraint[] = $query->contains('categories', $category);
|
||||
if (count($subCategories) > 0) {
|
||||
foreach ($subCategories as $subCategory) {
|
||||
$subCategoryConstraint[] = $query->contains('categories', $subCategory);
|
||||
}
|
||||
}
|
||||
if ($subCategoryConstraint) {
|
||||
$categoryConstraints[] = $query->logicalOr($subCategoryConstraint);
|
||||
}
|
||||
} else {
|
||||
$categoryConstraints[] = $query->contains('categories', $category);
|
||||
}
|
||||
}
|
||||
|
||||
if ($categoryConstraints) {
|
||||
switch (strtolower($conjunction)) {
|
||||
case 'or':
|
||||
$constraint = $query->logicalOr($categoryConstraints);
|
||||
break;
|
||||
case 'notor':
|
||||
$constraint = $query->logicalNot($query->logicalOr($categoryConstraints));
|
||||
break;
|
||||
case 'notand':
|
||||
$constraint = $query->logicalNot($query->logicalAnd($categoryConstraints));
|
||||
break;
|
||||
case 'and':
|
||||
default:
|
||||
$constraint = $query->logicalAnd($categoryConstraints);
|
||||
}
|
||||
}
|
||||
|
||||
return $constraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of constraints created from a given demand object.
|
||||
*
|
||||
* @param QueryInterface $query
|
||||
* @param DemandInterface $demand
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return (\TYPO3\CMS\Extbase\Persistence\Generic\Qom\AndInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\NotInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\OrInterface|null)[]
|
||||
*
|
||||
* @psalm-return array<string, \TYPO3\CMS\Extbase\Persistence\Generic\Qom\AndInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\NotInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\OrInterface|null>
|
||||
*/
|
||||
protected function createConstraintsFromDemand(QueryInterface $query, DemandInterface $demand): array
|
||||
{
|
||||
/** @var NewsDemand $demand */
|
||||
$constraints = [];
|
||||
|
||||
if ($demand->getCategories() && $demand->getCategories() !== '0') {
|
||||
$constraints['categories'] = $this->createCategoryConstraint(
|
||||
$query,
|
||||
$demand->getCategories(),
|
||||
$demand->getCategoryConjunction(),
|
||||
$demand->getIncludeSubCategories()
|
||||
);
|
||||
}
|
||||
|
||||
if ($demand->getAuthor()) {
|
||||
$constraints['author'] = $query->equals('author', $demand->getAuthor());
|
||||
}
|
||||
|
||||
if ($demand->getTypes()) {
|
||||
$constraints['types'] = $query->in('type', $demand->getTypes());
|
||||
}
|
||||
|
||||
// archived
|
||||
if ($demand->getArchiveRestriction() === 'archived') {
|
||||
$constraints['archived'] = $query->logicalAnd(
|
||||
$query->lessThan('archive', $GLOBALS['SIM_EXEC_TIME']),
|
||||
$query->greaterThan('archive', 0)
|
||||
);
|
||||
} elseif ($demand->getArchiveRestriction() === 'active') {
|
||||
$constraints['active'] = $query->logicalOr(
|
||||
$query->greaterThanOrEqual('archive', $GLOBALS['SIM_EXEC_TIME']),
|
||||
$query->equals('archive', 0)
|
||||
);
|
||||
}
|
||||
|
||||
// Time restriction greater than or equal
|
||||
$timeRestrictionField = $demand->getDateField();
|
||||
$timeRestrictionField = (empty($timeRestrictionField)) ? 'datetime' : $timeRestrictionField;
|
||||
|
||||
if ($demand->getTimeRestriction()) {
|
||||
$timeLimit = ConstraintHelper::getTimeRestrictionLow($demand->getTimeRestriction());
|
||||
|
||||
$constraints['timeRestrictionGreater'] = $query->greaterThanOrEqual(
|
||||
$timeRestrictionField,
|
||||
$timeLimit
|
||||
);
|
||||
}
|
||||
|
||||
// Time restriction less than or equal
|
||||
if ($demand->getTimeRestrictionHigh()) {
|
||||
$timeLimit = ConstraintHelper::getTimeRestrictionHigh($demand->getTimeRestrictionHigh());
|
||||
|
||||
$constraints['timeRestrictionLess'] = $query->lessThanOrEqual(
|
||||
$timeRestrictionField,
|
||||
$timeLimit
|
||||
);
|
||||
}
|
||||
|
||||
// top news
|
||||
if ($demand->getTopNewsRestriction() == 1) {
|
||||
$constraints['topNews1'] = $query->equals('istopnews', 1);
|
||||
} elseif ($demand->getTopNewsRestriction() == 2) {
|
||||
$constraints['topNews2'] = $query->equals('istopnews', 0);
|
||||
}
|
||||
|
||||
// storage page
|
||||
if ($demand->getStoragePage()) {
|
||||
$pidList = GeneralUtility::intExplode(',', $demand->getStoragePage(), true);
|
||||
$constraints['pid'] = $query->in('pid', $pidList);
|
||||
}
|
||||
|
||||
// month & year OR year only
|
||||
if ($demand->getYear() > 0) {
|
||||
if (null === $demand->getDateField()) {
|
||||
throw new \InvalidArgumentException('No Datefield is set, therefore no Datemenu is possible!');
|
||||
}
|
||||
if ($demand->getMonth() > 0) {
|
||||
if ($demand->getDay() > 0) {
|
||||
$begin = mktime(0, 0, 0, $demand->getMonth(), $demand->getDay(), $demand->getYear());
|
||||
$end = mktime(23, 59, 59, $demand->getMonth(), $demand->getDay(), $demand->getYear());
|
||||
} else {
|
||||
$begin = mktime(0, 0, 0, $demand->getMonth(), 1, $demand->getYear());
|
||||
$end = mktime(23, 59, 59, ($demand->getMonth() + 1), 0, $demand->getYear());
|
||||
}
|
||||
} else {
|
||||
$begin = mktime(0, 0, 0, 1, 1, $demand->getYear());
|
||||
$end = mktime(23, 59, 59, 12, 31, $demand->getYear());
|
||||
}
|
||||
$constraints['datetime'] = $query->logicalAnd([
|
||||
$query->greaterThanOrEqual($demand->getDateField(), $begin),
|
||||
$query->lessThanOrEqual($demand->getDateField(), $end)
|
||||
]);
|
||||
}
|
||||
|
||||
// Tags
|
||||
$tags = $demand->getTags();
|
||||
if ($tags && is_string($tags)) {
|
||||
$tagList = explode(',', $tags);
|
||||
|
||||
$subConstraints = [];
|
||||
foreach ($tagList as $singleTag) {
|
||||
$subConstraints[] = $query->contains('tags', $singleTag);
|
||||
}
|
||||
if (count($subConstraints) > 0) {
|
||||
$constraints['tags'] = $query->logicalOr($subConstraints);
|
||||
}
|
||||
}
|
||||
|
||||
// Search
|
||||
$searchConstraints = $this->getSearchConstraints($query, $demand);
|
||||
if (!empty($searchConstraints)) {
|
||||
$constraints['search'] = $query->logicalAnd($searchConstraints);
|
||||
}
|
||||
|
||||
// Exclude already displayed
|
||||
if ($demand->getExcludeAlreadyDisplayedNews() && isset($GLOBALS['EXT']['news']['alreadyDisplayed']) && !empty($GLOBALS['EXT']['news']['alreadyDisplayed'])) {
|
||||
$constraints['excludeAlreadyDisplayedNews'] = $query->logicalNot(
|
||||
$query->in(
|
||||
'uid',
|
||||
$GLOBALS['EXT']['news']['alreadyDisplayed']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Hide id list
|
||||
$hideIdList = $demand->getHideIdList();
|
||||
if ($hideIdList) {
|
||||
$constraints['hideIdInList'] = $query->logicalNot(
|
||||
$query->in(
|
||||
'uid',
|
||||
GeneralUtility::intExplode(',', $hideIdList, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Id list
|
||||
$idList = $demand->getIdList();
|
||||
if ($idList) {
|
||||
$constraints['idList'] = $query->in('uid', GeneralUtility::intExplode(',', $idList, true));
|
||||
}
|
||||
|
||||
// Clean not used constraints
|
||||
foreach ($constraints as $key => $value) {
|
||||
if (null === $value) {
|
||||
unset($constraints[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of orderings created from a given demand object.
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
protected function createOrderingsFromDemand(DemandInterface $demand): array
|
||||
{
|
||||
$orderings = [];
|
||||
if ($demand->getTopNewsFirst()) {
|
||||
$orderings['istopnews'] = QueryInterface::ORDER_DESCENDING;
|
||||
}
|
||||
|
||||
if (Validation::isValidOrdering($demand->getOrder(), $demand->getOrderByAllowed())) {
|
||||
$orderList = GeneralUtility::trimExplode(',', $demand->getOrder(), true);
|
||||
|
||||
if (!empty($orderList)) {
|
||||
// go through every order statement
|
||||
foreach ($orderList as $orderItem) {
|
||||
$orderSplit = GeneralUtility::trimExplode(' ', $orderItem, true);
|
||||
$orderField = $orderSplit[0];
|
||||
$ascDesc = $orderSplit[1] ?? '';
|
||||
if ($ascDesc) {
|
||||
$orderings[$orderField] = ((strtolower($ascDesc) === 'desc') ?
|
||||
QueryInterface::ORDER_DESCENDING :
|
||||
QueryInterface::ORDER_ASCENDING);
|
||||
} else {
|
||||
$orderings[$orderField] = QueryInterface::ORDER_ASCENDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $orderings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first news by import and source id
|
||||
*
|
||||
* @param string $importSource import source
|
||||
* @param int $importId import id
|
||||
* @param bool $asArray return result as array
|
||||
* @return \GeorgRinger\News\Domain\Model\News|array
|
||||
*/
|
||||
public function findOneByImportSourceAndImportId($importSource, $importId, $asArray = false)
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||
$query->getQuerySettings()->setIgnoreEnableFields(true);
|
||||
|
||||
$result = $query->matching(
|
||||
$query->logicalAnd(
|
||||
$query->equals('importSource', $importSource),
|
||||
$query->equals('importId', $importId)
|
||||
)
|
||||
)->execute($asArray);
|
||||
if ($asArray) {
|
||||
if (isset($result[0])) {
|
||||
return $result[0];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
return $result->getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default findByUid function to enable also the option to turn of
|
||||
* the enableField setting
|
||||
*
|
||||
* @param int $uid id of record
|
||||
* @param bool $respectEnableFields if set to false, hidden records are shown
|
||||
* @return \GeorgRinger\News\Domain\Model\News|null
|
||||
*/
|
||||
public function findByUid($uid, $respectEnableFields = true): ?\GeorgRinger\News\Domain\Model\News
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||
|
||||
if (!$respectEnableFields) {
|
||||
$query->getQuerySettings()->setIgnoreEnableFields(true);
|
||||
$query->getQuerySettings()->setLanguageOverlayMode(false);
|
||||
}
|
||||
|
||||
return $query->matching(
|
||||
$query->logicalAnd(
|
||||
$query->equals('uid', $uid),
|
||||
$query->equals('deleted', 0)
|
||||
)
|
||||
)->execute()->getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of news records by month/year and
|
||||
* returns the result compiled as array
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
* @return array
|
||||
*/
|
||||
public function countByDate(DemandInterface $demand): array
|
||||
{
|
||||
$data = [];
|
||||
$sql = $this->findDemandedRaw($demand);
|
||||
|
||||
// strip unwanted order by
|
||||
$sql = $this->stripOrderBy($sql);
|
||||
|
||||
// Get the month/year into the result
|
||||
$field = $demand->getDateField();
|
||||
$field = empty($field) ? 'datetime' : $field;
|
||||
|
||||
$sql = 'SELECT MONTH(FROM_UNIXTIME(0) + INTERVAL ' . $field . ' SECOND ) AS "_Month",' .
|
||||
' YEAR(FROM_UNIXTIME(0) + INTERVAL ' . $field . ' SECOND) AS "_Year" ,' .
|
||||
' count(MONTH(FROM_UNIXTIME(0) + INTERVAL ' . $field . ' SECOND )) as count_month,' .
|
||||
' count(YEAR(FROM_UNIXTIME(0) + INTERVAL ' . $field . ' SECOND)) as count_year' .
|
||||
' FROM tx_news_domain_model_news ' . substr($sql, strpos($sql, 'WHERE '));
|
||||
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getConnectionForTable('tx_news_domain_model_news');
|
||||
|
||||
if (TYPO3_MODE === 'FE') {
|
||||
$sql .= $GLOBALS['TSFE']->sys_page->enableFields('tx_news_domain_model_news');
|
||||
} else {
|
||||
$expressionBuilder = $connection
|
||||
->createQueryBuilder()
|
||||
->expr();
|
||||
$sql .= BackendUtility::BEenableFields('tx_news_domain_model_news') .
|
||||
' AND ' . $expressionBuilder->eq('deleted', 0);
|
||||
}
|
||||
|
||||
// group by custom month/year fields
|
||||
$orderDirection = strtolower($demand->getOrder());
|
||||
if ($orderDirection !== 'desc' && $orderDirection !== 'asc') {
|
||||
$orderDirection = 'asc';
|
||||
}
|
||||
$sql .= ' GROUP BY _Month, _Year ORDER BY _Year ' . $orderDirection . ', _Month ' . $orderDirection;
|
||||
|
||||
$res = $connection->query($sql);
|
||||
while ($row = $res->fetch()) {
|
||||
$month = strlen($row['_Month']) === 1 ? ('0' . $row['_Month']) : $row['_Month'];
|
||||
$data['single'][$row['_Year']][$month] = $row['count_month'];
|
||||
}
|
||||
|
||||
// Add totals
|
||||
if (is_array($data['single'])) {
|
||||
foreach ($data['single'] as $year => $months) {
|
||||
$countOfYear = 0;
|
||||
foreach ($months as $month) {
|
||||
$countOfYear += $month;
|
||||
}
|
||||
$data['total'][$year] = $countOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the search constraints
|
||||
*
|
||||
* @param QueryInterface $query
|
||||
* @param DemandInterface $demand
|
||||
* @return array
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
protected function getSearchConstraints(QueryInterface $query, DemandInterface $demand): array
|
||||
{
|
||||
$constraints = [];
|
||||
if ($demand->getSearch() === null) {
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/* @var $searchObject \GeorgRinger\News\Domain\Model\Dto\Search */
|
||||
$searchObject = $demand->getSearch();
|
||||
|
||||
$searchSubject = $searchObject->getSubject();
|
||||
if (!empty($searchSubject)) {
|
||||
$queryBuilder = $this->getQueryBuilder('tx_news_domain_model_news');
|
||||
|
||||
$searchFields = GeneralUtility::trimExplode(',', $searchObject->getFields(), true);
|
||||
$searchConstraints = [];
|
||||
|
||||
if (count($searchFields) === 0) {
|
||||
throw new \UnexpectedValueException('No search fields defined', 1318497755);
|
||||
}
|
||||
$searchSubjectSplitted = str_getcsv($searchSubject, ' ');
|
||||
if ($searchObject->isSplitSubjectWords()) {
|
||||
foreach ($searchFields as $field) {
|
||||
$subConstraints = [];
|
||||
foreach ($searchSubjectSplitted as $searchSubjectSplittedPart) {
|
||||
$searchSubjectSplittedPart = trim($searchSubjectSplittedPart);
|
||||
if ($searchSubjectSplittedPart) {
|
||||
$subConstraints[] = $query->like($field, '%' . $searchSubjectSplittedPart . '%');
|
||||
}
|
||||
}
|
||||
$searchConstraints[] = $query->logicalAnd($subConstraints);
|
||||
}
|
||||
if (count($searchConstraints)) {
|
||||
$constraints[] = $query->logicalOr($searchConstraints);
|
||||
}
|
||||
} else {
|
||||
if (!empty($searchSubject)) {
|
||||
foreach ($searchFields as $field) {
|
||||
$searchConstraints[] = $query->like($field, '%' . $searchSubject . '%');
|
||||
}
|
||||
}
|
||||
if (count($searchConstraints)) {
|
||||
$constraints[] = $query->logicalOr($searchConstraints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$minimumDate = strtotime($searchObject->getMinimumDate());
|
||||
if ($minimumDate) {
|
||||
$field = $searchObject->getDateField();
|
||||
if (empty($field)) {
|
||||
throw new \UnexpectedValueException('No date field is defined', 1396348732);
|
||||
}
|
||||
$constraints[] = $query->greaterThanOrEqual($field, $minimumDate);
|
||||
}
|
||||
$maximumDate = strtotime($searchObject->getMaximumDate());
|
||||
if ($maximumDate) {
|
||||
$field = $searchObject->getDateField();
|
||||
if (empty($field)) {
|
||||
throw new \UnexpectedValueException('No date field is defined', 1396348733);
|
||||
}
|
||||
$maximumDate += 86400;
|
||||
$constraints[] = $query->lessThanOrEqual($field, $maximumDate);
|
||||
}
|
||||
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table table name
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
protected function getQueryBuilder(string $table): QueryBuilder
|
||||
{
|
||||
return GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return stripped order sql
|
||||
*
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
private function stripOrderBy(string $str): string
|
||||
{
|
||||
/** @noinspection NotOptimalRegularExpressionsInspection */
|
||||
return preg_replace('/(?:ORDER[[:space:]]*BY[[:space:]]*.*)+/i', '', trim($str));
|
||||
}
|
||||
}
|
||||
125
typo3conf/ext/news/Classes/Domain/Repository/TagRepository.php
Normal file
125
typo3conf/ext/news/Classes/Domain/Repository/TagRepository.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
use GeorgRinger\News\Domain\Model\DemandInterface;
|
||||
use GeorgRinger\News\Utility\Validation;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||
|
||||
/**
|
||||
* Repository for tag objects
|
||||
*/
|
||||
class TagRepository extends AbstractDemandedRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* Find categories by a given pid
|
||||
*
|
||||
* @param array $idList list of id s
|
||||
* @param array $ordering ordering
|
||||
* @param string $startingPoint starting point uid or comma separated list
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array
|
||||
*/
|
||||
public function findByIdList(array $idList, array $ordering = [], $startingPoint = null)
|
||||
{
|
||||
if (empty($idList)) {
|
||||
throw new \InvalidArgumentException('The given id list is empty.', 1484823596);
|
||||
}
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||
|
||||
if (count($ordering) > 0) {
|
||||
$query->setOrderings($ordering);
|
||||
}
|
||||
|
||||
$conditions = [];
|
||||
$conditions[] = $query->in('uid', $idList);
|
||||
|
||||
if ($startingPoint !== null) {
|
||||
$conditions[] = $query->in('pid', GeneralUtility::trimExplode(',', $startingPoint, true));
|
||||
}
|
||||
|
||||
return $query->matching(
|
||||
$query->logicalAnd(
|
||||
$conditions
|
||||
)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of constraints created from a given demand object.
|
||||
*
|
||||
* @param QueryInterface $query
|
||||
* @param DemandInterface $demand
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface[]
|
||||
*/
|
||||
protected function createConstraintsFromDemand(QueryInterface $query, DemandInterface $demand): array
|
||||
{
|
||||
$constraints = [];
|
||||
|
||||
// Storage page
|
||||
if ($demand->getStoragePage()) {
|
||||
$pidList = GeneralUtility::intExplode(',', $demand->getStoragePage(), true);
|
||||
$constraints[] = $query->in('pid', $pidList);
|
||||
}
|
||||
|
||||
// Tags
|
||||
if ($demand->getTags()) {
|
||||
$tagList = GeneralUtility::intExplode(',', $demand->getTags(), true);
|
||||
$constraints[] = $query->in('uid', $tagList);
|
||||
}
|
||||
|
||||
// Clean not used constraints
|
||||
foreach ($constraints as $key => $value) {
|
||||
if (is_null($value)) {
|
||||
unset($constraints[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of orderings created from a given demand object.
|
||||
*
|
||||
* @param DemandInterface $demand
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
protected function createOrderingsFromDemand(DemandInterface $demand): array
|
||||
{
|
||||
$orderings = [];
|
||||
|
||||
if (Validation::isValidOrdering($demand->getOrder(), $demand->getOrderByAllowed())) {
|
||||
$orderList = GeneralUtility::trimExplode(',', $demand->getOrder(), true);
|
||||
|
||||
if (!empty($orderList)) {
|
||||
// go through every order statement
|
||||
foreach ($orderList as $orderItem) {
|
||||
list($orderField, $ascDesc) = GeneralUtility::trimExplode(' ', $orderItem, true);
|
||||
// count == 1 means that no direction is given
|
||||
if ($ascDesc) {
|
||||
$orderings[$orderField] = ((strtolower($ascDesc) == 'desc') ?
|
||||
QueryInterface::ORDER_DESCENDING :
|
||||
QueryInterface::ORDER_ASCENDING);
|
||||
} else {
|
||||
$orderings[$orderField] = QueryInterface::ORDER_ASCENDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $orderings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
|
||||
/**
|
||||
* This file is part of the "news" Extension for TYPO3 CMS.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*/
|
||||
/**
|
||||
* Repository for tt_content objects
|
||||
*/
|
||||
class TtContentRepository extends Repository
|
||||
{
|
||||
protected $objectType = '\GeorgRinger\News\Domain\Model\Ttcontent';
|
||||
}
|
||||
Reference in New Issue
Block a user