diff --git a/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php b/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php index b0a54629adea5e20e9347f1b086d3fa7f4f8befa..07b6cefc2b3390497a2ea976b253bf74f0cabdc3 100644 --- a/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php +++ b/typo3/sysext/core/Classes/Category/Collection/CategoryCollection.php @@ -14,10 +14,12 @@ namespace TYPO3\CMS\Core\Category\Collection; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Collection\AbstractRecordCollection; use TYPO3\CMS\Core\Collection\CollectionInterface; use TYPO3\CMS\Core\Collection\EditableCollectionInterface; +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\Utility\GeneralUtility; /** @@ -96,53 +98,93 @@ class CategoryCollection extends AbstractRecordCollection implements EditableCol */ public static function load($id, $fillItems = false, $tableName = '', $fieldName = '') { - $collectionRecord = self::getDatabaseConnection()->exec_SELECTgetSingleRow( - '*', - static::$storageTableName, - 'uid = ' . (int)$id . BackendUtility::deleteClause(static::$storageTableName) - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable(static::$storageTableName); + + $queryBuilder->getRestrictions() + ->removeAll() + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); + + $collectionRecord = $queryBuilder->select('*') + ->from(static::$storageTableName) + ->where( + $queryBuilder->expr()->eq('uid', (int)$id) + ) + ->setMaxResults(1) + ->execute() + ->fetch(); + $collectionRecord['table_name'] = $tableName; $collectionRecord['field_name'] = $fieldName; + return self::create($collectionRecord, $fillItems); } /** - * Gets the collected records in this collection, by + * Selects the collected records in this collection, by * looking up the MM relations of this record to the * table name defined in the local field 'table_name'. * + * @return QueryBuilder + */ + protected function getCollectedRecordsQueryBuilder() + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable(static::$storageTableName); + $queryBuilder->getRestrictions()->removeAll(); + + $queryBuilder->select($this->getItemTableName() . '.*') + ->from(static::$storageTableName) + ->join( + static::$storageTableName, + 'sys_category_record_mm', + 'sys_category_record_mm', + $queryBuilder->expr()->eq( + 'sys_category_record_mm.uid_local', + $queryBuilder->quoteIdentifier(static::$storageTableName . '.uid') + ) + ) + ->join( + 'sys_category_record_mm', + $this->getItemTableName(), + $this->getItemTableName(), + $queryBuilder->expr()->eq( + 'sys_category_record_mm.uid_foreign', + $queryBuilder->quoteIdentifier($this->getItemTableName() . '.uid') + ) + ) + ->where( + $queryBuilder->expr()->eq(static::$storageTableName . '.uid', (int)$this->getIdentifier()), + $queryBuilder->expr()->eq( + 'sys_category_record_mm.tablenames', + $queryBuilder->createNamedParameter($this->getItemTableName()) + ), + $queryBuilder->expr()->eq( + 'sys_category_record_mm.fieldname', + $queryBuilder->createNamedParameter($this->getRelationFieldName()) + ) + ); + + return $queryBuilder; + } + + /** + * Gets the collected records in this collection, by + * using <getCollectedRecordsQueryBuilder>. + * * @return array */ protected function getCollectedRecords() { - $db = self::getDatabaseConnection(); + $relatedRecords = []; - $relatedRecords = array(); - // Assemble where clause - $where = 'AND ' . self::$storageTableName . '.uid = ' . (int)$this->getIdentifier(); - // Add condition on tablenames fields - $where .= ' AND sys_category_record_mm.tablenames = ' . $db->fullQuoteStr( - $this->getItemTableName(), - 'sys_category_record_mm' - ); - // Add condition on fieldname field - $where .= ' AND sys_category_record_mm.fieldname = ' . $db->fullQuoteStr( - $this->getRelationFieldName(), - 'sys_category_record_mm' - ); - $resource = $db->exec_SELECT_mm_query( - $this->getItemTableName() . '.*', - self::$storageTableName, - 'sys_category_record_mm', - $this->getItemTableName(), - $where - ); - if ($resource) { - while ($record = $db->sql_fetch_assoc($resource)) { - $relatedRecords[] = $record; - } - $db->sql_free_result($resource); + $queryBuilder = $this->getCollectedRecordsQueryBuilder(); + $result = $queryBuilder->execute(); + + while ($record = $result->fetch()) { + $relatedRecords[] = $record; } + return $relatedRecords; } diff --git a/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php b/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php index 64efce3642713e71bdbb87546dea8600e8e55ede..f01c19fba46d3d1502f37238ccfcdb0292e78a2a 100644 --- a/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php +++ b/typo3/sysext/frontend/Classes/Category/Collection/CategoryCollection.php @@ -14,6 +14,8 @@ namespace TYPO3\CMS\Frontend\Category\Collection; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -35,7 +37,8 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol public static function create(array $collectionRecord, $fillItems = false) { /** @var $collection \TYPO3\CMS\Frontend\Category\Collection\CategoryCollection */ - $collection = GeneralUtility::makeInstance(__CLASS__, + $collection = GeneralUtility::makeInstance( + __CLASS__, $collectionRecord['table_name'], $collectionRecord['field_name'] ); @@ -62,13 +65,23 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol */ public static function load($id, $fillItems = false, $tableName = '', $fieldName = '') { - $collectionRecord = self::getDatabaseConnection()->exec_SELECTgetSingleRow( - '*', - static::$storageTableName, - 'uid = ' . (int)$id . self::getTypoScriptFrontendController()->sys_page->enableFields(static::$storageTableName) - ); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable(static::$storageTableName); + $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); + + $collectionRecord = $queryBuilder + ->select('*') + ->from(static::$storageTableName) + ->where( + $queryBuilder->expr()->eq('uid', (int)$id) + ) + ->setMaxResults(1) + ->execute() + ->fetch(); + $collectionRecord['table_name'] = $tableName; $collectionRecord['field_name'] = $fieldName; + return self::create($collectionRecord, $fillItems); } @@ -84,75 +97,73 @@ class CategoryCollection extends \TYPO3\CMS\Core\Category\Collection\CategoryCol */ protected function getCollectedRecords() { - $db = self::getDatabaseConnection(); - - $relatedRecords = array(); - // Assemble where clause - $where = 'AND ' . self::$storageTableName . '.uid = ' . (int)$this->getIdentifier(); - // Add condition on tablenames fields - $where .= ' AND sys_category_record_mm.tablenames = ' . $db->fullQuoteStr( - $this->getItemTableName(), - 'sys_category_record_mm' - ); - // Add condition on fieldname field - $where .= ' AND sys_category_record_mm.fieldname = ' . $db->fullQuoteStr( - $this->getRelationFieldName(), - 'sys_category_record_mm' - ); - // Add enable fields for item table + $relatedRecords = []; + + $queryBuilder = $this->getCollectedRecordsQueryBuilder(); + $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); $tsfe = self::getTypoScriptFrontendController(); - $where .= $tsfe->sys_page->enableFields($this->getItemTableName()); + // If language handling is defined for item table, add language condition if (isset($GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField'])) { // Consider default or "all" language - $languageField = $this->getItemTableName() . '.' . $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField']; - $languageCondition = $languageField . ' IN (0, -1)'; + $languageField = sprintf( + '%s.%s', + $this->getItemTableName(), + $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['languageField'] + ); + + $languageConstraint = $queryBuilder->expr()->in($languageField, [0, -1]); + // If not in default language, also consider items in current language with no original if ($tsfe->sys_language_content > 0) { - $languageCondition .= ' - OR (' . $languageField . ' = ' . (int)$tsfe->sys_language_content . ' - AND ' . $this->getItemTableName() . '.' . - $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['transOrigPointerField'] . ' = 0) - '; + $transOrigPointerField = sprintf( + '%s.%s', + $this->getItemTableName(), + $GLOBALS['TCA'][$this->getItemTableName()]['ctrl']['transOrigPointerField'] + ); + + $languageConstraint = $queryBuilder->expr()->orX( + $languageConstraint, + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq($languageField, (int)$tsfe->sys_language_content), + $queryBuilder->expr()->eq($transOrigPointerField, 0) + ) + ); } - $where .= ' AND (' . $languageCondition . ')'; + + $queryBuilder->andWhere($languageConstraint); } + // Get the related records from the database - $resource = $db->exec_SELECT_mm_query( - $this->getItemTableName() . '.*', - self::$storageTableName, - 'sys_category_record_mm', - $this->getItemTableName(), - $where - ); + $result = $queryBuilder->execute(); - if ($resource) { - while ($record = $db->sql_fetch_assoc($resource)) { - // Overlay the record for workspaces - $tsfe->sys_page->versionOL( - $this->getItemTableName(), - $record - ); - // Overlay the record for translations - if (is_array($record) && $tsfe->sys_language_contentOL) { - if ($this->getItemTableName() === 'pages') { - $record = $tsfe->sys_page->getPageOverlay($record); - } else { - $record = $tsfe->sys_page->getRecordOverlay( - $this->getItemTableName(), - $record, - $tsfe->sys_language_content, - $tsfe->sys_language_contentOL - ); - } - } - // Record may have been unset during the overlay process - if (is_array($record)) { - $relatedRecords[] = $record; + while ($record = $result->fetch()) { + // Overlay the record for workspaces + $tsfe->sys_page->versionOL( + $this->getItemTableName(), + $record + ); + + // Overlay the record for translations + if (is_array($record) && $tsfe->sys_language_contentOL) { + if ($this->getItemTableName() === 'pages') { + $record = $tsfe->sys_page->getPageOverlay($record); + } else { + $record = $tsfe->sys_page->getRecordOverlay( + $this->getItemTableName(), + $record, + $tsfe->sys_language_content, + $tsfe->sys_language_contentOL + ); } } - $db->sql_free_result($resource); + + // Record may have been unset during the overlay process + if (is_array($record)) { + $relatedRecords[] = $record; + } } + return $relatedRecords; }