From c650698ac529a8c70c9664d6f0fcfd75288ad469 Mon Sep 17 00:00:00 2001 From: Umherirrender Date: Wed, 23 Mar 2022 23:41:16 +0100 Subject: [PATCH] Call IDatabase::timestamp before inserting echo_unread_wikis The default timestamp of 00000000000000 cannot represent as timestamp, because it gets a negative timestamp -00011130000000 This is needed for proper cross-RDBMS support This reapply a change from I46206e0b3a687dff3168a81cf0020e669133e876, reverted with I1c8c409b7820512b3e31246a7f3d8c1cf4db209c. Bug: T244898 Change-Id: I109b783de0a8d60ccb161b280ce5fa09e145017b --- includes/EchoHooks.php | 5 +++ includes/UnreadWikis.php | 23 ++++++---- tests/phpunit/UnreadWikisTest.php | 70 +++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 tests/phpunit/UnreadWikisTest.php diff --git a/includes/EchoHooks.php b/includes/EchoHooks.php index a06fdb44d..101afebf9 100644 --- a/includes/EchoHooks.php +++ b/includes/EchoHooks.php @@ -211,6 +211,11 @@ class EchoHooks implements RecentChange_saveHook { $updater->modifyExtensionField( 'echo_unread_wikis', 'euw_wiki', "$dir/db_patches/patch-increase-varchar-echo_unread_wikis-euw_wiki.sql" ); + + global $wgWikimediaJenkinsCI; + if ( !empty( $wgWikimediaJenkinsCI ) ) { + $updater->addExtensionTable( 'echo_unread_wikis', "$dir/db_patches/echo_unread_wikis.sql" ); + } } /** diff --git a/includes/UnreadWikis.php b/includes/UnreadWikis.php index dbe6ec395..3ffc8b153 100644 --- a/includes/UnreadWikis.php +++ b/includes/UnreadWikis.php @@ -9,6 +9,7 @@ use MediaWiki\User\UserIdentity; class EchoUnreadWikis { private const DEFAULT_TS = '00000000000000'; + private const DEFAULT_TS_DB = '00010101010101'; /** * @var int @@ -82,11 +83,13 @@ class EchoUnreadWikis { $wikis[$row->euw_wiki] = [ EchoAttributeManager::ALERT => [ 'count' => $row->euw_alerts, - 'ts' => $row->euw_alerts_ts, + 'ts' => $row->euw_alerts_ts === static::DEFAULT_TS_DB ? + static::DEFAULT_TS : wfTimestamp( TS_MW, $row->euw_alerts_ts ), ], EchoAttributeManager::MESSAGE => [ 'count' => $row->euw_messages, - 'ts' => $row->euw_messages_ts, + 'ts' => $row->euw_messages_ts === static::DEFAULT_TS_DB ? + static::DEFAULT_TS : wfTimestamp( TS_MW, $row->euw_messages_ts ), ], ]; } @@ -117,13 +120,17 @@ class EchoUnreadWikis { if ( $alertCount || $msgCount ) { $values = [ 'euw_alerts' => $alertCount, - 'euw_alerts_ts' => $alertTime - ? $alertTime->getTimestamp( TS_MW ) - : static::DEFAULT_TS, + 'euw_alerts_ts' => $dbw->timestamp( + $alertTime + ? $alertTime->getTimestamp( TS_MW ) + : static::DEFAULT_TS_DB + ), 'euw_messages' => $msgCount, - 'euw_messages_ts' => $msgTime - ? $msgTime->getTimestamp( TS_MW ) - : static::DEFAULT_TS, + 'euw_messages_ts' => $dbw->timestamp( + $msgTime + ? $msgTime->getTimestamp( TS_MW ) + : static::DEFAULT_TS_DB + ), ]; // when there is unread alert(s) and/or message(s), upsert the row diff --git a/tests/phpunit/UnreadWikisTest.php b/tests/phpunit/UnreadWikisTest.php new file mode 100644 index 000000000..d6546c92d --- /dev/null +++ b/tests/phpunit/UnreadWikisTest.php @@ -0,0 +1,70 @@ +dbFactory = $this->mockMWEchoDbFactory( $this->db ); + $unread->updateCount( + 'foobar', + 2, + new MWTimestamp( '20220322222222' ), + 3, + new MWTimestamp( '20220322222223' ) + ); + $this->assertSame( + [ + 'foobar' => [ + 'alert' => [ 'count' => '2', 'ts' => '20220322222222' ], + 'message' => [ 'count' => '3', 'ts' => '20220322222223' ], + ] + ], + $unread->getUnreadCounts() + ); + } + + public function testUpdateCountFalse() { + $unread = TestingAccessWrapper::newFromObject( new EchoUnreadWikis( 1 ) ); + $unread->dbFactory = $this->mockMWEchoDbFactory( $this->db ); + $unread->updateCount( + 'foobar', + 3, + false, + 4, + false + ); + $this->assertSame( + [ + 'foobar' => [ + 'alert' => [ 'count' => '3', 'ts' => '00000000000000' ], + 'message' => [ 'count' => '4', 'ts' => '00000000000000' ], + ] + ], + $unread->getUnreadCounts() + ); + } + + /** + * Mock object of MWEchoDbFactory + * @param \Wikimedia\Rdbms\IDatabase $db + * @return MWEchoDbFactory + */ + protected function mockMWEchoDbFactory( $db ) { + $dbFactory = $this->getMockBuilder( MWEchoDbFactory::class ) + ->disableOriginalConstructor() + ->getMock(); + $dbFactory->expects( $this->any() ) + ->method( 'getSharedDb' ) + ->will( $this->returnValue( $db ) ); + + return $dbFactory; + } +}