Commit 198ff6e3 authored by Benni Mack's avatar Benni Mack

[TASK] Add compatibility with Doctrine DBAL 2.13.0

This change removes some type hints which are invalid with
Doctrine DBAL 2.13.0 / 3.0 (builds forward compatibility),
and some hard logic to bindValue() functionality
which is PDO-specific and not supported anymore, as a
Result object is returned instead of a Statement object
from DB queries.

Resolves: #93848
Releases: master, 10.4
Change-Id: Ibf69d5ba027e54471d2a98772674ef0139548b8c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68665Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 5044fe4d
......@@ -18,6 +18,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Backend\Domain\Repository\Localization;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\ForwardCompatibility\Result;
use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\Connection;
......@@ -180,9 +181,9 @@ class LocalizationRepository
* @param int $destLanguageId
* @param int $languageId
* @param string $fields
* @return Statement
* @return Statement|Result
*/
public function getRecordsToCopyDatabaseResult(int $pageId, int $destLanguageId, int $languageId, string $fields = '*'): Statement
public function getRecordsToCopyDatabaseResult(int $pageId, int $destLanguageId, int $languageId, string $fields = '*')
{
$originalUids = [];
......
......@@ -425,8 +425,8 @@ class BackendUtility
if (is_array($pageForRootlineCache[$ident] ?? false)) {
$row = $pageForRootlineCache[$ident];
} else {
$statement = $runtimeCache->get('getPageForRootlineStatement-' . $statementCacheIdent);
if (!$statement) {
$queryBuilder = $runtimeCache->get('getPageForRootlineStatement-' . $statementCacheIdent);
if (!$queryBuilder) {
$queryBuilder = static::getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()
->removeAll()
......@@ -459,17 +459,14 @@ class BackendUtility
)
->from('pages')
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT)),
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT, ':uid')),
QueryHelper::stripLogicalOperatorPrefix($clause)
);
$statement = $queryBuilder->execute();
$runtimeCache->set('getPageForRootlineStatement-' . $statementCacheIdent, $statement);
} else {
$statement->bindValue(1, (int)$uid);
$statement->execute();
$runtimeCache->set('getPageForRootlineStatement-' . $statementCacheIdent, $queryBuilder);
}
$queryBuilder->setParameter('uid', (int)$uid);
$statement = $queryBuilder->execute();
$row = $statement->fetch();
$statement->closeCursor();
if ($row) {
if ($workspaceOL) {
......
......@@ -17,7 +17,6 @@ declare(strict_types=1);
namespace TYPO3\CMS\Backend\View\BackendLayout;
use Doctrine\DBAL\Driver\Statement;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\PageLayoutContext;
use TYPO3\CMS\Backend\View\PageLayoutView;
......@@ -78,7 +77,6 @@ class ContentFetcher
if (empty($this->fetchedContentRecords)) {
$isLanguageMode = $this->context->getDrawingConfiguration()->getLanguageMode();
$queryBuilder = $this->getQueryBuilder();
/** @var Statement $result */
$result = $queryBuilder->execute();
$records = $this->getResult($result);
foreach ($records as $record) {
......@@ -260,7 +258,7 @@ class ContentFetcher
return $queryBuilder;
}
protected function getResult(Statement $result): array
protected function getResult($result): array
{
$output = [];
while ($row = $result->fetch()) {
......
......@@ -16,6 +16,7 @@
namespace TYPO3\CMS\Backend\View;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\ForwardCompatibility\Result;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
......@@ -1620,10 +1621,10 @@ class PageLayoutView implements LoggerAwareInterface
/**
* Traverse the result pointer given, adding each record to array and setting some internal values at the same time.
*
* @param Statement $result DBAL Statement
* @param Statement|Result $result DBAL Statement or Result
* @return array The selected rows returned in this array.
*/
public function getResult(Statement $result): array
public function getResult($result): array
{
$output = [];
// Traverse the result:
......
......@@ -37,6 +37,7 @@ use TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException;
use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
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\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface;
......@@ -2320,13 +2321,14 @@ class DataHandler implements LoggerAwareInterface
}
$newValue = $originalValue = $value;
$statement = $this->getUniqueCountStatement($newValue, $table, $field, (int)$id, (int)$newPid);
$queryBuilder = $this->getUniqueCountStatement($newValue, $table, $field, (int)$id, (int)$newPid);
// For as long as records with the test-value existing, try again (with incremented numbers appended)
$statement = $queryBuilder->execute();
if ($statement->fetchColumn()) {
for ($counter = 0; $counter <= 100; $counter++) {
$newValue = $value . $counter;
$statement->bindValue(1, $newValue);
$statement->execute();
$queryBuilder->setParameter('value', $newValue);
$statement = $queryBuilder->execute();
if (!$statement->fetchColumn()) {
break;
}
......@@ -2348,7 +2350,7 @@ class DataHandler implements LoggerAwareInterface
* @param string $field Field name for which $value must be unique
* @param int $uid UID to filter out in the lookup (the record itself...)
* @param int $pid If set, the value will be unique for this PID
* @return \Doctrine\DBAL\Driver\Statement Return the prepared statement to check uniqueness
* @return QueryBuilder Return the prepared statement to check uniqueness
*/
protected function getUniqueCountStatement(
string $value,
......@@ -2356,15 +2358,15 @@ class DataHandler implements LoggerAwareInterface
string $field,
int $uid,
int $pid
): Statement {
) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$this->addDeleteRestriction($queryBuilder->getRestrictions()->removeAll());
$queryBuilder
->count('uid')
->from($table)
->where(
$queryBuilder->expr()->eq($field, $queryBuilder->createPositionalParameter($value, \PDO::PARAM_STR)),
$queryBuilder->expr()->neq('uid', $queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT))
$queryBuilder->expr()->eq($field, $queryBuilder->createNamedParameter($value, \PDO::PARAM_STR, ':value')),
$queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
);
// ignore translations of current record if field is configured with l10n_mode = "exclude"
if (($GLOBALS['TCA'][$table]['columns'][$field]['l10n_mode'] ?? '') === 'exclude'
......@@ -2376,27 +2378,27 @@ class DataHandler implements LoggerAwareInterface
// records without l10n_parent must be taken into account (in any language)
$queryBuilder->expr()->eq(
$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
$queryBuilder->createPositionalParameter(0, \PDO::PARAM_INT)
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
),
// translations of other records must be taken into account
$queryBuilder->expr()->neq(
$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
$queryBuilder->createPositionalParameter($uid, \PDO::PARAM_INT)
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
)
)
);
}
if ($pid !== 0) {
$queryBuilder->andWhere(
$queryBuilder->expr()->eq('pid', $queryBuilder->createPositionalParameter($pid, \PDO::PARAM_INT))
$queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
);
} else {
// pid>=0 for versioning
$queryBuilder->andWhere(
$queryBuilder->expr()->gte('pid', $queryBuilder->createPositionalParameter(0, \PDO::PARAM_INT))
$queryBuilder->expr()->gte('pid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
);
}
return $queryBuilder->execute();
return $queryBuilder;
}
/**
......
......@@ -22,6 +22,7 @@ use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\ForwardCompatibility\Result;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform as PostgreSqlPlatform;
use Doctrine\DBAL\Platforms\SQLServer2012Platform;
use Doctrine\DBAL\VersionAwarePlatformDriver;
......@@ -242,7 +243,7 @@ class Connection extends \Doctrine\DBAL\Connection implements LoggerAwareInterfa
* @param int $limit The maximum number of rows to return.
* @param int $offset The first result row to select (when used with limit)
*
* @return Statement The executed statement.
* @return Statement|Result The executed statement.
*/
public function select(
array $columns,
......@@ -252,7 +253,7 @@ class Connection extends \Doctrine\DBAL\Connection implements LoggerAwareInterfa
array $orderBy = [],
int $limit = 0,
int $offset = 0
): Statement {
) {
$query = $this->createQueryBuilder();
$query->select(...$columns)
->from($tableName);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment