Initial commit - Typo3 11.5.41
This commit is contained in:
171
typo3conf/ext/news/Classes/Service/AccessControlService.php
Normal file
171
typo3conf/ext/news/Classes/Service/AccessControlService.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Service;
|
||||
|
||||
/**
|
||||
* 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\Dto\EmConfiguration;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Service for access control related stuff
|
||||
*/
|
||||
class AccessControlService
|
||||
{
|
||||
|
||||
/**
|
||||
* Check if a user has access to all categories of a news record
|
||||
*
|
||||
* @param array $newsRecord
|
||||
* @return bool
|
||||
*/
|
||||
public static function userHasCategoryPermissionsForRecord(array $newsRecord): bool
|
||||
{
|
||||
$settings = GeneralUtility::makeInstance(EmConfiguration::class);
|
||||
if (!$settings->getCategoryBeGroupTceFormsRestriction()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (self::getBackendUser()->isAdmin()) {
|
||||
// an admin may edit all news
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there are any categories with denied access, the user has no permission
|
||||
if (count(self::getAccessDeniedCategories($newsRecord))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array with the uid and title of all categories the user doesn't have access to
|
||||
*
|
||||
* @param array $newsRecord
|
||||
* @return array
|
||||
*/
|
||||
public static function getAccessDeniedCategories(array $newsRecord): array
|
||||
{
|
||||
if (self::getBackendUser()->isAdmin()) {
|
||||
// an admin may edit all news so no categories without access
|
||||
return [];
|
||||
}
|
||||
|
||||
// no category mounts set means access to all
|
||||
$backendUserCategories = self::getBackendUser()->getCategoryMountPoints();
|
||||
if ($backendUserCategories === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$catService = GeneralUtility::makeInstance(CategoryService::class);
|
||||
$subCategories = $catService::getChildrenCategories(implode(',', $backendUserCategories));
|
||||
if (!empty($subCategories)) {
|
||||
$backendUserCategories = explode(',', $subCategories);
|
||||
}
|
||||
|
||||
$newsRecordCategories = self::getCategoriesForNewsRecord($newsRecord);
|
||||
|
||||
// Remove categories the user has access to
|
||||
foreach ($newsRecordCategories as $key => $newsRecordCategory) {
|
||||
if (in_array($newsRecordCategory['uid'], $backendUserCategories)) {
|
||||
unset($newsRecordCategories[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $newsRecordCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all categories for a news record respecting l10n_mode
|
||||
*
|
||||
* @param array $newsRecord
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategoriesForNewsRecord($newsRecord): array
|
||||
{
|
||||
// determine localization overlay mode to select categories either from parent or localized record
|
||||
if ($newsRecord['sys_language_uid'] > 0 && $newsRecord['l10n_parent'] > 0) {
|
||||
// localized version of a news record
|
||||
$categoryL10nMode = $GLOBALS['TCA']['tx_news_domain_model_news']['columns']['categories']['l10n_mode'];
|
||||
if ($categoryL10nMode === 'mergeIfNotBlank') {
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category_record_mm');
|
||||
$newsRecordCategoriesCount = $queryBuilder->count('*')
|
||||
->from('sys_category_record_mm')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter($newsRecord['uid'], \PDO::PARAM_INT)),
|
||||
$queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->eq('fieldname', $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR))
|
||||
)
|
||||
->execute()
|
||||
->fetchColumn(0);
|
||||
if ($newsRecordCategoriesCount > 0) {
|
||||
// take categories from localized version
|
||||
$newsRecordUid = $newsRecord['uid'];
|
||||
} else {
|
||||
// inherit categories from parent
|
||||
$newsRecordUid = $newsRecord['l10n_parent'];
|
||||
}
|
||||
} elseif ($categoryL10nMode === 'exclude') {
|
||||
// exclude: The localized version inherits the categories of the parent
|
||||
$newsRecordUid = $newsRecord['l10n_parent'];
|
||||
} else {
|
||||
// noCopy/prefixLangTitle: no inheritance
|
||||
$newsRecordUid = $newsRecord['uid'];
|
||||
}
|
||||
} else {
|
||||
$newsRecordUid = $newsRecord['uid'];
|
||||
}
|
||||
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category');
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeByType(StartTimeRestriction::class)
|
||||
->removeByType(HiddenRestriction::class)
|
||||
->removeByType(EndTimeRestriction::class);
|
||||
$res = $queryBuilder
|
||||
->select('sys_category_record_mm.uid_local', 'sys_category.title')
|
||||
->from('sys_category')
|
||||
->leftJoin(
|
||||
'sys_category',
|
||||
'sys_category_record_mm',
|
||||
'sys_category_record_mm',
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.uid_local', $queryBuilder->quoteIdentifier('sys_category.uid'))
|
||||
)
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.fieldname', $queryBuilder->createNamedParameter('categories', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.uid_foreign', $queryBuilder->createNamedParameter($newsRecordUid, \PDO::PARAM_INT))
|
||||
)
|
||||
->execute();
|
||||
|
||||
$categories = [];
|
||||
while ($row =$res->fetch()) {
|
||||
$categories[] = [
|
||||
'uid' => $row['uid_local'],
|
||||
'title' => $row['title']
|
||||
];
|
||||
}
|
||||
return $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current BE user.
|
||||
*
|
||||
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
|
||||
*/
|
||||
protected static function getBackendUser(): \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
}
|
||||
172
typo3conf/ext/news/Classes/Service/CategoryService.php
Normal file
172
typo3conf/ext/news/Classes/Service/CategoryService.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Service;
|
||||
|
||||
/**
|
||||
* 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\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Cache\CacheManager;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Service for category related stuff
|
||||
*/
|
||||
class CategoryService
|
||||
{
|
||||
|
||||
/**
|
||||
* Get child categories by calling recursive function
|
||||
* and using the caching framework to save some queries
|
||||
*
|
||||
* @param string $idList list of category ids to start
|
||||
* @param int $counter
|
||||
* @param string $additionalWhere additional where clause
|
||||
* @param bool $removeGivenIdListFromResult remove the given id list from result
|
||||
* @return string comma separated list of category ids
|
||||
*/
|
||||
public static function getChildrenCategories(
|
||||
$idList,
|
||||
$counter = 0,
|
||||
$additionalWhere = '',
|
||||
$removeGivenIdListFromResult = false
|
||||
): string {
|
||||
if ($additionalWhere !== '') {
|
||||
throw new \UnexpectedValueException('The argument $additionalWhere is not supported anymore');
|
||||
}
|
||||
$cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('news_category');
|
||||
$cacheIdentifier = sha1('children' . $idList);
|
||||
|
||||
$entry = $cache->get($cacheIdentifier);
|
||||
if (!$entry) {
|
||||
$entry = self::getChildrenCategoriesRecursive($idList, $counter, $additionalWhere);
|
||||
$cache->set($cacheIdentifier, $entry);
|
||||
}
|
||||
|
||||
if ($removeGivenIdListFromResult) {
|
||||
$entry = self::removeValuesFromString($entry, $idList);
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove values of a comma separated list from another comma separated list
|
||||
*
|
||||
* @param string $result string comma separated list
|
||||
* @param $toBeRemoved string comma separated list
|
||||
* @return string
|
||||
*/
|
||||
public static function removeValuesFromString($result, string $toBeRemoved): string
|
||||
{
|
||||
$resultAsArray = GeneralUtility::trimExplode(',', $result, true);
|
||||
$idListAsArray = GeneralUtility::trimExplode(',', $toBeRemoved, true);
|
||||
|
||||
$result = implode(',', array_diff($resultAsArray, $idListAsArray));
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child categories
|
||||
*
|
||||
* @param string $idList list of category ids to start
|
||||
* @param int $counter
|
||||
* @param string $additionalWhere additional where clause
|
||||
* @return string comma separated list of category ids
|
||||
*/
|
||||
private static function getChildrenCategoriesRecursive($idList, $counter = 0, $additionalWhere = ''): string
|
||||
{
|
||||
$result = [];
|
||||
|
||||
// add idlist to the output too
|
||||
if ($counter === 0) {
|
||||
$result[] = self::cleanIntList($idList);
|
||||
}
|
||||
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category');
|
||||
$res = $queryBuilder
|
||||
->select('uid')
|
||||
->from('sys_category')
|
||||
->where(
|
||||
$queryBuilder->expr()->in('parent', $queryBuilder->createNamedParameter(array_map('intval', explode(',', $idList)), Connection::PARAM_INT_ARRAY))
|
||||
)
|
||||
->execute();
|
||||
|
||||
while (($row = $res->fetch())) {
|
||||
$counter++;
|
||||
if ($counter > 10000) {
|
||||
GeneralUtility::makeInstance(TimeTracker::class)->setTSlogMessage('EXT:news: one or more recursive categories where found');
|
||||
return implode(',', $result);
|
||||
}
|
||||
$subcategories = self::getChildrenCategoriesRecursive($row['uid'], $counter);
|
||||
$result[] = $row['uid'] . ($subcategories ? ',' . $subcategories : '');
|
||||
}
|
||||
|
||||
$result = implode(',', $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a category record in the backend
|
||||
*
|
||||
* @param string $default default label
|
||||
* @param array $row category record
|
||||
* @return string
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function translateCategoryRecord($default, array $row = []): string
|
||||
{
|
||||
if (TYPO3_MODE !== 'BE') {
|
||||
throw new \UnexpectedValueException('TYPO3 Mode must be BE');
|
||||
}
|
||||
|
||||
$overlayLanguage = (int)($GLOBALS['BE_USER']->uc['newsoverlay'] ?? 0);
|
||||
|
||||
$title = '';
|
||||
|
||||
if ($row['uid'] > 0 && $overlayLanguage > 0 && !isset($row['sys_language_uid'])) {
|
||||
$row = BackendUtility::getRecord('sys_category', $row['uid']);
|
||||
}
|
||||
|
||||
if ($row['uid'] > 0 && $overlayLanguage > 0 && $row['sys_language_uid'] === 0) {
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category');
|
||||
$overlayRecord = $queryBuilder
|
||||
->select('title')
|
||||
->from('sys_category')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($overlayLanguage, \PDO::PARAM_INT)),
|
||||
$queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($row['uid'], \PDO::PARAM_INT))
|
||||
)
|
||||
->setMaxResults(1)
|
||||
->execute()->fetch();
|
||||
|
||||
if (is_array($overlayRecord) && !empty($overlayRecord)) {
|
||||
$title = $overlayRecord['title'] . ' (' . $row['title'] . ')';
|
||||
}
|
||||
}
|
||||
|
||||
$title = $title ?: $default ?: '';
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean list of integers
|
||||
*
|
||||
* @param string $list
|
||||
* @return string
|
||||
*/
|
||||
private static function cleanIntList($list): string
|
||||
{
|
||||
return implode(',', GeneralUtility::intExplode(',', $list));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Service\Import;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Import Service interface
|
||||
*/
|
||||
interface DataProviderServiceInterface
|
||||
{
|
||||
public function getTotalRecordCount();
|
||||
|
||||
public function getImportData();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GeorgRinger\News\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
class LinkHandlerTargetPageService
|
||||
{
|
||||
|
||||
/** @var ContentObjectRenderer */
|
||||
public $cObj;
|
||||
|
||||
public function process(string $content = '', array $configuration = []): int
|
||||
{
|
||||
$fallbackPageId = (int)($configuration['fallback'] ?? 0);
|
||||
|
||||
$newsId = (int)$this->cObj->stdWrapValue('news', $configuration, null);
|
||||
if ($newsId === 0) {
|
||||
return $fallbackPageId;
|
||||
}
|
||||
|
||||
$singlePid = $this->getSinglePidFromCategory($newsId);
|
||||
return $singlePid ?: $fallbackPageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a pid for the single view from the category.
|
||||
*
|
||||
* @param int $newsId
|
||||
* @return int
|
||||
*/
|
||||
protected function getSinglePidFromCategory(int $newsId): int
|
||||
{
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('sys_category');
|
||||
$categoryRecord = $queryBuilder
|
||||
->select('title', 'single_pid')
|
||||
->from('sys_category')
|
||||
->leftJoin(
|
||||
'sys_category',
|
||||
'sys_category_record_mm',
|
||||
'sys_category_record_mm',
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.uid_local', $queryBuilder->quoteIdentifier('sys_category.uid'))
|
||||
)
|
||||
->where(
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.tablenames', $queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->gt('sys_category.single_pid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
|
||||
$queryBuilder->expr()->eq('sys_category_record_mm.sorting_foreign', $queryBuilder->createNamedParameter($newsId, \PDO::PARAM_INT))
|
||||
)
|
||||
->orderBy('sys_category_record_mm.sorting')
|
||||
->setMaxResults(1)
|
||||
->execute()->fetch();
|
||||
return (int)$categoryRecord['single_pid'];
|
||||
}
|
||||
}
|
||||
83
typo3conf/ext/news/Classes/Service/SettingsService.php
Normal file
83
typo3conf/ext/news/Classes/Service/SettingsService.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Service;
|
||||
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Provide a way to get the configuration just everywhere
|
||||
*
|
||||
* Example
|
||||
* $pluginSettingsService =
|
||||
* $this->objectManager->get('GeorgRinger\\News\\Service\\SettingsService');
|
||||
* \TYPO3\CMS\Core\Utility\GeneralUtility::print_array($pluginSettingsService->getSettings());
|
||||
*
|
||||
* If objectManager is not available:
|
||||
* http://forge.typo3.org/projects/typo3v4-mvc/wiki/
|
||||
* Dependency_Injection_%28DI%29#Creating-Prototype-Objects-through-the-Object-Manager
|
||||
*/
|
||||
class SettingsService
|
||||
{
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* Injects the Configuration Manager and loads the settings
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager An instance of the Configuration Manager
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function injectConfigurationManager(
|
||||
ConfigurationManagerInterface $configurationManager
|
||||
): void {
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSettings(): array
|
||||
{
|
||||
if ($this->settings === null) {
|
||||
$this->settings = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||
'News',
|
||||
'Pi1'
|
||||
);
|
||||
}
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings at path $path, which is separated by ".",
|
||||
* e.g. "pages.uid".
|
||||
* "pages.uid" would return $this->settings['pages']['uid'].
|
||||
*
|
||||
* If the path is invalid or no entry is found, false is returned.
|
||||
*
|
||||
* @param string $path
|
||||
* @return mixed
|
||||
*/
|
||||
public function getByPath($path)
|
||||
{
|
||||
return ObjectAccess::getPropertyPath($this->getSettings(), $path);
|
||||
}
|
||||
}
|
||||
305
typo3conf/ext/news/Classes/Service/SlugService.php
Normal file
305
typo3conf/ext/news/Classes/Service/SlugService.php
Normal file
@@ -0,0 +1,305 @@
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\News\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
|
||||
use TYPO3\CMS\Core\DataHandling\SlugHelper;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
class SlugService
|
||||
{
|
||||
|
||||
/** @var NewsSlugHelper */
|
||||
protected $slugService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$fieldConfig = $GLOBALS['TCA']['tx_news_domain_model_news']['columns']['path_segment']['config'];
|
||||
$this->slugService = GeneralUtility::makeInstance(SlugHelper::class, 'tx_news_domain_model_news', 'path_segment', $fieldConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function countOfSlugUpdates(): int
|
||||
{
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_news_domain_model_news');
|
||||
$queryBuilder->getRestrictions()->removeAll();
|
||||
$elementCount = $queryBuilder->count('uid')
|
||||
->from('tx_news_domain_model_news')
|
||||
->where(
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq('path_segment', $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->isNull('path_segment')
|
||||
)
|
||||
)
|
||||
->execute()->fetchColumn(0);
|
||||
|
||||
return $elementCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function performUpdates(): array
|
||||
{
|
||||
$databaseQueries = [];
|
||||
|
||||
/** @var Connection $connection */
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tx_news_domain_model_news');
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = $connection->createQueryBuilder();
|
||||
$queryBuilder->getRestrictions()->removeAll();
|
||||
$statement = $queryBuilder->select('*')
|
||||
->from('tx_news_domain_model_news')
|
||||
->where(
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq('path_segment', $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)),
|
||||
$queryBuilder->expr()->isNull('path_segment')
|
||||
)
|
||||
)
|
||||
->execute();
|
||||
while ($record = $statement->fetch()) {
|
||||
if ((string)$record['title'] !== '') {
|
||||
$slug = $this->slugService->generate($record, $record['pid']);
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = $connection->createQueryBuilder();
|
||||
$queryBuilder->update('tx_news_domain_model_news')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'uid',
|
||||
$queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->set('path_segment', $this->getUniqueValue($record['uid'], $record['sys_language_uid'], $slug));
|
||||
$databaseQueries[] = $queryBuilder->getSQL();
|
||||
$queryBuilder->execute();
|
||||
}
|
||||
}
|
||||
|
||||
return $databaseQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param string $slug
|
||||
* @return string
|
||||
*/
|
||||
protected function getUniqueValue(int $uid, int $languageId, string $slug): string
|
||||
{
|
||||
$statement = $this->getUniqueCountStatement($uid, $languageId, $slug);
|
||||
if ($statement->fetchColumn()) {
|
||||
for ($counter = 1; $counter <= 100; $counter++) {
|
||||
$newSlug = $slug . '-' . $counter;
|
||||
$statement->bindValue(1, $newSlug);
|
||||
$statement->execute();
|
||||
if (!$statement->fetchColumn()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $newSlug ?? $slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param int $languageId
|
||||
* @param string $slug
|
||||
* @return \Doctrine\DBAL\Driver\Statement|int
|
||||
*/
|
||||
protected function getUniqueCountStatement(int $uid, int $languageId, string $slug)
|
||||
{
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_news_domain_model_news');
|
||||
/** @var DeletedRestriction $deleteRestriction */
|
||||
$deleteRestriction = GeneralUtility::makeInstance(DeletedRestriction::class);
|
||||
$queryBuilder->getRestrictions()->removeAll()->add($deleteRestriction);
|
||||
|
||||
return $queryBuilder
|
||||
->count('uid')
|
||||
->from('tx_news_domain_model_news')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'path_segment',
|
||||
$queryBuilder->createPositionalParameter($slug, \PDO::PARAM_STR)
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'sys_language_uid',
|
||||
$queryBuilder->createPositionalParameter($languageId, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->neq('uid', $queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT))
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Count valid entries from EXT:realurl table tx_realurl_uniqalias which can be migrated
|
||||
* Checks also for existance of third party extension table 'tx_realurl_uniqalias'
|
||||
* EXT:realurl requires not to be installed
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countOfRealurlAliasMigrations(): int
|
||||
{
|
||||
$elementCount = 0;
|
||||
// Check if table 'tx_realurl_uniqalias' exists
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('tx_realurl_uniqalias');
|
||||
$schemaManager = $queryBuilder->getConnection()->getSchemaManager();
|
||||
if ($schemaManager->tablesExist(['tx_realurl_uniqalias']) === true) {
|
||||
// Count valid aliases for news
|
||||
$queryBuilder->getRestrictions()->removeAll();
|
||||
$elementCount = $queryBuilder->selectLiteral('COUNT(DISTINCT tx_news_domain_model_news.uid)')
|
||||
->from('tx_realurl_uniqalias')
|
||||
->join(
|
||||
'tx_realurl_uniqalias',
|
||||
'tx_news_domain_model_news',
|
||||
'tx_news_domain_model_news',
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_realurl_uniqalias.value_id',
|
||||
$queryBuilder->quoteIdentifier('tx_news_domain_model_news.uid')
|
||||
)
|
||||
)
|
||||
->where(
|
||||
$queryBuilder->expr()->andX(
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.path_segment',
|
||||
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
|
||||
),
|
||||
$queryBuilder->expr()->isNull('tx_news_domain_model_news.path_segment')
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.sys_language_uid',
|
||||
'tx_realurl_uniqalias.lang'
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_realurl_uniqalias.tablename',
|
||||
$queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)
|
||||
),
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_realurl_uniqalias.expire',
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->gte(
|
||||
'tx_realurl_uniqalias.expire',
|
||||
$queryBuilder->createNamedParameter($GLOBALS['ACCESS_TIME'], \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->execute()->fetchColumn(0);
|
||||
}
|
||||
return $elementCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform migration of EXT:realurl unique alias into empty news slugs
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function performRealurlAliasMigration(): array
|
||||
{
|
||||
$databaseQueries = [];
|
||||
|
||||
// Check if table 'tx_realurl_uniqalias' exists
|
||||
/** @var QueryBuilder $queryBuilderForRealurl */
|
||||
$queryBuilderForRealurl = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('tx_realurl_uniqalias');
|
||||
$schemaManager = $queryBuilderForRealurl->getConnection()->getSchemaManager();
|
||||
if ($schemaManager->tablesExist(['tx_realurl_uniqalias']) === true) {
|
||||
/** @var Connection $connection */
|
||||
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getConnectionForTable('tx_news_domain_model_news');
|
||||
$queryBuilder = $connection->createQueryBuilder();
|
||||
|
||||
// Get entries to update
|
||||
$statement = $queryBuilder
|
||||
->selectLiteral(
|
||||
'DISTINCT tx_news_domain_model_news.uid, tx_realurl_uniqalias.value_alias, tx_news_domain_model_news.uid, tx_news_domain_model_news.l10n_parent,tx_news_domain_model_news.sys_language_uid'
|
||||
)
|
||||
->from('tx_news_domain_model_news')
|
||||
->join(
|
||||
'tx_news_domain_model_news',
|
||||
'tx_realurl_uniqalias',
|
||||
'tx_realurl_uniqalias',
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.uid',
|
||||
$queryBuilder->quoteIdentifier('tx_realurl_uniqalias.value_id')
|
||||
),
|
||||
$queryBuilder->expr()->andX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.l10n_parent',
|
||||
$queryBuilder->quoteIdentifier('tx_realurl_uniqalias.value_id')
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.sys_language_uid',
|
||||
$queryBuilder->quoteIdentifier('tx_realurl_uniqalias.lang')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->where(
|
||||
$queryBuilder->expr()->andX(
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.path_segment',
|
||||
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
|
||||
),
|
||||
$queryBuilder->expr()->isNull('tx_news_domain_model_news.path_segment')
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_news_domain_model_news.sys_language_uid',
|
||||
'tx_realurl_uniqalias.lang'
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_realurl_uniqalias.tablename',
|
||||
$queryBuilder->createNamedParameter('tx_news_domain_model_news', \PDO::PARAM_STR)
|
||||
),
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'tx_realurl_uniqalias.expire',
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->gte(
|
||||
'tx_realurl_uniqalias.expire',
|
||||
$queryBuilder->createNamedParameter($GLOBALS['ACCESS_TIME'], \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
->execute();
|
||||
|
||||
// Update entries
|
||||
while ($record = $statement->fetch()) {
|
||||
$slug = $this->slugService->sanitize((string)$record['value_alias']);
|
||||
$queryBuilder = $connection->createQueryBuilder();
|
||||
$queryBuilder->update('tx_news_domain_model_news')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'uid',
|
||||
$queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->set('path_segment', $this->getUniqueValue($record['uid'], $record['sys_language_uid'], $slug));
|
||||
$databaseQueries[] = $queryBuilder->getSQL();
|
||||
$queryBuilder->execute();
|
||||
}
|
||||
}
|
||||
|
||||
return $databaseQueries;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user