diff --git a/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php b/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php index 3621a9d2a93179caa4656cd216d2f703e4e3cda2..6d6311a8de35d011baa646eb6ffd2e92995e8a66 100644 --- a/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php +++ b/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php @@ -18,7 +18,8 @@ use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryHelper; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -832,9 +833,16 @@ abstract class AbstractTreeView $res = $this->getDataInit($uid); return $this->getDataCount($res); } else { - $db = $this->getDatabaseConnection(); - $where = $this->parentField . '=' . $db->fullQuoteStr($uid, $this->table) . BackendUtility::deleteClause($this->table) . BackendUtility::versioningPlaceholderClause($this->table) . $this->clause; - return $db->exec_SELECTcountRows('uid', $this->table, $where); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); + $count = $queryBuilder + ->count('uid') + ->from($this->table) + ->where($queryBuilder->expr()->eq($this->parentField, $queryBuilder->createNamedParameter($uid))) + ->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->clause)) + ->execute() + ->fetchColumn(); + + return (int)$count; } } @@ -885,9 +893,19 @@ abstract class AbstractTreeView } return $parentId; } else { - $db = $this->getDatabaseConnection(); - $where = $this->parentField . '=' . $db->fullQuoteStr($parentId, $this->table) . BackendUtility::deleteClause($this->table) . BackendUtility::versioningPlaceholderClause($this->table) . $this->clause; - return $db->exec_SELECTquery(implode(',', $this->fieldArray), $this->table, $where, '', $this->orderByFields); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); + $queryBuilder + ->select(...$this->fieldArray) + ->from($this->table) + ->where($queryBuilder->expr()->eq($this->parentField, $queryBuilder->createNamedParameter($parentId))) + ->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->clause)); + + foreach (QueryHelper::parseOrderBy($this->orderByFields) as $orderPair) { + list($fieldName, $order) = $orderPair; + $queryBuilder->addOrderBy($fieldName, $order); + } + + return $queryBuilder->execute(); } } @@ -904,7 +922,7 @@ abstract class AbstractTreeView if (is_array($this->data)) { return count($this->dataLookup[$res][$this->subLevelID]); } else { - return $this->getDatabaseConnection()->sql_num_rows($res); + return count($res); } } @@ -927,7 +945,7 @@ abstract class AbstractTreeView } return $row; } else { - while ($row = @$this->getDatabaseConnection()->sql_fetch_assoc($res)) { + while ($row = $res->fetch()) { BackendUtility::workspaceOL($this->table, $row, $this->BE_USER->workspace, true); if (is_array($row)) { break; @@ -947,7 +965,7 @@ abstract class AbstractTreeView public function getDataFree(&$res) { if (!is_array($this->data)) { - $this->getDatabaseConnection()->sql_free_result($res); + $res->closeCursor(); } } @@ -1010,12 +1028,4 @@ abstract class AbstractTreeView { return $GLOBALS['BE_USER']; } - - /** - * @return DatabaseConnection - */ - protected function getDatabaseConnection() - { - return $GLOBALS['TYPO3_DB']; - } } diff --git a/typo3/sysext/backend/Classes/Tree/View/BrowseTreeView.php b/typo3/sysext/backend/Classes/Tree/View/BrowseTreeView.php index f0d47ba499e0d1719b3450a7f241c9b1f8e63518..e93ede27de53426b09a344b6b144546f83d00bd2 100644 --- a/typo3/sysext/backend/Classes/Tree/View/BrowseTreeView.php +++ b/typo3/sysext/backend/Classes/Tree/View/BrowseTreeView.php @@ -15,6 +15,7 @@ namespace TYPO3\CMS\Backend\Tree\View; */ use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -83,7 +84,7 @@ class BrowseTreeView extends AbstractTreeView // This will hide records from display - it has nothing to do with user rights!! $clauseExcludePidList = ''; if ($pidList = $this->getBackendUser()->getTSConfigVal('options.hideRecords.pages')) { - if ($pidList = $this->getDatabaseConnection()->cleanIntList($pidList)) { + if ($pidList = implode(',', GeneralUtility::intExplode(',', $pidList))) { $clauseExcludePidList = ' AND pages.uid NOT IN (' . $pidList . ')'; } } @@ -148,18 +149,18 @@ class BrowseTreeView extends AbstractTreeView $title = parent::getTitleStr($row, $titleLen); } if (!empty($row['is_siteroot']) && $this->getBackendUser()->getTSConfigVal('options.pageTree.showDomainNameWithTitle')) { - $rows = $this->getDatabaseConnection()->exec_SELECTgetRows( - 'domainName,sorting', - 'sys_domain', - 'pid=' . $this->getDatabaseConnection()->quoteStr( - $row['uid'] . BackendUtility::deleteClause('sys_domain') . BackendUtility::BEenableFields('sys_domain'), - 'sys_domain' - ), - '', - 'sorting', - 1); - if (is_array($rows) && !empty($rows)) { - $title = sprintf('%s [%s]', $title, htmlspecialchars($rows[0]['domainName'])); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_domain'); + $row = $queryBuilder + ->select('domainName', 'sorting') + ->from('sys_domain') + ->where($queryBuilder->expr()->eq('pid', (int)$row['uid'])) + ->orderBy('sorting') + ->setMaxResults(1) + ->execute() + ->fetch(); + + if ($row !== false) { + $title = sprintf('%s [%s]', $title, htmlspecialchars($row['domainName'])); } } return $title; diff --git a/typo3/sysext/backend/Classes/Tree/View/PagePositionMap.php b/typo3/sysext/backend/Classes/Tree/View/PagePositionMap.php index aca5bf1bfdef149a2bfb9c540210b5e1620d36ed..80d652419df03166f786bfc0370be9e5d407a4e9 100644 --- a/typo3/sysext/backend/Classes/Tree/View/PagePositionMap.php +++ b/typo3/sysext/backend/Classes/Tree/View/PagePositionMap.php @@ -16,7 +16,8 @@ namespace TYPO3\CMS\Backend\Tree\View; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Database\DatabaseConnection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryContextType; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; @@ -339,17 +340,33 @@ class PagePositionMap $colPosArray = GeneralUtility::trimExplode(',', $colPosList, true); $lines = array(); foreach ($colPosArray as $kk => $vv) { - $res = $this->getDatabase()->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$pid . ($showHidden ? '' : BackendUtility::BEenableFields('tt_content')) . ' AND colPos=' . (int)$vv . ((string)$this->cur_sys_language !== '' ? ' AND sys_language_uid=' . (int)$this->cur_sys_language : '') . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting'); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content'); + $queryBuilder->getQueryContext() + ->setContext(QueryContextType::BACKEND_NO_VERSIONING_PLACEHOLDERS) + ->setIgnoreEnableFields($showHidden); + + $queryBuilder + ->select('*') + ->from('tt_content') + ->where($queryBuilder->expr()->eq('pid', (int)$pid)) + ->andWhere($queryBuilder->expr()->eq('colPos', (int)$vv)) + ->orderBy('sorting'); + + if ((string)$this->cur_sys_language !== '') { + $queryBuilder->andWhere($queryBuilder->expr()->eq('sys_language_uid', (int)$this->cur_sys_language)); + } + + $res = $queryBuilder->execute(); $lines[$vv] = array(); $lines[$vv][] = $this->insertPositionIcon('', $vv, $kk, $moveUid, $pid); - while ($row = $this->getDatabase()->sql_fetch_assoc($res)) { + + while ($row = $res->fetch()) { BackendUtility::workspaceOL('tt_content', $row); if (is_array($row)) { $lines[$vv][] = $this->wrapRecordHeader($this->getRecordHeader($row), $row); $lines[$vv][] = $this->insertPositionIcon($row, $vv, $kk, $moveUid, $pid); } } - $this->getDatabase()->sql_free_result($res); } return $this->printRecordMap($lines, $colPosArray, $pid); } @@ -579,12 +596,4 @@ class PagePositionMap { return $GLOBALS['LANG']; } - - /** - * @return DatabaseConnection - */ - protected function getDatabase() - { - return $GLOBALS['TYPO3_DB']; - } } diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-75645-DoctrineMigrateExtbackendTree.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-75645-DoctrineMigrateExtbackendTree.rst new file mode 100644 index 0000000000000000000000000000000000000000..3b0e8b92da9921d4fa284f3db9f5b1b2e0753a68 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-75645-DoctrineMigrateExtbackendTree.rst @@ -0,0 +1,29 @@ +===================================================== +Breaking: #75645 - Doctrine: migrate ext:backend/Tree +===================================================== + +Description +=========== + +This patch changes all database related functions to use the new Doctrine database API. +The method :php:``getDatabaseConnection()`` has been removed. + +Impact +====== + +Calls to the method :php:``AbstractTreeView::getDataInit()`` will now return :php:``Statement`` objects. +All other :php:``AbstractTreeView::getData*`` methods now expects such as ::php:``Statement`` object +instead of a SQL resource. + + +Affected Installations +====================== + +All installations using TreeViews extending the AbstractTreeView. + + +Migration +========= + +Migrate all calls that work with the result :php:``Statement`` from TreeView to be able to +handle :php:``Statement`` objects.