diff --git a/Classes/Command/MigrateNewsCommandController.php b/Classes/Command/MigrateNewsCommandController.php index 5e502eb4754bb8424c3b022282bdb12f40c260f9..5edcc18287b26c5548977ab9a6ff02ebba5172da 100644 --- a/Classes/Command/MigrateNewsCommandController.php +++ b/Classes/Command/MigrateNewsCommandController.php @@ -27,17 +27,20 @@ namespace SGalinski\SgNews\Command; ***************************************************************/ use SGalinski\SgNews\Domain\Model\News; -use SGalinski\SgNews\Domain\Model\Tag; +use SGalinski\SgNews\Domain\Repository\FileReferenceRepository; +use SGalinski\SgNews\Domain\Repository\NewsRepository; use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Mvc\Controller\CommandController; use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException; +use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; /** @@ -50,29 +53,41 @@ class MigrateNewsCommandController extends CommandController { protected $requestAdminPermissions = TRUE; /** - * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager - * @inject + * @var PersistenceManager */ protected $persistenceManager; /** - * @var \SGalinski\SgNews\Domain\Repository\NewsRepository - * @inject + * @param PersistenceManager $persistenceManager + */ + public function injectPersistenceManager(PersistenceManager $persistenceManager) { + $this->persistenceManager = $persistenceManager; + } + + /** + * @var NewsRepository */ protected $newsRepository; /** - * @var \SGalinski\SgNews\Domain\Repository\TagRepository - * @inject + * @param NewsRepository $newsRepository */ - private $tagRepository; + public function injectNewsRepository(NewsRepository $newsRepository) { + $this->newsRepository = $newsRepository; + } /** - * @var \SGalinski\SgNews\Domain\Repository\FileReferenceRepository - * @inject + * @var FileReferenceRepository */ private $fileReferenceRepository; + /** + * @param FileReferenceRepository $fileReferenceRepository + */ + public function injectFileReferenceRepository(FileReferenceRepository $fileReferenceRepository) { + $this->fileReferenceRepository = $fileReferenceRepository; + } + /** * this array maps new pages to their original entry in the tx_news table * @@ -117,8 +132,7 @@ class MigrateNewsCommandController extends CommandController { ) { // fix repair translation bug where tsfe is missing from command controller, can be removed when v1.5 is released if (!$GLOBALS['TSFE']) { - /** @var TypoScriptFrontendController $typoScriptController */ - $GLOBALS['TSFE'] = $typoScriptController = $this->objectManager->get( + $GLOBALS['TSFE'] = $this->objectManager->get( TypoScriptFrontendController::class, $GLOBALS['TYPO3_CONF_VARS'], 0, 0 ); } @@ -126,13 +140,14 @@ class MigrateNewsCommandController extends CommandController { $this->languageMap = json_decode($languageMapAsJson, TRUE); $this->categoryMap = json_decode($categoryMapAsJson, TRUE); - /** @var DatabaseConnection $db */ - $db = $GLOBALS['TYPO3_DB']; - $where = 'hidden = 0 and deleted = 0 and endtime = 0 and pid = ' . (int) $pId; - - /** @var \mysqli_result $result */ - $result = $db->exec_SELECTquery('*', 'tx_news_domain_model_news', $where); - + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_news_domain_model_news'); + $queryBuilder->getRestrictions()->removeByType(StartTimeRestriction::class); + $rows = $queryBuilder->select('*') + ->from('tx_news_domain_model_news') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pId, \PDO::PARAM_INT)) + ) + ->execute()->fetchAll(); $localDataHandler = GeneralUtility::makeInstance(DataHandler::class); $beUser = $this->simulateBackendUser(); $localCommandMap = [ @@ -143,13 +158,11 @@ class MigrateNewsCommandController extends CommandController { ] ]; - $resultArray = []; - while ($row = $result->fetch_assoc()) { + foreach ($rows as $row) { // ignore the entry if its not within the given year if ((int) date('Y', $row['datetime']) !== $year) { continue; } - $resultArray[] = $row; // if no l10n_parent exists, create a copy of the page if ((int) $row['l10n_parent'] === 0) { @@ -199,8 +212,17 @@ class MigrateNewsCommandController extends CommandController { $this->persistenceManager->persistAll(); // update content element from the new page - $where = 'pid = ' . $newPageId . ' AND sys_language_uid = ' . $this->languageMap[(int) $row['sys_language_uid']]; - $db->exec_UPDATEquery('tt_content', $where, ['bodytext' => $row['bodytext']]); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder->update('tt_content') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($newPageId, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->languageMap[(int) $row['sys_language_uid']], \PDO::PARAM_INT)) + ) + ) + ->set('bodytext', $queryBuilder->createNamedParameter($row['bodytext'])) + ->execute(); } } else { // this row is a translation and should simply update the content accordingly $this->updateTranslation($row); @@ -217,20 +239,30 @@ class MigrateNewsCommandController extends CommandController { */ private function getMatchingFile(array $row) { // match old page id with old file reference id - /** @var DatabaseConnection $db */ - $db = $GLOBALS['TYPO3_DB']; - $where = 'tablenames = "tx_news_domain_model_news" AND fieldname = "fal_media" AND uid_foreign = ' . $row['uid']; - /** @var \mysqli_result $result */ - $fileReferenceResult = $db->exec_SELECTgetSingleRow( - 'uid, uid_local', 'sys_file_reference_news_migration', $where - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference_news_migration'); + $queryBuilder->getRestrictions()->removeAll(); + $fileReferenceResult = $queryBuilder->select('uid', 'uid_local') + ->from('sys_file_reference_news_migration') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('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'], \PDO::PARAM_INT)) + ) + ) + ->execute()->fetch(); if (!$fileReferenceResult) { return NULL; } - $where = 'uid = ' . $fileReferenceResult['uid_local']; - /** @var \mysqli_result $result */ - $fileResult = $db->exec_SELECTgetSingleRow('identifier', 'sys_file_news_migration', $where); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_news_migration'); + $queryBuilder->getRestrictions()->removeAll(); + $fileResult = $queryBuilder->select('identifier') + ->from('sys_file_news_migration') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($fileReferenceResult['uid_local'], \PDO::PARAM_INT)) + ) + ->execute()->fetch(); if (!$fileResult) { return NULL; } @@ -249,17 +281,17 @@ class MigrateNewsCommandController extends CommandController { * Get the tag / category, matching the news * * @param array $row - * @return News */ private function setMatchingTag(array $row) { - /** @var DatabaseConnection $db */ - $db = $GLOBALS['TYPO3_DB']; - $where = 'uid_foreign = ' . (int) $row['uid']; - - /** @var \mysqli_result $result */ - $result = $db->exec_SELECTquery('uid_local, sorting_foreign', 'sys_category_record_mm_news_migration', $where); - - while ($mmRow = $result->fetch_assoc()) { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_category_record_mm_news_migration'); + $queryBuilder->getRestrictions()->removeAll(); + $mmRows = $queryBuilder->select('uid_local', 'sorting_foreign') + ->from('sys_category_record_mm_news_migration') + ->where( + $queryBuilder->expr()->eq('uid_foreign', $queryBuilder->createNamedParameter($row['uid'], \PDO::PARAM_INT)) + ) + ->execute()->fetchAll(); + foreach ($mmRows as $mmRow) { $values = [ 'uid_local' => $this->categoryMap[(int) $mmRow['uid_local']], 'uid_foreign' => $this->newsPagesMap[(int) $row['uid']], @@ -267,7 +299,8 @@ class MigrateNewsCommandController extends CommandController { 'fieldname' => 'tx_sgnews_tags', 'sorting_foreign' => (int) $mmRow['sorting_foreign'] ]; - $db->exec_INSERTquery('sys_category_record_mm', $values); + $queryBuilder->insert('sys_category_record_mm') + ->values($values); } } @@ -277,68 +310,111 @@ class MigrateNewsCommandController extends CommandController { * @param array $row */ private function updateTranslation(array $row) { - /** @var DatabaseConnection $db */ - $db = $GLOBALS['TYPO3_DB']; - // get entry in news map $parentId = $this->newsPagesMap[$row['l10n_parent']]; - // get content element from the original page - $where = 'pid = ' . (int) $parentId; - - /** @var \mysqli_result $result */ - $result = $db->exec_SELECTquery('l18n_parent', 'tt_content', $where); - $originalContentElement = $result->fetch_row(); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); + $queryBuilder->getRestrictions()->removeAll(); + $originalContentElement = $queryBuilder->select('l18n_parent') + ->from('tt_content') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ) + ->execute()->fetch(); + $queryBuilder->update('tt_content'); // if its the new default, there is no l18n_parent if ((int) $this->languageMap[(int) $row['sys_language_uid'] === 0]) { - $where = 'uid = ' . (int) $originalContentElement[0]; + $queryBuilder->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($originalContentElement[0], \PDO::PARAM_INT)) + ); } else { - $where = 'l18n_parent = ' . (int) $originalContentElement[0]; + $queryBuilder->where( + $queryBuilder->expr()->eq('l18n_parent', $queryBuilder->createNamedParameter($originalContentElement[0], \PDO::PARAM_INT)) + ); } // look up the correct language id, if they have changed if (isset($this->languageMap[(int) $row['sys_language_uid']])) { - $where .= ' AND sys_language_uid = ' . $this->languageMap[(int) $row['sys_language_uid']]; + $queryBuilder->andWhere( + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->languageMap[(int) $row['sys_language_uid']], \PDO::PARAM_INT)) + ); } else { - $where .= ' AND sys_language_uid = ' . (int) $row['sys_language_uid']; + $queryBuilder->andWhere( + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($row['sys_language_uid'], \PDO::PARAM_INT)) + ); } - - $db->exec_UPDATEquery('tt_content', $where, ['bodytext' => $row['bodytext']]); + $queryBuilder->set('bodytext', $queryBuilder->createNamedParameter($row['bodytext'])) + ->execute(); // possibly the default language needs to be overwritten and the old default translation needs to be preserved if (isset($this->languageMap[(int) $row['sys_language_uid']]) && $this->languageMap[(int) $row['sys_language_uid']] === 0) { - $where = 'uid = ' . (int) $parentId; - /** @var \mysqli_result $result */ - $result = $db->exec_SELECTgetSingleRow('title, subtitle', 'pages', $where); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll(); + $result = $queryBuilder->select('title', 'subtitle') + ->from('pages') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ) + ->execute()->fetch(); if ($result) { - $where = 'pid = ' . (int) $parentId . ' AND sys_language_uid = ' . $this->languageMap[0]; - $db->exec_UPDATEquery( - 'pages_language_overlay', $where, - ['title' => $result['title'], 'subtitle' => $result['subtitle'], 'navtitle' => ''] + $queryBuilder->where( + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->languageMap[0], \PDO::PARAM_INT)) ); + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) { + $queryBuilder->update('pages_language_overlay') + ->andWhere( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ); + } else { + $queryBuilder->update('pages') + ->andWhere( + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->languageMap[0], \PDO::PARAM_INT)) + ); + } + $queryBuilder->set('title', $queryBuilder->createNamedParameter($result['title'])) + ->set('subtitle', $queryBuilder->createNamedParameter($result['subtitle'])) + ->set('navtitle', $queryBuilder->createNamedParameter('')) + ->execute(); } - $where = 'uid = ' . (int) $parentId; - $db->exec_UPDATEquery( - 'pages', $where, ['title' => date( - 'Y-m-d', $row['datetime'] - ) . ' - ' . $row['title'], 'subtitle' => $row['title'], 'lastUpdated' => $row['datetime'], 'navtitle' => ''] - ); + $newTitle = date('Y-m-d', $row['datetime']) . ' - ' . $row['title']; + $queryBuilder->update('pages') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ) + ->set('title', $queryBuilder->createNamedParameter($newTitle)) + ->set('subtitle', $queryBuilder->createNamedParameter($row['title'])) + ->set('lastUpdated', $queryBuilder->createNamedParameter($row['datetime'], \PDO::PARAM_INT)) + ->set('navtitle', $queryBuilder->createNamedParameter('')) + ->execute(); } else { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) { + $queryBuilder->update('pages_language_overlay') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ); + } else { + $queryBuilder->update('pages') + ->where( + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)) + ); + } + // finally translate the page title if necessary - /** @noinspection NotOptimalIfConditionsInspection */ if (isset($this->languageMap[(int) $row['sys_language_uid']]) && $this->languageMap[(int) $row['sys_language_uid']] > 0) { - $where = 'pid = ' . (int) $parentId . ' AND sys_language_uid = ' . $this->languageMap[(int) $row['sys_language_uid']]; + $queryBuilder->andWhere( + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($this->languageMap[(int) $row['sys_language_uid']], \PDO::PARAM_INT)) + ); } else { - $where = 'pid = ' . (int) $parentId . ' AND sys_language_uid = ' . (int) $row['sys_language_uid']; + $queryBuilder->andWhere( + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($row['sys_language_uid'], \PDO::PARAM_INT)) + ); } + $queryBuilder->set('title', $queryBuilder->createNamedParameter(date('Y-m-d', $row['datetime']) . ' - ' . $row['title'])) + ->execute(); } - - $db->exec_UPDATEquery( - 'pages_language_overlay', $where, ['title' => date('Y-m-d', $row['datetime']) . ' - ' . $row['title']] - ); } /** diff --git a/Classes/Controller/Ajax/LikeController.php b/Classes/Controller/Ajax/LikeController.php index 1b465c37ae160494706c6af985ce378d3295964a..5abaeb2b57c8c8e4f87f5cf1e9743991b3eedef4 100644 --- a/Classes/Controller/Ajax/LikeController.php +++ b/Classes/Controller/Ajax/LikeController.php @@ -27,9 +27,8 @@ namespace SGalinski\SgNews\Controller\Ajax; ***************************************************************/ use SGalinski\SgAjax\Controller\Ajax\AbstractAjaxController; -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\Page\PageRepository; /** * The LikeController handles the Ajax-Actions related to the like feature @@ -46,13 +45,13 @@ class LikeController extends AbstractAjaxController { */ public function addLikeAction($newsPid) { try { - /** @var DatabaseConnection $database */ - $database = $GLOBALS['TYPO3_DB']; - /** @var PageRepository $pageRepository */ - $pageRepository = GeneralUtility::makeInstance(PageRepository::class); - - $database->sql_query('UPDATE pages SET tx_sgnews_likes = tx_sgnews_likes ' . '+ 1 WHERE uid=' . (int) $newsPid . - $pageRepository->enableFields('pages')); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->update('pages') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($newsPid, \PDO::PARAM_INT)) + ) + ->set('tx_sgnews_likes', 'tx_sgnews_likes + 1') + ->execute(); } catch (\Exception $exception) { $this->returnData(['success' => false]); } diff --git a/Classes/Domain/Repository/FileReferenceRepository.php b/Classes/Domain/Repository/FileReferenceRepository.php index ef1cc95067da284064af6ca3b74b18642e4451ea..b26ff56edfb84d559a68e8a4f1c3e06694411f37 100644 --- a/Classes/Domain/Repository/FileReferenceRepository.php +++ b/Classes/Domain/Repository/FileReferenceRepository.php @@ -26,8 +26,9 @@ 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\DatabaseConnection; use TYPO3\CMS\Core\Resource\File; /** @@ -78,23 +79,23 @@ class FileReferenceRepository extends AbstractRepository { * @throws \Exception */ public function addFileReferenceFromFileId($fileId, array $reference, $tablename, $fieldname) { - /** @var DatabaseConnection $db */ - $db = $GLOBALS['TYPO3_DB']; - $arguments = [ - 'crdate' => $GLOBALS['EXEC_TIME'], - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'pid' => (int) $reference['pid'], - 'table_local' => 'sys_file', - 'uid_local' => $fileId, - 'uid_foreign' => (int) $reference['uid'], - 'tablenames' => $tablename, - 'fieldname' => $fieldname, - ]; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference'); + $success = $queryBuilder->insert('sys_file_reference') + ->values([ + 'crdate' => $GLOBALS['EXEC_TIME'], + 'tstamp' => $GLOBALS['EXEC_TIME'], + 'pid' => (int) $reference['pid'], + 'table_local' => 'sys_file', + 'uid_local' => $fileId, + 'uid_foreign' => (int) $reference['uid'], + 'tablenames' => $tablename, + 'fieldname' => $fieldname + ]); - if (!$db->exec_INSERTquery('sys_file_reference', $arguments)) { + if (!$success) { throw new \Exception('An error occurred while adding a file reference record.', 1452590219); } - return (int) $db->sql_insert_id(); + return (int) $queryBuilder->getConnection()->lastInsertId(); } } diff --git a/Classes/TCA/TcaProvider.php b/Classes/TCA/TcaProvider.php index d6cf5f9245022cab4e290fea446b42b8e840f7a3..9f937ae78788441fbef2b73184eed56c5ed71635 100644 --- a/Classes/TCA/TcaProvider.php +++ b/Classes/TCA/TcaProvider.php @@ -25,7 +25,7 @@ namespace SGalinski\SgNews\TCA; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -57,9 +57,6 @@ class TcaProvider implements SingletonInterface { * @return void */ public function processDatamap_afterAllOperations(DataHandler $tceMain) { - /** @var DatabaseConnection $database */ - $database = $GLOBALS['TYPO3_DB']; - /** @var array $tablesData */ foreach ($tceMain->datamap as $table => $tablesData) { if (!in_array($table, ['pages', 'pages_language_overlay'], TRUE)) { @@ -75,31 +72,42 @@ class TcaProvider implements SingletonInterface { $translationRow = []; $pagesIdentity = (int) $identity; if ($table === 'pages_language_overlay') { - $translationRow = $database->exec_SELECTgetSingleRow( - 'pid, subtitle, t3ver_oid', 'pages_language_overlay', 'uid = ' . (int) $identity - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages_language_overlay'); + $queryBuilder->getRestrictions()->removeAll(); + $translationRow = $queryBuilder->select('pid', 'subtitle', 't3ver_oid') + ->from('pages_language_overlay') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($identity, \PDO::PARAM_INT)) + ) + ->execute()->fetch(); $workspaceOriginalId = (int) $translationRow['t3ver_oid']; if ($workspaceOriginalId > 0) { - $translationRow = $database->exec_SELECTgetSingleRow( - 'pid, subtitle, t3ver_oid', 'pages_language_overlay', 'uid = ' . $workspaceOriginalId - ); + $translationRow = $queryBuilder->select('pid', 'subtitle', 't3ver_oid') + ->from('pages_language_overlay') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($workspaceOriginalId, \PDO::PARAM_INT)) + ) + ->execute()->fetch(); } $pagesIdentity = (int) $translationRow['pid']; } - $row = $database->exec_SELECTgetSingleRow( - 'doktype, subtitle, lastUpdated, tx_sgnews_highlighted, t3ver_oid', 'pages', 'uid = ' . - $pagesIdentity - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll(); + $row = $queryBuilder->select('doktype', 'subtitle', 'lastUpdated', 'tx_sgnews_highlighted', 't3ver_oid') + ->from('pages') + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($pagesIdentity, \PDO::PARAM_INT)) + ) + ->execute()->fetch(); $workspaceOriginalId = (int) $row['t3ver_oid']; if ($workspaceOriginalId > 0) { - $row = $database->exec_SELECTgetSingleRow( - 'doktype, subtitle, lastUpdated, tx_sgnews_highlighted, t3ver_oid', 'pages', 'uid = ' . - $workspaceOriginalId - ); + $row = $queryBuilder->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($workspaceOriginalId, \PDO::PARAM_INT)) + )->execute()->fetch(); } // only articles @@ -119,8 +127,14 @@ class TcaProvider implements SingletonInterface { } $calculatedTitle = $prefix . strftime('%Y-%m-%d', $row['lastUpdated']) . ' - ' . $subtitle; - $updateFields = ['nav_title' => $subtitle, 'title' => trim($calculatedTitle)]; - $database->exec_UPDATEquery($table, 'uid = ' . $identity, $updateFields); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); + $queryBuilder->update($table) + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($identity, \PDO::PARAM_INT)) + ) + ->set('nav_title', $queryBuilder->createNamedParameter($subtitle)) + ->set('title', $queryBuilder->createNamedParameter(trim($calculatedTitle))) + ->execute(); } } } diff --git a/Classes/Utility/BackendNewsUtility.php b/Classes/Utility/BackendNewsUtility.php index 7d239e603ff8f9b4e36ebd24180eb846db2f7589..904b3fc0a6b0f9e8b3135885f9ea4be247c3d48c 100644 --- a/Classes/Utility/BackendNewsUtility.php +++ b/Classes/Utility/BackendNewsUtility.php @@ -32,7 +32,11 @@ use SGalinski\SgNews\Domain\Repository\NewsRepository; use SGalinski\SgNews\Domain\Repository\TagRepository; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryHelper; +use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction; +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\Database\QueryGenerator; use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider; use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider; @@ -149,14 +153,18 @@ class BackendNewsUtility { $siteRootUid, PHP_INT_MAX, 0, $GLOBALS['BE_USER']->getPagePermsClause(1) ); - // if doktype = 117 (category) then get the category name (page title) - /** @var DatabaseConnection $databaseConnection */ - $databaseConnection = $GLOBALS['TYPO3_DB']; - - $where = 'deleted = 0 AND doktype = ' . self::CATEGORY_DOKTYPE . ' AND uid in (' . $childPids . ')'; - $result = $databaseConnection->exec_SELECTgetRows('uid, title', 'pages', $where); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); + $result = $queryBuilder->select('uid', 'title') + ->from('pages') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('doktype', $queryBuilder->createNamedParameter(self::CATEGORY_DOKTYPE, \PDO::PARAM_INT)), + $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter(explode(',', $childPids), Connection::PARAM_INT_ARRAY)) + ) + ) + ->execute()->fetchAll(); $categories = []; - /** @var array $result */ foreach ($result as $page) { $categoryPageInfo = BackendUtility::readPageAccess( (int) $page['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1) @@ -319,110 +327,72 @@ class BackendNewsUtility { return $out; } - /** @var DatabaseConnection $databaseConnection */ - $databaseConnection = $GLOBALS['TYPO3_DB']; - $result = $databaseConnection->exec_SELECTquery($select, $tables, $where, '`pages`.`uid`', '`pages`.`sorting`'); - while ($row = $result->fetch_assoc()) { - $out[] = $row; - } - $databaseConnection->sql_free_result($result); - return $out; - } - - /** - * Creates news query parts - * - * @param array $allowedUids - * @param array $filters - * @param int $languageUid - * @return array - */ - private static function getNewsQueryParts(array $allowedUids, array $filters = [], $languageUid = 0): array { - $out = [0 => ' - `pages`.`uid` AS uid, - `pages`.`pid` AS pid, - `pages`.`hidden` AS hidden, - `pages`.`sorting` AS sorting, - `pages`.`doktype` AS doktype, - `pages`.`title` AS title - ', 1 => '', 2 => '']; - $out[1] = '`pages`'; - $out[2] = '`pages`.`uid` IN(' . implode(',', $allowedUids) . ') ' . BackendUtility::deleteClause('pages') . - ' AND `pages`.`doktype` = ' . self::NEWS_DOKTYPE; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); + $queryBuilder->select('p.uid', + 'p.pid', + 'p.hidden', + 'p.sorting', + 'p.doktype', + 'p.title' + )->from('pages', 'p') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($allowedUids, Connection::PARAM_INT_ARRAY)), + $queryBuilder->expr()->eq('doktype', $queryBuilder->createNamedParameter(self::NEWS_DOKTYPE, \PDO::PARAM_INT)) + ) + ) + ->groupBy('p.uid') + ->orderBy('p.sorting'); if ($languageUid) { - $out[0] .= ', `translation`.`title` AS translation_title'; - $out[0] .= ', `translation`.`uid` AS translation_uid'; - $out[1] .= ' LEFT JOIN `pages_language_overlay` AS `translation` ON `translation`.`pid` = `pages`.`uid` ' . - BackendUtility::deleteClause('pages_language_overlay', 'translation') . - ' AND `translation`.`sys_language_uid` = ' . $languageUid; - } - if (isset($filters['tags']) && is_array($filters['tags']) && count($filters['tags'])) { - $tagUids = []; - /** @var array $filterTags */ - $filterTags = $filters['tags']; - foreach ($filterTags as $tagUid) { - if ((int) $tagUid && !in_array((int) $tagUid, $tagUids, TRUE)) { - $tagUids[] = (int) $tagUid; - } - } - if (count($tagUids)) { - $out[1] .= ' INNER JOIN `sys_category_record_mm` AS `tag` ON `tag`.`tablenames` = \'pages\'' . - ' AND `tag`.`fieldname` = \'tx_sgnews_tags\' AND `tag`.`uid_foreign` = `pages`.`uid`' . - ' AND `tag`.`uid_local` IN (' . implode(',', $filters['tags']) . ')'; + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) { + $queryBuilder->leftJoin('p', 'pages_language_overlay', 'translation', + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('translation.pid', 'p.uid'), + $queryBuilder->expr()->eq('translation.sys_language_uid', $queryBuilder->createNamedParameter($languageUid, \PDO::PARAM_INT)) + ) + ); + } else { + $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)) + ) + ); } } - if (isset($filters['search']) && trim($filters['search'])) { - $out[2] .= self::getNewsSearchClause(trim($filters['search']), $languageUid); + if (isset($filters['tags']) && is_array($filters['tags']) && count($filters['tags'])) { + $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')), + $queryBuilder->expr()->eq('tag.uid_foreign', 'p.uid'), + $queryBuilder->expr()->in('tag.uid_local', $queryBuilder->createNamedParameter(\array_unique($filters['tags']))) + ) + ); } - return $out; - } - - /** - * Creates constraints of query for searching news by search-word - * - * @param string $searchString - * @param int $languageUid - * @return string - */ - private static function getNewsSearchClause($searchString = '', $languageUid = 0): string { - $out = ''; - $searchString = strtolower(trim($searchString)); - $languageUid = (int) $languageUid; - if (!$searchString) { - return $out; - } - $out = ' AND ('; - /** @var DatabaseConnection $databaseConnection */ - $databaseConnection = $GLOBALS['TYPO3_DB']; - $likeString = 'LIKE \'%' . $databaseConnection->escapeStrForLike($searchString, 'pages') . '%\''; - $constraints = []; - $pageFields = [ - 'title' => TRUE, - 'description' => TRUE, - 'author' => TRUE, - 'abstract' => TRUE, - ]; - foreach ($pageFields as $fieldName => $isCommonField) { - if ($isCommonField) { - $constraints[] = 'LOWER(`pages`.`' . $fieldName . '`) ' . $likeString; - } - } - if (!$languageUid) { - foreach ($pageFields as $fieldName => $isCommonField) { - if (!$isCommonField) { - $constraints[] = 'LOWER(`pages`.`' . $fieldName . '`) ' . $likeString; - } - } - } else { - foreach ($pageFields as $fieldName => $isCommonField) { - if ($isCommonField) { - $constraints[] = 'LOWER(`translation`.`' . $fieldName . '`) ' . $likeString; - } + if (isset($filters['search']) && trim($filters['search'])) { + $expressions = [ + $queryBuilder->expr()->like('p.title', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')), + $queryBuilder->expr()->like('p.description', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')), + $queryBuilder->expr()->like('p.author', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')), + $queryBuilder->expr()->like('p.abstract', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')), + ]; + if ($languageUid) { + $expressions[] = $queryBuilder->expr()->like('translation.title', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')); + $expressions[] = $queryBuilder->expr()->like('translation.description', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')); + $expressions[] = $queryBuilder->expr()->like('translation.author', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')); + $expressions[] = $queryBuilder->expr()->like('translation.abstract', $queryBuilder->createNamedParameter('%' . trim($filters['search']) . '%')); } + $queryBuilder->andWhere( + $queryBuilder->expr()->orX( + $expressions + ) + ); } - $out .= implode(' OR ', $constraints) . ')'; - return $out; + + return $queryBuilder->execute()->fetchAll(); } /** @@ -447,15 +417,11 @@ class BackendNewsUtility { $languages = [ 0 => ['title' => $defaultLanguage, 'flag' => $defaultLanguageFlag] ]; - /** @var DatabaseConnection $databaseConnection */ - $databaseConnection = $GLOBALS['TYPO3_DB']; - $orderBy = ''; - if (VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) >= 8000000) { - $orderBy = 'sorting'; - } - $languageRows = $databaseConnection->exec_SELECTgetRows( - 'uid, title, flag', 'sys_language', 'hidden = 0', '', $orderBy - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); + $languageRows = $queryBuilder->select('uid', 'title', 'flag') + ->from('sys_language') + ->orderBy('sorting') + ->execute()->fetchAll(); if ($languageRows) { /** @var BackendUserAuthentication $backendUser */ $backendUser = $GLOBALS['BE_USER']; @@ -491,27 +457,48 @@ class BackendNewsUtility { $useDeleteClause = TRUE ) { if (is_array($GLOBALS['TCA'][$theTable])) { - /** @var DatabaseConnection $databaseConnection */ - $databaseConnection = $GLOBALS['TYPO3_DB']; - $result = $databaseConnection->exec_SELECTquery( - '*', - $theTable, - $theField . '=' . $databaseConnection->fullQuoteStr($theValue, $theTable) . - ($useDeleteClause ? BackendUtility::deleteClause($theTable) . ' ' : '') . - BackendUtility::versioningPlaceholderClause($theTable) . ' ' . - $whereClause, - $groupBy, - $orderBy, - $limit - ); - $rows = []; - while ($row = $databaseConnection->sql_fetch_assoc($result)) { - $rows[] = $row; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($theTable); + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));; + if ($useDeleteClause) { + $queryBuilder->getRestrictions() + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); } - $databaseConnection->sql_free_result($result); - if (!empty($rows)) { - return $rows; + + $queryBuilder->select('*') + ->from($theTable) + ->where( + $queryBuilder->expr()->eq($theField, $queryBuilder->createNamedParameter($theValue)) + ); + // additional where + if ($whereClause) { + $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($whereClause)); } + + // group by + if ($groupBy !== '') { + $queryBuilder->groupBy(QueryHelper::parseGroupBy($groupBy)); + } + + // order by + if ($orderBy !== '') { + foreach (QueryHelper::parseOrderBy($orderBy) as $orderPair) { + list($fieldName, $order) = $orderPair; + $queryBuilder->addOrderBy($fieldName, $order); + } + } + + // limit + if ($limit !== '') { + if (strpos($limit, ',')) { + $limitOffsetAndMax = GeneralUtility::intExplode(',', $limit); + $queryBuilder->setFirstResult((int)$limitOffsetAndMax[0]); + $queryBuilder->setMaxResults((int)$limitOffsetAndMax[1]); + } else { + $queryBuilder->setMaxResults((int)$limit); + } + } + + return $queryBuilder->execute()->fetchAll(); } return NULL; }