Merge pull request #20177 from MauricioFauth/tracker-clock

Replace Util::date() with ClockInterface
This commit is contained in:
Maurício Meneghini Fauth 2026-02-25 20:43:45 -03:00 committed by GitHub
commit da6b98fab3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 52 additions and 85 deletions

View File

@ -3610,7 +3610,7 @@ parameters:
path: src/Controllers/Table/StructureController.php
-
message: '#^Parameter \#2 \$entries of method PhpMyAdmin\\Tracking\\Tracking\:\:getDownloadInfoForExport\(\) expects array\<int, array\<string, int\|string\>\>, array\<mixed\> given\.$#'
message: '#^Parameter \#3 \$entries of method PhpMyAdmin\\Tracking\\Tracking\:\:getDownloadInfoForExport\(\) expects array\<int, array\<string, int\|string\>\>, array\<mixed\> given\.$#'
identifier: argument.type
count: 1
path: src/Controllers/Table/TrackingController.php
@ -16647,7 +16647,7 @@ parameters:
Use dependency injection instead\.$#
'''
identifier: staticMethod.deprecated
count: 4
count: 3
path: tests/unit/Tracking/TrackerTest.php
-
@ -16671,7 +16671,7 @@ parameters:
Use dependency injection instead\.$#
'''
identifier: staticMethod.deprecated
count: 3
count: 2
path: tests/unit/Tracking/TrackingTest.php
-

View File

