From 93da26c5021f99d7d8784f71516283006545781f Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 16:58:11 -0700 Subject: [PATCH 01/43] Improve query performance and add caching support --- includes/Query.php | 58 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 4e1847cb..086112f0 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -8,7 +8,11 @@ use MediaWiki\MediaWikiServices; use MediaWiki\User\UserFactory; use MWException; +use PoolCounterWorkViaCallback; +use WANObjectCache; +use Wikimedia\Rdbms\Database; use Wikimedia\Rdbms\IDatabase; +use WikiMap; class Query { /** @@ -318,7 +322,6 @@ public function buildAndSelect( $calcRows = false ) { } $this->sqlQuery = $sql; - $result = $this->DB->query( $sql, __METHOD__ ); if ( $calcRows ) { $calcRowsResult = $this->DB->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); @@ -327,14 +330,59 @@ public function buildAndSelect( $calcRows = false ) { $calcRowsResult->free(); } } catch ( Exception $e ) { - $queryError = true; + throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); } - if ( $queryError || $result === false ) { - throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); + // From intersection + global $wgDPLQueryCacheTime, $wgDPLMaxQueryTime; + + if ( $wgDPLMaxQueryTime ) { + $options['MAX_EXECUTION_TIME'] = $wgDPLMaxQueryTime; } - return $result; + $qname = __METHOD__ . ' - ' . $pageName; + $where = $this->where; + $join = $this->join; + + $dbr = wfGetDB( DB_REPLICA ); + + $doQuery = static function () use ( $qname, $dbr, $tables, $select, $where, $options, $join ) { + $res = $dbr->select( $tables, $select, $where, $qname, $options, $join ); + return iterator_to_array( $res ); + }; + + $poolCounterKey = 'nowait:dpl-query:' . WikiMap::getCurrentWikiId(); + $worker = new PoolCounterWorkViaCallback( 'DPL', $poolCounterKey, [ + 'doWork' => $doQuery, + ] ); + + if ( $wgDPLQueryCacheTime <= 0 ) { + return $worker->execute(); + } + + $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + + return $cache->getWithSetCallback( + $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), + $wgDPLQueryCacheTime, + static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ + $setOpts += Database::getCacheSetOptions( $dbr ); + $res = $worker->execute(); + if ( $res === false ) { + // Do not cache errors. + $ttl = WANObjectCache::TTL_UNCACHEABLE; + // If we have oldVal, prefer it to error + if ( is_array( $oldVal ) ) { + return $oldVal; + } + } + return $res; + }, + [ + 'lowTTL' => min( $cache::TTL_MINUTE, floor( $wgDPLQueryCacheTime * 0.75 ) ), + 'pcTTL' => min( $cache::TTL_PROC_LONG, $wgDPLQueryCacheTime ) + ] + ); } /** From 94b447e1cd79dcbb42fa412c28e957b232c7fca7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 9 Mar 2022 23:59:36 +0000 Subject: [PATCH 02/43] CI: lint code to MediaWiki standards Check commit and GitHub actions for more details --- includes/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Query.php b/includes/Query.php index 086112f0..ed9f7bae 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -10,9 +10,9 @@ use MWException; use PoolCounterWorkViaCallback; use WANObjectCache; +use WikiMap; use Wikimedia\Rdbms\Database; use Wikimedia\Rdbms\IDatabase; -use WikiMap; class Query { /** From 48801f6431660959741893a73f45f2d88c48ebc5 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:00:21 -0700 Subject: [PATCH 03/43] Update extension.json --- extension.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extension.json b/extension.json index caf80e22..7922e769 100644 --- a/extension.json +++ b/extension.json @@ -84,6 +84,14 @@ "runFromProtectedPagesOnly": false, "handleSectionTag": false, "alwaysCacheResults": false + }, + "DPLMaxQueryTime": { + "value": 10000, + "description": "Maximum allowed time for database queries in milliseconds." + }, + "DPLQueryCacheTime": { + "value": 0, + "description": "This is the query cache. It can help with situations where you have a template with the same query used on a large number of pages all being refreshed at once. The query cache cannot be purged. Suggested value between 30 to 600." } }, "TrackingCategories": [ From e7d1ab4a8a83bb13bd04ef6913f3052843b2964a Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:04:40 -0700 Subject: [PATCH 04/43] Update Query.php --- includes/Query.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/Query.php b/includes/Query.php index ed9f7bae..6873e85b 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -340,6 +340,9 @@ public function buildAndSelect( $calcRows = false ) { $options['MAX_EXECUTION_TIME'] = $wgDPLMaxQueryTime; } + $parser = MediaWikiServices::getInstance()->getParser(); + $pageName = str_replace( [ '*', '/' ], '-', $parser->getTitle()->getPrefixedDBkey() ); + $qname = __METHOD__ . ' - ' . $pageName; $where = $this->where; $join = $this->join; From 6d546ea2a7a7733dc72cd9c4b7d0379d5eb37b7c Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:08:37 -0700 Subject: [PATCH 05/43] Update Query.php --- includes/Query.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 6873e85b..90a9f417 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -333,11 +333,12 @@ public function buildAndSelect( $calcRows = false ) { throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); } - // From intersection - global $wgDPLQueryCacheTime, $wgDPLMaxQueryTime; + // Partially taken from intersection + $queryCacheTime = Config::getSetting( 'queryCacheTime' ); + $maxQueryTime = Config::getSetting( 'maxQueryTime' ); - if ( $wgDPLMaxQueryTime ) { - $options['MAX_EXECUTION_TIME'] = $wgDPLMaxQueryTime; + if ( $maxQueryTime ) { + $options['MAX_EXECUTION_TIME'] = $maxQueryTime; } $parser = MediaWikiServices::getInstance()->getParser(); @@ -359,7 +360,7 @@ public function buildAndSelect( $calcRows = false ) { 'doWork' => $doQuery, ] ); - if ( $wgDPLQueryCacheTime <= 0 ) { + if ( $queryCacheTime <= 0 ) { return $worker->execute(); } @@ -367,7 +368,7 @@ public function buildAndSelect( $calcRows = false ) { return $cache->getWithSetCallback( $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), - $wgDPLQueryCacheTime, + $queryCacheTime, static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ $setOpts += Database::getCacheSetOptions( $dbr ); $res = $worker->execute(); @@ -382,8 +383,8 @@ static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ return $res; }, [ - 'lowTTL' => min( $cache::TTL_MINUTE, floor( $wgDPLQueryCacheTime * 0.75 ) ), - 'pcTTL' => min( $cache::TTL_PROC_LONG, $wgDPLQueryCacheTime ) + 'lowTTL' => min( $cache::TTL_MINUTE, floor( $queryCacheTime * 0.75 ) ), + 'pcTTL' => min( $cache::TTL_PROC_LONG, $queryCacheTime ) ] ); } From a802730d6e394f76c1454b94dc30551bd9a15d21 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:09:40 -0700 Subject: [PATCH 06/43] Update extension.json --- extension.json | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/extension.json b/extension.json index 7922e769..f5700662 100644 --- a/extension.json +++ b/extension.json @@ -83,15 +83,9 @@ "recursiveTagParse": false, "runFromProtectedPagesOnly": false, "handleSectionTag": false, - "alwaysCacheResults": false - }, - "DPLMaxQueryTime": { - "value": 10000, - "description": "Maximum allowed time for database queries in milliseconds." - }, - "DPLQueryCacheTime": { - "value": 0, - "description": "This is the query cache. It can help with situations where you have a template with the same query used on a large number of pages all being refreshed at once. The query cache cannot be purged. Suggested value between 30 to 600." + "alwaysCacheResults": false, + "maxQueryTime": 10000, + "queryCacheTime": 0 } }, "TrackingCategories": [ From 7dc8497cce94159b1b430a856611f7ef8cdaf670 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:21:04 -0700 Subject: [PATCH 07/43] Update Parse.php --- includes/Parse.php | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/includes/Parse.php b/includes/Parse.php index 60befd1b..d5b09b65 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -215,14 +215,14 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa /*********/ try { $query = new Query( $this->parameters ); - $result = $query->buildAndSelect( $calcRows ); + $rows = $query->buildAndSelect( $calcRows ); } catch ( MWException $e ) { $this->logger->addMessage( DynamicPageListHooks::FATAL_SQLBUILDERROR, $e->getMessage() ); return $this->getFullOutput(); } - $numRows = $result->numRows(); - $articles = $this->processQueryResults( $result, $parser ); + $numRows = count( $rows ); + $articles = $this->processQueryResults( $rows, $parser ); global $wgDebugDumpSql; if ( DynamicPageListHooks::getDebugLevel() >= 4 && $wgDebugDumpSql ) { @@ -240,8 +240,6 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa /* Handle No Results */ /*********************/ if ( $numRows <= 0 || empty( $articles ) ) { - // Shortcut out since there is no processing to do. - $result->free(); return $this->getFullOutput( 0, false ); } @@ -341,17 +339,17 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa /** * Process Query Results * - * @param $result + * @param $rows * @param Parser $parser * @return array */ - private function processQueryResults( $result, Parser $parser ) { + private function processQueryResults( $rows, Parser $parser ) { /*******************************/ /* Random Count Pick Generator */ /*******************************/ $randomCount = $this->parameters->getParameter( 'randomcount' ); if ( $randomCount > 0 ) { - $nResults = $result->numRows(); + $nResults = count( $rows ); // mt_srand() seeding was removed due to PHP 5.2.1 and above no longer generating the same sequence for the same seed. //Constrain the total amount of random results to not be greater than the total results. if ( $randomCount > $nResults ) { @@ -373,7 +371,7 @@ private function processQueryResults( $result, Parser $parser ) { /* Article Processing */ /**********************/ $i = 0; - while ( $row = $result->fetchRow() ) { + foreach ( $rows as $row ) { $i++; // In random mode skip articles which were not chosen. @@ -383,15 +381,15 @@ private function processQueryResults( $result, Parser $parser ) { if ( $this->parameters->getParameter( 'goal' ) == 'categories' ) { $pageNamespace = NS_CATEGORY; - $pageTitle = $row['cl_to']; + $pageTitle = $row->cl_to; } elseif ( $this->parameters->getParameter( 'openreferences' ) ) { if ( count( $this->parameters->getParameter( 'imagecontainer' ) ) > 0 ) { $pageNamespace = NS_FILE; - $pageTitle = $row['il_to']; + $pageTitle = $row->il_to; } else { // Maybe non-existing title - $pageNamespace = $row['pl_namespace']; - $pageTitle = $row['pl_title']; + $pageNamespace = $row->pl_namespace; + $pageTitle = $row->pl_title; } if ( @@ -402,8 +400,8 @@ private function processQueryResults( $result, Parser $parser ) { } } else { // Existing PAGE TITLE - $pageNamespace = $row['page_namespace']; - $pageTitle = $row['page_title']; + $pageNamespace = $row->page_namespace; + $pageTitle = $row->page_title; } // if subpages are to be excluded: skip them @@ -422,8 +420,6 @@ private function processQueryResults( $result, Parser $parser ) { $articles[] = Article::newFromRow( $row, $this->parameters, $title, $pageNamespace, $pageTitle ); } - $result->free(); - return $articles; } From 1c8386217be842f9837b9e0f065e7bcfb054554c Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:28:27 -0700 Subject: [PATCH 08/43] Update Article.php --- includes/Article.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/Article.php b/includes/Article.php index 93a0624f..b4916b0a 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -187,9 +187,9 @@ public function __construct( Title $title, $namespace ) { /** * Initialize a new instance from a database row. * - * @param array $row + * @param object $row * @param Parameters $parameters - * @param Title $title + * @param Title $title * @param int $pageNamespace * @param string $pageTitle * @return Article @@ -203,6 +203,8 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ $article = new Article( $title, $pageNamespace ); $revActorName = null; + $row = (array)$row; + if ( isset( $row['revactor_actor'] ) ) { $revActorName = $userFactory->newFromActorId( $row['revactor_actor'] )->getName(); } From 5dc651a3f9f24e194655cf11900ffe97f83e8144 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:31:22 -0700 Subject: [PATCH 09/43] Update Parse.php --- includes/Parse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Parse.php b/includes/Parse.php index d5b09b65..8a9d457c 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -417,7 +417,7 @@ private function processQueryResults( $rows, Parser $parser ) { continue; } - $articles[] = Article::newFromRow( $row, $this->parameters, $title, $pageNamespace, $pageTitle ); + $articles[] = Article::newFromRow( (array)$row, $this->parameters, $title, $pageNamespace, $pageTitle ); } return $articles; From 2dc1c1e8f527458e317925463eb6f8d15ce085ed Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:31:59 -0700 Subject: [PATCH 10/43] Update Article.php --- includes/Article.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/includes/Article.php b/includes/Article.php index b4916b0a..f8a605b3 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -187,7 +187,7 @@ public function __construct( Title $title, $namespace ) { /** * Initialize a new instance from a database row. * - * @param object $row + * @param array $row * @param Parameters $parameters * @param Title $title * @param int $pageNamespace @@ -203,8 +203,6 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ $article = new Article( $title, $pageNamespace ); $revActorName = null; - $row = (array)$row; - if ( isset( $row['revactor_actor'] ) ) { $revActorName = $userFactory->newFromActorId( $row['revactor_actor'] )->getName(); } From 3aa6a79811971fd44610330395b3f04f3249a725 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:54:06 -0700 Subject: [PATCH 11/43] Update Query.php --- includes/Query.php | 73 +++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 90a9f417..8aad0085 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -169,12 +169,12 @@ public function __construct( Parameters $parameters ) { } /** - * Start a query build. + * Start a query build. Returns found rows. * * @param bool $calcRows - * @return mixed Mediawiki Result Object or False + * @return array */ - public function buildAndSelect( $calcRows = false ) { + public function buildAndSelect( bool $calcRows = false ) { global $wgNonincludableNamespaces; $options = []; @@ -265,10 +265,6 @@ public function buildAndSelect( $calcRows = false ) { $options[] = 'DISTINCT'; } else { - if ( $calcRows ) { - $options[] = 'SQL_CALC_FOUND_ROWS'; - } - if ( $this->distinct ) { $options[] = 'DISTINCT'; } @@ -322,13 +318,6 @@ public function buildAndSelect( $calcRows = false ) { } $this->sqlQuery = $sql; - - if ( $calcRows ) { - $calcRowsResult = $this->DB->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); - $total = $calcRowsResult->fetchRow(); - $this->foundRows = intval( $total['rowcount'] ); - $calcRowsResult->free(); - } } catch ( Exception $e ) { throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); } @@ -361,32 +350,38 @@ public function buildAndSelect( $calcRows = false ) { ] ); if ( $queryCacheTime <= 0 ) { - return $worker->execute(); - } - - $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); - - return $cache->getWithSetCallback( - $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), - $queryCacheTime, - static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ - $setOpts += Database::getCacheSetOptions( $dbr ); - $res = $worker->execute(); - if ( $res === false ) { - // Do not cache errors. - $ttl = WANObjectCache::TTL_UNCACHEABLE; - // If we have oldVal, prefer it to error - if ( is_array( $oldVal ) ) { - return $oldVal; + $rows = $worker->execute(); + } else { + $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + + $rows = $cache->getWithSetCallback( + $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), + $queryCacheTime, + static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ + $setOpts += Database::getCacheSetOptions( $dbr ); + $res = $worker->execute(); + if ( $res === false ) { + // Do not cache errors. + $ttl = WANObjectCache::TTL_UNCACHEABLE; + // If we have oldVal, prefer it to error + if ( is_array( $oldVal ) ) { + return $oldVal; + } } - } - return $res; - }, - [ - 'lowTTL' => min( $cache::TTL_MINUTE, floor( $queryCacheTime * 0.75 ) ), - 'pcTTL' => min( $cache::TTL_PROC_LONG, $queryCacheTime ) - ] - ); + return $res; + }, + [ + 'lowTTL' => min( $cache::TTL_MINUTE, floor( $queryCacheTime * 0.75 ) ), + 'pcTTL' => min( $cache::TTL_PROC_LONG, $queryCacheTime ) + ] + ); + } + + if ( $calcRows ) { + $this->foundRows = count( $rows ); + } + + return $rows; } /** From b6619353e80c9fbc7b2311fe6d122dc66c1fee45 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:58:41 -0700 Subject: [PATCH 12/43] Update Query.php --- includes/Query.php | 73 +++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 8aad0085..90a9f417 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -169,12 +169,12 @@ public function __construct( Parameters $parameters ) { } /** - * Start a query build. Returns found rows. + * Start a query build. * * @param bool $calcRows - * @return array + * @return mixed Mediawiki Result Object or False */ - public function buildAndSelect( bool $calcRows = false ) { + public function buildAndSelect( $calcRows = false ) { global $wgNonincludableNamespaces; $options = []; @@ -265,6 +265,10 @@ public function buildAndSelect( bool $calcRows = false ) { $options[] = 'DISTINCT'; } else { + if ( $calcRows ) { + $options[] = 'SQL_CALC_FOUND_ROWS'; + } + if ( $this->distinct ) { $options[] = 'DISTINCT'; } @@ -318,6 +322,13 @@ public function buildAndSelect( bool $calcRows = false ) { } $this->sqlQuery = $sql; + + if ( $calcRows ) { + $calcRowsResult = $this->DB->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); + $total = $calcRowsResult->fetchRow(); + $this->foundRows = intval( $total['rowcount'] ); + $calcRowsResult->free(); + } } catch ( Exception $e ) { throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); } @@ -350,38 +361,32 @@ public function buildAndSelect( bool $calcRows = false ) { ] ); if ( $queryCacheTime <= 0 ) { - $rows = $worker->execute(); - } else { - $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); - - $rows = $cache->getWithSetCallback( - $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), - $queryCacheTime, - static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ - $setOpts += Database::getCacheSetOptions( $dbr ); - $res = $worker->execute(); - if ( $res === false ) { - // Do not cache errors. - $ttl = WANObjectCache::TTL_UNCACHEABLE; - // If we have oldVal, prefer it to error - if ( is_array( $oldVal ) ) { - return $oldVal; - } + return $worker->execute(); + } + + $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + + return $cache->getWithSetCallback( + $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), + $queryCacheTime, + static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ + $setOpts += Database::getCacheSetOptions( $dbr ); + $res = $worker->execute(); + if ( $res === false ) { + // Do not cache errors. + $ttl = WANObjectCache::TTL_UNCACHEABLE; + // If we have oldVal, prefer it to error + if ( is_array( $oldVal ) ) { + return $oldVal; } - return $res; - }, - [ - 'lowTTL' => min( $cache::TTL_MINUTE, floor( $queryCacheTime * 0.75 ) ), - 'pcTTL' => min( $cache::TTL_PROC_LONG, $queryCacheTime ) - ] - ); - } - - if ( $calcRows ) { - $this->foundRows = count( $rows ); - } - - return $rows; + } + return $res; + }, + [ + 'lowTTL' => min( $cache::TTL_MINUTE, floor( $queryCacheTime * 0.75 ) ), + 'pcTTL' => min( $cache::TTL_PROC_LONG, $queryCacheTime ) + ] + ); } /** From 39dd702373eab34076fcb2173a212ff20df27ab7 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:00:12 -0700 Subject: [PATCH 13/43] Update Query.php --- includes/Query.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 90a9f417..1438a8c7 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -169,12 +169,12 @@ public function __construct( Parameters $parameters ) { } /** - * Start a query build. + * Start a query build. Returns found rows. * * @param bool $calcRows - * @return mixed Mediawiki Result Object or False + * @return array */ - public function buildAndSelect( $calcRows = false ) { + public function buildAndSelect( bool $calcRows = false ) { global $wgNonincludableNamespaces; $options = []; From 8b7c01fe1d8ca07ee37e041a46e5e09332354458 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:11:48 -0700 Subject: [PATCH 14/43] Cleanup + variable rename --- includes/Query.php | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 1438a8c7..2641ad00 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -178,6 +178,7 @@ public function buildAndSelect( bool $calcRows = false ) { global $wgNonincludableNamespaces; $options = []; + $dbr = $this->DB; $parameters = $this->parameters->getAllParameters(); foreach ( $parameters as $parameter => $option ) { @@ -228,12 +229,10 @@ public function buildAndSelect( bool $calcRows = false ) { if ( $this->parameters->getParameter( 'openreferences' ) ) { if ( count( $this->parameters->getParameter( 'imagecontainer' ) ) > 0 ) { - // $sSqlSelectFrom = $sSqlCl_to.'ic.il_to, '.$sSqlSelPage."ic.il_to AS sortkey".' FROM '.$this->tableNames['imagelinks'].' AS ic'; $tables = [ 'ic' => 'imagelinks' ]; } else { - // $sSqlSelectFrom = "SELECT $sSqlCalcFoundRows $sSqlDistinct ".$sSqlCl_to.'pl_namespace, pl_title'.$sSqlSelPage.$sSqlSortkey.' FROM '.$this->tableNames['pagelinks']; $this->addSelect( [ 'pl_namespace', @@ -259,7 +258,7 @@ public function buildAndSelect( bool $calcRows = false ) { } if ( $this->parameters->getParameter( 'goal' ) == 'categories' ) { $categoriesGoal = true; - $select = [ + $fields = [ $this->tableNames['page'] . '.page_id' ]; @@ -274,15 +273,15 @@ public function buildAndSelect( bool $calcRows = false ) { } $categoriesGoal = false; - $select = $this->select; + $fields = $this->select; } $queryError = false; try { if ( $categoriesGoal ) { - $result = $this->DB->select( + $result = $dbr->select( $tables, - $select, + $fields, $this->where, __METHOD__, $options, @@ -291,11 +290,11 @@ public function buildAndSelect( bool $calcRows = false ) { $pageIds = []; - while ( $row = $result->fetchRow() ) { - $pageIds[] = $row['page_id']; + foreach ( $result as $row ) { + $pageIds[] = $row->page_id; } - $sql = $this->DB->selectSQLText( + $query = $dbr->selectSQLText( [ 'clgoal' => 'categorylinks' ], @@ -311,9 +310,9 @@ public function buildAndSelect( bool $calcRows = false ) { ] ); } else { - $sql = $this->DB->selectSQLText( + $query = $dbr->selectSQLText( $tables, - $select, + $fields, $this->where, __METHOD__, $options, @@ -321,16 +320,16 @@ public function buildAndSelect( bool $calcRows = false ) { ); } - $this->sqlQuery = $sql; + $this->sqlQuery = $query; if ( $calcRows ) { - $calcRowsResult = $this->DB->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); + $calcRowsResult = $dbr->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); $total = $calcRowsResult->fetchRow(); $this->foundRows = intval( $total['rowcount'] ); $calcRowsResult->free(); } } catch ( Exception $e ) { - throw new MWException( __METHOD__ . ": " . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->DB->lastError() )->text() ); + throw new MWException( __METHOD__ . ': ' . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $dbr->lastError() )->text() ); } // Partially taken from intersection @@ -348,10 +347,8 @@ public function buildAndSelect( bool $calcRows = false ) { $where = $this->where; $join = $this->join; - $dbr = wfGetDB( DB_REPLICA ); - - $doQuery = static function () use ( $qname, $dbr, $tables, $select, $where, $options, $join ) { - $res = $dbr->select( $tables, $select, $where, $qname, $options, $join ); + $doQuery = static function () use ( $qname, $dbr, $tables, $fields, $where, $options, $join ) { + $res = $dbr->select( $tables, $fields, $where, $qname, $options, $join ); return iterator_to_array( $res ); }; @@ -367,7 +364,7 @@ public function buildAndSelect( bool $calcRows = false ) { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); return $cache->getWithSetCallback( - $cache->makeKey( "DPLQuery", hash( "sha256", $sql ) ), + $cache->makeKey( 'DPLQuery', hash( 'sha256', $query ) ), $queryCacheTime, static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ $setOpts += Database::getCacheSetOptions( $dbr ); From d3c5ffe03327c88916ee719427cb096862a90585 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:54:59 -0700 Subject: [PATCH 15/43] Update Article.php --- includes/Article.php | 85 ++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/includes/Article.php b/includes/Article.php index f8a605b3..e804dc98 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -4,6 +4,7 @@ use MediaWiki\MediaWikiServices; use RequestContext; +use stdClass; use Title; class Article { @@ -187,24 +188,30 @@ public function __construct( Title $title, $namespace ) { /** * Initialize a new instance from a database row. * - * @param array $row + * @param stdClass $row * @param Parameters $parameters * @param Title $title * @param int $pageNamespace * @param string $pageTitle - * @return Article + * @return self */ - public static function newFromRow( $row, Parameters $parameters, Title $title, $pageNamespace, $pageTitle ) { + public static function newFromRow( + stdClass $row, + Parameters $parameters, + Title $title, + int $pageNamespace, + string $pageTitle + ): self { $services = MediaWikiServices::getInstance(); $contentLanguage = $services->getContentLanguage(); $userFactory = $services->getUserFactory(); - $article = new Article( $title, $pageNamespace ); + $article = new self( $title, $pageNamespace ); $revActorName = null; - if ( isset( $row['revactor_actor'] ) ) { - $revActorName = $userFactory->newFromActorId( $row['revactor_actor'] )->getName(); + if ( isset( $row->revactor_actor ) ) { + $revActorName = $userFactory->newFromActorId( $row->revactor_actor )->getName(); } $titleText = $title->getText(); @@ -222,8 +229,8 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ $titleText = substr( $titleText, 0, $parameters->getParameter( 'titlemaxlen' ) ) . '...'; } - if ( $parameters->getParameter( 'showcurid' ) === true && isset( $row['page_id'] ) ) { - $articleLink = '[' . $title->getLinkURL( [ 'curid' => $row['page_id'] ] ) . ' ' . htmlspecialchars( $titleText ) . ']'; + if ( $parameters->getParameter( 'showcurid' ) === true && isset( $row->page_id ) ) { + $articleLink = '[' . $title->getLinkURL( [ 'curid' => $row->page_id ] ) . ' ' . htmlspecialchars( $titleText ) . ']'; } else { $articleLink = '[[' . ( $parameters->getParameter( 'escapelinks' ) && ( $pageNamespace == NS_CATEGORY || $pageNamespace == NS_FILE ) ? ':' : '' ) . $title->getFullText() . '|' . htmlspecialchars( $titleText ) . ']]'; } @@ -233,68 +240,68 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ $languageConverter = $services->getLanguageConverterFactory()->getLanguageConverter(); // get first char used for category-style output - if ( isset( $row['sortkey'] ) ) { - $article->mStartChar = $languageConverter->convert( $contentLanguage->firstChar( $row['sortkey'] ) ); + if ( isset( $row->sortkey ) ) { + $article->mStartChar = $languageConverter->convert( $contentLanguage->firstChar( $row->sortkey ) ); } else { $article->mStartChar = $languageConverter->convert( $contentLanguage->firstChar( $pageTitle ) ); } - $article->mID = intval( $row['page_id'] ); + $article->mID = intval( $row->page_id ); // External link - if ( isset( $row['el_to'] ) ) { - $article->mExternalLink = $row['el_to']; + if ( isset( $row->el_to ) ) { + $article->mExternalLink = $row->el_to; } // SHOW PAGE_COUNTER - if ( isset( $row['page_counter'] ) ) { - $article->mCounter = intval( $row['page_counter'] ); + if ( isset( $row->page_counter ) ) { + $article->mCounter = intval( $row->page_counter ); } // SHOW PAGE_SIZE - if ( isset( $row['page_len'] ) ) { - $article->mSize = intval( $row['page_len'] ); + if ( isset( $row->page_len ) ) { + $article->mSize = intval( $row->page_len ); } // STORE initially selected PAGE if ( is_array( $parameters->getParameter( 'linksto' ) ) && ( count( $parameters->getParameter( 'linksto' ) ) || count( $parameters->getParameter( 'linksfrom' ) ) ) ) { - if ( !isset( $row['sel_title'] ) ) { + if ( !isset( $row->sel_title ) ) { $article->mSelTitle = 'unknown page'; $article->mSelNamespace = 0; } else { - $article->mSelTitle = $row['sel_title']; - $article->mSelNamespace = $row['sel_ns']; + $article->mSelTitle = $row->sel_title; + $article->mSelNamespace = $row->sel_ns; } } // STORE selected image if ( is_array( $parameters->getParameter( 'imageused' ) ) && count( $parameters->getParameter( 'imageused' ) ) > 0 ) { - if ( !isset( $row['image_sel_title'] ) ) { + if ( !isset( $row->image_sel_title ) ) { $article->mImageSelTitle = 'unknown image'; } else { - $article->mImageSelTitle = $row['image_sel_title']; + $article->mImageSelTitle = $row->image_sel_title; } } if ( $parameters->getParameter( 'goal' ) != 'categories' ) { // REVISION SPECIFIED if ( $parameters->getParameter( 'lastrevisionbefore' ) || $parameters->getParameter( 'allrevisionsbefore' ) || $parameters->getParameter( 'firstrevisionsince' ) || $parameters->getParameter( 'allrevisionssince' ) ) { - $article->mRevision = $row['revactor_rev']; + $article->mRevision = $row->revactor_rev; $article->mUser = $revActorName; - $article->mDate = $row['revactor_timestamp']; + $article->mDate = $row->revactor_timestamp; - // $article->mComment = $row['rev_comment']; + // $article->mComment = $row->rev_comment; } // SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE if ( $parameters->getParameter( 'addpagetoucheddate' ) ) { - $article->mDate = $row['page_touched']; + $article->mDate = $row->page_touched; } elseif ( $parameters->getParameter( 'addfirstcategorydate' ) ) { - $article->mDate = $row['cl_timestamp']; - } elseif ( $parameters->getParameter( 'addeditdate' ) && isset( $row['revactor_timestamp'] ) ) { - $article->mDate = $row['revactor_timestamp']; - } elseif ( $parameters->getParameter( 'addeditdate' ) && isset( $row['page_touched'] ) ) { - $article->mDate = $row['page_touched']; + $article->mDate = $row->cl_timestamp; + } elseif ( $parameters->getParameter( 'addeditdate' ) && isset( $row->revactor_timestamp ) ) { + $article->mDate = $row->revactor_timestamp; + } elseif ( $parameters->getParameter( 'addeditdate' ) && isset( $row->page_touched ) ) { + $article->mDate = $row->page_touched; } // Time zone adjustment @@ -311,11 +318,11 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ // CONTRIBUTION, CONTRIBUTOR if ( $parameters->getParameter( 'addcontribution' ) ) { - $article->mContribution = $row['contribution']; + $article->mContribution = $row->contribution; - $article->mContributor = $userFactory->newFromActorId( $row['contributor'] )->getName(); + $article->mContributor = $userFactory->newFromActorId( $row->contributor )->getName(); - $article->mContrib = substr( '*****************', 0, (int)round( log( $row['contribution'] ) ) ); + $article->mContrib = substr( '*****************', 0, (int)round( log( $row->contribution ) ) ); } // USER/AUTHOR(S) @@ -327,8 +334,8 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ } // CATEGORY LINKS FROM CURRENT PAGE - if ( $parameters->getParameter( 'addcategories' ) && ( $row['cats'] ) ) { - $artCatNames = explode( ' | ', $row['cats'] ); + if ( $parameters->getParameter( 'addcategories' ) && ( $row->cats ) ) { + $artCatNames = explode( ' | ', $row->cats ); foreach ( $artCatNames as $artCatName ) { $article->mCategoryLinks[] = '[[:Category:' . $artCatName . '|' . str_replace( '_', ' ', $artCatName ) . ']]'; $article->mCategoryTexts[] = str_replace( '_', ' ', $artCatName ); @@ -340,12 +347,12 @@ public static function newFromRow( $row, Parameters $parameters, Title $title, $ switch ( $parameters->getParameter( 'ordermethod' )[0] ) { case 'category': // Count one more page in this heading - self::$headings[$row['cl_to']] = ( isset( self::$headings[$row['cl_to']] ) ? self::$headings[$row['cl_to']] + 1 : 1 ); - if ( $row['cl_to'] == '' ) { + self::$headings[$row->cl_to] = ( isset( self::$headings[$row->cl_to] ) ? self::$headings[$row->cl_to] + 1 : 1 ); + if ( $row->cl_to == '' ) { // uncategorized page (used if ordermethod=category,...) $article->mParentHLink = '[[:Special:Uncategorizedpages|' . wfMessage( 'uncategorizedpages' ) . ']]'; } else { - $article->mParentHLink = '[[:Category:' . $row['cl_to'] . '|' . str_replace( '_', ' ', $row['cl_to'] ) . ']]'; + $article->mParentHLink = '[[:Category:' . $row->cl_to . '|' . str_replace( '_', ' ', $row->cl_to ) . ']]'; } break; From 0f8353036719ead5458e80544f3c074c4a8b1c25 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:55:24 -0700 Subject: [PATCH 16/43] Update Parse.php --- includes/Parse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Parse.php b/includes/Parse.php index 8a9d457c..d5b09b65 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -417,7 +417,7 @@ private function processQueryResults( $rows, Parser $parser ) { continue; } - $articles[] = Article::newFromRow( (array)$row, $this->parameters, $title, $pageNamespace, $pageTitle ); + $articles[] = Article::newFromRow( $row, $this->parameters, $title, $pageNamespace, $pageTitle ); } return $articles; From 96baede4e3f76ee918b035740699937373edf8ea Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:08:01 -0700 Subject: [PATCH 17/43] Update Query.php --- includes/Query.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 2641ad00..18b64bca 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -677,7 +677,7 @@ public function getCollateSQL() { * @return array */ public static function getSubcategories( $categoryName, $depth = 1 ) { - $DB = wfGetDB( DB_REPLICA, 'dpl' ); + $dbr = wfGetDB( DB_REPLICA, 'dpl' ); if ( $depth > 2 ) { // Hard constrain depth because lots of recursion is bad. @@ -685,7 +685,7 @@ public static function getSubcategories( $categoryName, $depth = 1 ) { } $categories = []; - $result = $DB->select( + $res = $dbr->select( [ 'page', 'categorylinks' ], [ 'page_title' ], [ @@ -702,15 +702,15 @@ public static function getSubcategories( $categoryName, $depth = 1 ) { ] ); - while ( $row = $result->fetchRow() ) { - $categories[] = $row['page_title']; + foreach ( $res as $row ) { + $categories[] = $row->page_title; if ( $depth > 1 ) { - $categories = array_merge( $categories, self::getSubcategories( $row['page_title'], $depth - 1 ) ); + $categories = array_merge( $categories, self::getSubcategories( $row->page_title, $depth - 1 ) ); } } $categories = array_unique( $categories ); - $result->free(); + $res->free(); return $categories; } @@ -1695,13 +1695,13 @@ private function _order( $option ) { private function _ordercollation( $option ) { $option = mb_strtolower( $option ); - $results = $this->DB->query( 'SHOW CHARACTER SET' ); - if ( !$results ) { + $res = $this->DB->query( 'SHOW CHARACTER SET' ); + if ( !$res ) { return false; } - while ( $row = $results->fetchRow() ) { - if ( $option == $row['Default collation'] ) { + foreach ( $res as $row ) { + if ( $option == $row->{'Default collation'} ) { $this->setCollation( $option ); break; } From 02b33d1c1041588dee1be561f4cdf9cef2bd1a91 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:09:34 -0700 Subject: [PATCH 18/43] Update .phpcs.xml --- .phpcs.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/.phpcs.xml b/.phpcs.xml index 8e445048..c3ca0fa9 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -8,7 +8,6 @@ - From 640f863f4a50e2a0bfc838210ee57155053f20ab Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:10:42 -0700 Subject: [PATCH 19/43] Update Query.php --- includes/Query.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index 18b64bca..f6a1267c 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -279,7 +279,7 @@ public function buildAndSelect( bool $calcRows = false ) { $queryError = false; try { if ( $categoriesGoal ) { - $result = $dbr->select( + $res = $dbr->select( $tables, $fields, $this->where, @@ -290,7 +290,7 @@ public function buildAndSelect( bool $calcRows = false ) { $pageIds = []; - foreach ( $result as $row ) { + foreach ( $res as $row ) { $pageIds[] = $row->page_id; } From 096e716e70df02d0488feca62fa98261c210c1a5 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:17:04 -0700 Subject: [PATCH 20/43] Update Query.php --- includes/Query.php | 104 ++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index f6a1267c..17207271 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -27,7 +27,7 @@ class Query { * * @var IDatabase */ - private $DB; + private $dbr; /** * Array of prefixed and escaped table names. @@ -163,7 +163,7 @@ public function __construct( Parameters $parameters ) { $this->tableNames = self::getTableNames(); - $this->DB = wfGetDB( DB_REPLICA, 'dpl' ); + $this->dbr = wfGetDB( DB_REPLICA, 'dpl' ); $this->userFactory = MediaWikiServices::getInstance()->getUserFactory(); } @@ -178,7 +178,6 @@ public function buildAndSelect( bool $calcRows = false ) { global $wgNonincludableNamespaces; $options = []; - $dbr = $this->DB; $parameters = $this->parameters->getAllParameters(); foreach ( $parameters as $parameter => $option ) { @@ -279,7 +278,7 @@ public function buildAndSelect( bool $calcRows = false ) { $queryError = false; try { if ( $categoriesGoal ) { - $res = $dbr->select( + $res = $this->dbr->select( $tables, $fields, $this->where, @@ -294,7 +293,7 @@ public function buildAndSelect( bool $calcRows = false ) { $pageIds[] = $row->page_id; } - $query = $dbr->selectSQLText( + $query = $this->dbr->selectSQLText( [ 'clgoal' => 'categorylinks' ], @@ -310,7 +309,7 @@ public function buildAndSelect( bool $calcRows = false ) { ] ); } else { - $query = $dbr->selectSQLText( + $query = $this->dbr->selectSQLText( $tables, $fields, $this->where, @@ -323,13 +322,13 @@ public function buildAndSelect( bool $calcRows = false ) { $this->sqlQuery = $query; if ( $calcRows ) { - $calcRowsResult = $dbr->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); + $calcRowsResult = $this->dbr->query( 'SELECT FOUND_ROWS() AS rowcount', __METHOD__ ); $total = $calcRowsResult->fetchRow(); $this->foundRows = intval( $total['rowcount'] ); $calcRowsResult->free(); } } catch ( Exception $e ) { - throw new MWException( __METHOD__ . ': ' . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $dbr->lastError() )->text() ); + throw new MWException( __METHOD__ . ': ' . wfMessage( 'dpl_query_error', DynamicPageListHooks::getVersion(), $this->dbr->lastError() )->text() ); } // Partially taken from intersection @@ -346,6 +345,7 @@ public function buildAndSelect( bool $calcRows = false ) { $qname = __METHOD__ . ' - ' . $pageName; $where = $this->where; $join = $this->join; + $dbr = $this->dbr; $doQuery = static function () use ( $qname, $dbr, $tables, $fields, $where, $options, $join ) { $res = $dbr->select( $tables, $fields, $where, $qname, $options, $join ); @@ -410,7 +410,7 @@ public function getSqlQuery() { * @return array */ public static function getTableNames() { - $DB = wfGetDB( DB_REPLICA, 'dpl' ); + $dbr = wfGetDB( DB_REPLICA, 'dpl' ); $tables = [ 'categorylinks', @@ -428,7 +428,7 @@ public static function getTableNames() { $tableNames = []; foreach ( $tables as $table ) { - $tableNames[$table] = $DB->tableName( $table ); + $tableNames[$table] = $dbr->tableName( $table ); } return $tableNames; @@ -451,7 +451,7 @@ public function addTable( $table, $alias ) { } if ( !isset( $this->tables[$alias] ) ) { - $this->tables[$alias] = $this->DB->tableName( $table ); + $this->tables[$alias] = $this->dbr->tableName( $table ); return true; } else { @@ -506,7 +506,7 @@ public function addNotWhere( $where ) { if ( is_array( $where ) ) { foreach ( $where as $field => $values ) { - $this->where[] = $field . ( count( $values ) > 1 ? ' NOT IN(' . $this->DB->makeList( $values ) . ')' : ' != ' . $this->DB->addQuotes( current( $values ) ) ); + $this->where[] = $field . ( count( $values ) > 1 ? ' NOT IN(' . $this->dbr->makeList( $values ) . ')' : ' != ' . $this->dbr->addQuotes( current( $values ) ) ); } } else { throw new MWException( __METHOD__ . ': An invalid NOT WHERE clause was passed.' ); @@ -755,7 +755,7 @@ private function convertTimestamp( $inputDate ) { } if ( is_numeric( $timestamp ) ) { - return $this->DB->addQuotes( $timestamp ); + return $this->dbr->addQuotes( $timestamp ); } return 0; @@ -1004,7 +1004,7 @@ private function _allrevisionssince( $option ) { * @param mixed $option */ private function _articlecategory( $option ) { - $this->addWhere( "{$this->tableNames['page']}.page_title IN (SELECT p2.page_title FROM {$this->tableNames['page']} p2 INNER JOIN {$this->tableNames['categorylinks']} clstc ON (clstc.cl_from = p2.page_id AND clstc.cl_to = " . $this->DB->addQuotes( $option ) . ") WHERE p2.page_namespace = 0)" ); + $this->addWhere( "{$this->tableNames['page']}.page_title IN (SELECT p2.page_title FROM {$this->tableNames['page']} p2 INNER JOIN {$this->tableNames['categorylinks']} clstc ON (clstc.cl_from = p2.page_id AND clstc.cl_to = " . $this->dbr->addQuotes( $option ) . ") WHERE p2.page_namespace = 0)" ); } /** @@ -1047,7 +1047,7 @@ private function _category( $option ) { $tableAlias, [ 'INNER JOIN', - "{$this->tableNames['page']}.page_id = {$tableAlias}.cl_from AND $tableAlias.cl_to {$comparisonType} " . $this->DB->addQuotes( str_replace( ' ', '_', $category ) ) + "{$this->tableNames['page']}.page_id = {$tableAlias}.cl_from AND $tableAlias.cl_to {$comparisonType} " . $this->dbr->addQuotes( str_replace( ' ', '_', $category ) ) ] ); } @@ -1060,7 +1060,7 @@ private function _category( $option ) { $ors = []; foreach ( $categories as $category ) { - $ors[] = "{$tableAlias}.cl_to {$comparisonType} " . $this->DB->addQuotes( str_replace( ' ', '_', $category ) ); + $ors[] = "{$tableAlias}.cl_to {$comparisonType} " . $this->dbr->addQuotes( str_replace( ' ', '_', $category ) ); } $joinOn .= implode( " {$operatorType} ", $ors ); @@ -1097,7 +1097,7 @@ private function _notcategory( $option ) { $tableAlias, [ 'LEFT OUTER JOIN', - "{$this->tableNames['page']}.page_id = {$tableAlias}.cl_from AND {$tableAlias}.cl_to {$operatorType}" . $this->DB->addQuotes( str_replace( ' ', '_', $category ) ) + "{$this->tableNames['page']}.page_id = {$tableAlias}.cl_from AND {$tableAlias}.cl_to {$operatorType}" . $this->dbr->addQuotes( str_replace( ' ', '_', $category ) ) ] ); @@ -1122,7 +1122,7 @@ private function _createdby( $option ) { $this->addWhere( [ - $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = creation_rev_actor.revactor_actor', + $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = creation_rev_actor.revactor_actor', 'creation_rev_actor.revactor_page = page_id', 'creation_rev.rev_parent_id = 0' ] @@ -1160,7 +1160,7 @@ private function _firstrevisionsince( $option ) { $this->addWhere( [ $this->tableNames['page'] . '.page_id = rev.revactor_page', - 'rev.revactor_timestamp >= ' . $this->DB->addQuotes( $option ) + 'rev.revactor_timestamp >= ' . $this->dbr->addQuotes( $option ) ] ); @@ -1219,9 +1219,9 @@ private function _imagecontainer( $option ) { foreach ( $option as $linkGroup ) { foreach ( $linkGroup as $link ) { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $ors[] = 'LOWER(CAST(ic.il_from AS char) = LOWER(' . $this->DB->addQuotes( $link->getArticleID() ) . ')'; + $ors[] = 'LOWER(CAST(ic.il_from AS char) = LOWER(' . $this->dbr->addQuotes( $link->getArticleID() ) . ')'; } else { - $ors[] = 'ic.il_from = ' . $this->DB->addQuotes( $link->getArticleID() ); + $ors[] = 'ic.il_from = ' . $this->dbr->addQuotes( $link->getArticleID() ); } } } @@ -1255,9 +1255,9 @@ private function _imageused( $option ) { foreach ( $option as $linkGroup ) { foreach ( $linkGroup as $link ) { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $ors[] = 'LOWER(CAST(il.il_to AS char)) = LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $ors[] = 'LOWER(CAST(il.il_to AS char)) = LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } else { - $ors[] = 'il.il_to = ' . $this->DB->addQuotes( $link->getDBkey() ); + $ors[] = 'il.il_to = ' . $this->dbr->addQuotes( $link->getDBkey() ); } } } @@ -1272,7 +1272,7 @@ private function _imageused( $option ) { * @param mixed $option */ private function _lastmodifiedby( $option ) { - $this->addWhere( $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = (SELECT revactor_actor FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id ORDER BY ' . $this->tableNames['revision_actor_temp'] . '.revactor_timestamp DESC LIMIT 1)' ); + $this->addWhere( $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = (SELECT revactor_actor FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id ORDER BY ' . $this->tableNames['revision_actor_temp'] . '.revactor_timestamp DESC LIMIT 1)' ); } /** @@ -1378,9 +1378,9 @@ private function _linksto( $option ) { } if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or .= ' AND LOWER(CAST(pl.pl_title AS char)) ' . $operator . ' LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $_or .= ' AND LOWER(CAST(pl.pl_title AS char)) ' . $operator . ' LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } else { - $_or .= ' AND pl.pl_title ' . $operator . ' ' . $this->DB->addQuotes( $link->getDBkey() ); + $_or .= ' AND pl.pl_title ' . $operator . ' ' . $this->dbr->addQuotes( $link->getDBkey() ); } $_or .= ')'; @@ -1401,9 +1401,9 @@ private function _linksto( $option ) { } if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or .= ' AND LOWER(CAST(' . $this->tableNames['pagelinks'] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $_or .= ' AND LOWER(CAST(' . $this->tableNames['pagelinks'] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } else { - $_or .= ' AND ' . $this->tableNames['pagelinks'] . '.pl_title ' . $operator . ' ' . $this->DB->addQuotes( $link->getDBkey() ); + $_or .= ' AND ' . $this->tableNames['pagelinks'] . '.pl_title ' . $operator . ' ' . $this->dbr->addQuotes( $link->getDBkey() ); } $_or .= ')'; @@ -1478,9 +1478,9 @@ private function _notlinksto( $option ) { } if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or .= ' AND LOWER(CAST(' . $this->tableNames['pagelinks'] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . '))'; + $_or .= ' AND LOWER(CAST(' . $this->tableNames['pagelinks'] . '.pl_title AS char)) ' . $operator . ' LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . '))'; } else { - $_or .= ' AND ' . $this->tableNames['pagelinks'] . '.pl_title ' . $operator . ' ' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $_or .= ' AND ' . $this->tableNames['pagelinks'] . '.pl_title ' . $operator . ' ' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } $ors[] = $_or; @@ -1513,7 +1513,7 @@ private function _linkstoexternal( $option ) { $ors = []; foreach ( $linkGroup as $link ) { - $ors[] = 'el.el_to LIKE ' . $this->DB->addQuotes( $link ); + $ors[] = 'el.el_to LIKE ' . $this->dbr->addQuotes( $link ); } $where .= '(' . implode( ' OR ', $ors ) . ')'; @@ -1522,7 +1522,7 @@ private function _linkstoexternal( $option ) { $ors = []; foreach ( $linkGroup as $link ) { - $ors[] = $this->tableNames['externallinks'] . '.el_to LIKE ' . $this->DB->addQuotes( $link ); + $ors[] = $this->tableNames['externallinks'] . '.el_to LIKE ' . $this->dbr->addQuotes( $link ); } $where .= '(' . implode( ' OR ', $ors ) . ')'; @@ -1572,7 +1572,7 @@ private function _minrevisions( $option ) { private function _modifiedby( $option ) { $this->addTable( 'revision_actor_temp', 'change_rev' ); - $this->addWhere( $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = change_rev.revactor_actor AND change_rev.revactor_page = page_id' ); + $this->addWhere( $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' = change_rev.revactor_actor AND change_rev.revactor_page = page_id' ); } /** @@ -1607,7 +1607,7 @@ private function _notcreatedby( $option ) { $this->addTable( 'revision', 'no_creation_rev' ); $this->addTable( 'revision_actor_temp', 'no_creation_rev_actor' ); - $this->addWhere( $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' != no_creation_rev_actor.revactor_actor AND no_creation_rev_actor.revactor_page = page_id AND no_creation_rev.rev_parent_id = 0' ); + $this->addWhere( $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' != no_creation_rev_actor.revactor_actor AND no_creation_rev_actor.revactor_page = page_id AND no_creation_rev.rev_parent_id = 0' ); } /** @@ -1616,7 +1616,7 @@ private function _notcreatedby( $option ) { * @param mixed $option */ private function _notlastmodifiedby( $option ) { - $this->addWhere( $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' != (SELECT revactor_actor FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id ORDER BY ' . $this->tableNames['revision_actor_temp'] . '.revactor_timestamp DESC LIMIT 1)' ); + $this->addWhere( $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' != (SELECT revactor_actor FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id ORDER BY ' . $this->tableNames['revision_actor_temp'] . '.revactor_timestamp DESC LIMIT 1)' ); } /** @@ -1625,7 +1625,7 @@ private function _notlastmodifiedby( $option ) { * @param mixed $option */ private function _notmodifiedby( $option ) { - $this->addWhere( 'NOT EXISTS (SELECT 1 FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id AND ' . $this->tableNames['revision_actor_temp'] . '.revactor_actor = ' . $this->DB->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' LIMIT 1)' ); + $this->addWhere( 'NOT EXISTS (SELECT 1 FROM ' . $this->tableNames['revision_actor_temp'] . ' WHERE ' . $this->tableNames['revision_actor_temp'] . '.revactor_page=page_id AND ' . $this->tableNames['revision_actor_temp'] . '.revactor_actor = ' . $this->dbr->addQuotes( $this->userFactory->newFromName( $option )->getActorId() ) . ' LIMIT 1)' ); } /** @@ -1695,7 +1695,7 @@ private function _order( $option ) { private function _ordercollation( $option ) { $option = mb_strtolower( $option ); - $res = $this->DB->query( 'SHOW CHARACTER SET' ); + $res = $this->dbr->query( 'SHOW CHARACTER SET' ); if ( !$res ) { return false; } @@ -1730,7 +1730,7 @@ private function _ordermethod( $option ) { $_namespaceIdToText = "CASE {$this->tableNames['page']}.page_namespace"; foreach ( $namespaces as $id => $name ) { - $_namespaceIdToText .= ' WHEN ' . intval( $id ) . ' THEN ' . $this->DB->addQuotes( $name . ':' ); + $_namespaceIdToText .= ' WHEN ' . intval( $id ) . ' THEN ' . $this->dbr->addQuotes( $name . ':' ); } $_namespaceIdToText .= ' END'; @@ -2043,15 +2043,15 @@ private function _title( $option ) { foreach ( $titles as $title ) { if ( $this->parameters->getParameter( 'openreferences' ) ) { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or = "LOWER(CAST(pl_title AS char)) {$comparisonType}" . strtolower( $this->DB->addQuotes( $title ) ); + $_or = "LOWER(CAST(pl_title AS char)) {$comparisonType}" . strtolower( $this->dbr->addQuotes( $title ) ); } else { - $_or = "pl_title {$comparisonType} " . $this->DB->addQuotes( $title ); + $_or = "pl_title {$comparisonType} " . $this->dbr->addQuotes( $title ); } } else { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or = "LOWER(CAST({$this->tableNames['page']}.page_title AS char)) {$comparisonType}" . strtolower( $this->DB->addQuotes( $title ) ); + $_or = "LOWER(CAST({$this->tableNames['page']}.page_title AS char)) {$comparisonType}" . strtolower( $this->dbr->addQuotes( $title ) ); } else { - $_or = "{$this->tableNames['page']}.page_title {$comparisonType}" . $this->DB->addQuotes( $title ); + $_or = "{$this->tableNames['page']}.page_title {$comparisonType}" . $this->dbr->addQuotes( $title ); } } @@ -2075,15 +2075,15 @@ private function _nottitle( $option ) { foreach ( $titles as $title ) { if ( $this->parameters->getParameter( 'openreferences' ) ) { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or = "LOWER(CAST(pl_title AS char)) {$comparisonType}" . strtolower( $this->DB->addQuotes( $title ) ); + $_or = "LOWER(CAST(pl_title AS char)) {$comparisonType}" . strtolower( $this->dbr->addQuotes( $title ) ); } else { - $_or = "pl_title {$comparisonType} " . $this->DB->addQuotes( $title ); + $_or = "pl_title {$comparisonType} " . $this->dbr->addQuotes( $title ); } } else { if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or = "LOWER(CAST({$this->tableNames['page']}.page_title AS char)) {$comparisonType}" . strtolower( $this->DB->addQuotes( $title ) ); + $_or = "LOWER(CAST({$this->tableNames['page']}.page_title AS char)) {$comparisonType}" . strtolower( $this->dbr->addQuotes( $title ) ); } else { - $_or = "{$this->tableNames['page']}.page_title {$comparisonType}" . $this->DB->addQuotes( $title ); + $_or = "{$this->tableNames['page']}.page_title {$comparisonType}" . $this->dbr->addQuotes( $title ); } } @@ -2111,7 +2111,7 @@ private function _titlegt( $option ) { $operator = 'LIKE'; $option = '%'; } else { - $option = $this->DB->addQuotes( $option ); + $option = $this->dbr->addQuotes( $option ); } if ( $this->parameters->getParameter( 'openreferences' ) ) { @@ -2139,7 +2139,7 @@ private function _titlelt( $option ) { $operator = 'LIKE'; $option = '%'; } else { - $option = $this->DB->addQuotes( $option ); + $option = $this->dbr->addQuotes( $option ); } if ( $this->parameters->getParameter( 'openreferences' ) ) { @@ -2202,9 +2202,9 @@ private function _uses( $option ) { $_or = '(tl.tl_namespace=' . intval( $link->getNamespace() ); if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or .= ' AND LOWER(CAST(tl.tl_title AS char)) = LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . '))'; + $_or .= ' AND LOWER(CAST(tl.tl_title AS char)) = LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . '))'; } else { - $_or .= ' AND tl.tl_title = ' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $_or .= ' AND tl.tl_title = ' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } $ors[] = $_or; @@ -2230,9 +2230,9 @@ private function _notuses( $option ) { $_or = '(' . $this->tableNames['templatelinks'] . '.tl_namespace=' . intval( $link->getNamespace() ); if ( $this->parameters->getParameter( 'ignorecase' ) ) { - $_or .= ' AND LOWER(CAST(' . $this->tableNames['templatelinks'] . '.tl_title AS char)) = LOWER(' . $this->DB->addQuotes( $link->getDBkey() ) . '))'; + $_or .= ' AND LOWER(CAST(' . $this->tableNames['templatelinks'] . '.tl_title AS char)) = LOWER(' . $this->dbr->addQuotes( $link->getDBkey() ) . '))'; } else { - $_or .= ' AND ' . $this->tableNames['templatelinks'] . '.tl_title = ' . $this->DB->addQuotes( $link->getDBkey() ) . ')'; + $_or .= ' AND ' . $this->tableNames['templatelinks'] . '.tl_title = ' . $this->dbr->addQuotes( $link->getDBkey() ) . ')'; } $ors[] = $_or; } From 475319ac0dd1973062a330119774d5dde1cf9363 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:26:34 -0700 Subject: [PATCH 21/43] Update LST.php --- includes/LST.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/includes/LST.php b/includes/LST.php index 7a1405a7..0a90cb54 100644 --- a/includes/LST.php +++ b/includes/LST.php @@ -573,7 +573,9 @@ public static function includeTemplate( $parser, Lister $lister, $dplNr, $articl $tCalls = preg_split( '/°³²/', ' ' . $text2 ); foreach ( $tCalls as $i => $tCall ) { - if ( ( $n = strpos( $tCall, ':' ) ) !== false ) { + $n = strpos( $tCall, ':' ); + + if ( $n !== false ) { $tCalls[$i][$n] = ' '; } } @@ -735,7 +737,9 @@ public static function includeTemplate( $parser, Lister $lister, $dplNr, $articl foreach ( $extractParm as $exParmKey => $exParm ) { $maxlen = -1; - if ( ( $limpos = strpos( $exParm, '[' ) ) > 0 && $exParm[strlen( $exParm ) - 1] == ']' ) { + $limpos = strpos( $exParm, '[' ); + + if ( $limpos > 0 && $exParm[strlen( $exParm ) - 1] == ']' ) { $maxlen = intval( substr( $exParm, $limpos + 1, strlen( $exParm ) - $limpos - 2 ) ); $exParm = substr( $exParm, 0, $limpos ); } From b9e08c3b7f51fe56f0137291a97f68047d538c16 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:30:16 -0700 Subject: [PATCH 22/43] Update mediawiki-tests.yml --- .github/workflows/mediawiki-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mediawiki-tests.yml b/.github/workflows/mediawiki-tests.yml index 102c1f9f..b53fc294 100644 --- a/.github/workflows/mediawiki-tests.yml +++ b/.github/workflows/mediawiki-tests.yml @@ -203,10 +203,10 @@ jobs: stage: qunit # Latest stable MediaWiki - PHP 7.3 (composer-test) - - mw: 'REL1_36' + - mw: 'REL1_37' php: 7.3 php-docker: 73 - experimental: true + experimental: false stage: composer-test runs-on: ubuntu-latest From 024e4dcbe162c523cdd3d82942aa76e85e281d33 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:36:17 -0700 Subject: [PATCH 23/43] Update extension.json --- extension.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension.json b/extension.json index f5700662..15ab736b 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "DynamicPageList3", - "version": "3.3.10", + "version": "3.4.0", "author": [ "'''Universal Omega'''", "Alexia E. Smith", From ddea1ecfc75fbad016a527d1fd3702123bcd2b80 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:40:05 -0700 Subject: [PATCH 24/43] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba0b4e49..0f3ad2ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -730,3 +730,7 @@ Many thanks to GreenReaper on GitHub for reporting and finding issues with core # Version 3.3.10 * Fix MessagesDirs to prevent mergeMessageFileList issue + +# Version 3.4.0 +* Improved query performance +* Added `maxQueryTime` and `queryCacheTime` configuration From d45740e35b148ca0129780a1129f216a3ceda945 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:47:01 -0700 Subject: [PATCH 25/43] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba3330f4..bff5f126 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,10 @@ These are DPL's configuration settings and along with their default values. To | $wgDplSettings['recursiveTagParse'] | false | Do recursive tag parsing on parser tags converting tags and functions such as magic words like {{PAGENAME}}. This is similar to the {{#dpl}} parser function call, but may not work exactly the same in all cases. | | $wgDplSettings['runFromProtectedPagesOnly'] | false | Set this to true to allow DPL to run from protected pages only. This is recommend if wiki administrators are having issues with malicious users creating computationally intensive queries. | | $wgDplSettings['handleSectionTag'] | false | Set this to true to have DPL handle
tags outside of DPL parser tags. | +| $wgDplSettings['maxQueryTime'] | 10000 | Maximum allowed time for database queries in milliseconds. | +| $wgDplSettings['queryCacheTime'] | 0 | Can help with situations where you have a template with the same query used on a large number of pages all being refreshed at once. The query cache cannot be purged. Suggested value between 30 to 600. | -The global variable {{manual|$wgNonincludableNamespaces}} is automatically respected by DPL. It will prevent the contents of the listed namespaces from appearing in DPL's output. +The global variable $wgNonincludableNamespaces is automatically respected by DPL3. It will prevent the contents of the listed namespaces from appearing in DPL's output. **Note: $wgDplSettings['maxResultCount'] is a LIMIT *on the SQL query itself*. Some DPL query parameters like includematch are applied *after* the SQL query, however, so results here may easily be misleading.** From abb1c9abb0161f98b85d818f162f36512c4b8ec3 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:49:39 -0700 Subject: [PATCH 26/43] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3ad2ec..58387e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -734,3 +734,5 @@ Many thanks to GreenReaper on GitHub for reporting and finding issues with core # Version 3.4.0 * Improved query performance * Added `maxQueryTime` and `queryCacheTime` configuration +* Fixed `AssignmentInControlStructures` PHPCS violations +* Additional cleanup From 1b4d9d8b90522d3a8059eae947f9c91bda5339a5 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Wed, 9 Mar 2022 20:01:50 -0700 Subject: [PATCH 27/43] Update README.md --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index bff5f126..06d8b382 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ The **DynamicPageList3** extension is a reporting tool for MediaWiki, listing category members and intersections with various formats and details. For full documentation, see the [manual](https://help.fandom.com/Extension:DPL3/Manual). -When invoked with a basic set of selection parameters DPL displays a list of pages in one or more categories. Selections may also be based on factors such as author, namespace, date, name pattern, usage of templates, or references to other articles. Output takes a variety of forms, some of which incorporate elements of selected articles. +When invoked with a basic set of selection parameters DPL3 displays a list of pages in one or more categories. Selections may also be based on factors such as author, namespace, date, name pattern, usage of templates, or references to other articles. Output takes a variety of forms, some of which incorporate elements of selected articles. -This extension is invoked with the parser function {{#dpl: .... }} or parser tag <DPL>. A [Wikimedia](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:DynamicPageList_(Wikimedia))-compatible implementation of certain features can be invoked with <DynamicPageList>. +This extension is invoked with the parser function {{#dpl: .... }} or parser tag <DPL>. A [Wikimedia](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:DynamicPageList_(Wikimedia))-compatible implementation of certain features can be invoked with <DynamicPageList>. -Complex look ups can result in computationally expensive database queries. However, by default all output is cached for a period of one hour to reduce the need to rerun the query every page load. The [DPL:Parameters: Other Parameters](https://help.fandom.com/Extension:DPL3/Parameters:_Other_parameters#cacheperiod) manual page contains information on parameters that can be used to disable the cache and allow instant updates. +Complex look ups can result in computationally expensive database queries. However, by default all output is cached for a period of one hour to reduce the need to rerun the query every page load. The [DPL:Parameters: Other Parameters](https://help.fandom.com/Extension:DPL3/Parameters:_Other_parameters#cacheperiod) manual page contains information on parameters that can be used to disable the cache and allow instant updates. * Manual and Complete Documentation: [Documentation](https://help.fandom.com/Extension:DPL3/Manual) * Source Code: [Source code at GitHub](https://github.com/Universal-Omega/DynamicPageList3) @@ -18,51 +18,51 @@ Complex look ups can result in computationally expensive database queries. Howe Please see the [releases page](https://github.com/Universal-Omega/DynamicPageList3/releases) for the latest releases. ## Configuration -These are DPL's configuration settings and along with their default values. To change them make sure they are defined before including the extension on the wiki. More configuration information is available on the **[MediaWiki extension page](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:DynamicPageList3#Configuration)**. +These are DPL3's configuration settings and along with their default values. To change them make sure they are defined before including the extension on the wiki. More configuration information is available on the **[MediaWiki extension page](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:DynamicPageList3#Configuration)**. -**Note:** In release 3.0.4 the configuration variable name was changed from $dplSettings to $wgDplSettings. This was to faciliate compatibility with Mediawiki 1.25's extension registration change. +**Note:** In release 3.0.4 the configuration variable name was changed from $dplSettings to $wgDplSettings. This was to faciliate compatibility with Mediawiki 1.25's extension registration change. | Setting | Default | Description | |:--------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| $wgDplSettings['allowedNamespaces'] | null | By default all existing namespaces are used when DPL initializes. Customize this setting with an array of namespace constants to restrict DPL to work only in those namespaces. | +| $wgDplSettings['allowedNamespaces'] | null | By default all existing namespaces are used when DPL3 initializes. Customize this setting with an array of namespace constants to restrict DPL3 to work only in those namespaces. | | $wgDplSettings['allowUnlimitedCategories'] | false | Set this to true to ignore 'maxCategoryCount' and allow unlimited categories. Please note that large amounts of categories in a query can slow down or crash servers. | | $wgDplSettings['allowUnlimitedResults'] | false | Set this to true to ignore 'maxResultCount' and allow unlimited results. Please note that large result sets may result in slow or failed page loads. | -| $wgDplSettings['behavingLikeIntersection'] | false | Set DPL to always behave like Extension:Intersection. | +| $wgDplSettings['behavingLikeIntersection'] | false | Set DPL3 to always behave like Extension:Intersection. | | $wgDplSettings['categoryStyleListCutoff'] | 6 | Maximum number of items in a category list before being cut off. | -| $wgDplSettings['fixedCategories'] | [] | This does something with preventing DPL from "looking" at these categories. | +| $wgDplSettings['fixedCategories'] | [] | This does something with preventing DPL3 from "looking" at these categories. | | $wgDplSettings['functionalRichness'] | 3 | Set the level of parameters available to end users. | | $wgDplSettings['maxCategoryCount'] | 4 | Maximum number of categories to allow in queries. | | $wgDplSettings['minCategoryCount'] | 0 | Minimum number of categories to allow in queries. | | $wgDplSettings['maxResultCount'] | 500 | Maximum number of results to return from a query. | -| $wgDplSettings['recursiveTagParse'] | false | Do recursive tag parsing on parser tags converting tags and functions such as magic words like {{PAGENAME}}. This is similar to the {{#dpl}} parser function call, but may not work exactly the same in all cases. | -| $wgDplSettings['runFromProtectedPagesOnly'] | false | Set this to true to allow DPL to run from protected pages only. This is recommend if wiki administrators are having issues with malicious users creating computationally intensive queries. | -| $wgDplSettings['handleSectionTag'] | false | Set this to true to have DPL handle
tags outside of DPL parser tags. | +| $wgDplSettings['recursiveTagParse'] | false | Do recursive tag parsing on parser tags converting tags and functions such as magic words like {{PAGENAME}}. This is similar to the {{#dpl}} parser function call, but may not work exactly the same in all cases. | +| $wgDplSettings['runFromProtectedPagesOnly'] | false | Set this to true to allow DPL3 to run from protected pages only. This is recommend if wiki administrators are having issues with malicious users creating computationally intensive queries. | +| $wgDplSettings['handleSectionTag'] | false | Set this to true to have DPL3 handle
tags outside of the parser tags provided by DPL3. | | $wgDplSettings['maxQueryTime'] | 10000 | Maximum allowed time for database queries in milliseconds. | | $wgDplSettings['queryCacheTime'] | 0 | Can help with situations where you have a template with the same query used on a large number of pages all being refreshed at once. The query cache cannot be purged. Suggested value between 30 to 600. | -The global variable $wgNonincludableNamespaces is automatically respected by DPL3. It will prevent the contents of the listed namespaces from appearing in DPL's output. +The global variable $wgNonincludableNamespaces is automatically respected by DPL3. It will prevent the contents of the listed namespaces from appearing in DPL3's output. -**Note: $wgDplSettings['maxResultCount'] is a LIMIT *on the SQL query itself*. Some DPL query parameters like includematch are applied *after* the SQL query, however, so results here may easily be misleading.** +**Note: $wgDplSettings['maxResultCount'] is a LIMIT *on the SQL query itself*. Some DPL3 query parameters like includematch are applied *after* the SQL query, however, so results here may easily be misleading.** ### Functional Richness -DynamicPageList3 has many features which are unlocked based on the maximum functional richness level. There are some that can cause high CPU or database load and should be used sparingly. +DynamicPageList3 has many features which are unlocked based on the maximum functional richness level. There are some that can cause high CPU or database load and should be used sparingly. * $wgDplSettings['functionalRichness'] = 0 is equivalent to Wikimedia's [DynamicPageList](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:DynamicPageList_(Wikimedia)) * $wgDplSettings['functionalRichness'] = 1 adds additional formatting parameters * $wgDplSettings['functionalRichness'] = 2 adds performance equivalent features for templates and pagelinks * $wgDplSettings['functionalRichness'] = 3 allows more-expensive page inclusion features and regular expression queries. -* $wgDplSettings['functionalRichness'] = 4 permits exotic and potentially dangerous batch update and delete operations; not recommended for public websites. Includes debugging parameters for testing and development. +* $wgDplSettings['functionalRichness'] = 4 permits exotic and potentially dangerous batch update and delete operations; not recommended for public websites. Includes debugging parameters for testing and development. ## Usage -### Extended DPL Functionality -Extended DPL is invoked by using the parser function {{#dpl: .... }}, or the parser extension tag .... . +### Extended DPL3 Functionality +Extended DPL3 is invoked by using the parser function {{#dpl: .... }}, or the parser extension tag <DPL> .... </DPL>. *See [Manual - **General Usage and Invocation Syntax**](https://help.fandom.com/Extension:DPL3/General_usage_and_invocation_syntax) and [DPL:Parameters: **Criteria for Page Selection**](https://help.fandom.com/Extension:DPL3/Parameters:_Criteria_for_page_selection)* ### Backwards Compatibility -Functionality compatible with Wikimedia's DPL extension can be invoked with <DynamicPageList> .... </DynamicPageList>. Further information can be found on the [Compatibility manual page](https://help.fandom.com/Extension:DPL3/Compatibility). +Functionality compatible with Wikimedia's DPL extension (Intersection) can be invoked with <DynamicPageList> .... </DynamicPageList>. Further information can be found on the [Compatibility manual page](https://help.fandom.com/Extension:DPL3/Compatibility). ## Usage Philosophy and Overview With the assumption there are some articles writtne about *countries* those articles will typically have three things in common: @@ -79,7 +79,7 @@ category=countries }} -With DPL one could: +With DPL3 one could: * Generate a list of all those articles (or a random sample) * Show metadata of the articles (popularity, date of last update, ..) * Show one or more chapters of the articles ('transclude' content) @@ -134,8 +134,8 @@ With DPL one could: ## Considerations ### Performance -DPL's code execution and database access is typically fast for typical category and article look ups. However, using loose LIKE and REGEXP match parameters and/or requesting large data sets can result in long database access times. Parser time should also be kept in consideration. For example, having the query of image results go into a template that displays them will result in a parser media transform for each one. This can quickly eat up 2MBs of RAM per media transform. +DPL3's code execution and database access is typically fast for typical category and article look ups. However, using loose LIKE and REGEXP match parameters and/or requesting large data sets can result in long database access times. Parser time should also be kept in consideration. For example, having the query of image results go into a template that displays them will result in a parser media transform for each one. This can quickly eat up 2MBs of RAM per media transform. ## See Also ### Further Reading -DPL can do much more than we can explain here. A complete **[manual](https://help.fandom.com/Extension:DPL3/Manual)** is available with full parameter documentation. +DPL3 can do much more than we can explain here. A complete **[manual](https://help.fandom.com/Extension:DPL3/Manual)** is available with full parameter documentation. From 34932fdebbe0a730f1c26174f8c92b526036c0b9 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Thu, 10 Mar 2022 11:20:56 -0700 Subject: [PATCH 28/43] Update Parse.php --- includes/Parse.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/includes/Parse.php b/includes/Parse.php index d5b09b65..8766b859 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -11,16 +11,8 @@ use RequestContext; use Title; use WebRequest; -use Wikimedia\Rdbms\IDatabase; class Parse { - /** - * Mediawiki Database Object - * - * @var IDatabase - */ - private $DB = null; - /** * Parameters Object * @@ -98,7 +90,6 @@ class Parse { ]; public function __construct() { - $this->DB = wfGetDB( DB_REPLICA, 'dpl' ); $this->parameters = new Parameters(); $this->logger = new Logger(); $this->tableNames = Query::getTableNames(); From 91b3ee1804089124296bffb20d1e5abaf3bb5dfe Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 11:47:52 -0700 Subject: [PATCH 29/43] Add poolcounter error --- i18n/en.json | 2 ++ includes/DynamicPageListHooks.php | 2 ++ includes/Logger.php | 2 ++ includes/Parse.php | 9 +++++++++ 4 files changed, 15 insertions(+) diff --git a/i18n/en.json b/i18n/en.json index d51623ea..a2bce8a1 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -10,6 +10,7 @@ "intersection_toofewcats": "Error: Too few categories!", "intersection_noresults": "Error: No results!", "intersection_noincludecats": "Error: You need to include at least one category, or specify a namespace!", + "intersection_pcerror": "This list cannot be displayed because the servers are overloaded. Please try again later.", "dpl-desc": "A highly flexible report generator for MediaWikis", "dpl_log_1": "Error: Wrong '$1' parameter: '$2'! Help: $1= empty string (Main)$3.", "dpl_log_2": "Error: Wrong '$1' parameter: '$2'! Help: $1= full pagename.", @@ -33,6 +34,7 @@ "dpl_log_20": "Warning: An infinite transclusion loop is created by page '$0'.", "dpl_log_21": "Query: $0", "dpl_log_22": "Warning: No parameter option supplied for '$1'. (Missing '=')", + "dpl_log_23": "Warning: List cannot be displayed because the servers are overloaded.", "dpl_articlecount": "There {{PLURAL:$1|is one article|are $1 articles}} in this heading.", "action-dpl_param_update_rules": "to use the parameter 'updaterules'", "action-dpl_param_delete_rules": "to use the parameter 'deleterules'", diff --git a/includes/DynamicPageListHooks.php b/includes/DynamicPageListHooks.php index 0509ad8e..f4c08a5d 100644 --- a/includes/DynamicPageListHooks.php +++ b/includes/DynamicPageListHooks.php @@ -54,6 +54,8 @@ class DynamicPageListHooks { public const WARN_TRANSCLUSIONLOOP = 2020; + public const WARN_POOLCOUNTER = 2023; + public const DEBUG_QUERY = 3021; /** @var array */ diff --git a/includes/Logger.php b/includes/Logger.php index 28bb9651..e7254309 100644 --- a/includes/Logger.php +++ b/includes/Logger.php @@ -53,6 +53,8 @@ public function msg() { $text = wfMessage( 'intersection_noresults', $args )->text(); } elseif ( $errorId == DynamicPageListHooks::FATAL_NOSELECTION ) { $text = wfMessage( 'intersection_noincludecats', $args )->text(); + } elseif ( $errorId == DynamicPageListHooks::WARN_POOLCOUNTER ) { + $text = wfMessage( 'intersection_pcerror', $args )->text(); } } diff --git a/includes/Parse.php b/includes/Parse.php index 8766b859..7dc5c4a6 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -207,6 +207,15 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa try { $query = new Query( $this->parameters ); $rows = $query->buildAndSelect( $calcRows ); + if ( $rows === false ) { + // This error path is very fast (We exit immediately if poolcounter is full) + // Thus it should be safe to try again in ~5 minutes. + $parser->getOutput()->updateCacheExpiry( 4 * 60 + mt_rand( 0, 120 ) ); + + // Pool counter all threads in use. + $this->logger->addMessage( DynamicPageListHooks::WARN_POOLCOUNTER ); + return $this->getFullOutput( true ); + } } catch ( MWException $e ) { $this->logger->addMessage( DynamicPageListHooks::FATAL_SQLBUILDERROR, $e->getMessage() ); return $this->getFullOutput(); From df9f8c8bdad8ecce2e679e7b33f4f2a320458e3b Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 11:53:11 -0700 Subject: [PATCH 30/43] Update Query.php --- includes/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Query.php b/includes/Query.php index 17207271..d7ea1388 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -172,7 +172,7 @@ public function __construct( Parameters $parameters ) { * Start a query build. Returns found rows. * * @param bool $calcRows - * @return array + * @return array|bool */ public function buildAndSelect( bool $calcRows = false ) { global $wgNonincludableNamespaces; From c0c066c6a643d722c85cb2a3f5cc04cd12aeeb34 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:11:10 -0700 Subject: [PATCH 31/43] Update en.json --- i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.json b/i18n/en.json index a2bce8a1..470f3f8f 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -34,7 +34,7 @@ "dpl_log_20": "Warning: An infinite transclusion loop is created by page '$0'.", "dpl_log_21": "Query: $0", "dpl_log_22": "Warning: No parameter option supplied for '$1'. (Missing '=')", - "dpl_log_23": "Warning: List cannot be displayed because the servers are overloaded.", + "dpl_log_23": "Warning: List cannot be displayed because the servers are overloaded. Please try again later.", "dpl_articlecount": "There {{PLURAL:$1|is one article|are $1 articles}} in this heading.", "action-dpl_param_update_rules": "to use the parameter 'updaterules'", "action-dpl_param_delete_rules": "to use the parameter 'deleterules'", From 610868c182befe8047a04a7289ddc6d4fae8cd21 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:15:23 -0700 Subject: [PATCH 32/43] Update Parse.php --- includes/Parse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Parse.php b/includes/Parse.php index 7dc5c4a6..af6b64a1 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -239,7 +239,7 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa /*********************/ /* Handle No Results */ /*********************/ - if ( $numRows <= 0 || empty( $articles ) ) { + if ( $numRows == 0 || empty( $articles ) ) { return $this->getFullOutput( 0, false ); } From 1269869b273d012da93b682b2f9398e6ac92c5b1 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:18:58 -0700 Subject: [PATCH 33/43] Update Parse.php --- includes/Parse.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/includes/Parse.php b/includes/Parse.php index af6b64a1..1c1b19a5 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -350,17 +350,18 @@ private function processQueryResults( $rows, Parser $parser ) { $randomCount = $this->parameters->getParameter( 'randomcount' ); if ( $randomCount > 0 ) { $nResults = count( $rows ); - // mt_srand() seeding was removed due to PHP 5.2.1 and above no longer generating the same sequence for the same seed. - //Constrain the total amount of random results to not be greater than the total results. + + // Constrain the total amount of random results to not be greater than the total results. if ( $randomCount > $nResults ) { $randomCount = $nResults; } - // This is 50% to 150% faster than the old while (true) version that could keep rechecking the same random key over and over again. // Generate pick numbers for results. $pick = range( 1, $nResults ); + // Shuffle the pick numbers. shuffle( $pick ); + // Select pick numbers from the beginning to the maximum of $randomCount. $pick = array_slice( $pick, 0, $randomCount ); } From 2814701b3334203405a9c70854a17c57b3cc9000 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:16:41 -0700 Subject: [PATCH 34/43] Update DynamicPageListHooks.php --- includes/DynamicPageListHooks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/DynamicPageListHooks.php b/includes/DynamicPageListHooks.php index f4c08a5d..71bdf59a 100644 --- a/includes/DynamicPageListHooks.php +++ b/includes/DynamicPageListHooks.php @@ -36,6 +36,8 @@ class DynamicPageListHooks { public const FATAL_SQLBUILDERROR = 1024; + public const FATAL_POOLCOUNTER = 1025; + public const WARN_UNKNOWNPARAM = 2013; public const WARN_PARAMNOOPTION = 2022; @@ -54,8 +56,6 @@ class DynamicPageListHooks { public const WARN_TRANSCLUSIONLOOP = 2020; - public const WARN_POOLCOUNTER = 2023; - public const DEBUG_QUERY = 3021; /** @var array */ From 61a5e6918cd0e0b66be7e7a6ffe10d71e477043c Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:17:15 -0700 Subject: [PATCH 35/43] Update Logger.php --- includes/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Logger.php b/includes/Logger.php index e7254309..e20ff6d6 100644 --- a/includes/Logger.php +++ b/includes/Logger.php @@ -53,7 +53,7 @@ public function msg() { $text = wfMessage( 'intersection_noresults', $args )->text(); } elseif ( $errorId == DynamicPageListHooks::FATAL_NOSELECTION ) { $text = wfMessage( 'intersection_noincludecats', $args )->text(); - } elseif ( $errorId == DynamicPageListHooks::WARN_POOLCOUNTER ) { + } elseif ( $errorId == DynamicPageListHooks::FATAL_POOLCOUNTER ) { $text = wfMessage( 'intersection_pcerror', $args )->text(); } } From bdeabb631bca1ac2b3fdefaaf0064bb1416551b3 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:17:58 -0700 Subject: [PATCH 36/43] Update Parse.php --- includes/Parse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Parse.php b/includes/Parse.php index 1c1b19a5..dd8996af 100644 --- a/includes/Parse.php +++ b/includes/Parse.php @@ -213,7 +213,7 @@ public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTa $parser->getOutput()->updateCacheExpiry( 4 * 60 + mt_rand( 0, 120 ) ); // Pool counter all threads in use. - $this->logger->addMessage( DynamicPageListHooks::WARN_POOLCOUNTER ); + $this->logger->addMessage( DynamicPageListHooks::FATAL_POOLCOUNTER ); return $this->getFullOutput( true ); } } catch ( MWException $e ) { From 29a108e62cab72e852538962c60db68d7552febc Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:19:06 -0700 Subject: [PATCH 37/43] Update en.json --- i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.json b/i18n/en.json index 470f3f8f..0e61209e 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -34,7 +34,7 @@ "dpl_log_20": "Warning: An infinite transclusion loop is created by page '$0'.", "dpl_log_21": "Query: $0", "dpl_log_22": "Warning: No parameter option supplied for '$1'. (Missing '=')", - "dpl_log_23": "Warning: List cannot be displayed because the servers are overloaded. Please try again later.", + "dpl_log_25": "Error: List cannot be displayed because the servers are overloaded. Please try again later.", "dpl_articlecount": "There {{PLURAL:$1|is one article|are $1 articles}} in this heading.", "action-dpl_param_update_rules": "to use the parameter 'updaterules'", "action-dpl_param_delete_rules": "to use the parameter 'deleterules'", From 26783b9c0f03bd375e352b74c1876793219f5449 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:28:29 -0700 Subject: [PATCH 38/43] Update DynamicPageListHooks.php --- includes/DynamicPageListHooks.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/DynamicPageListHooks.php b/includes/DynamicPageListHooks.php index 71bdf59a..74218f7c 100644 --- a/includes/DynamicPageListHooks.php +++ b/includes/DynamicPageListHooks.php @@ -32,11 +32,11 @@ class DynamicPageListHooks { public const FATAL_MISSINGPARAMFUNCTION = 1022; - public const FATAL_NOTPROTECTED = 1023; + public const FATAL_POOLCOUNTER = 1023; - public const FATAL_SQLBUILDERROR = 1024; + public const FATAL_NOTPROTECTED = 1024; - public const FATAL_POOLCOUNTER = 1025; + public const FATAL_SQLBUILDERROR = 1025; public const WARN_UNKNOWNPARAM = 2013; From fe9947d64a4c89ab1bad4660bb54cb46439141df Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:29:06 -0700 Subject: [PATCH 39/43] Update en.json --- i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.json b/i18n/en.json index 0e61209e..18ea4007 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -34,7 +34,7 @@ "dpl_log_20": "Warning: An infinite transclusion loop is created by page '$0'.", "dpl_log_21": "Query: $0", "dpl_log_22": "Warning: No parameter option supplied for '$1'. (Missing '=')", - "dpl_log_25": "Error: List cannot be displayed because the servers are overloaded. Please try again later.", + "dpl_log_23": "Error: List cannot be displayed because the servers are overloaded. Please try again later.", "dpl_articlecount": "There {{PLURAL:$1|is one article|are $1 articles}} in this heading.", "action-dpl_param_update_rules": "to use the parameter 'updaterules'", "action-dpl_param_delete_rules": "to use the parameter 'deleterules'", From c5c85a65c03e7ee8bf9d9dbf4f91b5ba75625492 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:38:22 -0700 Subject: [PATCH 40/43] Update mediawiki-tests.yml --- .github/workflows/mediawiki-tests.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mediawiki-tests.yml b/.github/workflows/mediawiki-tests.yml index b53fc294..da01f76e 100644 --- a/.github/workflows/mediawiki-tests.yml +++ b/.github/workflows/mediawiki-tests.yml @@ -351,17 +351,19 @@ jobs: if [ -e composer.json ]; then composer install --prefer-dist --no-progress --no-interaction composer fix - rm composer.lock - - git config --global user.name "github-actions" - git config --global user.email "github-actions@users.noreply.github.com" - git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git checkout -b ${GITHUB_HEAD_REF} - git add . - git commit -am "CI: lint code to MediaWiki standards" -m "Check commit and GitHub actions for more details" || echo "No changes to commit" - git pull origin ${GITHUB_HEAD_REF} --rebase - git push --set-upstream origin ${GITHUB_HEAD_REF} + if ! git diff --exit-code --quiet; then + git config --global user.name "github-actions" + git config --global user.email "github-actions@users.noreply.github.com" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git checkout -b ${GITHUB_HEAD_REF} + git add . + git commit -am "CI: lint code to MediaWiki standards" -m "Check commit and GitHub actions for more details" + git pull origin ${GITHUB_HEAD_REF} --rebase + git push --set-upstream origin ${GITHUB_HEAD_REF} + else + echo "No changes to commit" + fi fi - name: Main Test From 4636a5941120eda0f9811159a881957f203e58a2 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:54:37 -0700 Subject: [PATCH 41/43] Update Query.php --- includes/Query.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/Query.php b/includes/Query.php index d7ea1388..075610de 100644 --- a/includes/Query.php +++ b/includes/Query.php @@ -352,8 +352,8 @@ public function buildAndSelect( bool $calcRows = false ) { return iterator_to_array( $res ); }; - $poolCounterKey = 'nowait:dpl-query:' . WikiMap::getCurrentWikiId(); - $worker = new PoolCounterWorkViaCallback( 'DPL', $poolCounterKey, [ + $poolCounterKey = 'nowait:dpl3-query:' . WikiMap::getCurrentWikiId(); + $worker = new PoolCounterWorkViaCallback( 'DPL3', $poolCounterKey, [ 'doWork' => $doQuery, ] ); @@ -364,7 +364,7 @@ public function buildAndSelect( bool $calcRows = false ) { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); return $cache->getWithSetCallback( - $cache->makeKey( 'DPLQuery', hash( 'sha256', $query ) ), + $cache->makeKey( 'DPL3Query', hash( 'sha256', $query ) ), $queryCacheTime, static function ( $oldVal, &$ttl, &$setOpts ) use ( $worker, $dbr ){ $setOpts += Database::getCacheSetOptions( $dbr ); From 55311f727a7eb9fef68fca2f245c20c2991398e8 Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sun, 13 Mar 2022 12:17:22 -0600 Subject: [PATCH 42/43] Update CHANGELOG.md --- CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58387e4d..ba0b4e49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -730,9 +730,3 @@ Many thanks to GreenReaper on GitHub for reporting and finding issues with core # Version 3.3.10 * Fix MessagesDirs to prevent mergeMessageFileList issue - -# Version 3.4.0 -* Improved query performance -* Added `maxQueryTime` and `queryCacheTime` configuration -* Fixed `AssignmentInControlStructures` PHPCS violations -* Additional cleanup From c89816cca78dbd836fa0aa2f9010c9783833a80a Mon Sep 17 00:00:00 2001 From: Universal Omega <54654040+Universal-Omega@users.noreply.github.com> Date: Sun, 13 Mar 2022 12:17:50 -0600 Subject: [PATCH 43/43] Update extension.json --- extension.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension.json b/extension.json index 15ab736b..f5700662 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "DynamicPageList3", - "version": "3.4.0", + "version": "3.3.10", "author": [ "'''Universal Omega'''", "Alexia E. Smith",