MediaWiki  1.29.1
Maintenance.php
Go to the documentation of this file.
1 <?php
23 // Bail on old versions of PHP, or if composer has not been run yet to install
24 // dependencies.
25 require_once __DIR__ . '/../includes/PHPVersionCheck.php';
26 wfEntryPointCheck( 'cli' );
27 
29 
35 // Define this so scripts can easily find doMaintenance.php
36 define( 'RUN_MAINTENANCE_IF_MAIN', __DIR__ . '/doMaintenance.php' );
37 define( 'DO_MAINTENANCE', RUN_MAINTENANCE_IF_MAIN ); // original name, harmless
38 
39 $maintClass = false;
40 
46 
57 abstract class Maintenance {
62  const DB_NONE = 0;
63  const DB_STD = 1;
64  const DB_ADMIN = 2;
65 
66  // Const for getStdin()
67  const STDIN_ALL = 'all';
68 
69  // This is the desired params
70  protected $mParams = [];
71 
72  // Array of mapping short parameters to long ones
73  protected $mShortParamsMap = [];
74 
75  // Array of desired args
76  protected $mArgList = [];
77 
78  // This is the list of options that were actually passed
79  protected $mOptions = [];
80 
81  // This is the list of arguments that were actually passed
82  protected $mArgs = [];
83 
84  // Name of the script currently running
85  protected $mSelf;
86 
87  // Special vars for params that are always used
88  protected $mQuiet = false;
89  protected $mDbUser, $mDbPass;
90 
91  // A description of the script, children should change this via addDescription()
92  protected $mDescription = '';
93 
94  // Have we already loaded our user input?
95  protected $mInputLoaded = false;
96 
103  protected $mBatchSize = null;
104 
105  // Generic options added by addDefaultParams()
106  private $mGenericParameters = [];
107  // Generic options which might or not be supported by the script
108  private $mDependantParameters = [];
109 
114  private $mDb = null;
115 
117  private $lastReplicationWait = 0.0;
118 
123  public $fileHandle;
124 
130  private $config;
131 
136  private $requiredExtensions = [];
137 
149  public $orderedOptions = [];
150 
155  public function __construct() {
156  // Setup $IP, using MW_INSTALL_PATH if it exists
157  global $IP;
158  $IP = strval( getenv( 'MW_INSTALL_PATH' ) ) !== ''
159  ? getenv( 'MW_INSTALL_PATH' )
160  : realpath( __DIR__ . '/..' );
161 
162  $this->addDefaultParams();
163  register_shutdown_function( [ $this, 'outputChanneled' ], false );
164  }
165 
173  public static function shouldExecute() {
175 
176  if ( !function_exists( 'debug_backtrace' ) ) {
177  // If someone has a better idea...
178  return $wgCommandLineMode;
179  }
180 
181  $bt = debug_backtrace();
182  $count = count( $bt );
183  if ( $count < 2 ) {
184  return false; // sanity
185  }
186  if ( $bt[0]['class'] !== 'Maintenance' || $bt[0]['function'] !== 'shouldExecute' ) {
187  return false; // last call should be to this function
188  }
189  $includeFuncs = [ 'require_once', 'require', 'include', 'include_once' ];
190  for ( $i = 1; $i < $count; $i++ ) {
191  if ( !in_array( $bt[$i]['function'], $includeFuncs ) ) {
192  return false; // previous calls should all be "requires"
193  }
194  }
195 
196  return true;
197  }
198 
202  abstract public function execute();
203 
215  protected function addOption( $name, $description, $required = false,
216  $withArg = false, $shortName = false, $multiOccurrence = false
217  ) {
218  $this->mParams[$name] = [
219  'desc' => $description,
220  'require' => $required,
221  'withArg' => $withArg,
222  'shortName' => $shortName,
223  'multiOccurrence' => $multiOccurrence
224  ];
225 
226  if ( $shortName !== false ) {
227  $this->mShortParamsMap[$shortName] = $name;
228  }
229  }
230 
236  protected function hasOption( $name ) {
237  return isset( $this->mOptions[$name] );
238  }
239 
250  protected function getOption( $name, $default = null ) {
251  if ( $this->hasOption( $name ) ) {
252  return $this->mOptions[$name];
253  } else {
254  // Set it so we don't have to provide the default again
255  $this->mOptions[$name] = $default;
256 
257  return $this->mOptions[$name];
258  }
259  }
260 
267  protected function addArg( $arg, $description, $required = true ) {
268  $this->mArgList[] = [
269  'name' => $arg,
270  'desc' => $description,
271  'require' => $required
272  ];
273  }
274 
279  protected function deleteOption( $name ) {
280  unset( $this->mParams[$name] );
281  }
282 
287  protected function addDescription( $text ) {
288  $this->mDescription = $text;
289  }
290 
296  protected function hasArg( $argId = 0 ) {
297  return isset( $this->mArgs[$argId] );
298  }
299 
306  protected function getArg( $argId = 0, $default = null ) {
307  return $this->hasArg( $argId ) ? $this->mArgs[$argId] : $default;
308  }
309 
314  protected function setBatchSize( $s = 0 ) {
315  $this->mBatchSize = $s;
316 
317  // If we support $mBatchSize, show the option.
318  // Used to be in addDefaultParams, but in order for that to
319  // work, subclasses would have to call this function in the constructor
320  // before they called parent::__construct which is just weird
321  // (and really wasn't done).
322  if ( $this->mBatchSize ) {
323  $this->addOption( 'batch-size', 'Run this many operations ' .
324  'per batch, default: ' . $this->mBatchSize, false, true );
325  if ( isset( $this->mParams['batch-size'] ) ) {
326  // This seems a little ugly...
327  $this->mDependantParameters['batch-size'] = $this->mParams['batch-size'];
328  }
329  }
330  }
331 
336  public function getName() {
337  return $this->mSelf;
338  }
339 
346  protected function getStdin( $len = null ) {
347  if ( $len == Maintenance::STDIN_ALL ) {
348  return file_get_contents( 'php://stdin' );
349  }
350  $f = fopen( 'php://stdin', 'rt' );
351  if ( !$len ) {
352  return $f;
353  }
354  $input = fgets( $f, $len );
355  fclose( $f );
356 
357  return rtrim( $input );
358  }
359 
363  public function isQuiet() {
364  return $this->mQuiet;
365  }
366 
373  protected function output( $out, $channel = null ) {
374  if ( $this->mQuiet ) {
375  return;
376  }
377  if ( $channel === null ) {
378  $this->cleanupChanneled();
379  print $out;
380  } else {
381  $out = preg_replace( '/\n\z/', '', $out );
382  $this->outputChanneled( $out, $channel );
383  }
384  }
385 
392  protected function error( $err, $die = 0 ) {
393  $this->outputChanneled( false );
394  if ( PHP_SAPI == 'cli' ) {
395  fwrite( STDERR, $err . "\n" );
396  } else {
397  print $err;
398  }
399  $die = intval( $die );
400  if ( $die > 0 ) {
401  die( $die );
402  }
403  }
404 
405  private $atLineStart = true;
406  private $lastChannel = null;
407 
411  public function cleanupChanneled() {
412  if ( !$this->atLineStart ) {
413  print "\n";
414  $this->atLineStart = true;
415  }
416  }
417 
426  public function outputChanneled( $msg, $channel = null ) {
427  if ( $msg === false ) {
428  $this->cleanupChanneled();
429 
430  return;
431  }
432 
433  // End the current line if necessary
434  if ( !$this->atLineStart && $channel !== $this->lastChannel ) {
435  print "\n";
436  }
437 
438  print $msg;
439 
440  $this->atLineStart = false;
441  if ( $channel === null ) {
442  // For unchanneled messages, output trailing newline immediately
443  print "\n";
444  $this->atLineStart = true;
445  }
446  $this->lastChannel = $channel;
447  }
448 
459  public function getDbType() {
460  return Maintenance::DB_STD;
461  }
462 
466  protected function addDefaultParams() {
467  # Generic (non script dependant) options:
468 
469  $this->addOption( 'help', 'Display this help message', false, false, 'h' );
470  $this->addOption( 'quiet', 'Whether to supress non-error output', false, false, 'q' );
471  $this->addOption( 'conf', 'Location of LocalSettings.php, if not default', false, true );
472  $this->addOption( 'wiki', 'For specifying the wiki ID', false, true );
473  $this->addOption( 'globals', 'Output globals at the end of processing for debugging' );
474  $this->addOption(
475  'memory-limit',
476  'Set a specific memory limit for the script, '
477  . '"max" for no limit or "default" to avoid changing it'
478  );
479  $this->addOption( 'server', "The protocol and server name to use in URLs, e.g. " .
480  "http://en.wikipedia.org. This is sometimes necessary because " .
481  "server name detection may fail in command line scripts.", false, true );
482  $this->addOption( 'profiler', 'Profiler output format (usually "text")', false, true );
483 
484  # Save generic options to display them separately in help
485  $this->mGenericParameters = $this->mParams;
486 
487  # Script dependant options:
488 
489  // If we support a DB, show the options
490  if ( $this->getDbType() > 0 ) {
491  $this->addOption( 'dbuser', 'The DB user to use for this script', false, true );
492  $this->addOption( 'dbpass', 'The password to use for this script', false, true );
493  }
494 
495  # Save additional script dependant options to display
496  # ┬áthem separately in help
497  $this->mDependantParameters = array_diff_key( $this->mParams, $this->mGenericParameters );
498  }
499 
504  public function getConfig() {
505  if ( $this->config === null ) {
506  $this->config = MediaWikiServices::getInstance()->getMainConfig();
507  }
508 
509  return $this->config;
510  }
511 
516  public function setConfig( Config $config ) {
517  $this->config = $config;
518  }
519 
529  protected function requireExtension( $name ) {
530  $this->requiredExtensions[] = $name;
531  }
532 
538  public function checkRequiredExtensions() {
539  $registry = ExtensionRegistry::getInstance();
540  $missing = [];
541  foreach ( $this->requiredExtensions as $name ) {
542  if ( !$registry->isLoaded( $name ) ) {
543  $missing[] = $name;
544  }
545  }
546 
547  if ( $missing ) {
548  $joined = implode( ', ', $missing );
549  $msg = "The following extensions are required to be installed "
550  . "for this script to run: $joined. Please enable them and then try again.";
551  $this->error( $msg, 1 );
552  }
553  }
554 
559  public function setAgentAndTriggers() {
560  if ( function_exists( 'posix_getpwuid' ) ) {
561  $agent = posix_getpwuid( posix_geteuid() )['name'];
562  } else {
563  $agent = 'sysadmin';
564  }
565  $agent .= '@' . wfHostname();
566 
567  $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
568  // Add a comment for easy SHOW PROCESSLIST interpretation
569  $lbFactory->setAgentName(
570  mb_strlen( $agent ) > 15 ? mb_substr( $agent, 0, 15 ) . '...' : $agent
571  );
573  }
574 
579  public static function setLBFactoryTriggers( LBFactory $LBFactory ) {
580  // Hook into period lag checks which often happen in long-running scripts
581  $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
582  $lbFactory->setWaitForReplicationListener(
583  __METHOD__,
584  function () {
586  // Check config in case of JobRunner and unit tests
587  if ( $wgCommandLineMode ) {
589  }
590  }
591  );
592  // Check for other windows to run them. A script may read or do a few writes
593  // to the master but mostly be writing to something else, like a file store.
594  $lbFactory->getMainLB()->setTransactionListener(
595  __METHOD__,
596  function ( $trigger ) {
598  // Check config in case of JobRunner and unit tests
599  if ( $wgCommandLineMode && $trigger === IDatabase::TRIGGER_COMMIT ) {
601  }
602  }
603  );
604  }
605 
613  public function runChild( $maintClass, $classFile = null ) {
614  // Make sure the class is loaded first
615  if ( !class_exists( $maintClass ) ) {
616  if ( $classFile ) {
617  require_once $classFile;
618  }
619  if ( !class_exists( $maintClass ) ) {
620  $this->error( "Cannot spawn child: $maintClass" );
621  }
622  }
623 
627  $child = new $maintClass();
628  $child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs );
629  if ( !is_null( $this->mDb ) ) {
630  $child->setDB( $this->mDb );
631  }
632 
633  return $child;
634  }
635 
639  public function setup() {
641 
642  # Abort if called from a web server
643  if ( isset( $_SERVER ) && isset( $_SERVER['REQUEST_METHOD'] ) ) {
644  $this->error( 'This script must be run from the command line', true );
645  }
646 
647  if ( $IP === null ) {
648  $this->error( "\$IP not set, aborting!\n" .
649  '(Did you forget to call parent::__construct() in your maintenance script?)', 1 );
650  }
651 
652  # Make sure we can handle script parameters
653  if ( !defined( 'HPHP_VERSION' ) && !ini_get( 'register_argc_argv' ) ) {
654  $this->error( 'Cannot get command line arguments, register_argc_argv is set to false', true );
655  }
656 
657  // Send PHP warnings and errors to stderr instead of stdout.
658  // This aids in diagnosing problems, while keeping messages
659  // out of redirected output.
660  if ( ini_get( 'display_errors' ) ) {
661  ini_set( 'display_errors', 'stderr' );
662  }
663 
664  $this->loadParamsAndArgs();
665  $this->maybeHelp();
666 
667  # Set the memory limit
668  # Note we need to set it again later in cache LocalSettings changed it
669  $this->adjustMemoryLimit();
670 
671  # Set max execution time to 0 (no limit). PHP.net says that
672  # "When running PHP from the command line the default setting is 0."
673  # But sometimes this doesn't seem to be the case.
674  ini_set( 'max_execution_time', 0 );
675 
676  $wgRequestTime = microtime( true );
677 
678  # Define us as being in MediaWiki
679  define( 'MEDIAWIKI', true );
680 
681  $wgCommandLineMode = true;
682 
683  # Turn off output buffering if it's on
684  while ( ob_get_level() > 0 ) {
685  ob_end_flush();
686  }
687 
688  $this->validateParamsAndArgs();
689  }
690 
700  public function memoryLimit() {
701  $limit = $this->getOption( 'memory-limit', 'max' );
702  $limit = trim( $limit, "\" '" ); // trim quotes in case someone misunderstood
703  return $limit;
704  }
705 
709  protected function adjustMemoryLimit() {
710  $limit = $this->memoryLimit();
711  if ( $limit == 'max' ) {
712  $limit = -1; // no memory limit
713  }
714  if ( $limit != 'default' ) {
715  ini_set( 'memory_limit', $limit );
716  }
717  }
718 
722  protected function activateProfiler() {
723  global $wgProfiler, $wgProfileLimit, $wgTrxProfilerLimits;
724 
725  $output = $this->getOption( 'profiler' );
726  if ( !$output ) {
727  return;
728  }
729 
730  if ( is_array( $wgProfiler ) && isset( $wgProfiler['class'] ) ) {
731  $class = $wgProfiler['class'];
733  $profiler = new $class(
734  [ 'sampling' => 1, 'output' => [ $output ] ]
735  + $wgProfiler
736  + [ 'threshold' => $wgProfileLimit ]
737  );
738  $profiler->setTemplated( true );
739  Profiler::replaceStubInstance( $profiler );
740  }
741 
742  $trxProfiler = Profiler::instance()->getTransactionProfiler();
743  $trxProfiler->setLogger( LoggerFactory::getInstance( 'DBPerformance' ) );
744  $trxProfiler->setExpectations( $wgTrxProfilerLimits['Maintenance'], __METHOD__ );
745  }
746 
750  public function clearParamsAndArgs() {
751  $this->mOptions = [];
752  $this->mArgs = [];
753  $this->mInputLoaded = false;
754  }
755 
763  public function loadWithArgv( $argv ) {
764  $options = [];
765  $args = [];
766  $this->orderedOptions = [];
767 
768  # Parse arguments
769  for ( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) {
770  if ( $arg == '--' ) {
771  # End of options, remainder should be considered arguments
772  $arg = next( $argv );
773  while ( $arg !== false ) {
774  $args[] = $arg;
775  $arg = next( $argv );
776  }
777  break;
778  } elseif ( substr( $arg, 0, 2 ) == '--' ) {
779  # Long options
780  $option = substr( $arg, 2 );
781  if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) {
782  $param = next( $argv );
783  if ( $param === false ) {
784  $this->error( "\nERROR: $option parameter needs a value after it\n" );
785  $this->maybeHelp( true );
786  }
787 
788  $this->setParam( $options, $option, $param );
789  } else {
790  $bits = explode( '=', $option, 2 );
791  if ( count( $bits ) > 1 ) {
792  $option = $bits[0];
793  $param = $bits[1];
794  } else {
795  $param = 1;
796  }
797 
798  $this->setParam( $options, $option, $param );
799  }
800  } elseif ( $arg == '-' ) {
801  # Lonely "-", often used to indicate stdin or stdout.
802  $args[] = $arg;
803  } elseif ( substr( $arg, 0, 1 ) == '-' ) {
804  # Short options
805  $argLength = strlen( $arg );
806  for ( $p = 1; $p < $argLength; $p++ ) {
807  $option = $arg[$p];
808  if ( !isset( $this->mParams[$option] ) && isset( $this->mShortParamsMap[$option] ) ) {
809  $option = $this->mShortParamsMap[$option];
810  }
811 
812  if ( isset( $this->mParams[$option]['withArg'] ) && $this->mParams[$option]['withArg'] ) {
813  $param = next( $argv );
814  if ( $param === false ) {
815  $this->error( "\nERROR: $option parameter needs a value after it\n" );
816  $this->maybeHelp( true );
817  }
818  $this->setParam( $options, $option, $param );
819  } else {
820  $this->setParam( $options, $option, 1 );
821  }
822  }
823  } else {
824  $args[] = $arg;
825  }
826  }
827 
828  $this->mOptions = $options;
829  $this->mArgs = $args;
830  $this->loadSpecialVars();
831  $this->mInputLoaded = true;
832  }
833 
846  private function setParam( &$options, $option, $value ) {
847  $this->orderedOptions[] = [ $option, $value ];
848 
849  if ( isset( $this->mParams[$option] ) ) {
850  $multi = $this->mParams[$option]['multiOccurrence'];
851  } else {
852  $multi = false;
853  }
854  $exists = array_key_exists( $option, $options );
855  if ( $multi && $exists ) {
856  $options[$option][] = $value;
857  } elseif ( $multi ) {
858  $options[$option] = [ $value ];
859  } elseif ( !$exists ) {
860  $options[$option] = $value;
861  } else {
862  $this->error( "\nERROR: $option parameter given twice\n" );
863  $this->maybeHelp( true );
864  }
865  }
866 
876  public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) {
877  # If we were given opts or args, set those and return early
878  if ( $self ) {
879  $this->mSelf = $self;
880  $this->mInputLoaded = true;
881  }
882  if ( $opts ) {
883  $this->mOptions = $opts;
884  $this->mInputLoaded = true;
885  }
886  if ( $args ) {
887  $this->mArgs = $args;
888  $this->mInputLoaded = true;
889  }
890 
891  # If we've already loaded input (either by user values or from $argv)
892  # skip on loading it again. The array_shift() will corrupt values if
893  # it's run again and again
894  if ( $this->mInputLoaded ) {
895  $this->loadSpecialVars();
896 
897  return;
898  }
899 
900  global $argv;
901  $this->mSelf = $argv[0];
902  $this->loadWithArgv( array_slice( $argv, 1 ) );
903  }
904 
908  protected function validateParamsAndArgs() {
909  $die = false;
910  # Check to make sure we've got all the required options
911  foreach ( $this->mParams as $opt => $info ) {
912  if ( $info['require'] && !$this->hasOption( $opt ) ) {
913  $this->error( "Param $opt required!" );
914  $die = true;
915  }
916  }
917  # Check arg list too
918  foreach ( $this->mArgList as $k => $info ) {
919  if ( $info['require'] && !$this->hasArg( $k ) ) {
920  $this->error( 'Argument <' . $info['name'] . '> required!' );
921  $die = true;
922  }
923  }
924 
925  if ( $die ) {
926  $this->maybeHelp( true );
927  }
928  }
929 
933  protected function loadSpecialVars() {
934  if ( $this->hasOption( 'dbuser' ) ) {
935  $this->mDbUser = $this->getOption( 'dbuser' );
936  }
937  if ( $this->hasOption( 'dbpass' ) ) {
938  $this->mDbPass = $this->getOption( 'dbpass' );
939  }
940  if ( $this->hasOption( 'quiet' ) ) {
941  $this->mQuiet = true;
942  }
943  if ( $this->hasOption( 'batch-size' ) ) {
944  $this->mBatchSize = intval( $this->getOption( 'batch-size' ) );
945  }
946  }
947 
952  protected function maybeHelp( $force = false ) {
953  if ( !$force && !$this->hasOption( 'help' ) ) {
954  return;
955  }
956 
957  $screenWidth = 80; // TODO: Calculate this!
958  $tab = " ";
959  $descWidth = $screenWidth - ( 2 * strlen( $tab ) );
960 
961  ksort( $this->mParams );
962  $this->mQuiet = false;
963 
964  // Description ...
965  if ( $this->mDescription ) {
966  $this->output( "\n" . wordwrap( $this->mDescription, $screenWidth ) . "\n" );
967  }
968  $output = "\nUsage: php " . basename( $this->mSelf );
969 
970  // ... append parameters ...
971  if ( $this->mParams ) {
972  $output .= " [--" . implode( array_keys( $this->mParams ), "|--" ) . "]";
973  }
974 
975  // ... and append arguments.
976  if ( $this->mArgList ) {
977  $output .= ' ';
978  foreach ( $this->mArgList as $k => $arg ) {
979  if ( $arg['require'] ) {
980  $output .= '<' . $arg['name'] . '>';
981  } else {
982  $output .= '[' . $arg['name'] . ']';
983  }
984  if ( $k < count( $this->mArgList ) - 1 ) {
985  $output .= ' ';
986  }
987  }
988  }
989  $this->output( "$output\n\n" );
990 
991  # TODO abstract some repetitive code below
992 
993  // Generic parameters
994  $this->output( "Generic maintenance parameters:\n" );
995  foreach ( $this->mGenericParameters as $par => $info ) {
996  if ( $info['shortName'] !== false ) {
997  $par .= " (-{$info['shortName']})";
998  }
999  $this->output(
1000  wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
1001  "\n$tab$tab" ) . "\n"
1002  );
1003  }
1004  $this->output( "\n" );
1005 
1006  $scriptDependantParams = $this->mDependantParameters;
1007  if ( count( $scriptDependantParams ) > 0 ) {
1008  $this->output( "Script dependant parameters:\n" );
1009  // Parameters description
1010  foreach ( $scriptDependantParams as $par => $info ) {
1011  if ( $info['shortName'] !== false ) {
1012  $par .= " (-{$info['shortName']})";
1013  }
1014  $this->output(
1015  wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
1016  "\n$tab$tab" ) . "\n"
1017  );
1018  }
1019  $this->output( "\n" );
1020  }
1021 
1022  // Script specific parameters not defined on construction by
1023  // Maintenance::addDefaultParams()
1024  $scriptSpecificParams = array_diff_key(
1025  # all script parameters:
1026  $this->mParams,
1027  # remove the Maintenance default parameters:
1028  $this->mGenericParameters,
1029  $this->mDependantParameters
1030  );
1031  if ( count( $scriptSpecificParams ) > 0 ) {
1032  $this->output( "Script specific parameters:\n" );
1033  // Parameters description
1034  foreach ( $scriptSpecificParams as $par => $info ) {
1035  if ( $info['shortName'] !== false ) {
1036  $par .= " (-{$info['shortName']})";
1037  }
1038  $this->output(
1039  wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
1040  "\n$tab$tab" ) . "\n"
1041  );
1042  }
1043  $this->output( "\n" );
1044  }
1045 
1046  // Print arguments
1047  if ( count( $this->mArgList ) > 0 ) {
1048  $this->output( "Arguments:\n" );
1049  // Arguments description
1050  foreach ( $this->mArgList as $info ) {
1051  $openChar = $info['require'] ? '<' : '[';
1052  $closeChar = $info['require'] ? '>' : ']';
1053  $this->output(
1054  wordwrap( "$tab$openChar" . $info['name'] . "$closeChar: " .
1055  $info['desc'], $descWidth, "\n$tab$tab" ) . "\n"
1056  );
1057  }
1058  $this->output( "\n" );
1059  }
1060 
1061  die( 1 );
1062  }
1063 
1067  public function finalSetup() {
1068  global $wgCommandLineMode, $wgShowSQLErrors, $wgServer;
1071 
1072  # Turn off output buffering again, it might have been turned on in the settings files
1073  if ( ob_get_level() ) {
1074  ob_end_flush();
1075  }
1076  # Same with these
1077  $wgCommandLineMode = true;
1078 
1079  # Override $wgServer
1080  if ( $this->hasOption( 'server' ) ) {
1081  $wgServer = $this->getOption( 'server', $wgServer );
1082  }
1083 
1084  # If these were passed, use them
1085  if ( $this->mDbUser ) {
1087  }
1088  if ( $this->mDbPass ) {
1090  }
1091 
1092  if ( $this->getDbType() == self::DB_ADMIN && isset( $wgDBadminuser ) ) {
1095 
1096  if ( $wgDBservers ) {
1100  foreach ( $wgDBservers as $i => $server ) {
1101  $wgDBservers[$i]['user'] = $wgDBuser;
1102  $wgDBservers[$i]['password'] = $wgDBpassword;
1103  }
1104  }
1105  if ( isset( $wgLBFactoryConf['serverTemplate'] ) ) {
1106  $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
1107  $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
1108  }
1109  MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->destroy();
1110  }
1111 
1112  // Per-script profiling; useful for debugging
1113  $this->activateProfiler();
1114 
1115  $this->afterFinalSetup();
1116 
1117  $wgShowSQLErrors = true;
1118 
1119  MediaWiki\suppressWarnings();
1120  set_time_limit( 0 );
1121  MediaWiki\restoreWarnings();
1122 
1123  $this->adjustMemoryLimit();
1124  }
1125 
1129  protected function afterFinalSetup() {
1130  if ( defined( 'MW_CMDLINE_CALLBACK' ) ) {
1131  call_user_func( MW_CMDLINE_CALLBACK );
1132  }
1133  }
1134 
1139  public function globals() {
1140  if ( $this->hasOption( 'globals' ) ) {
1141  print_r( $GLOBALS );
1142  }
1143  }
1144 
1149  public function loadSettings() {
1151 
1152  if ( isset( $this->mOptions['conf'] ) ) {
1153  $settingsFile = $this->mOptions['conf'];
1154  } elseif ( defined( "MW_CONFIG_FILE" ) ) {
1155  $settingsFile = MW_CONFIG_FILE;
1156  } else {
1157  $settingsFile = "$IP/LocalSettings.php";
1158  }
1159  if ( isset( $this->mOptions['wiki'] ) ) {
1160  $bits = explode( '-', $this->mOptions['wiki'] );
1161  if ( count( $bits ) == 1 ) {
1162  $bits[] = '';
1163  }
1164  define( 'MW_DB', $bits[0] );
1165  define( 'MW_PREFIX', $bits[1] );
1166  }
1167 
1168  if ( !is_readable( $settingsFile ) ) {
1169  $this->error( "A copy of your installation's LocalSettings.php\n" .
1170  "must exist and be readable in the source directory.\n" .
1171  "Use --conf to specify it.", true );
1172  }
1173  $wgCommandLineMode = true;
1174 
1175  return $settingsFile;
1176  }
1177 
1183  public function purgeRedundantText( $delete = true ) {
1184  # Data should come off the master, wrapped in a transaction
1185  $dbw = $this->getDB( DB_MASTER );
1186  $this->beginTransaction( $dbw, __METHOD__ );
1187 
1188  # Get "active" text records from the revisions table
1189  $cur = [];
1190  $this->output( 'Searching for active text records in revisions table...' );
1191  $res = $dbw->select( 'revision', 'rev_text_id', [], __METHOD__, [ 'DISTINCT' ] );
1192  foreach ( $res as $row ) {
1193  $cur[] = $row->rev_text_id;
1194  }
1195  $this->output( "done.\n" );
1196 
1197  # Get "active" text records from the archive table
1198  $this->output( 'Searching for active text records in archive table...' );
1199  $res = $dbw->select( 'archive', 'ar_text_id', [], __METHOD__, [ 'DISTINCT' ] );
1200  foreach ( $res as $row ) {
1201  # old pre-MW 1.5 records can have null ar_text_id's.
1202  if ( $row->ar_text_id !== null ) {
1203  $cur[] = $row->ar_text_id;
1204  }
1205  }
1206  $this->output( "done.\n" );
1207 
1208  # Get the IDs of all text records not in these sets
1209  $this->output( 'Searching for inactive text records...' );
1210  $cond = 'old_id NOT IN ( ' . $dbw->makeList( $cur ) . ' )';
1211  $res = $dbw->select( 'text', 'old_id', [ $cond ], __METHOD__, [ 'DISTINCT' ] );
1212  $old = [];
1213  foreach ( $res as $row ) {
1214  $old[] = $row->old_id;
1215  }
1216  $this->output( "done.\n" );
1217 
1218  # Inform the user of what we're going to do
1219  $count = count( $old );
1220  $this->output( "$count inactive items found.\n" );
1221 
1222  # Delete as appropriate
1223  if ( $delete && $count ) {
1224  $this->output( 'Deleting...' );
1225  $dbw->delete( 'text', [ 'old_id' => $old ], __METHOD__ );
1226  $this->output( "done.\n" );
1227  }
1228 
1229  # Done
1230  $this->commitTransaction( $dbw, __METHOD__ );
1231  }
1232 
1237  protected function getDir() {
1238  return __DIR__;
1239  }
1240 
1251  protected function getDB( $db, $groups = [], $wiki = false ) {
1252  if ( is_null( $this->mDb ) ) {
1253  return wfGetDB( $db, $groups, $wiki );
1254  } else {
1255  return $this->mDb;
1256  }
1257  }
1258 
1264  public function setDB( IDatabase $db ) {
1265  $this->mDb = $db;
1266  }
1267 
1278  protected function beginTransaction( IDatabase $dbw, $fname ) {
1279  $dbw->begin( $fname );
1280  }
1281 
1293  protected function commitTransaction( IDatabase $dbw, $fname ) {
1294  $dbw->commit( $fname );
1295  try {
1296  $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
1297  $lbFactory->waitForReplication(
1298  [ 'timeout' => 30, 'ifWritesSince' => $this->lastReplicationWait ]
1299  );
1300  $this->lastReplicationWait = microtime( true );
1301 
1302  return true;
1303  } catch ( DBReplicationWaitError $e ) {
1304  return false;
1305  }
1306  }
1307 
1318  protected function rollbackTransaction( IDatabase $dbw, $fname ) {
1319  $dbw->rollback( $fname );
1320  }
1321 
1326  private function lockSearchindex( $db ) {
1327  $write = [ 'searchindex' ];
1328  $read = [
1329  'page',
1330  'revision',
1331  'text',
1332  'interwiki',
1333  'l10n_cache',
1334  'user',
1335  'page_restrictions'
1336  ];
1337  $db->lockTables( $read, $write, __CLASS__ . '::' . __METHOD__ );
1338  }
1339 
1344  private function unlockSearchindex( $db ) {
1345  $db->unlockTables( __CLASS__ . '::' . __METHOD__ );
1346  }
1347 
1353  private function relockSearchindex( $db ) {
1354  $this->unlockSearchindex( $db );
1355  $this->lockSearchindex( $db );
1356  }
1357 
1365  public function updateSearchIndex( $maxLockTime, $callback, $dbw, $results ) {
1366  $lockTime = time();
1367 
1368  # Lock searchindex
1369  if ( $maxLockTime ) {
1370  $this->output( " --- Waiting for lock ---" );
1371  $this->lockSearchindex( $dbw );
1372  $lockTime = time();
1373  $this->output( "\n" );
1374  }
1375 
1376  # Loop through the results and do a search update
1377  foreach ( $results as $row ) {
1378  # Allow reads to be processed
1379  if ( $maxLockTime && time() > $lockTime + $maxLockTime ) {
1380  $this->output( " --- Relocking ---" );
1381  $this->relockSearchindex( $dbw );
1382  $lockTime = time();
1383  $this->output( "\n" );
1384  }
1385  call_user_func( $callback, $dbw, $row );
1386  }
1387 
1388  # Unlock searchindex
1389  if ( $maxLockTime ) {
1390  $this->output( " --- Unlocking --" );
1391  $this->unlockSearchindex( $dbw );
1392  $this->output( "\n" );
1393  }
1394  }
1395 
1402  public function updateSearchIndexForPage( $dbw, $pageId ) {
1403  // Get current revision
1404  $rev = Revision::loadFromPageId( $dbw, $pageId );
1405  $title = null;
1406  if ( $rev ) {
1407  $titleObj = $rev->getTitle();
1408  $title = $titleObj->getPrefixedDBkey();
1409  $this->output( "$title..." );
1410  # Update searchindex
1411  $u = new SearchUpdate( $pageId, $titleObj->getText(), $rev->getContent() );
1412  $u->doUpdate();
1413  $this->output( "\n" );
1414  }
1415 
1416  return $title;
1417  }
1418 
1427  public static function posix_isatty( $fd ) {
1428  if ( !function_exists( 'posix_isatty' ) ) {
1429  return !$fd;
1430  } else {
1431  return posix_isatty( $fd );
1432  }
1433  }
1434 
1440  public static function readconsole( $prompt = '> ' ) {
1441  static $isatty = null;
1442  if ( is_null( $isatty ) ) {
1443  $isatty = self::posix_isatty( 0 /*STDIN*/ );
1444  }
1445 
1446  if ( $isatty && function_exists( 'readline' ) ) {
1447  $resp = readline( $prompt );
1448  if ( $resp === null ) {
1449  // Workaround for https://github.com/facebook/hhvm/issues/4776
1450  return false;
1451  } else {
1452  return $resp;
1453  }
1454  } else {
1455  if ( $isatty ) {
1456  $st = self::readlineEmulation( $prompt );
1457  } else {
1458  if ( feof( STDIN ) ) {
1459  $st = false;
1460  } else {
1461  $st = fgets( STDIN, 1024 );
1462  }
1463  }
1464  if ( $st === false ) {
1465  return false;
1466  }
1467  $resp = trim( $st );
1468 
1469  return $resp;
1470  }
1471  }
1472 
1478  private static function readlineEmulation( $prompt ) {
1479  $bash = Installer::locateExecutableInDefaultPaths( [ 'bash' ] );
1480  if ( !wfIsWindows() && $bash ) {
1481  $retval = false;
1482  $encPrompt = wfEscapeShellArg( $prompt );
1483  $command = "read -er -p $encPrompt && echo \"\$REPLY\"";
1484  $encCommand = wfEscapeShellArg( $command );
1485  $line = wfShellExec( "$bash -c $encCommand", $retval, [], [ 'walltime' => 0 ] );
1486 
1487  if ( $retval == 0 ) {
1488  return $line;
1489  } elseif ( $retval == 127 ) {
1490  // Couldn't execute bash even though we thought we saw it.
1491  // Shell probably spit out an error message, sorry :(
1492  // Fall through to fgets()...
1493  } else {
1494  // EOF/ctrl+D
1495  return false;
1496  }
1497  }
1498 
1499  // Fallback... we'll have no editing controls, EWWW
1500  if ( feof( STDIN ) ) {
1501  return false;
1502  }
1503  print $prompt;
1504 
1505  return fgets( STDIN, 1024 );
1506  }
1507 
1515  public static function getTermSize() {
1516  $default = [ 80, 50 ];
1517  if ( wfIsWindows() ) {
1518  return $default;
1519  }
1520  // It's possible to get the screen size with VT-100 terminal escapes,
1521  // but reading the responses is not possible without setting raw mode
1522  // (unless you want to require the user to press enter), and that
1523  // requires an ioctl(), which we can't do. So we have to shell out to
1524  // something that can do the relevant syscalls. There are a few
1525  // options. Linux and Mac OS X both have "stty size" which does the
1526  // job directly.
1527  $retval = false;
1528  $size = wfShellExec( 'stty size', $retval );
1529  if ( $retval !== 0 ) {
1530  return $default;
1531  }
1532  if ( !preg_match( '/^(\d+) (\d+)$/', $size, $m ) ) {
1533  return $default;
1534  }
1535  return [ intval( $m[2] ), intval( $m[1] ) ];
1536  }
1537 
1542  public static function requireTestsAutoloader() {
1543  require_once __DIR__ . '/../tests/common/TestsAutoLoader.php';
1544  }
1545 }
1546 
1551  protected $mSelf = "FakeMaintenanceScript";
1552 
1553  public function execute() {
1554  return;
1555  }
1556 }
1557 
1562 abstract class LoggedUpdateMaintenance extends Maintenance {
1563  public function __construct() {
1564  parent::__construct();
1565  $this->addOption( 'force', 'Run the update even if it was completed already' );
1566  $this->setBatchSize( 200 );
1567  }
1568 
1569  public function execute() {
1570  $db = $this->getDB( DB_MASTER );
1571  $key = $this->getUpdateKey();
1572 
1573  if ( !$this->hasOption( 'force' )
1574  && $db->selectRow( 'updatelog', '1', [ 'ul_key' => $key ], __METHOD__ )
1575  ) {
1576  $this->output( "..." . $this->updateSkippedMessage() . "\n" );
1577 
1578  return true;
1579  }
1580 
1581  if ( !$this->doDBUpdates() ) {
1582  return false;
1583  }
1584 
1585  if ( $db->insert( 'updatelog', [ 'ul_key' => $key ], __METHOD__, 'IGNORE' ) ) {
1586  return true;
1587  } else {
1588  $this->output( $this->updatelogFailedMessage() . "\n" );
1589 
1590  return false;
1591  }
1592  }
1593 
1598  protected function updateSkippedMessage() {
1599  $key = $this->getUpdateKey();
1600 
1601  return "Update '{$key}' already logged as completed.";
1602  }
1603 
1608  protected function updatelogFailedMessage() {
1609  $key = $this->getUpdateKey();
1610 
1611  return "Unable to log update '{$key}' as completed.";
1612  }
1613 
1619  abstract protected function doDBUpdates();
1620 
1625  abstract protected function getUpdateKey();
1626 }
FakeMaintenance\$mSelf
$mSelf
Definition: Maintenance.php:1551
RUN_MAINTENANCE_IF_MAIN
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:36
Maintenance\$mBatchSize
int $mBatchSize
Batch size.
Definition: Maintenance.php:103
LoggedUpdateMaintenance\__construct
__construct()
Default constructor.
Definition: Maintenance.php:1563
Maintenance\setParam
setParam(&$options, $option, $value)
Helper function used solely by loadParamsAndArgs to prevent code duplication.
Definition: Maintenance.php:846
Maintenance\getTermSize
static getTermSize()
Get the terminal size as a two-element array where the first element is the width (number of columns)...
Definition: Maintenance.php:1515
Maintenance\$mShortParamsMap
$mShortParamsMap
Definition: Maintenance.php:73
Maintenance\getStdin
getStdin( $len=null)
Return input from stdin.
Definition: Maintenance.php:346
Profiler\replaceStubInstance
static replaceStubInstance(Profiler $profiler)
Replace the current profiler with $profiler if no non-stub profiler is set.
Definition: Profiler.php:97
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:62
Maintenance\getDbType
getDbType()
Does the script need different DB access? By default, we give Maintenance scripts normal rights to th...
Definition: Maintenance.php:459
$opt
$opt
Definition: postprocess-phan.php:115
Maintenance\maybeHelp
maybeHelp( $force=false)
Maybe show the help.
Definition: Maintenance.php:952
captcha-old.count
count
Definition: captcha-old.py:225
Maintenance\$mDbPass
$mDbPass
Definition: Maintenance.php:89
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:287
Maintenance\setup
setup()
Do some sanity checking and basic setup.
Definition: Maintenance.php:639
Maintenance\$requiredExtensions
array $requiredExtensions
Definition: Maintenance.php:136
Maintenance\runChild
runChild( $maintClass, $classFile=null)
Run a child maintenance script.
Definition: Maintenance.php:613
Maintenance\readconsole
static readconsole( $prompt='> ')
Prompt the console for input.
Definition: Maintenance.php:1440
Wikimedia\Rdbms\DBReplicationWaitError
Exception class for replica DB wait timeouts.
Definition: DBReplicationWaitError.php:28
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
Maintenance\loadParamsAndArgs
loadParamsAndArgs( $self=null, $opts=null, $args=null)
Process command line arguments $mOptions becomes an array with keys set to the option names $mArgs be...
Definition: Maintenance.php:876
$fname
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined.
Definition: Setup.php:36
Maintenance\relockSearchindex
relockSearchindex( $db)
Unlock and lock again Since the lock is low-priority, queued reads will be able to complete.
Definition: Maintenance.php:1353
Maintenance\getName
getName()
Get the script's name.
Definition: Maintenance.php:336
wfHostname
wfHostname()
Fetch server name for use in error reporting etc.
Definition: GlobalFunctions.php:1435
$wgLBFactoryConf
$wgLBFactoryConf
Load balancer factory configuration To set up a multi-master wiki farm, set the class here to somethi...
Definition: DefaultSettings.php:1961
$s
$s
Definition: mergeMessageFileList.php:188
Maintenance\hasArg
hasArg( $argId=0)
Does a given argument exist?
Definition: Maintenance.php:296
Maintenance\setDB
setDB(IDatabase $db)
Sets database object to be returned by getDB().
Definition: Maintenance.php:1264
$res
$res
Definition: database.txt:21
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:304
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: maintenance.txt:39
Maintenance\setConfig
setConfig(Config $config)
Definition: Maintenance.php:516
$lbFactory
$lbFactory
Definition: doMaintenance.php:117
$maintClass
$maintClass
Definition: Maintenance.php:39
$wgDBpassword
$wgDBpassword
Database user's password.
Definition: DefaultSettings.php:1770
Maintenance\$lastChannel
$lastChannel
Definition: Maintenance.php:406
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
Maintenance\loadWithArgv
loadWithArgv( $argv)
Load params and arguments from a given array of command-line arguments.
Definition: Maintenance.php:763
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:40
Maintenance\checkRequiredExtensions
checkRequiredExtensions()
Verify that the required extensions are installed.
Definition: Maintenance.php:538
Installer\locateExecutableInDefaultPaths
static locateExecutableInDefaultPaths( $names, $versionInfo=false)
Same as locateExecutable(), but checks in getPossibleBinPaths() by default.
Definition: Installer.php:1238
Maintenance\finalSetup
finalSetup()
Handle some last-minute setup here.
Definition: Maintenance.php:1067
Maintenance\rollbackTransaction
rollbackTransaction(IDatabase $dbw, $fname)
Rollback the transcation on a DB handle.
Definition: Maintenance.php:1318
wfEntryPointCheck
wfEntryPointCheck( $entryPoint)
Check php version and that external dependencies are installed, and display an informative error if e...
Definition: PHPVersionCheck.php:235
Wikimedia\Rdbms\IDatabase\commit
commit( $fname=__METHOD__, $flush='')
Commits a transaction previously started using begin().
Maintenance\$mDescription
$mDescription
Definition: Maintenance.php:92
Maintenance\beginTransaction
beginTransaction(IDatabase $dbw, $fname)
Begin a transcation on a DB.
Definition: Maintenance.php:1278
Maintenance\afterFinalSetup
afterFinalSetup()
Execute a callback function at the end of initialisation.
Definition: Maintenance.php:1129
ExtensionRegistry\getInstance
static getInstance()
Definition: ExtensionRegistry.php:80
$wgDBadminuser
$wgDBadminuser
Separate username for maintenance tasks.
Definition: DefaultSettings.php:1800
Maintenance\unlockSearchindex
unlockSearchindex( $db)
Unlock the tables.
Definition: Maintenance.php:1344
Maintenance\clearParamsAndArgs
clearParamsAndArgs()
Clear all params and arguments.
Definition: Maintenance.php:750
$wgDBservers
$wgDBservers
Database load balancer This is a two-dimensional array, an array of server info structures Fields are...
Definition: DefaultSettings.php:1949
Maintenance\$mSelf
$mSelf
Definition: Maintenance.php:85
Maintenance\updateSearchIndex
updateSearchIndex( $maxLockTime, $callback, $dbw, $results)
Perform a search index update with locking.
Definition: Maintenance.php:1365
Maintenance\$mArgs
$mArgs
Definition: Maintenance.php:82
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:934
Maintenance\loadSpecialVars
loadSpecialVars()
Handle the special variables that are global to all scripts.
Definition: Maintenance.php:933
Maintenance\getConfig
getConfig()
Definition: Maintenance.php:504
LoggedUpdateMaintenance
Class for scripts that perform database maintenance and want to log the update in updatelog so we can...
Definition: Maintenance.php:1562
script
script(document.cookie)%253c/script%253e</pre ></div > !! end !! test XSS is escaped(inline) !!input< source lang
Maintenance\$atLineStart
$atLineStart
Definition: Maintenance.php:405
$wgCommandLineMode
global $wgCommandLineMode
Definition: Setup.php:503
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3060
Maintenance\$lastReplicationWait
float $lastReplicationWait
UNIX timestamp.
Definition: Maintenance.php:117
$input
if(is_array( $mode)) switch( $mode) $input
Definition: postprocess-phan.php:141
Revision\loadFromPageId
static loadFromPageId( $db, $pageid, $id=0)
Load either the current, or a specified, revision that's attached to a given page.
Definition: Revision.php:262
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:215
$IP
$IP
Definition: update.php:3
Maintenance\$mDbUser
$mDbUser
Definition: Maintenance.php:89
Maintenance\requireExtension
requireExtension( $name)
Indicate that the specified extension must be loaded before the script can run.
Definition: Maintenance.php:529
$limit
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 and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers please use GetContentModels hook to make them known to core if desired 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 inclusive $limit
Definition: hooks.txt:1049
Maintenance\$orderedOptions
array $orderedOptions
Used to read the options in the order they were passed.
Definition: Maintenance.php:149
Maintenance\globals
globals()
Potentially debug globals.
Definition: Maintenance.php:1139
$output
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 and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object & $output
Definition: hooks.txt:1049
LoggedUpdateMaintenance\updatelogFailedMessage
updatelogFailedMessage()
Message to show that the update log was unable to log the completion of this update.
Definition: Maintenance.php:1608
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
FakeMaintenance
Fake maintenance wrapper, mostly used for the web installer/updater.
Definition: Maintenance.php:1550
$GLOBALS
$GLOBALS['wgAutoloadClasses']['LocalisationUpdate']
Definition: Autoload.php:10
DB_MASTER
const DB_MASTER
Definition: defines.php:26
Maintenance\addDefaultParams
addDefaultParams()
Add the default parameters to the scripts.
Definition: Maintenance.php:466
Maintenance\readlineEmulation
static readlineEmulation( $prompt)
Emulate readline()
Definition: Maintenance.php:1478
Maintenance\DB_ADMIN
const DB_ADMIN
Definition: Maintenance.php:64
Maintenance\$mGenericParameters
$mGenericParameters
Definition: Maintenance.php:106
Maintenance\deleteOption
deleteOption( $name)
Remove an option.
Definition: Maintenance.php:279
Maintenance\shouldExecute
static shouldExecute()
Should we execute the maintenance script, or just allow it to be included as a standalone class?...
Definition: Maintenance.php:173
$command
$command
Definition: cdb.php:64
$line
$line
Definition: cdb.php:58
LoggedUpdateMaintenance\execute
execute()
Do the actual work.
Definition: Maintenance.php:1569
Maintenance\DB_STD
const DB_STD
Definition: Maintenance.php:63
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2122
Maintenance\updateSearchIndexForPage
updateSearchIndexForPage( $dbw, $pageId)
Update the searchindex table for a given pageid.
Definition: Maintenance.php:1402
$value
$value
Definition: styleTest.css.php:45
Maintenance\$mQuiet
$mQuiet
Definition: Maintenance.php:88
Maintenance\isQuiet
isQuiet()
Definition: Maintenance.php:363
Maintenance\activateProfiler
activateProfiler()
Activate the profiler (assuming $wgProfiler is set)
Definition: Maintenance.php:722
DeferredUpdates\tryOpportunisticExecute
static tryOpportunisticExecute( $mode='run')
Run all deferred updates immediately if there are no DB writes active.
Definition: DeferredUpdates.php:281
$retval
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 incomplete not yet checked for validity & $retval
Definition: hooks.txt:246
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:2033
Maintenance\$mParams
$mParams
Definition: Maintenance.php:70
$wgServer
$wgServer
URL of the server.
Definition: DefaultSettings.php:109
wfEscapeShellArg
wfEscapeShellArg()
Version of escapeshellarg() that works better on Windows.
Definition: GlobalFunctions.php:2195
Maintenance\requireTestsAutoloader
static requireTestsAutoloader()
Call this to set up the autoloader to allow classes to be used from the tests directory.
Definition: Maintenance.php:1542
Maintenance\posix_isatty
static posix_isatty( $fd)
Wrapper for posix_isatty() We default as considering stdin a tty (for nice readline methods) but trea...
Definition: Maintenance.php:1427
LoggedUpdateMaintenance\updateSkippedMessage
updateSkippedMessage()
Message to show that the update was done already and was just skipped.
Definition: Maintenance.php:1598
Wikimedia\Rdbms\IDatabase\rollback
rollback( $fname=__METHOD__, $flush='')
Rollback a transaction previously started using begin().
Maintenance\$mDependantParameters
$mDependantParameters
Definition: Maintenance.php:108
Maintenance\commitTransaction
commitTransaction(IDatabase $dbw, $fname)
Commit the transcation on a DB handle and wait for replica DBs to catch up.
Definition: Maintenance.php:1293
Maintenance\validateParamsAndArgs
validateParamsAndArgs()
Run some validation checks on the params, etc.
Definition: Maintenance.php:908
Maintenance\$config
Config $config
Accessible via getConfig()
Definition: Maintenance.php:130
Maintenance\cleanupChanneled
cleanupChanneled()
Clean up channeled output.
Definition: Maintenance.php:411
Maintenance\DB_NONE
const DB_NONE
Constants for DB access type.
Definition: Maintenance.php:62
Maintenance\loadSettings
loadSettings()
Generic setup for most installs.
Definition: Maintenance.php:1149
LoggedUpdateMaintenance\doDBUpdates
doDBUpdates()
Do the actual work.
Maintenance\adjustMemoryLimit
adjustMemoryLimit()
Adjusts PHP's memory limit to better suit our needs, if needed.
Definition: Maintenance.php:709
Maintenance\setLBFactoryTriggers
static setLBFactoryTriggers(LBFactory $LBFactory)
Definition: Maintenance.php:579
LoggedUpdateMaintenance\getUpdateKey
getUpdateKey()
Get the update key name to go in the update log table.
Maintenance\purgeRedundantText
purgeRedundantText( $delete=true)
Support function for cleaning up redundant text records.
Definition: Maintenance.php:1183
$self
$self
Definition: doMaintenance.php:56
Maintenance\$fileHandle
resource $fileHandle
Used when creating separate schema files.
Definition: Maintenance.php:123
$args
if( $line===false) $args
Definition: cdb.php:63
Maintenance\$mInputLoaded
$mInputLoaded
Definition: Maintenance.php:95
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:250
Maintenance\STDIN_ALL
const STDIN_ALL
Definition: Maintenance.php:67
$wgRequestTime
float $wgRequestTime
Request start time as fractional seconds since epoch.
Definition: WebStart.php:43
Maintenance\addArg
addArg( $arg, $description, $required=true)
Add some args that are needed.
Definition: Maintenance.php:267
Wikimedia\Rdbms\LBFactory
An interface for generating database load balancers.
Definition: LBFactory.php:38
$rev
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition: hooks.txt:1741
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
Maintenance\$mOptions
$mOptions
Definition: Maintenance.php:79
Maintenance\setAgentAndTriggers
setAgentAndTriggers()
Set triggers like when to try to run deferred updates.
Definition: Maintenance.php:559
$wgProfiler
$wgProfiler
Definition: WebStart.php:73
Maintenance\getDB
getDB( $db, $groups=[], $wiki=false)
Returns a database to be used by current maintenance script.
Definition: Maintenance.php:1251
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
Maintenance\error
error( $err, $die=0)
Throw an error to the user.
Definition: Maintenance.php:392
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:373
Maintenance\$mArgList
$mArgList
Definition: Maintenance.php:76
$argv
global $argv
Definition: autoload.ide.php:24
Maintenance\getDir
getDir()
Get the maintenance directory.
Definition: Maintenance.php:1237
$wgDBuser
$wgDBuser
Database username.
Definition: DefaultSettings.php:1765
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
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular param exists.
Definition: Maintenance.php:236
Maintenance\getArg
getArg( $argId=0, $default=null)
Get an argument.
Definition: Maintenance.php:306
Maintenance::execute
public function execute()
Definition: maintenance.txt:45
$wgDBadminpassword
$wgDBadminpassword
Separate password for maintenance tasks.
Definition: DefaultSettings.php:1805
Maintenance\outputChanneled
outputChanneled( $msg, $channel=null)
Message outputter with channeled message support.
Definition: Maintenance.php:426
Maintenance\__construct
__construct()
Default constructor.
Definition: Maintenance.php:155
Wikimedia\Rdbms\IMaintainableDatabase
Advanced database interface for IDatabase handles that include maintenance methods.
Definition: IMaintainableDatabase.php:39
FakeMaintenance\execute
execute()
Do the actual work.
Definition: Maintenance.php:1553
$options
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 and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1049
Wikimedia\Rdbms\IDatabase\begin
begin( $fname=__METHOD__, $mode=self::TRANSACTION_EXPLICIT)
Begin a transaction.
Maintenance\lockSearchindex
lockSearchindex( $db)
Lock the search index.
Definition: Maintenance.php:1326
array
the array() calling protocol came about after MediaWiki 1.4rc1.
Maintenance\setBatchSize
setBatchSize( $s=0)
Set the batch size.
Definition: Maintenance.php:314
Maintenance\$mDb
IMaintainableDatabase $mDb
Used by getDB() / setDB()
Definition: Maintenance.php:114
Maintenance\memoryLimit
memoryLimit()
Normally we disable the memory_limit when running admin scripts.
Definition: Maintenance.php:700
wfShellExec
wfShellExec( $cmd, &$retval=null, $environ=[], $limits=[], $options=[])
Execute a shell command, with time and memory limits mirrored from the PHP configuration if supported...
Definition: GlobalFunctions.php:2297
$out
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 $out
Definition: hooks.txt:783