@ -10642,7 +10642,6 @@
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[Config::getInstance()]]></code>
</DeprecatedMethod>
<InvalidPropertyAssignmentValue>
<code><![CDATA[$config->selectedServer]]></code>
@ -10663,7 +10662,6 @@
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
</DeprecatedMethod>
<MixedArrayAccess>
<code><![CDATA[$entries[0]['statement']]]></code>

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Controllers\Table;
use DateTimeImmutable;
use PhpMyAdmin\Clock\Clock;
use PhpMyAdmin\Controllers\InvocableController;
use PhpMyAdmin\Core;
use PhpMyAdmin\Current;
@ -130,7 +131,7 @@ final class TrackingController implements InvocableController
// Export as file download
if ($reportExportType === 'sqldumpfile') {
$downloadInfo = $this->tracking->getDownloadInfoForExport($tableParam, $entries);
$downloadInfo = $this->tracking->getDownloadInfoForExport(new Clock(), $tableParam, $entries);
$response = $this->responseFactory->createResponse();
Core::downloadHeader($downloadInfo['filename'], 'text/x-sql', mb_strlen($downloadInfo['dump']));

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tracking;
use PhpMyAdmin\Clock\Clock;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Features\TrackingFeature;
use PhpMyAdmin\ConfigStorage\Relation;
@ -25,6 +26,7 @@ use PhpMyAdmin\SqlParser\Statements\RenameStatement;
use PhpMyAdmin\SqlParser\Statements\TruncateStatement;
use PhpMyAdmin\SqlParser\Statements\UpdateStatement;
use PhpMyAdmin\Util;
use Psr\Clock\ClockInterface;
use function in_array;
use function preg_quote;
@ -134,9 +136,9 @@ class Tracker
*
* @return string Comment, contains date and username
*/
public static function getLogComment(): string
public static function getLogComment(ClockInterface $clock): string
{
$date = Util::date('Y-m-d H:i:s');
$date = $clock->now()->format('Y-m-d H:i:s');
$user = preg_replace('/\s+/', ' ', Config::getInstance()->selectedServer['user']);
return '# log ' . $date . ' ' . $user . "\n";
@ -174,7 +176,8 @@ class Tracker
$exportSqlPlugin->useSqlBackquotes(true);
$date = Util::date('Y-m-d H:i:s');
$clock = new Clock();
$date = $clock->now()->format('Y-m-d H:i:s');
// Get data definition snapshot of table
@ -199,18 +202,17 @@ class Tracker
// Get DROP TABLE / DROP VIEW and CREATE TABLE SQL statements
$createSql = '';
if ($config->selectedServer['tracking_add_drop_table'] && ! $isView) {
$createSql .= self::getLogComment()
$createSql .= self::getLogComment($clock)
. 'DROP TABLE IF EXISTS ' . Util::backquote($tableName) . ";\n";
}
if ($config->selectedServer['tracking_add_drop_view'] && $isView) {
$createSql .= self::getLogComment()
$createSql .= self::getLogComment($clock)
. 'DROP VIEW IF EXISTS ' . Util::backquote($tableName) . ";\n";
}
$createSql .= self::getLogComment() . $exportSqlPlugin->getTableDef($dbName, $tableName);
$createSql .= self::getLogComment($clock) . $exportSqlPlugin->getTableDef($dbName, $tableName);
// Save version
$trackingFeature = $relation->getRelationParameters()->trackingFeature;
@ -259,7 +261,8 @@ class Tracker
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$date = Util::date('Y-m-d H:i:s');
$clock = new Clock();
$date = $clock->now()->format('Y-m-d H:i:s');
$config = Config::getInstance();
if ($trackingSet === '') {
@ -267,12 +270,11 @@ class Tracker
}
$createSql = '';
if ($config->selectedServer['tracking_add_drop_database']) {
$createSql .= self::getLogComment() . 'DROP DATABASE IF EXISTS ' . Util::backquote($dbName) . ";\n";
$createSql .= self::getLogComment($clock) . 'DROP DATABASE IF EXISTS ' . Util::backquote($dbName) . ";\n";
}
$createSql .= self::getLogComment() . $query;
$createSql .= self::getLogComment($clock) . $query;
$trackingFeature = $relation->getRelationParameters()->trackingFeature;
if ($trackingFeature === null) {
@ -619,7 +621,8 @@ class Tracker
default => '',
};
$date = Util::date('Y-m-d H:i:s');
$clock = new Clock();
$date = $clock->now()->format('Y-m-d H:i:s');
// Cut off `dbname`. from query
$query = preg_replace(
@ -629,7 +632,7 @@ class Tracker
);
// Add log information
$query = self::getLogComment() . $query;
$query = self::getLogComment($clock) . $query;
$relation = new Relation($dbi);
$trackingFeature = $relation->getRelationParameters()->trackingFeature;

View File

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tracking;
use DateTimeImmutable;
use PhpMyAdmin\Clock\Clock;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Core;
@ -20,12 +21,12 @@ use PhpMyAdmin\SqlQueryForm;
use PhpMyAdmin\Template;
use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
use Psr\Clock\ClockInterface;
use Webmozart\Assert\Assert;
use function __;
use function array_merge;
use function array_multisort;
use function date;
use function explode;
use function htmlspecialchars;
use function in_array;
@ -616,7 +617,8 @@ class Tracking
$logSchemaEntries = explode('# log ', (string) $mixed['schema_sql']);
$logDataEntries = explode('# log ', (string) $mixed['data_sql']);
$ddlDateFrom = $date = Util::date('Y-m-d H:i:s');
$clock = new Clock();
$ddlDateFrom = $date = $clock->now()->format('Y-m-d H:i:s');
$ddlog = [];
$firstIteration = true;
@ -829,14 +831,14 @@ class Tracking
* @return array<string, string>
* @psalm-return array{filename: non-empty-string, dump: non-empty-string}
*/
public function getDownloadInfoForExport(string $table, array $entries): array
public function getDownloadInfoForExport(ClockInterface $clock, string $table, array $entries): array
{
ini_set('url_rewriter.tags', '');
// Replace all multiple whitespaces by a single space
$table = htmlspecialchars((string) preg_replace('/\s+/', ' ', $table));
$dump = '# ' . sprintf(__('Tracking report for table `%s`'), $table) . "\n"
. '# ' . date('Y-m-d H:i:sP') . "\n";
. '# ' . $clock->now()->format('Y-m-d H:i:sP') . "\n";
foreach ($entries as $entry) {
$dump .= $entry['statement'];
}

View File

@ -26,7 +26,6 @@ use function bin2hex;
use function chr;
use function count;
use function ctype_digit;
use function date;
use function decbin;
use function explode;
use function extension_loaded;
@ -1558,16 +1557,6 @@ class Util
return $asHex ? bin2hex($result) : $result;
}
/**
* Wrapper around PHP date function
*
* @param string $format Date format string
*/
public static function date(string $format): string
{
return date($format);
}
/**
* Wrapper around php's set_time_limit
*

View File

@ -12,9 +12,9 @@ use PhpMyAdmin\Current;
use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Clock\MockClock;
use PhpMyAdmin\Tests\Stubs\DummyResult;
use PhpMyAdmin\Tracking\Tracker;
use PhpMyAdmin\Util;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use ReflectionMethod;
@ -136,12 +136,12 @@ class TrackerTest extends AbstractTestCase
*/
public function testGetLogComment(): void
{
$date = Util::date('Y-m-d H:i:s');
Config::getInstance()->selectedServer['user'] = 'pma_test_user';
$config = Config::$instance = new Config();
$config->selectedServer['user'] = 'pma_test_user';
self::assertSame(
'# log ' . $date . " pma_test_user\n",
Tracker::getLogComment(),
"# log 2015-10-21 05:28:00 pma_test_user\n",
Tracker::getLogComment(MockClock::from('2015-10-21T05:28:00-02:00')),
);
}

View File

@ -14,6 +14,7 @@ use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\SqlQueryForm;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Clock\MockClock;
use PhpMyAdmin\Tests\Stubs\DummyResult;
use PhpMyAdmin\Tracking\LogType;
use PhpMyAdmin\Tracking\TrackedData;
@ -21,14 +22,12 @@ use PhpMyAdmin\Tracking\TrackedDataType;
use PhpMyAdmin\Tracking\Tracking;
use PhpMyAdmin\Tracking\TrackingChecker;
use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use ReflectionProperty;
use function __;
use function _pgettext;
use function date;
use function htmlspecialchars;
use function ini_get;
use function ini_restore;
@ -558,9 +557,10 @@ final class TrackingTest extends AbstractTestCase
ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,form=,fieldset=');
$entries = [['statement' => 'first statement'], ['statement' => 'second statement']];
$expectedDump = '# Tracking report for table `test&gt; table`' . "\n"
. '# ' . date('Y-m-d H:i:sP') . "\n"
. '# 2015-10-21 05:28:00-02:00' . "\n"
. 'first statementsecond statement';
$actual = $tracking->getDownloadInfoForExport('test> table', $entries);
$clock = MockClock::from('2015-10-21T05:28:00-02:00');
$actual = $tracking->getDownloadInfoForExport($clock, 'test> table', $entries);
self::assertSame('log_test&gt; table.sql', $actual['filename']);
self::assertSame($expectedDump, $actual['dump']);
self::assertSame('', ini_get('url_rewriter.tags'));
@ -600,61 +600,35 @@ final class TrackingTest extends AbstractTestCase
self::assertTrue($tracking->deleteTracking('testdb', 'testtable'));
}
/**
* Test for changeTrackingData()
*/
public function testChangeTrackingData(): void
{
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
->getMock();
$sqlQuery1 = 'UPDATE `pmadb`.`tracking`' .
" SET `schema_sql` = '# new_data_processed'" .
" WHERE `db_name` = 'pma_db'" .
" AND `table_name` = 'pma_table'" .
" AND `version` = '1.0'";
$date = Util::date('Y-m-d H:i:s');
$newData = [
['date' => $date, 'username' => 'user1', 'statement' => 'test_statement1'],
['date' => $date, 'username' => 'user2', 'statement' => 'test_statement2'],
['date' => '2026-02-25 19:29:34', 'username' => 'user1', 'statement' => 'test_statement1'],
['date' => '2026-02-25 19:29:34', 'username' => 'user2', 'statement' => 'test_statement2'],
];
$sqlQuery2 = 'UPDATE `pmadb`.`tracking`' .
" SET `data_sql` = '# log " . $date . " user1test_statement1\n" .
'# log ' . $date . " user2test_statement2\n'" .
" WHERE `db_name` = 'pma_db'" .
" AND `table_name` = 'pma_table'" .
" AND `version` = '1.0'";
$resultStub1 = self::createMock(DummyResult::class);
$resultStub2 = self::createMock(DummyResult::class);
$dbi->method('queryAsControlUser')
->willReturnMap([[$sqlQuery1, $resultStub1], [$sqlQuery2, $resultStub2]]);
$dbi->expects(self::any())->method('quoteString')
->willReturnCallback(static fn (string $string): string => "'" . $string . "'");
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addResult(
'UPDATE `pmadb`.`tracking`' .
" SET `data_sql` = '# log 2026-02-25 19:29:34 user1test_statement1 " .
"# log 2026-02-25 19:29:34 user2test_statement2 '" .
" WHERE `db_name` = 'pma_db'" .
" AND `table_name` = 'pma_table'" .
" AND `version` = '1.0'",
true,
);
$dbi = $this->createDatabaseInterface($dbiDummy);
$tracking = new Tracking(
self::createStub(SqlQueryForm::class),
self::createStub(Template::class),
new Relation(DatabaseInterface::getInstance()),
new Relation($dbi, new Config()),
$dbi,
self::createStub(TrackingChecker::class),
);
self::assertTrue(
$tracking->changeTrackingData(
'pma_db',
'pma_table',
'1.0',
TrackedDataType::DML,
$newData,
),
);
self::assertTrue($tracking->changeTrackingData('pma_db', 'pma_table', '1.0', TrackedDataType::DML, $newData));
$dbiDummy->assertAllQueriesConsumed();
}
/**