From 335193c1c66bd08a03a63f201603a782344c05e9 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 22 Aug 2024 18:43:44 +0200 Subject: [PATCH 1/8] Add a script to check if a wiki is OK for enabling ReplaceText --- maintenance/replaceTextEligible.php | 148 ++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 maintenance/replaceTextEligible.php diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php new file mode 100644 index 000000000..d20348f14 --- /dev/null +++ b/maintenance/replaceTextEligible.php @@ -0,0 +1,148 @@ +addDescription( 'Checks if the current wiki is eligible for enabling ReplaceText\n See https://meta.miraheze.org/wiki/Tech:Noticeboard?oldid=414759#The_state_of_the_ReplaceText_extension' ); + } + + public function execute() { + $dbr = $this->getDB( DB_REPLICA ); + + $pages = $dbr->newSelectQueryBuilder() + ->select( [ 'page_id', 'page_latest', 'page_name' ] ) + ->from( 'page' ) + ->caller( __METHOD__ )->fetchResultSet(); + $deletedPageIDs = $dbr->newSelectQueryBuilder() + ->select( [ 'ar_page_id' ] ) + ->from( 'archive' ) + ->distinct() + ->caller( __METHOD__ )->fetchResultSet(); + $this->output( snprintf( 'Got %d pages from the page table and %d deleted pages from the archive table to process, hang tight...', $pages->numRows(), $deletedPageIDs->numRows() ) ); + + // Arrays to hold the names of pages preventing ReplaceText from working correctly + $problematicPages = []; + $problematicDeletedPages = []; + + // Regular pages + $this->output( 'Processing regular pages' ); + foreach ( $pages as $page ) { + // TODO: Use JOINs? + $slotContentID = $dbr->newSelectQueryBuilder() + ->select( [ 'slot_content_id' ] ) + ->from( 'slots' ) + ->where( [ 'slot_revision_id' => $page->page_latest ] ) + ->caller( __METHOD__ )->fetchRow(); + $contentAddress = $dbr->newSelectQueryBuilder() + ->select( [ 'content_address' ] ) + ->from( 'content' ) + ->where( [ 'content_id' => $slotContentID ] ) + ->caller( __METHOD__ )->fetchRow(); + $oldID = substr( $contentAddress, 3 ); + $textFlags = $dbr->newSelectQueryBuilder() + ->select( [ 'old_flags' ] ) + ->from( 'text' ) + ->where( [ 'old_id' => $oldID ] ) + ->caller( __METHOD__ )->fetchRow(); + + if ( str_contains( $textFlags, 'gzip' ) ) { + // The latest revision of this page is compressed + $problematicPages[] = $page->page_name; + } + } + + // Deleted pages + // These can be undeleted on-wiki, and if so, they may also cause issues with ReplaceText + $this->output( 'Processing deleted pages' ); + foreach ( $deletedPageIDs as $deletedPageID ) { + // TODO: Use JOINs? + // Get the latest revision + $revID = $dbr->newSelectQueryBuilder() + ->select( [ 'ar_rev_id' ] ) + ->from( 'archive' ) + ->where( [ 'ar_page_id' => $deletedPageID->ar_page_id ] ) + ->orderBy( 'ar_rev_id', SelectQueryBuilder::SORT_DESC ) + ->limit( 1 ) + ->caller( __METHOD__ )->fetchRow(); + $slotContentID = $dbr->newSelectQueryBuilder() + ->select( [ 'slot_content_id' ] ) + ->from( 'slots' ) + ->where( [ 'slot_revision_id' => $revID ] ) + ->caller( __METHOD__ )->fetchRow(); + $contentAddress = $dbr->newSelectQueryBuilder() + ->select( [ 'content_address' ] ) + ->from( 'content' ) + ->where( [ 'content_id' => $slotContentID ] ) + ->caller( __METHOD__ )->fetchRow(); + $oldID = substr( $contentAddress, 3 ); + $textFlags = $dbr->newSelectQueryBuilder() + ->select( [ 'old_flags' ] ) + ->from( 'text' ) + ->where( [ 'old_id' => $oldID ] ) + ->caller( __METHOD__ )->fetchRow(); + if ( str_contains( $textFlags, 'gzip' ) ) { + // The latest revision of this page is compressed + $deletedPageName = $dbr->newSelectQueryBuilder + ->select( [ 'ar_page_name' ] ) + ->from( 'archive' ) + ->where( [ 'ar_page_id' => $deletedPageID->ar_page_id ] ) + ->limit( 1 ) + ->caller( __METHOD__ )->fetchRow(); + $problematicDeletedPages[] = $deletedPageName; + } + } + if ( count( $problematicPages ) > 0 || count( $problematicDeletedPages ) > 0 ) { + $this->output( 'ReplaceText should not be enabled on this wiki.' ); + if ( count( $problematicPages ) > 0 ) { + $this->output( 'The following pages\' latest revisions are compressed:' ); + $this->output( implode( ', ', $problematicPages ) ); + } + if ( count( $problematicDeletedPages ) > 0 ) { + $this->output( 'The following deleted pages\' latest revisions are compressed:' ); + $this->output( implode( ', ', $problematicDeletedPages ) ); + $this->output( 'If these pages are undeleted with ReplaceText enabled, usage of the extension will cause problems.' ); + } + } else { + $this->output( 'There\'s no problem with this wiki\'s pages; enabling ReplaceText in this wiki is safe.' ); + } + } +} + +$maintClass = ReplaceTextEligible::class; +require_once RUN_MAINTENANCE_IF_MAIN; From 3c6a8c0eda98fdcdfd1e076434f8d3e92f93dce4 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 22 Aug 2024 18:51:19 +0200 Subject: [PATCH 2/8] snprintf -> sprintf --- maintenance/replaceTextEligible.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index d20348f14..ff1bfa642 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -54,7 +54,7 @@ public function execute() { ->from( 'archive' ) ->distinct() ->caller( __METHOD__ )->fetchResultSet(); - $this->output( snprintf( 'Got %d pages from the page table and %d deleted pages from the archive table to process, hang tight...', $pages->numRows(), $deletedPageIDs->numRows() ) ); + $this->output( sprintf( 'Got %d pages from the page table and %d deleted pages from the archive table to process, hang tight...', $pages->numRows(), $deletedPageIDs->numRows() ) ); // Arrays to hold the names of pages preventing ReplaceText from working correctly $problematicPages = []; From ffa64459296df65eb39d8fcc8b7dff5e59d94d63 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 23 Aug 2024 12:21:59 +0200 Subject: [PATCH 3/8] Fix getting the name of the deleted page --- maintenance/replaceTextEligible.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index ff1bfa642..427a0aeac 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -124,7 +124,7 @@ public function execute() { ->where( [ 'ar_page_id' => $deletedPageID->ar_page_id ] ) ->limit( 1 ) ->caller( __METHOD__ )->fetchRow(); - $problematicDeletedPages[] = $deletedPageName; + $problematicDeletedPages[] = $deletedPageName->ar_page_name; } } if ( count( $problematicPages ) > 0 || count( $problematicDeletedPages ) > 0 ) { From eaf55d94819d96eb5a5c79c2104c920dbd23215e Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 23 Aug 2024 13:26:11 +0200 Subject: [PATCH 4/8] fix indent --- maintenance/replaceTextEligible.php | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index 427a0aeac..e3a4b529c 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -101,31 +101,31 @@ public function execute() { ->limit( 1 ) ->caller( __METHOD__ )->fetchRow(); $slotContentID = $dbr->newSelectQueryBuilder() - ->select( [ 'slot_content_id' ] ) - ->from( 'slots' ) - ->where( [ 'slot_revision_id' => $revID ] ) - ->caller( __METHOD__ )->fetchRow(); - $contentAddress = $dbr->newSelectQueryBuilder() - ->select( [ 'content_address' ] ) - ->from( 'content' ) - ->where( [ 'content_id' => $slotContentID ] ) - ->caller( __METHOD__ )->fetchRow(); - $oldID = substr( $contentAddress, 3 ); - $textFlags = $dbr->newSelectQueryBuilder() - ->select( [ 'old_flags' ] ) - ->from( 'text' ) - ->where( [ 'old_id' => $oldID ] ) - ->caller( __METHOD__ )->fetchRow(); + ->select( [ 'slot_content_id' ] ) + ->from( 'slots' ) + ->where( [ 'slot_revision_id' => $revID ] ) + ->caller( __METHOD__ )->fetchRow(); + $contentAddress = $dbr->newSelectQueryBuilder() + ->select( [ 'content_address' ] ) + ->from( 'content' ) + ->where( [ 'content_id' => $slotContentID ] ) + ->caller( __METHOD__ )->fetchRow(); + $oldID = substr( $contentAddress, 3 ); + $textFlags = $dbr->newSelectQueryBuilder() + ->select( [ 'old_flags' ] ) + ->from( 'text' ) + ->where( [ 'old_id' => $oldID ] ) + ->caller( __METHOD__ )->fetchRow(); if ( str_contains( $textFlags, 'gzip' ) ) { - // The latest revision of this page is compressed + // The latest revision of this page is compressed $deletedPageName = $dbr->newSelectQueryBuilder ->select( [ 'ar_page_name' ] ) ->from( 'archive' ) ->where( [ 'ar_page_id' => $deletedPageID->ar_page_id ] ) ->limit( 1 ) ->caller( __METHOD__ )->fetchRow(); - $problematicDeletedPages[] = $deletedPageName->ar_page_name; - } + $problematicDeletedPages[] = $deletedPageName->ar_page_name; + } } if ( count( $problematicPages ) > 0 || count( $problematicDeletedPages ) > 0 ) { $this->output( 'ReplaceText should not be enabled on this wiki.' ); From c2b655d5c304a95b620b5fd9e515dfb0b3511b95 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 23 Aug 2024 14:17:48 +0200 Subject: [PATCH 5/8] oops --- maintenance/replaceTextEligible.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index e3a4b529c..daf596fa1 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -33,7 +33,7 @@ use Exception; use Maintenance; -use Wikimedia\Rdbms\SelectQueryBuilder;; +use Wikimedia\Rdbms\SelectQueryBuilder; class ReplaceTextEligible extends Maintenance { public function __construct() { From 035295fd75533ea38160962cade8d3d141008192 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Sep 2024 06:02:50 +0000 Subject: [PATCH 6/8] CI: lint code to MediaWiki standards Check commit and GitHub actions for more details --- maintenance/replaceTextEligible.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index daf596fa1..1239a4b98 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -31,7 +31,6 @@ require_once "$IP/maintenance/Maintenance.php"; -use Exception; use Maintenance; use Wikimedia\Rdbms\SelectQueryBuilder; @@ -46,7 +45,7 @@ public function execute() { $dbr = $this->getDB( DB_REPLICA ); $pages = $dbr->newSelectQueryBuilder() - ->select( [ 'page_id', 'page_latest', 'page_name' ] ) + ->select( [ 'page_id', 'page_latest', 'page_name' ] ) ->from( 'page' ) ->caller( __METHOD__ )->fetchResultSet(); $deletedPageIDs = $dbr->newSelectQueryBuilder() From 7299c23638327ab34d7d52a2736c0124d321288b Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 12 Oct 2024 13:53:16 +0000 Subject: [PATCH 7/8] CI: lint code to MediaWiki standards Check commit and GitHub actions for more details --- maintenance/replaceTextEligible.php | 1 + 1 file changed, 1 insertion(+) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index 1239a4b98..deb611704 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -35,6 +35,7 @@ use Wikimedia\Rdbms\SelectQueryBuilder; class ReplaceTextEligible extends Maintenance { + public function __construct() { parent::__construct(); From e76f554fd4bb12a84dbbfc35e4da515bf4cf6382 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 12 Oct 2024 16:06:40 +0200 Subject: [PATCH 8/8] Fix function call --- maintenance/replaceTextEligible.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintenance/replaceTextEligible.php b/maintenance/replaceTextEligible.php index deb611704..85d58085a 100644 --- a/maintenance/replaceTextEligible.php +++ b/maintenance/replaceTextEligible.php @@ -118,7 +118,7 @@ public function execute() { ->caller( __METHOD__ )->fetchRow(); if ( str_contains( $textFlags, 'gzip' ) ) { // The latest revision of this page is compressed - $deletedPageName = $dbr->newSelectQueryBuilder + $deletedPageName = $dbr->newSelectQueryBuilder() ->select( [ 'ar_page_name' ] ) ->from( 'archive' ) ->where( [ 'ar_page_id' => $deletedPageID->ar_page_id ] )