MagicWordFactory to replace MagicWord static members/methods

Static members of MagicWord have been removed.

Static methods are soft-deprecated and forward to the factory.  They
will be hard-deprecated when all callers are removed from core.

MagicWord::clearCache() has been removed.  Instead, call
resetServiceForTesting( 'MagicWordFactory' ) on your MediaWikiServices
object.

Change-Id: Ie061fe90f9b9eca0cbf7e8199d9ca325c464867a
Bug: T200247
This commit is contained in:
Aryeh Gregor 2018-07-24 19:44:09 +03:00
parent 0b8c620818
commit 5189333c39
10 changed files with 306 additions and 199 deletions

View file

@ -209,6 +209,11 @@ because of Phabricator reports.
* getItemsData: Use getItems instead and get the data property
* Two OutputPage methods, addMetadataLink() and getMetadataAttribute(), were
removed. Use addLink() instead.
* All MagicWord static member variables have been removed. Use appropriate
hooks or MagicWordFactory methods instead.
* MagicWord::clearCache() has been removed. Instead, create a new
MagicWordFactory, such as by calling
resetServiceForTesting( 'MagicWordFactory' ) on a MediaWikiServices.
=== Deprecations in 1.32 ===
* Use of a StartProfiler.php file is deprecated in favour of placing
@ -304,6 +309,8 @@ because of Phabricator reports.
* The $wgExternalDiffEngine value 'wikidiff2' is deprecated. To use wikidiff2
just enable the PHP extension, and it will be autodetected.
* The wfUseMW function, soft-deprecated in 1.26, is now hard deprecated.
* All MagicWord static methods are now deprecated. Use the MagicWordFactory
methods instead.
=== Other changes in 1.32 ===
* (T198811) The following tables have had their UNIQUE indexes turned into

View file

