Commit 8972957a authored by Christian Kuhn's avatar Christian Kuhn
Browse files

[BUGFIX] Properly mark QueryView as deprecated

The class logs a deprecation in __construct(),
but the @deprecated annotation is missing.

Unit and functional tests of QueryGenerator are
moved now and a PHP8 related patch that has been
done to core QueryGenerator is now merged into
lowlevel QueryGenerator, too.

Resolves: #94587
Related: #92129
Releases: master
Change-Id: Ibb59c6bf576c6589a1cbb654ebd4773065b3e8c2
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69962

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent d6fa37ea
......@@ -241,7 +241,7 @@ class QueryGenerator
*/
protected $settings = [];
public function __contruct()
public function __construct()
{
trigger_error(__CLASS__ . ' will be removed in TYPO3 v12.', E_USER_DEPRECATED);
}
......
......@@ -37,6 +37,8 @@ use TYPO3\CMS\Core\Utility\HttpUtility;
/**
* Class used in module tools/dbint (advanced search) and which may hold code specific for that module
* However the class has a general principle in it which may be used in the web/export module.
*
* @deprecated since v11, will be removed in v12
*/
class QueryView
{
......@@ -103,7 +105,7 @@ class QueryView
*/
public function __construct(array $settings = null, $menuItems = null, $moduleName = null)
{
trigger_error(__CLASS__ . ' will be removed in TYPO3 v11.', E_USER_DEPRECATED);
trigger_error(__CLASS__ . ' will be removed in TYPO3 v12.', E_USER_DEPRECATED);
$this->backendUserAuthentication = $GLOBALS['BE_USER'];
$this->languageService = $GLOBALS['LANG'];
$this->languageService->includeLLFile('EXT:core/Resources/Private/Language/locallang_t3lib_fullsearch.xlf');
......
......@@ -274,16 +274,6 @@ class QueryGenerator
*/
protected $enableQueryParts = false;
/**
* @var int
*/
protected $limitBegin;
/**
* @var int
*/
protected $limitLength;
/**
* @var string
*/
......@@ -1107,10 +1097,13 @@ class QueryGenerator
->from('pages')
->where(
$queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)),
$queryBuilder->expr()->eq('sys_language_uid', 0),
QueryHelper::stripLogicalOperatorPrefix($permsClause)
$queryBuilder->expr()->eq('sys_language_uid', 0)
)
->execute();
->orderBy('uid');
if ($permsClause !== '') {
$queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($permsClause));
}
$statement = $queryBuilder->execute();
while ($row = $statement->fetch()) {
if ($begin <= 0) {
$theList .= ',' . $row['uid'];
......@@ -1398,17 +1391,17 @@ class QueryGenerator
{
$fieldListArr = [];
if (is_array($GLOBALS['TCA'][$this->table])) {
$fieldListArr = array_keys($GLOBALS['TCA'][$this->table]['columns']);
$fieldListArr = array_keys($GLOBALS['TCA'][$this->table]['columns'] ?? []);
$fieldListArr[] = 'uid';
$fieldListArr[] = 'pid';
$fieldListArr[] = 'deleted';
if ($GLOBALS['TCA'][$this->table]['ctrl']['tstamp']) {
if ($GLOBALS['TCA'][$this->table]['ctrl']['tstamp'] ?? false) {
$fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['tstamp'];
}
if ($GLOBALS['TCA'][$this->table]['ctrl']['crdate']) {
if ($GLOBALS['TCA'][$this->table]['ctrl']['crdate'] ?? false) {
$fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['crdate'];
}
if ($GLOBALS['TCA'][$this->table]['ctrl']['cruser_id']) {
if ($GLOBALS['TCA'][$this->table]['ctrl']['cruser_id'] ?? false) {
$fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['cruser_id'];
}
if ($GLOBALS['TCA'][$this->table]['ctrl']['sortby'] ?? false) {
......@@ -2552,11 +2545,11 @@ class QueryGenerator
$this->extFieldLists['queryLimit'] = 100;
}
$parts = GeneralUtility::intExplode(',', $this->extFieldLists['queryLimit']);
if ($parts[1] ?? false) {
$this->limitBegin = $parts[0];
$this->limitLength = $parts[1];
} else {
$this->limitLength = $this->extFieldLists['queryLimit'];
$limitBegin = 0;
$limitLength = (int)($this->extFieldLists['queryLimit'] ?? 0);
if ($parts[1]) {
$limitBegin = (int)$parts[0];
$limitLength = (int)$parts[1];
}
$this->extFieldLists['queryLimit'] = implode(',', array_slice($parts, 0, 2));
// Insert Descending parts
......@@ -2623,23 +2616,23 @@ class QueryGenerator
$limit[] = ' <input type="text" class="form-control" value="' . htmlspecialchars($this->extFieldLists['queryLimit']) . '" name="SET[queryLimit]" id="queryLimit">';
$limit[] = '</div>';
$prevLimit = $this->limitBegin - $this->limitLength < 0 ? 0 : $this->limitBegin - $this->limitLength;
$prevLimit = $limitBegin - $limitLength < 0 ? 0 : $limitBegin - $limitLength;
$prevButton = '';
$nextButton = '';
if ($this->limitBegin) {
$prevButton = '<input type="button" class="btn btn-default" value="previous ' . htmlspecialchars($this->limitLength) . '" data-value="' . htmlspecialchars($prevLimit . ',' . $this->limitLength) . '">';
if ($limitBegin) {
$prevButton = '<input type="button" class="btn btn-default" value="previous ' . htmlspecialchars((string)$limitLength) . '" data-value="' . htmlspecialchars($prevLimit . ',' . $limitLength) . '">';
}
if (!$this->limitLength) {
$this->limitLength = 100;
if (!$limitLength) {
$limitLength = 100;
}
$nextLimit = $this->limitBegin + $this->limitLength;
$nextLimit = $limitBegin + $limitLength;
if ($nextLimit < 0) {
$nextLimit = 0;
}
if ($nextLimit) {
$nextButton = '<input type="button" class="btn btn-default" value="next ' . htmlspecialchars($this->limitLength) . '" data-value="' . htmlspecialchars($nextLimit . ',' . $this->limitLength) . '">';
$nextButton = '<input type="button" class="btn btn-default" value="next ' . htmlspecialchars((string)$limitLength) . '" data-value="' . htmlspecialchars($nextLimit . ',' . $limitLength) . '">';
}
$out[] = '<div class="form-group">';
......
......@@ -15,17 +15,14 @@ declare(strict_types=1);
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Tests\Functional\Database;
namespace TYPO3\CMS\Lowlevel\Tests\Functional\Database;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\QueryGenerator;
use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Lowlevel\Database\QueryGenerator;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Test case
*/
class QueryGeneratorTest extends FunctionalTestCase
{
protected function setUp(): void
......@@ -42,11 +39,9 @@ class QueryGeneratorTest extends FunctionalTestCase
{
$id = 1;
$depth = 0;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
self::assertSame($id, $treeList);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertEquals($id, $treeList);
}
/**
......@@ -56,11 +51,9 @@ class QueryGeneratorTest extends FunctionalTestCase
{
$id = 0;
$depth = 1;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
self::assertSame($id, $treeList);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertEquals($id, $treeList);
}
/**
......@@ -70,11 +63,9 @@ class QueryGeneratorTest extends FunctionalTestCase
{
$id = -1;
$depth = 0;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
self::assertSame(1, $treeList);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertEquals(1, $treeList);
}
/**
......@@ -85,10 +76,8 @@ class QueryGeneratorTest extends FunctionalTestCase
$id = 0;
$depth = 0;
$begin = 1;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth, $begin);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth, $begin);
self::assertSame('', $treeList);
}
......@@ -99,11 +88,9 @@ class QueryGeneratorTest extends FunctionalTestCase
{
$id = 1;
$depth = 1;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
self::assertSame($id, $treeList);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertEquals($id, $treeList);
}
/**
......@@ -111,31 +98,23 @@ class QueryGeneratorTest extends FunctionalTestCase
*/
public function getTreeListRespectsPermClauses(): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeStraightTreeSet.csv');
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeStraightTreeSet.csv');
$id = 1;
$depth = 99;
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth, 0, 'hidden = 0');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth, 0, 'hidden=0');
self::assertSame('1,2,3,4,5', $treeList);
}
/**
* @test
* @dataProvider dataForGetTreeListReturnsListOfIdsWithBeginSetToZero
* @param int $id
* @param int $depth
* @param mixed $expectation
*/
public function getTreeListReturnsListOfIdsWithBeginSetToZero(int $id, int $depth, $expectation): void
public function getTreeListReturnsListOfIdsWithBeginSetToZero(int $id, int $depth, string $expectation): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeStraightTreeSet.csv');
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeStraightTreeSet.csv');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertSame($expectation, $treeList);
}
......@@ -172,17 +151,12 @@ class QueryGeneratorTest extends FunctionalTestCase
/**
* @test
* @dataProvider dataForGetTreeListReturnsListOfIdsWithBeginSetToMinusOne
* @param int $id
* @param int $depth
* @param mixed $expectation
*/
public function getTreeListReturnsListOfIdsWithBeginSetToMinusOne(int $id, int $depth, $expectation): void
public function getTreeListReturnsListOfIdsWithBeginSetToMinusOne(int $id, int $depth, string $expectation): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeStraightTreeSet.csv');
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth, -1);
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeStraightTreeSet.csv');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth, -1);
self::assertSame($expectation, $treeList);
}
......@@ -223,12 +197,9 @@ class QueryGeneratorTest extends FunctionalTestCase
{
$id = 1;
$depth = 3;
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeBranchedTreeSet.csv');
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth);
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeBranchedTreeSet.csv');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth);
self::assertSame('1,2,3,4,5', $treeList);
}
......@@ -240,12 +211,9 @@ class QueryGeneratorTest extends FunctionalTestCase
$id = 1;
$depth = 3;
$begin = 1;
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeBranchedTreeSet.csv');
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth, $begin);
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeBranchedTreeSet.csv');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth, $begin);
self::assertSame('2,3,4,5', $treeList);
}
......@@ -257,12 +225,9 @@ class QueryGeneratorTest extends FunctionalTestCase
$id = 1;
$depth = 3;
$begin = 2;
$this->importCSVDataSet(__DIR__ . '/Fixtures/DataSet/TestGetPageTreeBranchedTreeSet.csv');
$queryGenerator = new QueryGenerator();
$treeList = $queryGenerator->getTreeList($id, $depth, $begin);
$this->importCSVDataSet(__DIR__ . '/Fixtures/TestGetPageTreeBranchedTreeSet.csv');
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$treeList = $subject->_call('getTreeList', $id, $depth, $begin);
self::assertSame('3,5', $treeList);
}
......@@ -325,8 +290,6 @@ class QueryGeneratorTest extends FunctionalTestCase
'columns' => [],
]
];
$queryGenerator = new QueryGenerator();
$inputConf = [
[
'operator' => '',
......@@ -336,9 +299,9 @@ class QueryGeneratorTest extends FunctionalTestCase
'inputValue1' => $inputValue1,
],
];
$queryGenerator->init('queryConfig', 'aTable');
self::assertSame($expected, trim($queryGenerator->getQuery($inputConf), "\n\r"));
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$subject->_call('init', 'queryConfig', 'aTable');
self::assertSame($expected, trim($subject->_call('getQuery', $inputConf), "\n\r"));
}
public function arbitraryDataIsEscapedDataProvider(): array
......@@ -351,7 +314,8 @@ class QueryGeneratorTest extends FunctionalTestCase
// ' ECT
'INJ %quoteCharacter%%commentStart% %commentEnd%%quoteCharacter% ECT'
];
$comparisons = array_keys((new QueryGenerator())->compSQL);
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$comparisons = array_keys($subject->_get('compSQL'));
foreach ($injectors as $injector) {
foreach ($comparisons as $comparison) {
$dataSet[] = [
......@@ -386,9 +350,6 @@ class QueryGeneratorTest extends FunctionalTestCase
}
/**
* @param string $injector
* @param array $settings
*
* @test
* @dataProvider arbitraryDataIsEscapedDataProvider
* @throws \Doctrine\DBAL\Exception
......@@ -405,13 +366,13 @@ class QueryGeneratorTest extends FunctionalTestCase
$injector = str_replace(array_keys($replacements), $replacements, $injector);
$settings = $this->prepareSettings($settings, $replacements);
$queryGenerator = new QueryGenerator();
$queryGenerator->init('queryConfig', $settings['queryTable']);
$queryGenerator->makeSelectorTable($settings);
$queryGenerator->enablePrefix = true;
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
$subject->_call('init', 'queryConfig', $settings['queryTable']);
$subject->_call('makeSelectorTable', $settings);
$subject->_set('enablePrefix', true);
$queryString = $queryGenerator->getQuery($queryGenerator->queryConfig);
$query = $queryGenerator->getSelectQuery($queryString);
$queryString = $subject->_call('getQuery', $subject->_get('queryConfig'));
$query = $subject->_call('getSelectQuery', $queryString);
self::assertStringNotContainsString($injector, $query);
}
......
......@@ -15,9 +15,9 @@ declare(strict_types=1);
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Tests\Unit\Database;
namespace TYPO3\CMS\Lowlevel\Tests\Unit\Database;
use TYPO3\CMS\Core\Database\QueryGenerator;
use TYPO3\CMS\Lowlevel\Database\QueryGenerator;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
......@@ -113,12 +113,10 @@ class QueryGeneratorTest extends UnitTestCase
/**
* @test
* @dataProvider getSubscriptReturnsExpectedValuesDataProvider
* @param $input
* @param array $expectedArray
*/
public function getSubscriptReturnsExpectedValues($input, array $expectedArray): void
{
$subject = new QueryGenerator();
self::assertSame($expectedArray, $subject->getSubscript($input));
$subject = $this->getAccessibleMock(QueryGenerator::class, ['dummy'], [], '', false);
self::assertSame($expectedArray, $subject->_call('getSubscript', $input));
}
}
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