MediaWiki  1.30.0
MediaWikiTestCase.php
Go to the documentation of this file.
1 <?php
2 
7 use Psr\Log\LoggerInterface;
10 use Wikimedia\TestingAccessWrapper;
11 
15 abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
16 
24  private static $serviceLocator = null;
25 
38  private $called = [];
39 
44  public static $users;
45 
52  protected $db;
53 
58  protected $tablesUsed = []; // tables with data
59 
60  private static $useTemporaryTables = true;
61  private static $reuseDB = false;
62  private static $dbSetup = false;
63  private static $oldTablePrefix = '';
64 
70  private $phpErrorLevel;
71 
78  private $tmpFiles = [];
79 
86  private $mwGlobals = [];
87 
93  private $mwGlobalsToUnset = [];
94 
99  private $loggers = [];
100 
104  const DB_PREFIX = 'unittest_';
105  const ORA_DB_PREFIX = 'ut_';
106 
111  protected $supportedDBs = [
112  'mysql',
113  'sqlite',
114  'postgres',
115  'oracle'
116  ];
117 
118  public function __construct( $name = null, array $data = [], $dataName = '' ) {
119  parent::__construct( $name, $data, $dataName );
120 
121  $this->backupGlobals = false;
122  $this->backupStaticAttributes = false;
123  }
124 
125  public function __destruct() {
126  // Complain if self::setUp() was called, but not self::tearDown()
127  // $this->called['setUp'] will be checked by self::testMediaWikiTestCaseParentSetupCalled()
128  if ( isset( $this->called['setUp'] ) && !isset( $this->called['tearDown'] ) ) {
129  throw new MWException( static::class . "::tearDown() must call parent::tearDown()" );
130  }
131  }
132 
133  public static function setUpBeforeClass() {
134  parent::setUpBeforeClass();
135 
136  // Get the service locator, and reset services if it's not done already
137  self::$serviceLocator = self::prepareServices( new GlobalVarConfig() );
138  }
139 
148  public static function getTestUser( $groups = [] ) {
149  return TestUserRegistry::getImmutableTestUser( $groups );
150  }
151 
160  public static function getMutableTestUser( $groups = [] ) {
161  return TestUserRegistry::getMutableTestUser( __CLASS__, $groups );
162  }
163 
172  public static function getTestSysop() {
173  return self::getTestUser( [ 'sysop', 'bureaucrat' ] );
174  }
175 
195  public static function prepareServices( Config $bootstrapConfig ) {
196  static $services = null;
197 
198  if ( !$services ) {
199  $services = self::resetGlobalServices( $bootstrapConfig );
200  }
201  return $services;
202  }
203 
218  protected static function resetGlobalServices( Config $bootstrapConfig = null ) {
219  $oldServices = MediaWikiServices::getInstance();
220  $oldConfigFactory = $oldServices->getConfigFactory();
221  $oldLoadBalancerFactory = $oldServices->getDBLoadBalancerFactory();
222 
223  $testConfig = self::makeTestConfig( $bootstrapConfig );
224 
225  MediaWikiServices::resetGlobalInstance( $testConfig );
226 
227  $serviceLocator = MediaWikiServices::getInstance();
229  $oldConfigFactory,
230  $oldLoadBalancerFactory,
232  );
233  return $serviceLocator;
234  }
235 
245  private static function makeTestConfig(
246  Config $baseConfig = null,
247  Config $customOverrides = null
248  ) {
249  $defaultOverrides = new HashConfig();
250 
251  if ( !$baseConfig ) {
252  $baseConfig = MediaWikiServices::getInstance()->getBootstrapConfig();
253  }
254 
255  /* Some functions require some kind of caching, and will end up using the db,
256  * which we can't allow, as that would open a new connection for mysql.
257  * Replace with a HashBag. They would not be going to persist anyway.
258  */
259  $hashCache = [ 'class' => 'HashBagOStuff', 'reportDupes' => false ];
260  $objectCaches = [
261  CACHE_DB => $hashCache,
262  CACHE_ACCEL => $hashCache,
263  CACHE_MEMCACHED => $hashCache,
264  'apc' => $hashCache,
265  'apcu' => $hashCache,
266  'xcache' => $hashCache,
267  'wincache' => $hashCache,
268  ] + $baseConfig->get( 'ObjectCaches' );
269 
270  $defaultOverrides->set( 'ObjectCaches', $objectCaches );
271  $defaultOverrides->set( 'MainCacheType', CACHE_NONE );
272  $defaultOverrides->set( 'JobTypeConf', [ 'default' => [ 'class' => 'JobQueueMemory' ] ] );
273 
274  // Use a fast hash algorithm to hash passwords.
275  $defaultOverrides->set( 'PasswordDefault', 'A' );
276 
277  $testConfig = $customOverrides
278  ? new MultiConfig( [ $customOverrides, $defaultOverrides, $baseConfig ] )
279  : new MultiConfig( [ $defaultOverrides, $baseConfig ] );
280 
281  return $testConfig;
282  }
283 
291  private static function installTestServices(
292  ConfigFactory $oldConfigFactory,
293  LBFactory $oldLoadBalancerFactory,
294  MediaWikiServices $newServices
295  ) {
296  // Use bootstrap config for all configuration.
297  // This allows config overrides via global variables to take effect.
298  $bootstrapConfig = $newServices->getBootstrapConfig();
299  $newServices->resetServiceForTesting( 'ConfigFactory' );
300  $newServices->redefineService(
301  'ConfigFactory',
302  self::makeTestConfigFactoryInstantiator(
303  $oldConfigFactory,
304  [ 'main' => $bootstrapConfig ]
305  )
306  );
307  $newServices->resetServiceForTesting( 'DBLoadBalancerFactory' );
308  $newServices->redefineService(
309  'DBLoadBalancerFactory',
310  function ( MediaWikiServices $services ) use ( $oldLoadBalancerFactory ) {
311  return $oldLoadBalancerFactory;
312  }
313  );
314  }
315 
322  private static function makeTestConfigFactoryInstantiator(
323  ConfigFactory $oldFactory,
324  array $configurations
325  ) {
326  return function ( MediaWikiServices $services ) use ( $oldFactory, $configurations ) {
327  $factory = new ConfigFactory();
328 
329  // clone configurations from $oldFactory that are not overwritten by $configurations
330  $namesToClone = array_diff(
331  $oldFactory->getConfigNames(),
332  array_keys( $configurations )
333  );
334 
335  foreach ( $namesToClone as $name ) {
336  $factory->register( $name, $oldFactory->makeConfig( $name ) );
337  }
338 
339  foreach ( $configurations as $name => $config ) {
340  $factory->register( $name, $config );
341  }
342 
343  return $factory;
344  };
345  }
346 
358  private function doLightweightServiceReset() {
360 
363  $services = MediaWikiServices::getInstance();
364  $services->resetServiceForTesting( 'MainObjectStash' );
365  $services->resetServiceForTesting( 'LocalServerObjectCache' );
366  $services->getMainWANObjectCache()->clearProcessCache();
368 
369  // TODO: move global state into MediaWikiServices
371  if ( session_id() !== '' ) {
372  session_write_close();
373  session_id( '' );
374  }
375 
376  $wgRequest = new FauxRequest();
378  }
379 
380  public function run( PHPUnit_Framework_TestResult $result = null ) {
381  // Reset all caches between tests.
382  $this->doLightweightServiceReset();
383 
384  $needsResetDB = false;
385 
386  if ( !self::$dbSetup || $this->needsDB() ) {
387  // set up a DB connection for this test to use
388 
389  self::$useTemporaryTables = !$this->getCliArg( 'use-normal-tables' );
390  self::$reuseDB = $this->getCliArg( 'reuse-db' );
391 
392  $this->db = wfGetDB( DB_MASTER );
393 
394  $this->checkDbIsSupported();
395 
396  if ( !self::$dbSetup ) {
397  $this->setupAllTestDBs();
398  $this->addCoreDBData();
399 
400  if ( ( $this->db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
401  $this->resetDB( $this->db, $this->tablesUsed );
402  }
403  }
404 
405  // TODO: the DB setup should be done in setUpBeforeClass(), so the test DB
406  // is available in subclass's setUpBeforeClass() and setUp() methods.
407  // This would also remove the need for the HACK that is oncePerClass().
408  if ( $this->oncePerClass() ) {
409  $this->addDBDataOnce();
410  }
411 
412  $this->addDBData();
413  $needsResetDB = true;
414  }
415 
416  parent::run( $result );
417 
418  if ( $needsResetDB ) {
419  $this->resetDB( $this->db, $this->tablesUsed );
420  }
421  }
422 
426  private function oncePerClass() {
427  // Remember current test class in the database connection,
428  // so we know when we need to run addData.
429 
430  $class = static::class;
431 
432  $first = !isset( $this->db->_hasDataForTestClass )
433  || $this->db->_hasDataForTestClass !== $class;
434 
435  $this->db->_hasDataForTestClass = $class;
436  return $first;
437  }
438 
444  public function usesTemporaryTables() {
446  }
447 
457  protected function getNewTempFile() {
458  $fileName = tempnam( wfTempDir(), 'MW_PHPUnit_' . static::class . '_' );
459  $this->tmpFiles[] = $fileName;
460 
461  return $fileName;
462  }
463 
474  protected function getNewTempDirectory() {
475  // Starting of with a temporary /file/.
476  $fileName = $this->getNewTempFile();
477 
478  // Converting the temporary /file/ to a /directory/
479  // The following is not atomic, but at least we now have a single place,
480  // where temporary directory creation is bundled and can be improved
481  unlink( $fileName );
482  $this->assertTrue( wfMkdirParents( $fileName ) );
483 
484  return $fileName;
485  }
486 
487  protected function setUp() {
488  parent::setUp();
489  $this->called['setUp'] = true;
490 
491  $this->phpErrorLevel = intval( ini_get( 'error_reporting' ) );
492 
493  // Cleaning up temporary files
494  foreach ( $this->tmpFiles as $fileName ) {
495  if ( is_file( $fileName ) || ( is_link( $fileName ) ) ) {
496  unlink( $fileName );
497  } elseif ( is_dir( $fileName ) ) {
498  wfRecursiveRemoveDir( $fileName );
499  }
500  }
501 
502  if ( $this->needsDB() && $this->db ) {
503  // Clean up open transactions
504  while ( $this->db->trxLevel() > 0 ) {
505  $this->db->rollback( __METHOD__, 'flush' );
506  }
507  // Check for unsafe queries
508  if ( $this->db->getType() === 'mysql' ) {
509  $this->db->query( "SET sql_mode = 'STRICT_ALL_TABLES'" );
510  }
511  }
512 
514  ObjectCache::getMainWANInstance()->clearProcessCache();
515 
516  // XXX: reset maintenance triggers
517  // Hook into period lag checks which often happen in long-running scripts
518  $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
519  Maintenance::setLBFactoryTriggers( $lbFactory );
520 
521  ob_start( 'MediaWikiTestCase::wfResetOutputBuffersBarrier' );
522  }
523 
524  protected function addTmpFiles( $files ) {
525  $this->tmpFiles = array_merge( $this->tmpFiles, (array)$files );
526  }
527 
528  protected function tearDown() {
530 
531  $status = ob_get_status();
532  if ( isset( $status['name'] ) &&
533  $status['name'] === 'MediaWikiTestCase::wfResetOutputBuffersBarrier'
534  ) {
535  ob_end_flush();
536  }
537 
538  $this->called['tearDown'] = true;
539  // Cleaning up temporary files
540  foreach ( $this->tmpFiles as $fileName ) {
541  if ( is_file( $fileName ) || ( is_link( $fileName ) ) ) {
542  unlink( $fileName );
543  } elseif ( is_dir( $fileName ) ) {
544  wfRecursiveRemoveDir( $fileName );
545  }
546  }
547 
548  if ( $this->needsDB() && $this->db ) {
549  // Clean up open transactions
550  while ( $this->db->trxLevel() > 0 ) {
551  $this->db->rollback( __METHOD__, 'flush' );
552  }
553  if ( $this->db->getType() === 'mysql' ) {
554  $this->db->query( "SET sql_mode = " . $this->db->addQuotes( $wgSQLMode ) );
555  }
556  }
557 
558  // Restore mw globals
559  foreach ( $this->mwGlobals as $key => $value ) {
560  $GLOBALS[$key] = $value;
561  }
562  foreach ( $this->mwGlobalsToUnset as $value ) {
563  unset( $GLOBALS[$value] );
564  }
565  $this->mwGlobals = [];
566  $this->mwGlobalsToUnset = [];
567  $this->restoreLoggers();
568 
569  if ( self::$serviceLocator && MediaWikiServices::getInstance() !== self::$serviceLocator ) {
570  MediaWikiServices::forceGlobalInstance( self::$serviceLocator );
571  }
572 
573  // TODO: move global state into MediaWikiServices
575  if ( session_id() !== '' ) {
576  session_write_close();
577  session_id( '' );
578  }
579  $wgRequest = new FauxRequest();
582 
583  $phpErrorLevel = intval( ini_get( 'error_reporting' ) );
584 
585  if ( $phpErrorLevel !== $this->phpErrorLevel ) {
586  ini_set( 'error_reporting', $this->phpErrorLevel );
587 
588  $oldHex = strtoupper( dechex( $this->phpErrorLevel ) );
589  $newHex = strtoupper( dechex( $phpErrorLevel ) );
590  $message = "PHP error_reporting setting was left dirty: "
591  . "was 0x$oldHex before test, 0x$newHex after test!";
592 
593  $this->fail( $message );
594  }
595 
596  parent::tearDown();
597  }
598 
607  final public function testMediaWikiTestCaseParentSetupCalled() {
608  $this->assertArrayHasKey( 'setUp', $this->called,
609  static::class . '::setUp() must call parent::setUp()'
610  );
611  }
612 
622  protected function setService( $name, $object ) {
623  // If we did not yet override the service locator, so so now.
624  if ( MediaWikiServices::getInstance() === self::$serviceLocator ) {
625  $this->overrideMwServices();
626  }
627 
628  MediaWikiServices::getInstance()->disableService( $name );
629  MediaWikiServices::getInstance()->redefineService(
630  $name,
631  function () use ( $object ) {
632  return $object;
633  }
634  );
635  }
636 
672  protected function setMwGlobals( $pairs, $value = null ) {
673  if ( is_string( $pairs ) ) {
674  $pairs = [ $pairs => $value ];
675  }
676 
677  $this->stashMwGlobals( array_keys( $pairs ) );
678 
679  foreach ( $pairs as $key => $value ) {
680  $GLOBALS[$key] = $value;
681  }
682  }
683 
692  private static function canShallowCopy( $value ) {
693  if ( is_scalar( $value ) || $value === null ) {
694  return true;
695  }
696  if ( is_array( $value ) ) {
697  foreach ( $value as $subValue ) {
698  if ( !is_scalar( $subValue ) && $subValue !== null ) {
699  return false;
700  }
701  }
702  return true;
703  }
704  return false;
705  }
706 
724  protected function stashMwGlobals( $globalKeys ) {
725  if ( is_string( $globalKeys ) ) {
726  $globalKeys = [ $globalKeys ];
727  }
728 
729  foreach ( $globalKeys as $globalKey ) {
730  // NOTE: make sure we only save the global once or a second call to
731  // setMwGlobals() on the same global would override the original
732  // value.
733  if (
734  !array_key_exists( $globalKey, $this->mwGlobals ) &&
735  !array_key_exists( $globalKey, $this->mwGlobalsToUnset )
736  ) {
737  if ( !array_key_exists( $globalKey, $GLOBALS ) ) {
738  $this->mwGlobalsToUnset[$globalKey] = $globalKey;
739  continue;
740  }
741  // NOTE: we serialize then unserialize the value in case it is an object
742  // this stops any objects being passed by reference. We could use clone
743  // and if is_object but this does account for objects within objects!
744  if ( self::canShallowCopy( $GLOBALS[$globalKey] ) ) {
745  $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey];
746  } elseif (
747  // Many MediaWiki types are safe to clone. These are the
748  // ones that are most commonly stashed.
749  $GLOBALS[$globalKey] instanceof Language ||
750  $GLOBALS[$globalKey] instanceof User ||
751  $GLOBALS[$globalKey] instanceof FauxRequest
752  ) {
753  $this->mwGlobals[$globalKey] = clone $GLOBALS[$globalKey];
754  } elseif ( $this->containsClosure( $GLOBALS[$globalKey] ) ) {
755  // Serializing Closure only gives a warning on HHVM while
756  // it throws an Exception on Zend.
757  // Workaround for https://github.com/facebook/hhvm/issues/6206
758  $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey];
759  } else {
760  try {
761  $this->mwGlobals[$globalKey] = unserialize( serialize( $GLOBALS[$globalKey] ) );
762  } catch ( Exception $e ) {
763  $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey];
764  }
765  }
766  }
767  }
768  }
769 
776  private function containsClosure( $var, $maxDepth = 15 ) {
777  if ( $var instanceof Closure ) {
778  return true;
779  }
780  if ( !is_array( $var ) || $maxDepth === 0 ) {
781  return false;
782  }
783 
784  foreach ( $var as $value ) {
785  if ( $this->containsClosure( $value, $maxDepth - 1 ) ) {
786  return true;
787  }
788  }
789  return false;
790  }
791 
807  protected function mergeMwGlobalArrayValue( $name, $values ) {
808  if ( !isset( $GLOBALS[$name] ) ) {
809  $merged = $values;
810  } else {
811  if ( !is_array( $GLOBALS[$name] ) ) {
812  throw new MWException( "MW global $name is not an array." );
813  }
814 
815  // NOTE: do not use array_merge, it screws up for numeric keys.
816  $merged = $GLOBALS[$name];
817  foreach ( $values as $k => $v ) {
818  $merged[$k] = $v;
819  }
820  }
821 
822  $this->setMwGlobals( $name, $merged );
823  }
824 
839  protected function overrideMwServices( Config $configOverrides = null, array $services = [] ) {
840  if ( !$configOverrides ) {
841  $configOverrides = new HashConfig();
842  }
843 
844  $oldInstance = MediaWikiServices::getInstance();
845  $oldConfigFactory = $oldInstance->getConfigFactory();
846  $oldLoadBalancerFactory = $oldInstance->getDBLoadBalancerFactory();
847 
848  $testConfig = self::makeTestConfig( null, $configOverrides );
849  $newInstance = new MediaWikiServices( $testConfig );
850 
851  // Load the default wiring from the specified files.
852  // NOTE: this logic mirrors the logic in MediaWikiServices::newInstance.
853  $wiringFiles = $testConfig->get( 'ServiceWiringFiles' );
854  $newInstance->loadWiringFiles( $wiringFiles );
855 
856  // Provide a traditional hook point to allow extensions to configure services.
857  Hooks::run( 'MediaWikiServices', [ $newInstance ] );
858 
859  foreach ( $services as $name => $callback ) {
860  $newInstance->redefineService( $name, $callback );
861  }
862 
864  $oldConfigFactory,
865  $oldLoadBalancerFactory,
866  $newInstance
867  );
868  MediaWikiServices::forceGlobalInstance( $newInstance );
869 
870  return $newInstance;
871  }
872 
877  public function setUserLang( $lang ) {
878  RequestContext::getMain()->setLanguage( $lang );
879  $this->setMwGlobals( 'wgLang', RequestContext::getMain()->getLanguage() );
880  }
881 
886  public function setContentLang( $lang ) {
887  if ( $lang instanceof Language ) {
888  $langCode = $lang->getCode();
889  $langObj = $lang;
890  } else {
891  $langCode = $lang;
892  $langObj = Language::factory( $langCode );
893  }
894  $this->setMwGlobals( [
895  'wgLanguageCode' => $langCode,
896  'wgContLang' => $langObj,
897  ] );
898  }
899 
906  protected function setLogger( $channel, LoggerInterface $logger ) {
907  // TODO: Once loggers are managed by MediaWikiServices, use
908  // overrideMwServices() to set loggers.
909 
910  $provider = LoggerFactory::getProvider();
911  $wrappedProvider = TestingAccessWrapper::newFromObject( $provider );
912  $singletons = $wrappedProvider->singletons;
913  if ( $provider instanceof MonologSpi ) {
914  if ( !isset( $this->loggers[$channel] ) ) {
915  $this->loggers[$channel] = isset( $singletons['loggers'][$channel] )
916  ? $singletons['loggers'][$channel] : null;
917  }
918  $singletons['loggers'][$channel] = $logger;
919  } elseif ( $provider instanceof LegacySpi ) {
920  if ( !isset( $this->loggers[$channel] ) ) {
921  $this->loggers[$channel] = isset( $singletons[$channel] ) ? $singletons[$channel] : null;
922  }
923  $singletons[$channel] = $logger;
924  } else {
925  throw new LogicException( __METHOD__ . ': setting a logger for ' . get_class( $provider )
926  . ' is not implemented' );
927  }
928  $wrappedProvider->singletons = $singletons;
929  }
930 
935  private function restoreLoggers() {
936  $provider = LoggerFactory::getProvider();
937  $wrappedProvider = TestingAccessWrapper::newFromObject( $provider );
938  $singletons = $wrappedProvider->singletons;
939  foreach ( $this->loggers as $channel => $logger ) {
940  if ( $provider instanceof MonologSpi ) {
941  if ( $logger === null ) {
942  unset( $singletons['loggers'][$channel] );
943  } else {
944  $singletons['loggers'][$channel] = $logger;
945  }
946  } elseif ( $provider instanceof LegacySpi ) {
947  if ( $logger === null ) {
948  unset( $singletons[$channel] );
949  } else {
950  $singletons[$channel] = $logger;
951  }
952  }
953  }
954  $wrappedProvider->singletons = $singletons;
955  $this->loggers = [];
956  }
957 
962  public function dbPrefix() {
963  return $this->db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
964  }
965 
970  public function needsDB() {
971  # if the test says it uses database tables, it needs the database
972  if ( $this->tablesUsed ) {
973  return true;
974  }
975 
976  # if the test says it belongs to the Database group, it needs the database
977  $rc = new ReflectionClass( $this );
978  if ( preg_match( '/@group +Database/im', $rc->getDocComment() ) ) {
979  return true;
980  }
981 
982  return false;
983  }
984 
996  protected function insertPage(
997  $pageName,
998  $text = 'Sample page for unit test.',
999  $namespace = null
1000  ) {
1001  if ( is_string( $pageName ) ) {
1002  $title = Title::newFromText( $pageName, $namespace );
1003  } else {
1004  $title = $pageName;
1005  }
1006 
1007  $user = static::getTestSysop()->getUser();
1008  $comment = __METHOD__ . ': Sample page for unit test.';
1009 
1010  // Avoid memory leak...?
1011  // LinkCache::singleton()->clear();
1012  // Maybe. But doing this absolutely breaks $title->isRedirect() when called during unit tests....
1013 
1014  $page = WikiPage::factory( $title );
1015  $page->doEditContent( ContentHandler::makeContent( $text, $title ), $comment, 0, false, $user );
1016 
1017  return [
1018  'title' => $title,
1019  'id' => $page->getId(),
1020  ];
1021  }
1022 
1038  public function addDBDataOnce() {
1039  }
1040 
1050  public function addDBData() {
1051  }
1052 
1053  private function addCoreDBData() {
1054  if ( $this->db->getType() == 'oracle' ) {
1055  # Insert 0 user to prevent FK violations
1056  # Anonymous user
1057  if ( !$this->db->selectField( 'user', '1', [ 'user_id' => 0 ] ) ) {
1058  $this->db->insert( 'user', [
1059  'user_id' => 0,
1060  'user_name' => 'Anonymous' ], __METHOD__, [ 'IGNORE' ] );
1061  }
1062 
1063  # Insert 0 page to prevent FK violations
1064  # Blank page
1065  if ( !$this->db->selectField( 'page', '1', [ 'page_id' => 0 ] ) ) {
1066  $this->db->insert( 'page', [
1067  'page_id' => 0,
1068  'page_namespace' => 0,
1069  'page_title' => ' ',
1070  'page_restrictions' => null,
1071  'page_is_redirect' => 0,
1072  'page_is_new' => 0,
1073  'page_random' => 0,
1074  'page_touched' => $this->db->timestamp(),
1075  'page_latest' => 0,
1076  'page_len' => 0 ], __METHOD__, [ 'IGNORE' ] );
1077  }
1078  }
1079 
1081 
1082  // Make sysop user
1083  $user = static::getTestSysop()->getUser();
1084 
1085  // Make 1 page with 1 revision
1086  $page = WikiPage::factory( Title::newFromText( 'UTPage' ) );
1087  if ( $page->getId() == 0 ) {
1088  $page->doEditContent(
1089  new WikitextContent( 'UTContent' ),
1090  'UTPageSummary',
1092  false,
1093  $user
1094  );
1095  // an edit always attempt to purge backlink links such as history
1096  // pages. That is unneccessary.
1097  JobQueueGroup::singleton()->get( 'htmlCacheUpdate' )->delete();
1098  // WikiPages::doEditUpdates randomly adds RC purges
1099  JobQueueGroup::singleton()->get( 'recentChangesUpdate' )->delete();
1100 
1101  // doEditContent() probably started the session via
1102  // User::loadFromSession(). Close it now.
1103  if ( session_id() !== '' ) {
1104  session_write_close();
1105  session_id( '' );
1106  }
1107  }
1108  }
1109 
1117  public static function teardownTestDB() {
1119 
1120  if ( !self::$dbSetup ) {
1121  return;
1122  }
1123 
1124  Hooks::run( 'UnitTestsBeforeDatabaseTeardown' );
1125 
1126  foreach ( $wgJobClasses as $type => $class ) {
1127  // Delete any jobs under the clone DB (or old prefix in other stores)
1128  JobQueueGroup::singleton()->get( $type )->delete();
1129  }
1130 
1131  CloneDatabase::changePrefix( self::$oldTablePrefix );
1132 
1133  self::$oldTablePrefix = false;
1134  self::$dbSetup = false;
1135  }
1136 
1150  protected static function setupDatabaseWithTestPrefix( IMaintainableDatabase $db, $prefix ) {
1151  $tablesCloned = self::listTables( $db );
1152  $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
1153  $dbClone->useTemporaryTables( self::$useTemporaryTables );
1154 
1155  if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
1156  CloneDatabase::changePrefix( $prefix );
1157 
1158  return false;
1159  } else {
1160  $dbClone->cloneTableStructure();
1161  return true;
1162  }
1163  }
1164 
1168  public function setupAllTestDBs() {
1170 
1171  self::$oldTablePrefix = $wgDBprefix;
1172 
1173  $testPrefix = $this->dbPrefix();
1174 
1175  // switch to a temporary clone of the database
1176  self::setupTestDB( $this->db, $testPrefix );
1177 
1178  if ( self::isUsingExternalStoreDB() ) {
1179  self::setupExternalStoreTestDBs( $testPrefix );
1180  }
1181  }
1182 
1204  public static function setupTestDB( Database $db, $prefix ) {
1205  if ( self::$dbSetup ) {
1206  return;
1207  }
1208 
1209  if ( $db->tablePrefix() === $prefix ) {
1210  throw new MWException(
1211  'Cannot run unit tests, the database prefix is already "' . $prefix . '"' );
1212  }
1213 
1214  // TODO: the below should be re-written as soon as LBFactory, LoadBalancer,
1215  // and Database no longer use global state.
1216 
1217  self::$dbSetup = true;
1218 
1219  if ( !self::setupDatabaseWithTestPrefix( $db, $prefix ) ) {
1220  return;
1221  }
1222 
1223  // Assuming this isn't needed for External Store database, and not sure if the procedure
1224  // would be available there.
1225  if ( $db->getType() == 'oracle' ) {
1226  $db->query( 'BEGIN FILL_WIKI_INFO; END;' );
1227  }
1228 
1229  Hooks::run( 'UnitTestsAfterDatabaseSetup', [ $db, $prefix ] );
1230  }
1231 
1237  protected static function setupExternalStoreTestDBs( $testPrefix ) {
1239  foreach ( $connections as $dbw ) {
1240  // Hack: cloneTableStructure sets $wgDBprefix to the unit test
1241  // prefix,. Even though listTables now uses tablePrefix, that
1242  // itself is populated from $wgDBprefix by default.
1243 
1244  // We have to set it back, or we won't find the original 'blobs'
1245  // table to copy.
1246 
1247  $dbw->tablePrefix( self::$oldTablePrefix );
1248  self::setupDatabaseWithTestPrefix( $dbw, $testPrefix );
1249  }
1250  }
1251 
1258  protected static function getExternalStoreDatabaseConnections() {
1260 
1262  $externalStoreDB = ExternalStore::getStoreObject( 'DB' );
1263  $defaultArray = (array)$wgDefaultExternalStore;
1264  $dbws = [];
1265  foreach ( $defaultArray as $url ) {
1266  if ( strpos( $url, 'DB://' ) === 0 ) {
1267  list( $proto, $cluster ) = explode( '://', $url, 2 );
1268  // Avoid getMaster() because setupDatabaseWithTestPrefix()
1269  // requires Database instead of plain DBConnRef/IDatabase
1270  $dbws[] = $externalStoreDB->getMaster( $cluster );
1271  }
1272  }
1273 
1274  return $dbws;
1275  }
1276 
1282  protected static function isUsingExternalStoreDB() {
1284  if ( !$wgDefaultExternalStore ) {
1285  return false;
1286  }
1287 
1288  $defaultArray = (array)$wgDefaultExternalStore;
1289  foreach ( $defaultArray as $url ) {
1290  if ( strpos( $url, 'DB://' ) === 0 ) {
1291  return true;
1292  }
1293  }
1294 
1295  return false;
1296  }
1297 
1304  private function resetDB( $db, $tablesUsed ) {
1305  if ( $db ) {
1306  $userTables = [ 'user', 'user_groups', 'user_properties' ];
1307  $pageTables = [ 'page', 'revision', 'ip_changes', 'revision_comment_temp', 'comment' ];
1308  $coreDBDataTables = array_merge( $userTables, $pageTables );
1309 
1310  // If any of the user or page tables were marked as used, we should clear all of them.
1311  if ( array_intersect( $tablesUsed, $userTables ) ) {
1312  $tablesUsed = array_unique( array_merge( $tablesUsed, $userTables ) );
1314  }
1315  if ( array_intersect( $tablesUsed, $pageTables ) ) {
1316  $tablesUsed = array_unique( array_merge( $tablesUsed, $pageTables ) );
1317  }
1318 
1319  $truncate = in_array( $db->getType(), [ 'oracle', 'mysql' ] );
1320  foreach ( $tablesUsed as $tbl ) {
1321  // TODO: reset interwiki table to its original content.
1322  if ( $tbl == 'interwiki' ) {
1323  continue;
1324  }
1325 
1326  if ( $truncate ) {
1327  $db->query( 'TRUNCATE TABLE ' . $db->tableName( $tbl ), __METHOD__ );
1328  } else {
1329  $db->delete( $tbl, '*', __METHOD__ );
1330  }
1331 
1332  if ( $tbl === 'page' ) {
1333  // Forget about the pages since they don't
1334  // exist in the DB.
1335  LinkCache::singleton()->clear();
1336  }
1337  }
1338 
1339  if ( array_intersect( $tablesUsed, $coreDBDataTables ) ) {
1340  // Re-add core DB data that was deleted
1341  $this->addCoreDBData();
1342  }
1343  }
1344  }
1345 
1355  public function __call( $func, $args ) {
1356  static $compatibility = [
1357  'createMock' => 'createMock2',
1358  ];
1359 
1360  if ( isset( $compatibility[$func] ) ) {
1361  return call_user_func_array( [ $this, $compatibility[$func] ], $args );
1362  } else {
1363  throw new MWException( "Called non-existent $func method on " . static::class );
1364  }
1365  }
1366 
1374  private function createMock2( $originalClassName ) {
1375  return $this->getMockBuilder( $originalClassName )
1376  ->disableOriginalConstructor()
1377  ->disableOriginalClone()
1378  ->disableArgumentCloning()
1379  // New in phpunit-mock-objects 3.2 (phpunit 5.4.0)
1380  // ->disallowMockingUnknownTypes()
1381  ->getMock();
1382  }
1383 
1384  private static function unprefixTable( &$tableName, $ind, $prefix ) {
1385  $tableName = substr( $tableName, strlen( $prefix ) );
1386  }
1387 
1388  private static function isNotUnittest( $table ) {
1389  return strpos( $table, 'unittest_' ) !== 0;
1390  }
1391 
1399  public static function listTables( IMaintainableDatabase $db ) {
1400  $prefix = $db->tablePrefix();
1401  $tables = $db->listTables( $prefix, __METHOD__ );
1402 
1403  if ( $db->getType() === 'mysql' ) {
1404  static $viewListCache = null;
1405  if ( $viewListCache === null ) {
1406  $viewListCache = $db->listViews( null, __METHOD__ );
1407  }
1408  // T45571: cannot clone VIEWs under MySQL
1409  $tables = array_diff( $tables, $viewListCache );
1410  }
1411  array_walk( $tables, [ __CLASS__, 'unprefixTable' ], $prefix );
1412 
1413  // Don't duplicate test tables from the previous fataled run
1414  $tables = array_filter( $tables, [ __CLASS__, 'isNotUnittest' ] );
1415 
1416  if ( $db->getType() == 'sqlite' ) {
1417  $tables = array_flip( $tables );
1418  // these are subtables of searchindex and don't need to be duped/dropped separately
1419  unset( $tables['searchindex_content'] );
1420  unset( $tables['searchindex_segdir'] );
1421  unset( $tables['searchindex_segments'] );
1422  $tables = array_flip( $tables );
1423  }
1424 
1425  return $tables;
1426  }
1427 
1432  protected function checkDbIsSupported() {
1433  if ( !in_array( $this->db->getType(), $this->supportedDBs ) ) {
1434  throw new MWException( $this->db->getType() . " is not currently supported for unit testing." );
1435  }
1436  }
1437 
1443  public function getCliArg( $offset ) {
1444  if ( isset( PHPUnitMaintClass::$additionalOptions[$offset] ) ) {
1445  return PHPUnitMaintClass::$additionalOptions[$offset];
1446  }
1447 
1448  return null;
1449  }
1450 
1456  public function setCliArg( $offset, $value ) {
1458  }
1459 
1467  public function hideDeprecated( $function ) {
1468  MediaWiki\suppressWarnings();
1469  wfDeprecated( $function );
1470  MediaWiki\restoreWarnings();
1471  }
1472 
1491  protected function assertSelect( $table, $fields, $condition, array $expectedRows ) {
1492  if ( !$this->needsDB() ) {
1493  throw new MWException( 'When testing database state, the test cases\'s needDB()' .
1494  ' method should return true. Use @group Database or $this->tablesUsed.' );
1495  }
1496 
1497  $db = wfGetDB( DB_REPLICA );
1498 
1499  $res = $db->select( $table, $fields, $condition, wfGetCaller(), [ 'ORDER BY' => $fields ] );
1500  $this->assertNotEmpty( $res, "query failed: " . $db->lastError() );
1501 
1502  $i = 0;
1503 
1504  foreach ( $expectedRows as $expected ) {
1505  $r = $res->fetchRow();
1506  self::stripStringKeys( $r );
1507 
1508  $i += 1;
1509  $this->assertNotEmpty( $r, "row #$i missing" );
1510 
1511  $this->assertEquals( $expected, $r, "row #$i mismatches" );
1512  }
1513 
1514  $r = $res->fetchRow();
1515  self::stripStringKeys( $r );
1516 
1517  $this->assertFalse( $r, "found extra row (after #$i)" );
1518  }
1519 
1531  protected function arrayWrap( array $elements ) {
1532  return array_map(
1533  function ( $element ) {
1534  return [ $element ];
1535  },
1536  $elements
1537  );
1538  }
1539 
1552  protected function assertArrayEquals( array $expected, array $actual,
1553  $ordered = false, $named = false
1554  ) {
1555  if ( !$ordered ) {
1556  $this->objectAssociativeSort( $expected );
1557  $this->objectAssociativeSort( $actual );
1558  }
1559 
1560  if ( !$named ) {
1561  $expected = array_values( $expected );
1562  $actual = array_values( $actual );
1563  }
1564 
1565  call_user_func_array(
1566  [ $this, 'assertEquals' ],
1567  array_merge( [ $expected, $actual ], array_slice( func_get_args(), 4 ) )
1568  );
1569  }
1570 
1583  protected function assertHTMLEquals( $expected, $actual, $msg = '' ) {
1584  $expected = str_replace( '>', ">\n", $expected );
1585  $actual = str_replace( '>', ">\n", $actual );
1586 
1587  $this->assertEquals( $expected, $actual, $msg );
1588  }
1589 
1597  protected function objectAssociativeSort( array &$array ) {
1598  uasort(
1599  $array,
1600  function ( $a, $b ) {
1601  return serialize( $a ) > serialize( $b ) ? 1 : -1;
1602  }
1603  );
1604  }
1605 
1615  protected static function stripStringKeys( &$r ) {
1616  if ( !is_array( $r ) ) {
1617  return;
1618  }
1619 
1620  foreach ( $r as $k => $v ) {
1621  if ( is_string( $k ) ) {
1622  unset( $r[$k] );
1623  }
1624  }
1625  }
1626 
1640  protected function assertTypeOrValue( $type, $actual, $value = false, $message = '' ) {
1641  if ( $actual === $value ) {
1642  $this->assertTrue( true, $message );
1643  } else {
1644  $this->assertType( $type, $actual, $message );
1645  }
1646  }
1647 
1659  protected function assertType( $type, $actual, $message = '' ) {
1660  if ( class_exists( $type ) || interface_exists( $type ) ) {
1661  $this->assertInstanceOf( $type, $actual, $message );
1662  } else {
1663  $this->assertInternalType( $type, $actual, $message );
1664  }
1665  }
1666 
1676  protected function isWikitextNS( $ns ) {
1678 
1679  if ( isset( $wgNamespaceContentModels[$ns] ) ) {
1681  }
1682 
1683  return true;
1684  }
1685 
1693  protected function getDefaultWikitextNS() {
1695 
1696  static $wikitextNS = null; // this is not going to change
1697  if ( $wikitextNS !== null ) {
1698  return $wikitextNS;
1699  }
1700 
1701  // quickly short out on most common case:
1702  if ( !isset( $wgNamespaceContentModels[NS_MAIN] ) ) {
1703  return NS_MAIN;
1704  }
1705 
1706  // NOTE: prefer content namespaces
1707  $namespaces = array_unique( array_merge(
1709  [ NS_MAIN, NS_HELP, NS_PROJECT ], // prefer these
1711  ) );
1712 
1713  $namespaces = array_diff( $namespaces, [
1714  NS_FILE, NS_CATEGORY, NS_MEDIAWIKI, NS_USER // don't mess with magic namespaces
1715  ] );
1716 
1717  $talk = array_filter( $namespaces, function ( $ns ) {
1718  return MWNamespace::isTalk( $ns );
1719  } );
1720 
1721  // prefer non-talk pages
1722  $namespaces = array_diff( $namespaces, $talk );
1723  $namespaces = array_merge( $namespaces, $talk );
1724 
1725  // check default content model of each namespace
1726  foreach ( $namespaces as $ns ) {
1727  if ( !isset( $wgNamespaceContentModels[$ns] ) ||
1729  ) {
1730  $wikitextNS = $ns;
1731 
1732  return $wikitextNS;
1733  }
1734  }
1735 
1736  // give up
1737  // @todo Inside a test, we could skip the test as incomplete.
1738  // But frequently, this is used in fixture setup.
1739  throw new MWException( "No namespace defaults to wikitext!" );
1740  }
1741 
1748  protected function markTestSkippedIfNoDiff3() {
1749  global $wgDiff3;
1750 
1751  # This check may also protect against code injection in
1752  # case of broken installations.
1753  MediaWiki\suppressWarnings();
1754  $haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
1755  MediaWiki\restoreWarnings();
1756 
1757  if ( !$haveDiff3 ) {
1758  $this->markTestSkipped( "Skip test, since diff3 is not configured" );
1759  }
1760  }
1761 
1770  protected function checkPHPExtension( $extName ) {
1771  $loaded = extension_loaded( $extName );
1772  if ( !$loaded ) {
1773  $this->markTestSkipped( "PHP extension '$extName' is not loaded, skipping." );
1774  }
1775 
1776  return $loaded;
1777  }
1778 
1793  protected function assertValidHtmlSnippet( $html ) {
1794  $html = '<!DOCTYPE html><html><head><title>test</title></head><body>' . $html . '</body></html>';
1795  $this->assertValidHtmlDocument( $html );
1796  }
1797 
1809  protected function assertValidHtmlDocument( $html ) {
1810  // Note: we only validate if the tidy PHP extension is available.
1811  // In case wgTidyInternal is false, MWTidy would fall back to the command line version
1812  // of tidy. In that case however, we can not reliably detect whether a failing validation
1813  // is due to malformed HTML, or caused by tidy not being installed as a command line tool.
1814  // That would cause all HTML assertions to fail on a system that has no tidy installed.
1815  if ( !$GLOBALS['wgTidyInternal'] || !MWTidy::isEnabled() ) {
1816  $this->markTestSkipped( 'Tidy extension not installed' );
1817  }
1818 
1819  $errorBuffer = '';
1820  MWTidy::checkErrors( $html, $errorBuffer );
1821  $allErrors = preg_split( '/[\r\n]+/', $errorBuffer );
1822 
1823  // Filter Tidy warnings which aren't useful for us.
1824  // Tidy eg. often cries about parameters missing which have actually
1825  // been deprecated since HTML4, thus we should not care about them.
1826  $errors = preg_grep(
1827  '/^(.*Warning: (trimming empty|.* lacks ".*?" attribute).*|\s*)$/m',
1828  $allErrors, PREG_GREP_INVERT
1829  );
1830 
1831  $this->assertEmpty( $errors, implode( "\n", $errors ) );
1832  }
1833 
1839  public static function wfResetOutputBuffersBarrier( $buffer ) {
1840  return $buffer;
1841  }
1842 
1850  protected function setTemporaryHook( $hookName, $handler ) {
1851  $this->mergeMwGlobalArrayValue( 'wgHooks', [ $hookName => [ $handler ] ] );
1852  }
1853 
1863  protected function assertFileContains(
1864  $fileName,
1865  $actualData,
1866  $createIfMissing = true,
1867  $msg = ''
1868  ) {
1869  if ( $createIfMissing ) {
1870  if ( !file_exists( $fileName ) ) {
1871  file_put_contents( $fileName, $actualData );
1872  $this->markTestSkipped( 'Data file $fileName does not exist' );
1873  }
1874  } else {
1875  self::assertFileExists( $fileName );
1876  }
1877  self::assertEquals( file_get_contents( $fileName ), $actualData, $msg );
1878  }
1879 }
MediaWikiTestCase\createMock2
createMock2( $originalClassName)
Return a test double for the specified class.
Definition: MediaWikiTestCase.php:1374
Wikimedia\Rdbms\Database\tablePrefix
tablePrefix( $prefix=null)
Get/set the table prefix.
Definition: Database.php:480
ObjectCache\clear
static clear()
Clear all the cached instances.
Definition: ObjectCache.php:400
MediaWiki\Logger\LegacySpi
LoggerFactory service provider that creates LegacyLogger instances.
Definition: LegacySpi.php:37
MediaWikiTestCase\$reuseDB
static $reuseDB
Definition: MediaWikiTestCase.php:61
MediaWikiTestCase\assertValidHtmlDocument
assertValidHtmlDocument( $html)
Asserts that the given string is valid HTML document.
Definition: MediaWikiTestCase.php:1809
MediaWiki\Logger\MonologSpi
LoggerFactory service provider that creates loggers implemented by Monolog.
Definition: MonologSpi.php:115
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:45
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:244
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:33
$wgNamespaceContentModels
$wgNamespaceContentModels
Associative array mapping namespace IDs to the name of the content model pages in that namespace shou...
Definition: DefaultSettings.php:8448
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:268
MediaWikiTestCase\assertArrayEquals
assertArrayEquals(array $expected, array $actual, $ordered=false, $named=false)
Assert that two arrays are equal.
Definition: MediaWikiTestCase.php:1552
MediaWikiTestCase\stashMwGlobals
stashMwGlobals( $globalKeys)
Stashes the global, will be restored in tearDown()
Definition: MediaWikiTestCase.php:724
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
NS_HELP
const NS_HELP
Definition: Defines.php:77
MWNamespace\getValidNamespaces
static getValidNamespaces()
Returns an array of the namespaces (by integer id) that exist on the wiki.
Definition: MWNamespace.php:264
$tables
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
Definition: hooks.txt:988
Wikimedia\Rdbms\Database\listTables
listTables( $prefix=null, $fname=__METHOD__)
List all tables on the database.
Definition: Database.php:3073
MWNamespace\isTalk
static isTalk( $index)
Is the given namespace a talk namespace?
Definition: MWNamespace.php:96
MediaWikiTestCase\mergeMwGlobalArrayValue
mergeMwGlobalArrayValue( $name, $values)
Merges the given values into a MW global array variable.
Definition: MediaWikiTestCase.php:807
MediaWikiTestCase\restoreLoggers
restoreLoggers()
Restores loggers replaced by setLogger().
Definition: MediaWikiTestCase.php:935
MediaWikiTestCase\getTestUser
static getTestUser( $groups=[])
Convenience method for getting an immutable test user.
Definition: MediaWikiTestCase.php:148
MediaWikiTestCase\wfResetOutputBuffersBarrier
static wfResetOutputBuffersBarrier( $buffer)
Used as a marker to prevent wfResetOutputBuffers from breaking PHPUnit.
Definition: MediaWikiTestCase.php:1839
MediaWikiTestCase\stripStringKeys
static stripStringKeys(&$r)
Utility function for eliminating all string keys from an array.
Definition: MediaWikiTestCase.php:1615
MultiConfig
Provides a fallback sequence for Config objects.
Definition: MultiConfig.php:28
wfMkdirParents
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
Definition: GlobalFunctions.php:2126
MediaWikiTestCase\makeTestConfigFactoryInstantiator
static makeTestConfigFactoryInstantiator(ConfigFactory $oldFactory, array $configurations)
Definition: MediaWikiTestCase.php:322
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:78
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
HashConfig
A Config instance which stores all settings as a member variable.
Definition: HashConfig.php:28
MediaWikiTestCase\$tmpFiles
array $tmpFiles
Holds the paths of temporary files/directories created through getNewTempFile, and getNewTempDirector...
Definition: MediaWikiTestCase.php:78
MediaWikiTestCase\setUpBeforeClass
static setUpBeforeClass()
Definition: MediaWikiTestCase.php:133
$wgDiff3
$wgDiff3
Path to the GNU diff3 utility.
Definition: DefaultSettings.php:6562
MediaWikiTestCase\assertFileContains
assertFileContains( $fileName, $actualData, $createIfMissing=true, $msg='')
Check whether file contains given data.
Definition: MediaWikiTestCase.php:1863
CACHE_NONE
const CACHE_NONE
Definition: Defines.php:103
MediaWikiTestCase\setupAllTestDBs
setupAllTestDBs()
Set up all test DBs.
Definition: MediaWikiTestCase.php:1168
MediaWikiTestCase\isWikitextNS
isWikitextNS( $ns)
Returns true if the given namespace defaults to Wikitext according to $wgNamespaceContentModels.
Definition: MediaWikiTestCase.php:1676
MediaWikiTestCase\needsDB
needsDB()
Definition: MediaWikiTestCase.php:970
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1963
CACHE_MEMCACHED
const CACHE_MEMCACHED
Definition: Defines.php:105
$namespaces
namespace and then decline to actually register it & $namespaces
Definition: hooks.txt:932
MediaWiki\MediaWikiServices\getBootstrapConfig
getBootstrapConfig()
Returns the Config object containing the bootstrap configuration.
Definition: MediaWikiServices.php:402
MediaWikiTestCase\installTestServices
static installTestServices(ConfigFactory $oldConfigFactory, LBFactory $oldLoadBalancerFactory, MediaWikiServices $newServices)
Definition: MediaWikiTestCase.php:291
$status
Status::newGood()` to allow deletion, and then `return false` from the hook function. Ensure you consume the 'ChangeTagAfterDelete' hook to carry out custom deletion actions. $tag:name of the tag $user:user initiating the action & $status:Status object. See above. 'ChangeTagsListActive':Allows you to nominate which of the tags your extension uses are in active use. & $tags:list of all active tags. Append to this array. 'ChangeTagsAfterUpdateTags':Called after tags have been updated with the ChangeTags::updateTags function. Params:$addedTags:tags effectively added in the update $removedTags:tags effectively removed in the update $prevTags:tags that were present prior to the update $rc_id:recentchanges table id $rev_id:revision table id $log_id:logging table id $params:tag params $rc:RecentChange being tagged when the tagging accompanies the action or null $user:User who performed the tagging when the tagging is subsequent to the action or null 'ChangeTagsAllowedAdd':Called when checking if a user can add tags to a change. & $allowedTags:List of all the tags the user is allowed to add. Any tags the user wants to add( $addTags) that are not in this array will cause it to fail. You may add or remove tags to this array as required. $addTags:List of tags user intends to add. $user:User who is adding the tags. 'ChangeUserGroups':Called before user groups are changed. $performer:The User who will perform the change $user:The User whose groups will be changed & $add:The groups that will be added & $remove:The groups that will be removed 'Collation::factory':Called if $wgCategoryCollation is an unknown collation. $collationName:Name of the collation in question & $collationObject:Null. Replace with a subclass of the Collation class that implements the collation given in $collationName. 'ConfirmEmailComplete':Called after a user 's email has been confirmed successfully. $user:user(object) whose email is being confirmed 'ContentAlterParserOutput':Modify parser output for a given content object. Called by Content::getParserOutput after parsing has finished. Can be used for changes that depend on the result of the parsing but have to be done before LinksUpdate is called(such as adding tracking categories based on the rendered HTML). $content:The Content to render $title:Title of the page, as context $parserOutput:ParserOutput to manipulate 'ContentGetParserOutput':Customize parser output for a given content object, called by AbstractContent::getParserOutput. May be used to override the normal model-specific rendering of page content. $content:The Content to render $title:Title of the page, as context $revId:The revision ID, as context $options:ParserOptions for rendering. To avoid confusing the parser cache, the output can only depend on parameters provided to this hook function, not on global state. $generateHtml:boolean, indicating whether full HTML should be generated. If false, generation of HTML may be skipped, but other information should still be present in the ParserOutput object. & $output:ParserOutput, to manipulate or replace 'ContentHandlerDefaultModelFor':Called when the default content model is determined for a given title. May be used to assign a different model for that title. $title:the Title in question & $model:the model name. Use with CONTENT_MODEL_XXX constants. 'ContentHandlerForModelID':Called when a ContentHandler is requested for a given content model name, but no entry for that model exists in $wgContentHandlers. Note:if your extension implements additional models via this hook, please use GetContentModels hook to make them known to core. $modeName:the requested content model name & $handler:set this to a ContentHandler object, if desired. 'ContentModelCanBeUsedOn':Called to determine whether that content model can be used on a given page. This is especially useful to prevent some content models to be used in some special location. $contentModel:ID of the content model in question $title:the Title in question. & $ok:Output parameter, whether it is OK to use $contentModel on $title. Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok. 'ContribsPager::getQueryInfo':Before the contributions query is about to run & $pager:Pager object for contributions & $queryInfo:The query for the contribs Pager 'ContribsPager::reallyDoQuery':Called before really executing the query for My Contributions & $data:an array of results of all contribs queries $pager:The ContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'ContributionsLineEnding':Called before a contributions HTML line is finished $page:SpecialPage object for contributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'ContributionsToolLinks':Change tool links above Special:Contributions $id:User identifier $title:User page title & $tools:Array of tool links $specialPage:SpecialPage instance for context and services. Can be either SpecialContributions or DeletedContributionsPage. Extensions should type hint against a generic SpecialPage though. 'ConvertContent':Called by AbstractContent::convert when a conversion to another content model is requested. Handler functions that modify $result should generally return false to disable further attempts at conversion. $content:The Content object to be converted. $toModel:The ID of the content model to convert to. $lossy:boolean indicating whether lossy conversion is allowed. & $result:Output parameter, in case the handler function wants to provide a converted Content object. Note that $result->getContentModel() must return $toModel. 'CustomEditor':When invoking the page editor Return true to allow the normal editor to be used, or false if implementing a custom editor, e.g. for a special namespace, etc. $article:Article being edited $user:User performing the edit 'DatabaseOraclePostInit':Called after initialising an Oracle database $db:the DatabaseOracle object 'DeletedContribsPager::reallyDoQuery':Called before really executing the query for Special:DeletedContributions Similar to ContribsPager::reallyDoQuery & $data:an array of results of all contribs queries $pager:The DeletedContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'DeletedContributionsLineEnding':Called before a DeletedContributions HTML line is finished. Similar to ContributionsLineEnding $page:SpecialPage object for DeletedContributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'DifferenceEngineAfterLoadNewText':called in DifferenceEngine::loadNewText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before returning true from this function. $differenceEngine:DifferenceEngine object 'DifferenceEngineLoadTextAfterNewContentIsLoaded':called in DifferenceEngine::loadText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before checking if the variable 's value is null. This hook can be used to inject content into said class member variable. $differenceEngine:DifferenceEngine object 'DifferenceEngineMarkPatrolledLink':Allows extensions to change the "mark as patrolled" link which is shown both on the diff header as well as on the bottom of a page, usually wrapped in a span element which has class="patrollink". $differenceEngine:DifferenceEngine object & $markAsPatrolledLink:The "mark as patrolled" link HTML(string) $rcid:Recent change ID(rc_id) for this change(int) 'DifferenceEngineMarkPatrolledRCID':Allows extensions to possibly change the rcid parameter. For example the rcid might be set to zero due to the user being the same as the performer of the change but an extension might still want to show it under certain conditions. & $rcid:rc_id(int) of the change or 0 $differenceEngine:DifferenceEngine object $change:RecentChange object $user:User object representing the current user 'DifferenceEngineNewHeader':Allows extensions to change the $newHeader variable, which contains information about the new revision, such as the revision 's author, whether the revision was marked as a minor edit or not, etc. $differenceEngine:DifferenceEngine object & $newHeader:The string containing the various #mw-diff-otitle[1-5] divs, which include things like revision author info, revision comment, RevisionDelete link and more $formattedRevisionTools:Array containing revision tools, some of which may have been injected with the DiffRevisionTools hook $nextlink:String containing the link to the next revision(if any) $status
Definition: hooks.txt:1245
Wikimedia\Rdbms\IDatabase\lastError
lastError()
Get a description of the last error.
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
PHPUnitMaintClass\$additionalOptions
static $additionalOptions
Definition: phpunit.php:18
MediaWikiTestCase\$useTemporaryTables
static $useTemporaryTables
Definition: MediaWikiTestCase.php:60
CACHE_ACCEL
const CACHE_ACCEL
Definition: Defines.php:106
unserialize
unserialize( $serialized)
Definition: ApiMessage.php:185
NS_FILE
const NS_FILE
Definition: Defines.php:71
MediaWikiTestCase\checkDbIsSupported
checkDbIsSupported()
Definition: MediaWikiTestCase.php:1432
serialize
serialize()
Definition: ApiMessage.php:177
MediaWikiTestCase\getCliArg
getCliArg( $offset)
Definition: MediaWikiTestCase.php:1443
MediaWikiTestCase\testMediaWikiTestCaseParentSetupCalled
testMediaWikiTestCaseParentSetupCalled()
Make sure MediaWikiTestCase extending classes have called their parent setUp method.
Definition: MediaWikiTestCase.php:607
MediaWikiTestCase\assertValidHtmlSnippet
assertValidHtmlSnippet( $html)
Asserts that the given string is a valid HTML snippet.
Definition: MediaWikiTestCase.php:1793
MediaWikiTestCase\isNotUnittest
static isNotUnittest( $table)
Definition: MediaWikiTestCase.php:1388
$res
$res
Definition: database.txt:21
JobQueueGroup\destroySingletons
static destroySingletons()
Destroy the singleton instances.
Definition: JobQueueGroup.php:94
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
MWTidy\isEnabled
static isEnabled()
Definition: MWTidy.php:79
DeferredUpdates\clearPendingUpdates
static clearPendingUpdates()
Clear all pending updates without performing them.
Definition: DeferredUpdates.php:352
CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:236
MediaWikiTestCase\prepareServices
static prepareServices(Config $bootstrapConfig)
Prepare service configuration for unit testing.
Definition: MediaWikiTestCase.php:195
$wgDefaultExternalStore
array $wgDefaultExternalStore
The place to put new revisions, false to put them in the local text table.
Definition: DefaultSettings.php:2146
MWNamespace\getContentNamespaces
static getContentNamespaces()
Get a list of all namespace indices which are considered to contain content.
Definition: MWNamespace.php:353
$wgDBprefix
$wgDBprefix
Table name prefix.
Definition: DefaultSettings.php:1849
MediaWikiTestCase\addDBDataOnce
addDBDataOnce()
Stub.
Definition: MediaWikiTestCase.php:1038
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
MediaWikiTestCase\teardownTestDB
static teardownTestDB()
Restores MediaWiki to using the table set (table prefix) it was using before setupTestDB() was called...
Definition: MediaWikiTestCase.php:1117
TestUser
Wraps the user object, so we can also retain full access to properties like password if we log in via...
Definition: TestUser.php:7
MediaWikiTestCase\overrideMwServices
overrideMwServices(Config $configOverrides=null, array $services=[])
Stashes the global instance of MediaWikiServices, and installs a new one, allowing test cases to over...
Definition: MediaWikiTestCase.php:839
MediaWikiTestCase\__call
__call( $func, $args)
Definition: MediaWikiTestCase.php:1355
FileBackendGroup\destroySingleton
static destroySingleton()
Destroy the singleton instance.
Definition: FileBackendGroup.php:57
MediaWikiTestCase\$called
$called
$called tracks whether the setUp and tearDown method has been called.
Definition: MediaWikiTestCase.php:38
NS_MAIN
const NS_MAIN
Definition: Defines.php:65
MediaWiki\Services\ServiceContainer\redefineService
redefineService( $name, callable $instantiator)
Replace an already defined service.
Definition: ServiceContainer.php:238
MediaWikiTestCase\getExternalStoreDatabaseConnections
static getExternalStoreDatabaseConnections()
Gets master database connections for all of the ExternalStoreDB stores configured in $wgDefaultExtern...
Definition: MediaWikiTestCase.php:1258
MediaWikiTestCase\setupDatabaseWithTestPrefix
static setupDatabaseWithTestPrefix(IMaintainableDatabase $db, $prefix)
Setups a database with the given prefix.
Definition: MediaWikiTestCase.php:1150
Wikimedia\Rdbms\Database\delete
delete( $table, $conds, $fname=__METHOD__)
DELETE query wrapper.
Definition: Database.php:2355
$html
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition: hooks.txt:1965
MWException
MediaWiki exception.
Definition: MWException.php:26
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:932
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:121
NS_PROJECT
const NS_PROJECT
Definition: Defines.php:69
MediaWiki\MediaWikiServices\resetServiceForTesting
resetServiceForTesting( $name, $destroy=true)
Resets the given service for testing purposes.
Definition: MediaWikiServices.php:327
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1176
MediaWikiTestCase\$phpErrorLevel
int $phpErrorLevel
Original value of PHP's error_reporting setting.
Definition: MediaWikiTestCase.php:70
MediaWikiTestCase\assertSelect
assertSelect( $table, $fields, $condition, array $expectedRows)
Asserts that the given database query yields the rows given by $expectedRows.
Definition: MediaWikiTestCase.php:1491
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2856
MediaWikiTestCase\setMwGlobals
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown.
Definition: MediaWikiTestCase.php:672
MediaWikiTestCase\getNewTempFile
getNewTempFile()
Obtains a new temporary file name.
Definition: MediaWikiTestCase.php:457
MediaWikiTestCase\addCoreDBData
addCoreDBData()
Definition: MediaWikiTestCase.php:1053
MediaWikiTestCase\run
run(PHPUnit_Framework_TestResult $result=null)
Definition: MediaWikiTestCase.php:380
MediaWikiTestCase
Definition: MediaWikiTestCase.php:15
MediaWikiTestCase\$oldTablePrefix
static $oldTablePrefix
Definition: MediaWikiTestCase.php:63
MediaWikiTestCase\hideDeprecated
hideDeprecated( $function)
Don't throw a warning if $function is deprecated and called later.
Definition: MediaWikiTestCase.php:1467
MediaWikiTestCase\isUsingExternalStoreDB
static isUsingExternalStoreDB()
Check whether ExternalStoreDB is being used.
Definition: MediaWikiTestCase.php:1282
MediaWikiTestCase\listTables
static listTables(IMaintainableDatabase $db)
Definition: MediaWikiTestCase.php:1399
MediaWikiTestCase\$users
static TestUser[] $users
Definition: MediaWikiTestCase.php:44
MediaWikiTestCase\doLightweightServiceReset
doLightweightServiceReset()
Resets some well known services that typically have state that may interfere with unit tests.
Definition: MediaWikiTestCase.php:358
GlobalVarConfig
Accesses configuration settings from $GLOBALS.
Definition: GlobalVarConfig.php:28
MediaWikiTestCase\getDefaultWikitextNS
getDefaultWikitextNS()
Returns the ID of a namespace that defaults to Wikitext.
Definition: MediaWikiTestCase.php:1693
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:79
MediaWikiTestCase\setUserLang
setUserLang( $lang)
Definition: MediaWikiTestCase.php:877
$GLOBALS
$GLOBALS['wgAutoloadClasses']['LocalisationUpdate']
Definition: Autoload.php:10
DB_MASTER
const DB_MASTER
Definition: defines.php:26
WikitextContent
Content object for wiki text pages.
Definition: WikitextContent.php:33
MediaWikiTestCase\__construct
__construct( $name=null, array $data=[], $dataName='')
Definition: MediaWikiTestCase.php:118
MediaWiki\Session\SessionManager\resetCache
static resetCache()
Reset the internal caching for unit testing.
Definition: SessionManager.php:955
MediaWiki\Auth\AuthManager\resetCache
static resetCache()
Reset the internal caching for unit testing.
Definition: AuthManager.php:2433
MediaWikiTestCase\arrayWrap
arrayWrap(array $elements)
Utility method taking an array of elements and wrapping each element in its own array.
Definition: MediaWikiTestCase.php:1531
run
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a and you may at your option offer warranty protection in exchange for a fee You may modify your copy or copies of the Program or any portion of thus forming a work based on the and copy and distribute such modifications or work under the terms of Section provided that you also meet all of these that in whole or in part contains or is derived from the Program or any part to be licensed as a whole at no charge to all third parties under the terms of this License c If the modified program normally reads commands interactively when run
Definition: COPYING.txt:87
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
$services
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title after the basic globals have been set but before ordinary actions take place or wrap services the preferred way to define a new service is the $wgServiceWiringFiles array $services
Definition: hooks.txt:2198
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:129
MediaWikiTestCase\setContentLang
setContentLang( $lang)
Definition: MediaWikiTestCase.php:886
MediaWikiTestCase\setupExternalStoreTestDBs
static setupExternalStoreTestDBs( $testPrefix)
Clones the External Store database(s) for testing.
Definition: MediaWikiTestCase.php:1237
MediaWikiTestCase\markTestSkippedIfNoDiff3
markTestSkippedIfNoDiff3()
Check, if $wgDiff3 is set and ready to merge Will mark the calling test as skipped,...
Definition: MediaWikiTestCase.php:1748
MediaWikiTestCase\resetGlobalServices
static resetGlobalServices(Config $bootstrapConfig=null)
Reset global services, and install testing environment.
Definition: MediaWikiTestCase.php:218
MediaWikiTestCase\$serviceLocator
static MediaWikiServices null $serviceLocator
The service locator created by prepareServices().
Definition: MediaWikiTestCase.php:24
RequestContext\resetMain
static resetMain()
Resets singleton returned by getMain().
Definition: RequestContext.php:496
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2141
MediaWikiTestCase\assertHTMLEquals
assertHTMLEquals( $expected, $actual, $msg='')
Put each HTML element on its own line and then equals() the results.
Definition: MediaWikiTestCase.php:1583
MediaWikiTestCase\setupTestDB
static setupTestDB(Database $db, $prefix)
Creates an empty skeleton of the wiki database by cloning its structure to equivalent tables using th...
Definition: MediaWikiTestCase.php:1204
MediaWikiTestCase\addTmpFiles
addTmpFiles( $files)
Definition: MediaWikiTestCase.php:524
$value
$value
Definition: styleTest.css.php:45
MediaWikiTestCase\assertTypeOrValue
assertTypeOrValue( $type, $actual, $value=false, $message='')
Asserts that the provided variable is of the specified internal type or equals the $value argument.
Definition: MediaWikiTestCase.php:1640
LegacySpi
MediaWiki Logger LegacySpi
Definition: logger.txt:53
ConfigFactory\makeConfig
makeConfig( $name)
Create a given Config using the registered callback for $name.
Definition: ConfigFactory.php:124
MediaWikiTestCase\getMutableTestUser
static getMutableTestUser( $groups=[])
Convenience method for getting a mutable test user.
Definition: MediaWikiTestCase.php:160
MediaWikiTestCase\dbPrefix
dbPrefix()
Definition: MediaWikiTestCase.php:962
MediaWikiTestCase\$mwGlobalsToUnset
array $mwGlobalsToUnset
Holds list of MediaWiki configuration settings to be unset in tearDown().
Definition: MediaWikiTestCase.php:93
MediaWikiTestCase\resetDB
resetDB( $db, $tablesUsed)
Empty all tables so they can be repopulated for tests.
Definition: MediaWikiTestCase.php:1304
MediaWikiTestCase\getTestSysop
static getTestSysop()
Convenience method for getting an immutable admin test user.
Definition: MediaWikiTestCase.php:172
Wikimedia\Rdbms\Database\tableName
tableName( $name, $format='quoted')
Format a table name ready for use in constructing an SQL query.
Definition: Database.php:1788
Wikimedia\Rdbms\Database\query
query( $sql, $fname=__METHOD__, $tempIgnore=false)
Run an SQL query and return the result.
Definition: Database.php:888
$handler
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable modifiable after all normalizations have been except for the $wgMaxImageArea check set to true or false to override the $wgMaxImageArea check result gives extension the possibility to transform it themselves $handler
Definition: hooks.txt:781
RequestContext\getMain
static getMain()
Static methods.
Definition: RequestContext.php:470
MediaWikiTestCase\addDBData
addDBData()
Stub.
Definition: MediaWikiTestCase.php:1050
MediaWikiTestCase\setUp
setUp()
Definition: MediaWikiTestCase.php:487
Maintenance\setLBFactoryTriggers
static setLBFactoryTriggers(LBFactory $LBFactory)
Definition: Maintenance.php:579
$wgJobClasses
$wgJobClasses
Maps jobs to their handlers; extensions can add to this to provide custom jobs.
Definition: DefaultSettings.php:7396
MediaWikiTestCase\objectAssociativeSort
objectAssociativeSort(array &$array)
Does an associative sort that works for objects.
Definition: MediaWikiTestCase.php:1597
EDIT_NEW
const EDIT_NEW
Definition: Defines.php:153
MediaWikiTestCase\DB_PREFIX
const DB_PREFIX
Table name prefixes.
Definition: MediaWikiTestCase.php:104
$args
if( $line===false) $args
Definition: cdb.php:63
MonologSpi
MediaWiki Logger MonologSpi
Definition: logger.txt:58
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:2107
ConfigFactory\getConfigNames
getConfigNames()
Definition: ConfigFactory.php:93
ExternalStore\getStoreObject
static getStoreObject( $proto, array $params=[])
Get an external store object of the given type, with the given parameters.
Definition: ExternalStore.php:54
MediaWikiTestCase\$supportedDBs
array $supportedDBs
Definition: MediaWikiTestCase.php:111
CloneDatabase
Definition: CloneDatabase.php:29
MediaWikiTestCase\canShallowCopy
static canShallowCopy( $value)
Check if we can back up a value by performing a shallow copy.
Definition: MediaWikiTestCase.php:692
MediaWikiTestCase\ORA_DB_PREFIX
const ORA_DB_PREFIX
Definition: MediaWikiTestCase.php:105
ObjectCache\getMainWANInstance
static getMainWANInstance()
Get the main WAN cache object.
Definition: ObjectCache.php:370
MediaWikiTestCase\setLogger
setLogger( $channel, LoggerInterface $logger)
Sets the logger for a specified channel, for the duration of the test.
Definition: MediaWikiTestCase.php:906
CloneDatabase\changePrefix
static changePrefix( $prefix)
Change the table prefix on all open DB connections/.
Definition: CloneDatabase.php:136
MediaWikiTestCase\insertPage
insertPage( $pageName, $text='Sample page for unit test.', $namespace=null)
Insert a new page.
Definition: MediaWikiTestCase.php:996
User\resetIdByNameCache
static resetIdByNameCache()
Reset the cache used in idFromName().
Definition: User.php:805
wfRecursiveRemoveDir
wfRecursiveRemoveDir( $dir)
Remove a directory and all its content.
Definition: GlobalFunctions.php:2169
LinkCache\singleton
static singleton()
Get an instance of this class.
Definition: LinkCache.php:67
MediaWikiTestCase\makeTestConfig
static makeTestConfig(Config $baseConfig=null, Config $customOverrides=null)
Create a config suitable for testing, based on a base config, default overrides, and custom overrides...
Definition: MediaWikiTestCase.php:245
JobQueueGroup\singleton
static singleton( $wiki=false)
Definition: JobQueueGroup.php:72
MediaWikiTestCase\$tablesUsed
array $tablesUsed
Definition: MediaWikiTestCase.php:58
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Wikimedia\Rdbms\IDatabase\getType
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
MediaWikiTestCase\oncePerClass
oncePerClass()
Definition: MediaWikiTestCase.php:426
ConfigFactory
Factory class to create Config objects.
Definition: ConfigFactory.php:31
MediaWikiTestCase\containsClosure
containsClosure( $var, $maxDepth=15)
Definition: MediaWikiTestCase.php:776
NS_USER
const NS_USER
Definition: Defines.php:67
MediaWikiTestCase\checkPHPExtension
checkPHPExtension( $extName)
Check if $extName is a loaded PHP extension, will skip the test whenever it is not loaded.
Definition: MediaWikiTestCase.php:1770
LoggerFactory
MediaWiki Logger LoggerFactory implements a PSR[0] compatible message logging system Named Psr Log LoggerInterface instances can be obtained from the MediaWiki Logger LoggerFactory::getInstance() static method. MediaWiki\Logger\LoggerFactory expects a class implementing the MediaWiki\Logger\Spi interface to act as a factory for new Psr\Log\LoggerInterface instances. The "Spi" in MediaWiki\Logger\Spi stands for "service provider interface". An SPI is an API intended to be implemented or extended by a third party. This software design pattern is intended to enable framework extension and replaceable components. It is specifically used in the MediaWiki\Logger\LoggerFactory service to allow alternate PSR-3 logging implementations to be easily integrated with MediaWiki. The service provider interface allows the backend logging library to be implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the classname of the default MediaWiki\Logger\Spi implementation to be loaded at runtime. This can either be the name of a class implementing the MediaWiki\Logger\Spi with a zero argument const ructor or a callable that will return an MediaWiki\Logger\Spi instance. Alternately the MediaWiki\Logger\LoggerFactory MediaWiki Logger LoggerFactory
Definition: logger.txt:5
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:183
Wikimedia\Rdbms\Database\select
select( $table, $vars, $conds='', $fname=__METHOD__, $options=[], $join_conds=[])
Execute a SELECT query constructed using the various parameters provided.
Definition: Database.php:1339
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:73
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
TestUserRegistry\getMutableTestUser
static getMutableTestUser( $testName, $groups=[])
Get a TestUser object that the caller may modify.
Definition: TestUserRegistry.php:34
EDIT_SUPPRESS_RC
const EDIT_SUPPRESS_RC
Definition: Defines.php:156
MediaWikiTestCase\$mwGlobals
array $mwGlobals
Holds original values of MediaWiki configuration settings to be restored in tearDown().
Definition: MediaWikiTestCase.php:86
MediaWikiTestCase\$loggers
LoggerInterface[] $loggers
Holds original loggers which have been replaced by setLogger()
Definition: MediaWikiTestCase.php:99
MediaWikiTestCase\setTemporaryHook
setTemporaryHook( $hookName, $handler)
Create a temporary hook handler which will be reset by tearDown.
Definition: MediaWikiTestCase.php:1850
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:662
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
MWTidy\checkErrors
static checkErrors( $text, &$errorStr=null)
Check HTML for errors, used if $wgValidateAllHtml = true.
Definition: MWTidy.php:63
MediaWikiTestCase\usesTemporaryTables
usesTemporaryTables()
Definition: MediaWikiTestCase.php:444
MediaWikiTestCase\assertType
assertType( $type, $actual, $message='')
Asserts the type of the provided value.
Definition: MediaWikiTestCase.php:1659
TestUserRegistry\getImmutableTestUser
static getImmutableTestUser( $groups=[])
Get a TestUser object that the caller may not modify.
Definition: TestUserRegistry.php:60
MediaWikiTestCase\setCliArg
setCliArg( $offset, $value)
Definition: MediaWikiTestCase.php:1456
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:51
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:203
MediaWikiTestCase\setService
setService( $name, $object)
Sets a service, maintaining a stashed version of the previous service to be restored in tearDown.
Definition: MediaWikiTestCase.php:622
Wikimedia\Rdbms\Database\listViews
listViews( $prefix=null, $fname=__METHOD__)
Lists all the VIEWs in the database.
Definition: Database.php:3077
wfGetCaller
wfGetCaller( $level=2)
Get the name of the function which called this function wfGetCaller( 1 ) is the function with the wfG...
Definition: GlobalFunctions.php:1607
Wikimedia\Rdbms\IMaintainableDatabase
Advanced database interface for IDatabase handles that include maintenance methods.
Definition: IMaintainableDatabase.php:39
MediaWikiTestCase\__destruct
__destruct()
Definition: MediaWikiTestCase.php:125
Language
Internationalisation code.
Definition: Language.php:35
MediaWikiTestCase\unprefixTable
static unprefixTable(&$tableName, $ind, $prefix)
Definition: MediaWikiTestCase.php:1384
MediaWikiTestCase\$db
Database $db
Primary database.
Definition: MediaWikiTestCase.php:52
$buffer
$buffer
Definition: mwdoc-filter.php:49
CACHE_DB
const CACHE_DB
Definition: Defines.php:104
MediaWikiTestCase\tearDown
tearDown()
Definition: MediaWikiTestCase.php:528
array
the array() calling protocol came about after MediaWiki 1.4rc1.
MediaWikiTestCase\$dbSetup
static $dbSetup
Definition: MediaWikiTestCase.php:62
$wgSQLMode
$wgSQLMode
SQL Mode - default is turning off all modes, including strict, if set.
Definition: DefaultSettings.php:1862
TestUserRegistry\clear
static clear()
Clear the registry.
Definition: TestUserRegistry.php:107
$type
$type
Definition: testCompression.php:48
MediaWikiTestCase\getNewTempDirectory
getNewTempDirectory()
obtains a new temporary directory
Definition: MediaWikiTestCase.php:474