@ -832,6 +832,7 @@ $wgAutoloadLocalClasses = [
'MachineReadableRCFeedFormatter' => __DIR__ . '/includes/rcfeed/MachineReadableRCFeedFormatter.php',
'MagicWord' => __DIR__ . '/includes/MagicWord.php',
'MagicWordArray' => __DIR__ . '/includes/MagicWordArray.php',
'MagicWordFactory' => __DIR__ . '/includes/MagicWordFactory.php',
'MailAddress' => __DIR__ . '/includes/mail/MailAddress.php',
'MainConfigDependency' => __DIR__ . '/includes/cache/CacheDependency.php',
'MaintainableDBConnRef' => __DIR__ . '/includes/libs/rdbms/database/MaintainableDBConnRef.php',

View file

@ -21,20 +21,18 @@
* @ingroup Parser
*/
use MediaWiki\MediaWikiServices;
/**
* This class encapsulates "magic words" such as "#redirect", __NOTOC__, etc.
*
* @par Usage:
* @code
* if (MagicWord::get( 'redirect' )->match( $text ) ) {
* if ( $magicWordFactory->get( 'redirect' )->match( $text ) ) {
* // some code
* }
* @endcode
*
* Possible future improvements:
* * Simultaneous searching for a number of magic words
* * MagicWord::$mObjects in shared memory
*
* Please avoid reading the data out of one of these objects and then writing
* special case code. If possible, add another match()-like function here.
*
@ -92,170 +90,12 @@ class MagicWord {
/** @var bool */
private $mFound = false;
/** @var bool */
public static $mVariableIDsInitialised = false;
/** @var string[] */
public static $mVariableIDs = [
'!',
'currentmonth',
'currentmonth1',
'currentmonthname',
'currentmonthnamegen',
'currentmonthabbrev',
'currentday',
'currentday2',
'currentdayname',
'currentyear',
'currenttime',
'currenthour',
'localmonth',
'localmonth1',
'localmonthname',
'localmonthnamegen',
'localmonthabbrev',
'localday',
'localday2',
'localdayname',
'localyear',
'localtime',
'localhour',
'numberofarticles',
'numberoffiles',
'numberofedits',
'articlepath',
'pageid',
'sitename',
'server',
'servername',
'scriptpath',
'stylepath',
'pagename',
'pagenamee',
'fullpagename',
'fullpagenamee',
'namespace',
'namespacee',
'namespacenumber',
'currentweek',
'currentdow',
'localweek',
'localdow',
'revisionid',
'revisionday',
'revisionday2',
'revisionmonth',
'revisionmonth1',
'revisionyear',
'revisiontimestamp',
'revisionuser',
'revisionsize',
'subpagename',
'subpagenamee',
'talkspace',
'talkspacee',
'subjectspace',
'subjectspacee',
'talkpagename',
'talkpagenamee',
'subjectpagename',
'subjectpagenamee',
'numberofusers',
'numberofactiveusers',
'numberofpages',
'currentversion',
'rootpagename',
'rootpagenamee',
'basepagename',
'basepagenamee',
'currenttimestamp',
'localtimestamp',
'directionmark',
'contentlanguage',
'pagelanguage',
'numberofadmins',
'cascadingsources',
];
/** Array of caching hints for ParserCache
* @var array [ string => int ]
*/
public static $mCacheTTLs = [
'currentmonth' => 86400,
'currentmonth1' => 86400,
'currentmonthname' => 86400,
'currentmonthnamegen' => 86400,
'currentmonthabbrev' => 86400,
'currentday' => 3600,
'currentday2' => 3600,
'currentdayname' => 3600,
'currentyear' => 86400,
'currenttime' => 3600,
'currenthour' => 3600,
'localmonth' => 86400,
'localmonth1' => 86400,
'localmonthname' => 86400,
'localmonthnamegen' => 86400,
'localmonthabbrev' => 86400,
'localday' => 3600,
'localday2' => 3600,
'localdayname' => 3600,
'localyear' => 86400,
'localtime' => 3600,
'localhour' => 3600,
'numberofarticles' => 3600,
'numberoffiles' => 3600,
'numberofedits' => 3600,
'currentweek' => 3600,
'currentdow' => 3600,
'localweek' => 3600,
'localdow' => 3600,
'numberofusers' => 3600,
'numberofactiveusers' => 3600,
'numberofpages' => 3600,
'currentversion' => 86400,
'currenttimestamp' => 3600,
'localtimestamp' => 3600,
'pagesinnamespace' => 3600,
'numberofadmins' => 3600,
'numberingroup' => 3600,
];
/** @var string[] */
public static $mDoubleUnderscoreIDs = [
'notoc',
'nogallery',
'forcetoc',
'toc',
'noeditsection',
'newsectionlink',
'nonewsectionlink',
'hiddencat',
'index',
'noindex',
'staticredirect',
'notitleconvert',
'nocontentconvert',
];
/** @var string[] */
public static $mSubstIDs = [
'subst',
'safesubst',
];
/** @var array [ string => MagicWord ] */
public static $mObjects = [];
/** @var MagicWordArray */
public static $mDoubleUnderscoreArray = null;
/**#@-*/
/**
* Create a new MagicWord object
*
* Use factory instead: MagicWord::get
* Use factory instead: MagicWordFactory::get
*
* @param string|null $id The internal name of the magic word
* @param string[]|string $syn synonyms for the magic word
@ -273,36 +113,29 @@ class MagicWord {
* @param string $id The internal name of the magic word
*
* @return MagicWord
* @deprecated since 1.32, use MagicWordFactory::get
*/
public static function &get( $id ) {
if ( !isset( self::$mObjects[$id] ) ) {
$mw = new MagicWord();
$mw->load( $id );
self::$mObjects[$id] = $mw;
}
return self::$mObjects[$id];
public static function get( $id ) {
return MediaWikiServices::getInstance()->getMagicWordFactory()->get( $id );
}
/**
* Get an array of parser variable IDs
*
* @return string[]
* @deprecated since 1.32, use MagicWordFactory::getVariableIDs
*/
public static function getVariableIDs() {
if ( !self::$mVariableIDsInitialised ) {
# Get variable IDs
Hooks::run( 'MagicWordwgVariableIDs', [ &self::$mVariableIDs ] );
self::$mVariableIDsInitialised = true;
}
return self::$mVariableIDs;
return MediaWikiServices::getInstance()->getMagicWordFactory()->getVariableIDs();
}
/**
* Get an array of parser substitution modifier IDs
* @return string[]
* @deprecated since 1.32, use MagicWordFactory::getSubstIDs
*/
public static function getSubstIDs() {
return self::$mSubstIDs;
return MediaWikiServices::getInstance()->getMagicWordFactory()->getSubstIDs();
}
/**
@ -310,34 +143,20 @@ class MagicWord {
*
* @param string $id
* @return int
* @deprecated since 1.32, use MagicWordFactory::getCacheTTL
*/
public static function getCacheTTL( $id ) {
if ( array_key_exists( $id, self::$mCacheTTLs ) ) {
return self::$mCacheTTLs[$id];
} else {
return -1;
}
return MediaWikiServices::getInstance()->getMagicWordFactory()->getCacheTTL( $id );
}
/**
* Get a MagicWordArray of double-underscore entities
*
* @return MagicWordArray
* @deprecated since 1.32, use MagicWordFactory::getDoubleUnderscoreArray
*/
public static function getDoubleUnderscoreArray() {
if ( is_null( self::$mDoubleUnderscoreArray ) ) {
Hooks::run( 'GetDoubleUnderscoreIDs', [ &self::$mDoubleUnderscoreIDs ] );
self::$mDoubleUnderscoreArray = new MagicWordArray( self::$mDoubleUnderscoreIDs );
}
return self::$mDoubleUnderscoreArray;
}
/**
* Clear the self::$mObjects variable
* For use in parser tests
*/
public static function clearCache() {
self::$mObjects = [];
return MediaWikiServices::getInstance()->getMagicWordFactory()->getDoubleUnderscoreArray();
}
/**

View file

@ -0,0 +1,261 @@
<?php
/**
* See docs/magicword.txt.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Parser
*/
/**
* A factory that stores information about MagicWords, and creates them on demand with caching.
*
* Possible future improvements:
* * Simultaneous searching for a number of magic words
* * $mObjects in shared memory
*
* @since 1.32
* @ingroup Parser
*/
class MagicWordFactory {
/**#@-*/
/** @var bool */
private $mVariableIDsInitialised = false;
/** @var string[] */
private $mVariableIDs = [
'!',
'currentmonth',
'currentmonth1',
'currentmonthname',
'currentmonthnamegen',
'currentmonthabbrev',
'currentday',
'currentday2',
'currentdayname',
'currentyear',
'currenttime',
'currenthour',
'localmonth',
'localmonth1',
'localmonthname',
'localmonthnamegen',
'localmonthabbrev',
'localday',
'localday2',
'localdayname',
'localyear',
'localtime',
'localhour',
'numberofarticles',
'numberoffiles',
'numberofedits',
'articlepath',
'pageid',
'sitename',
'server',
'servername',
'scriptpath',
'stylepath',
'pagename',
'pagenamee',
'fullpagename',
'fullpagenamee',
'namespace',
'namespacee',
'namespacenumber',
'currentweek',
'currentdow',
'localweek',
'localdow',
'revisionid',
'revisionday',
'revisionday2',
'revisionmonth',
'revisionmonth1',
'revisionyear',
'revisiontimestamp',
'revisionuser',
'revisionsize',
'subpagename',
'subpagenamee',
'talkspace',
'talkspacee',
'subjectspace',
'subjectspacee',
'talkpagename',
'talkpagenamee',
'subjectpagename',
'subjectpagenamee',
'numberofusers',
'numberofactiveusers',
'numberofpages',
'currentversion',
'rootpagename',
'rootpagenamee',
'basepagename',
'basepagenamee',
'currenttimestamp',
'localtimestamp',
'directionmark',
'contentlanguage',
'pagelanguage',
'numberofadmins',
'cascadingsources',
];
/** Array of caching hints for ParserCache
* @var array [ string => int ]
*/
private $mCacheTTLs = [
'currentmonth' => 86400,
'currentmonth1' => 86400,
'currentmonthname' => 86400,
'currentmonthnamegen' => 86400,
'currentmonthabbrev' => 86400,
'currentday' => 3600,
'currentday2' => 3600,
'currentdayname' => 3600,
'currentyear' => 86400,
'currenttime' => 3600,
'currenthour' => 3600,
'localmonth' => 86400,
'localmonth1' => 86400,
'localmonthname' => 86400,
'localmonthnamegen' => 86400,
'localmonthabbrev' => 86400,
'localday' => 3600,
'localday2' => 3600,
'localdayname' => 3600,
'localyear' => 86400,
'localtime' => 3600,
'localhour' => 3600,
'numberofarticles' => 3600,
'numberoffiles' => 3600,
'numberofedits' => 3600,
'currentweek' => 3600,
'currentdow' => 3600,
'localweek' => 3600,
'localdow' => 3600,
'numberofusers' => 3600,
'numberofactiveusers' => 3600,
'numberofpages' => 3600,
'currentversion' => 86400,
'currenttimestamp' => 3600,
'localtimestamp' => 3600,
'pagesinnamespace' => 3600,
'numberofadmins' => 3600,
'numberingroup' => 3600,
];
/** @var string[] */
private $mDoubleUnderscoreIDs = [
'notoc',
'nogallery',
'forcetoc',
'toc',
'noeditsection',
'newsectionlink',
'nonewsectionlink',
'hiddencat',
'index',
'noindex',
'staticredirect',
'notitleconvert',
'nocontentconvert',
];
/** @var string[] */
private $mSubstIDs = [
'subst',
'safesubst',
];
/** @var array [ string => MagicWord ] */
private $mObjects = [];
/** @var MagicWordArray */
private $mDoubleUnderscoreArray = null;
/**#@-*/
/**
* Factory: creates an object representing an ID
*
* @param string $id The internal name of the magic word
*
* @return MagicWord
*/
public function get( $id ) {
if ( !isset( $this->mObjects[$id] ) ) {
$mw = new MagicWord();
$mw->load( $id );
$this->mObjects[$id] = $mw;
}
return $this->mObjects[$id];
}
/**
* Get an array of parser variable IDs
*
* @return string[]
*/
public function getVariableIDs() {
if ( !$this->mVariableIDsInitialised ) {
# Get variable IDs
Hooks::run( 'MagicWordwgVariableIDs', [ &$this->mVariableIDs ] );
$this->mVariableIDsInitialised = true;
}
return $this->mVariableIDs;
}
/**
* Get an array of parser substitution modifier IDs
* @return string[]
*/
public function getSubstIDs() {
return $this->mSubstIDs;
}
/**
* Allow external reads of TTL array
*
* @param string $id
* @return int
*/
public function getCacheTTL( $id ) {
if ( array_key_exists( $id, $this->mCacheTTLs ) ) {
return $this->mCacheTTLs[$id];
} else {
return -1;
}
}
/**
* Get a MagicWordArray of double-underscore entities
*
* @return MagicWordArray
*/
public function getDoubleUnderscoreArray() {
if ( is_null( $this->mDoubleUnderscoreArray ) ) {
Hooks::run( 'GetDoubleUnderscoreIDs', [ &$this->mDoubleUnderscoreIDs ] );
$this->mDoubleUnderscoreArray = new MagicWordArray( $this->mDoubleUnderscoreIDs );
}
return $this->mDoubleUnderscoreArray;
}
}

View file

@ -51,6 +51,7 @@ use TitleFormatter;
use TitleParser;
use VirtualRESTServiceClient;
use MediaWiki\Interwiki\InterwikiLookup;
use MagicWordFactory;
/**
* Service locator for MediaWiki core services.
@ -864,6 +865,14 @@ class MediaWikiServices extends ServiceContainer {
return $this->getService( 'ConfigRepository' );
}
/**
* @since 1.32
* @return MagicWordFactory
*/
public function getMagicWordFactory() {
return $this->getService( 'MagicWordFactory' );
}
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service getter here, don't forget to add a test
// case for it in MediaWikiServicesTest::provideGetters() and in

View file

@ -600,6 +600,11 @@ return [
);
},
'MagicWordFactory' => function ( MediaWikiServices $services ) {
global $wgContLang;
return new MagicWordFactory( $wgContLang );
},
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service here, don't forget to add a getter function
// in the MediaWikiServices class. The convenience getter should just call

View file

@ -1152,7 +1152,7 @@ class ParserTestRunner {
$lang->resetNamespaces();
$setup['wgContLang'] = $lang;
$reset = function () {
MagicWord::clearCache();
MediaWikiServices::getInstance()->resetServiceForTesting( 'MagicWordFactory' );
$this->resetTitleServices();
};
$setup[] = $reset;

View file

@ -1,5 +1,7 @@
<?php
use MediaWiki\MediaWikiServices;
/**
* Parser-related tests that don't suit for parserTests.txt
*
@ -28,7 +30,7 @@ class ExtraParserTest extends MediaWikiTestCase {
$this->options->setTemplateCallback( [ __CLASS__, 'statelessFetchTemplate' ] );
$this->parser = new Parser;
MagicWord::clearCache();
MediaWikiServices::getInstance()->resetServiceForTesting( 'MagicWordFactory' );
}
/**

View file

@ -365,6 +365,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
'PreferencesFactory' => [ 'PreferencesFactory', PreferencesFactory::class ],
'ActorMigration' => [ 'ActorMigration', ActorMigration::class ],
'ConfigRepository' => [ 'ConfigRepository', \MediaWiki\Config\ConfigRepository::class ],
'MagicWordFactory' => [ 'MagicWordFactory', MagicWordFactory::class ],
];
}

View file

@ -1,5 +1,7 @@
<?php
use MediaWiki\MediaWikiServices;
/**
* @group ContentHandler
*/
@ -81,7 +83,7 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
global $wgContLang;
$wgContLang->resetNamespaces();
MagicWord::clearCache();
MediaWikiServices::getInstance()->resetServiceForTesting( 'MagicWordFactory' );
if ( is_string( $title ) ) {
$title = Title::newFromText( $title );