'ApiLogin' => __DIR__ . '/includes/api/ApiLogin.php',
'ApiLogout' => __DIR__ . '/includes/api/ApiLogout.php',
'ApiMain' => __DIR__ . '/includes/api/ApiMain.php',
+ 'ApiManageTags' => __DIR__ . '/includes/api/ApiManageTags.php',
'ApiModuleManager' => __DIR__ . '/includes/api/ApiModuleManager.php',
'ApiMove' => __DIR__ . '/includes/api/ApiMove.php',
'ApiOpenSearch' => __DIR__ . '/includes/api/ApiOpenSearch.php',
'DjVuImage' => __DIR__ . '/includes/media/DjVuImage.php',
'DoubleRedirectJob' => __DIR__ . '/includes/jobqueue/jobs/DoubleRedirectJob.php',
'DoubleRedirectsPage' => __DIR__ . '/includes/specials/SpecialDoubleRedirects.php',
- 'DoubleReplacer' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'DoubleReplacer' => __DIR__ . '/includes/libs/replacers/DoubleReplacer.php',
'DummyLinker' => __DIR__ . '/includes/Linker.php',
'DummyTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
'Dump7ZipOutput' => __DIR__ . '/includes/Export.php',
'ErrorPageError' => __DIR__ . '/includes/exception/ErrorPageError.php',
'Exif' => __DIR__ . '/includes/media/Exif.php',
'ExifBitmapHandler' => __DIR__ . '/includes/media/ExifBitmap.php',
- 'ExplodeIterator' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'ExplodeIterator' => __DIR__ . '/includes/libs/ExplodeIterator.php',
'ExportProgressFilter' => __DIR__ . '/maintenance/backup.inc',
'ExtensionLanguages' => __DIR__ . '/maintenance/language/languages.inc',
'ExtensionProcessor' => __DIR__ . '/includes/registration/ExtensionProcessor.php',
'HashBagOStuff' => __DIR__ . '/includes/objectcache/HashBagOStuff.php',
'HashConfig' => __DIR__ . '/includes/config/HashConfig.php',
'HashRing' => __DIR__ . '/includes/libs/HashRing.php',
- 'HashtableReplacer' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'HashtableReplacer' => __DIR__ . '/includes/libs/replacers/HashtableReplacer.php',
'HistoryAction' => __DIR__ . '/includes/actions/HistoryAction.php',
'HistoryBlob' => __DIR__ . '/includes/HistoryBlob.php',
'HistoryBlobCurStub' => __DIR__ . '/includes/HistoryBlob.php',
'ImageQueryPage' => __DIR__ . '/includes/specialpage/ImageQueryPage.php',
'ImportReporter' => __DIR__ . '/includes/specials/SpecialImport.php',
'ImportSiteScripts' => __DIR__ . '/maintenance/importSiteScripts.php',
+ 'ImportSource' => __DIR__ . '/includes/Import.php',
'ImportStreamSource' => __DIR__ . '/includes/Import.php',
'ImportStringSource' => __DIR__ . '/includes/Import.php',
'ImportTitleFactory' => __DIR__ . '/includes/title/ImportTitleFactory.php',
'MWHookException' => __DIR__ . '/includes/Hooks.php',
'MWHttpRequest' => __DIR__ . '/includes/HttpFunctions.php',
'MWLogger' => __DIR__ . '/includes/debug/logger/Logger.php',
+ 'MWLoggerFactory' => __DIR__ . '/includes/debug/logger/Factory.php',
'MWLoggerLegacyLogger' => __DIR__ . '/includes/debug/logger/legacy/Logger.php',
'MWLoggerLegacySpi' => __DIR__ . '/includes/debug/logger/legacy/Spi.php',
'MWLoggerMonologHandler' => __DIR__ . '/includes/debug/logger/monolog/Handler.php',
'MediaTransformError' => __DIR__ . '/includes/media/MediaTransformOutput.php',
'MediaTransformOutput' => __DIR__ . '/includes/media/MediaTransformOutput.php',
'MediaWiki' => __DIR__ . '/includes/MediaWiki.php',
- 'MediaWikiBagOStuff' => __DIR__ . '/includes/objectcache/SqlBagOStuff.php',
'MediaWikiI18N' => __DIR__ . '/includes/skins/MediaWikiI18N.php',
'MediaWikiPageLinkRenderer' => __DIR__ . '/includes/title/MediaWikiPageLinkRenderer.php',
'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
'MessageBlobStore' => __DIR__ . '/includes/MessageBlobStore.php',
'MessageCache' => __DIR__ . '/includes/cache/MessageCache.php',
'MessageContent' => __DIR__ . '/includes/content/MessageContent.php',
+ 'MessageSpecifier' => __DIR__ . '/includes/libs/MessageSpecifier.php',
'MigrateUserGroup' => __DIR__ . '/maintenance/migrateUserGroup.php',
'MimeMagic' => __DIR__ . '/includes/MimeMagic.php',
'MinifyScript' => __DIR__ . '/maintenance/minify.php',
'RebuildSitesCache' => __DIR__ . '/maintenance/rebuildSitesCache.php',
'RebuildTextIndex' => __DIR__ . '/maintenance/rebuildtextindex.php',
'RecentChange' => __DIR__ . '/includes/changes/RecentChange.php',
+ 'RecentChangesUpdateJob' => __DIR__ . '/includes/jobqueue/jobs/RecentChangesUpdateJob.php',
'RecompressTracked' => __DIR__ . '/maintenance/storage/recompressTracked.php',
'RedirectSpecialArticle' => __DIR__ . '/includes/specialpage/RedirectSpecialPage.php',
'RedirectSpecialPage' => __DIR__ . '/includes/specialpage/RedirectSpecialPage.php',
'RefreshLinks' => __DIR__ . '/maintenance/refreshLinks.php',
'RefreshLinksJob' => __DIR__ . '/includes/jobqueue/jobs/RefreshLinksJob.php',
'RefreshLinksJob2' => __DIR__ . '/includes/jobqueue/jobs/RefreshLinksJob2.php',
- 'RegexlikeReplacer' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'RegexlikeReplacer' => __DIR__ . '/includes/libs/replacers/RegexlikeReplacer.php',
'RemoveInvalidEmails' => __DIR__ . '/maintenance/removeInvalidEmails.php',
'RemoveUnusedAccounts' => __DIR__ . '/maintenance/removeUnusedAccounts.php',
'RenameDbPrefix' => __DIR__ . '/maintenance/renameDbPrefix.php',
'RenderAction' => __DIR__ . '/includes/actions/RenderAction.php',
- 'ReplacementArray' => __DIR__ . '/includes/utils/StringUtils.php',
- 'Replacer' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'ReplacementArray' => __DIR__ . '/includes/libs/ReplacementArray.php',
+ 'Replacer' => __DIR__ . '/includes/libs/replacers/Replacer.php',
'RepoGroup' => __DIR__ . '/includes/filerepo/RepoGroup.php',
'RequestContext' => __DIR__ . '/includes/context/RequestContext.php',
'ResetUserTokens' => __DIR__ . '/maintenance/resetUserTokens.php',
'StatCounter' => __DIR__ . '/includes/StatCounter.php',
'StatsOutput' => __DIR__ . '/maintenance/language/StatOutputs.php',
'Status' => __DIR__ . '/includes/Status.php',
+ 'StatusValue' => __DIR__ . '/includes/libs/StatusValue.php',
'StorageTypeStats' => __DIR__ . '/maintenance/storage/storageTypeStats.php',
'StoreFileOp' => __DIR__ . '/includes/filebackend/FileOp.php',
'StreamFile' => __DIR__ . '/includes/StreamFile.php',
'StringPrefixSearch' => __DIR__ . '/includes/PrefixSearch.php',
- 'StringUtils' => __DIR__ . '/includes/utils/StringUtils.php',
+ 'StringUtils' => __DIR__ . '/includes/libs/StringUtils.php',
'StripState' => __DIR__ . '/includes/parser/StripState.php',
'StubObject' => __DIR__ . '/includes/StubObject.php',
'StubUserLang' => __DIR__ . '/includes/StubObject.php',
'UserloginTemplate' => __DIR__ . '/includes/templates/Userlogin.php',
'UserrightsPage' => __DIR__ . '/includes/specials/SpecialUserrights.php',
'UsersPager' => __DIR__ . '/includes/specials/SpecialListusers.php',
- 'UtfNormal' => __DIR__ . '/includes/normal/UtfNormal.php',
+ 'UtfNormal' => __DIR__ . '/includes/libs/normal/UtfNormal.php',
'UzConverter' => __DIR__ . '/languages/classes/LanguageUz.php',
'VFormHTMLForm' => __DIR__ . '/includes/htmlform/VFormHTMLForm.php',
'ValidateRegistrationFile' => __DIR__ . '/maintenance/validateRegistrationFile.php',
*/
$wgAppleTouchIcon = false;
+/**
+ * Value for the referrer policy meta tag.
+ * One of 'never', 'default', 'origin', 'always'. Setting it to false just
+ * prevents the meta tag from being output.
+ * See http://www.w3.org/TR/referrer-policy/ for details.
+ *
+ * @since 1.25
+ */
+$wgReferrerPolicy = false;
+
/**
* The local filesystem path to a temporary directory. This is not required to
* be web accessible.
* are passed as parameters after $srcPath, $dstPath, $width, $height
*/
$wgSVGConverters = array(
- 'ImageMagick' => '$path/convert -background white -thumbnail $widthx$height\! $input PNG:$output',
+ 'ImageMagick' => '$path/convert -background "#ffffff00" -thumbnail $widthx$height\! $input PNG:$output',
'sodipodi' => '$path/sodipodi -z -w $width -f $input -e $output',
'inkscape' => '$path/inkscape -z -w $width -f $input -e $output',
'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d '
. '$output $input',
- 'rsvg' => '$path/rsvg -w $width -h $height $input $output',
+ 'rsvg' => '$path/rsvg-convert -w $width -h $height -o $output $input',
'imgserv' => '$path/imgserv-wrapper -i svg -o png -w$width $input $output',
'ImagickExt' => array( 'SvgHandler::rasterizeImagickExt' ),
);
*/
$wgObjectCaches = array(
CACHE_NONE => array( 'class' => 'EmptyBagOStuff' ),
- CACHE_DB => array( 'class' => 'SqlBagOStuff' ),
+ CACHE_DB => array( 'class' => 'SqlBagOStuff', 'loggroup' => 'SQLBagOStuff' ),
CACHE_ANYTHING => array( 'factory' => 'ObjectCache::newAnything' ),
CACHE_ACCEL => array( 'factory' => 'ObjectCache::newAccelerator' ),
- CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached' ),
+ CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached', 'loggroup' => 'memcached' ),
'apc' => array( 'class' => 'APCBagOStuff' ),
'xcache' => array( 'class' => 'XCacheBagOStuff' ),
'wincache' => array( 'class' => 'WinCacheBagOStuff' ),
- 'memcached-php' => array( 'class' => 'MemcachedPhpBagOStuff' ),
- 'memcached-pecl' => array( 'class' => 'MemcachedPeclBagOStuff' ),
+ 'memcached-php' => array( 'class' => 'MemcachedPhpBagOStuff', 'loggroup' => 'memcached' ),
+ 'memcached-pecl' => array( 'class' => 'MemcachedPeclBagOStuff', 'loggroup' => 'memcached' ),
'hash' => array( 'class' => 'HashBagOStuff' ),
);
* for the icon, the following keys are used:
* - src: An absolute url to the image to use for the icon, this is recommended
* but not required, however some skins will ignore icons without an image
+ * - srcset: optional additional-resolution images; see HTML5 specs
* - url: The url to use in the a element around the text or icon, if not set an a element will
* not be outputted
* - alt: This is the text form of the icon, it will be displayed without an image in
),
"poweredby" => array(
"mediawiki" => array(
- "src" => null, // Defaults to "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
+ "src" => null, // Defaults to point at
+ // "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
+ // plus srcset for 1.5x, 2x resolution variants.
"url" => "//www.mediawiki.org/",
"alt" => "Powered by MediaWiki",
)
* A message with the suffix '-desc' should be added as a description message
* to have extra information on Special:TrackingCategories.
*
+ * @deprecated since 1.25 Extensions should now register tracking categories using
+ * the new extension registration system.
+ *
* @since 1.23
*/
-$wgTrackingCategories = array(
- 'index-category',
- 'noindex-category',
- 'duplicate-args-category',
- 'expensive-parserfunction-category',
- 'post-expand-template-argument-category',
- 'post-expand-template-inclusion-category',
- 'hidden-category-category',
- 'broken-file-category',
- 'node-count-exceeded-category',
- 'expansion-depth-exceeded-category',
-);
+$wgTrackingCategories = array();
/**
* Array of namespaces which can be deemed to contain valid "content", as far
#$wgGroupPermissions['sysop']['pagelang'] = true;
#$wgGroupPermissions['sysop']['upload_by_url'] = true;
$wgGroupPermissions['sysop']['mergehistory'] = true;
+$wgGroupPermissions['sysop']['managechangetags'] = true;
// Permission to change users' group assignments
$wgGroupPermissions['bureaucrat']['userrights'] = true;
$wgDebugLogGroups = array();
/**
- * Default service provider for creating MWLogger instances.
+ * Default service provider for creating Psr\Log\LoggerInterface instances.
*
* The value should be an array suitable for use with
* ObjectFactory::getObjectFromSpec(). The created object is expected to
* implement the MWLoggerSpi interface. See ObjectFactory for additional
* details.
*
- * Alternately the MWLogger::registerProvider method can be called to inject
- * an MWLoggerSpi instance into MWLogger and bypass the use of this
- * configuration variable entirely.
+ * Alternately the MWLoggerFactory::registerProvider method can be called to
+ * inject an MWLoggerSpi instance into MWLoggerFactory and bypass the use of
+ * this configuration variable entirely.
*
* @since 1.25
* @var array $wgMWLoggerDefaultSpi
* 'version' => '1.9.0',
* 'url' => 'http://example.org/example-extension/',
* 'descriptionmsg' => 'exampleextension-desc',
- * 'license-name' => 'GPL-2.0',
+ * 'license-name' => 'GPL-2.0+',
* );
* @endcode
*
* localizable message (omit in favour of 'descriptionmsg').
*
* - license-name: Short name of the license (used as label for the link), such
- * as "GPL-2.0" or "MIT" (https://spdx.org/licenses/ for a list of identifiers).
+ * as "GPL-2.0+" or "MIT" (https://spdx.org/licenses/ for a list of identifiers).
*/
$wgExtensionCredits = array();
'AssembleUploadChunks' => 'AssembleUploadChunksJob',
'PublishStashedFile' => 'PublishStashedFileJob',
'ThumbnailRender' => 'ThumbnailRenderJob',
+ 'recentChangesUpdate' => 'RecentChangesUpdateJob',
'null' => 'NullJob'
);
'patrol',
'merge',
'suppress',
+ 'managetags',
);
/**
'upload/overwrite' => 'LogFormatter',
'upload/revert' => 'LogFormatter',
'merge/merge' => 'MergeLogFormatter',
+ 'managetags/create' => 'LogFormatter',
+ 'managetags/delete' => 'LogFormatter',
+ 'managetags/activate' => 'LogFormatter',
+ 'managetags/deactivate' => 'LogFormatter',
);
/**
/** Maximum time to wait before retry */
const DEADLOCK_DELAY_MAX = 1500000;
- /** How many row changes in a write query trigger a log entry */
- const LOG_WRITE_THRESHOLD = 300;
-
protected $mLastQuery = '';
protected $mDoneWrites = false;
protected $mPHPError = false;
# Log the query time and feed it into the DB trx profiler
if ( $queryProf != '' ) {
+ $that = $this;
$queryStartTime = microtime( true );
$queryProfile = new ScopedCallback(
- function () use ( $queryStartTime, $queryProf, $isMaster ) {
- $trxProfiler = Profiler::instance()->getTransactionProfiler();
- $trxProfiler->recordQueryCompletion( $queryProf, $queryStartTime, $isMaster );
+ function () use ( $that, $queryStartTime, $queryProf, $isMaster ) {
+ $n = $that->affectedRows();
+ $trxProf = Profiler::instance()->getTransactionProfiler();
+ $trxProf->recordQueryCompletion( $queryProf, $queryStartTime, $isMaster, $n );
}
);
}
if ( false === $ret ) {
$this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
- } else {
- $n = $this->affectedRows();
- if ( $isWriteQuery && $n > self::LOG_WRITE_THRESHOLD && PHP_SAPI !== 'cli' ) {
- wfDebugLog( 'DBPerformance',
- "Query affected $n rows:\n" .
- DatabaseBase::generalizeSQL( $sql ) . "\n" . wfBacktrace( true ) );
- }
}
$res = $this->resultObject( $ret );
*
* @return bool|mixed The value from the field, or false on failure.
*/
- public function selectField( $table, $var, $cond = '', $fname = __METHOD__,
- $options = array()
+ public function selectField(
+ $table, $var, $cond = '', $fname = __METHOD__, $options = array()
) {
+ if ( $var === '*' ) { // sanity
+ throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" );
+ }
+
if ( !is_array( $options ) ) {
$options = array( $options );
}
$options['LIMIT'] = 1;
$res = $this->select( $table, $var, $cond, $fname, $options );
-
if ( $res === false || !$this->numRows( $res ) ) {
return false;
}
}
}
+ /**
+ * A SELECT wrapper which returns a list of single field values from result rows.
+ *
+ * Usually throws a DBQueryError on failure. If errors are explicitly
+ * ignored, returns false on failure.
+ *
+ * If no result rows are returned from the query, false is returned.
+ *
+ * @param string|array $table Table name. See DatabaseBase::select() for details.
+ * @param string $var The field name to select. This must be a valid SQL
+ * fragment: do not use unvalidated user input.
+ * @param string|array $cond The condition array. See DatabaseBase::select() for details.
+ * @param string $fname The function name of the caller.
+ * @param string|array $options The query options. See DatabaseBase::select() for details.
+ *
+ * @return bool|array The values from the field, or false on failure
+ * @since 1.25
+ */
+ public function selectFieldValues(
+ $table, $var, $cond = '', $fname = __METHOD__, $options = array()
+ ) {
+ if ( $var === '*' ) { // sanity
+ throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" );
+ }
+
+ if ( !is_array( $options ) ) {
+ $options = array( $options );
+ }
+
+ $res = $this->select( $table, $var, $cond, $fname, $options );
+ if ( $res === false ) {
+ return false;
+ }
+
+ $values = array();
+ foreach ( $res as $row ) {
+ $values[] = $row->$var;
+ }
+
+ return $values;
+ }
+
/**
* Returns an optional USE INDEX clause to go after the table, and a
* string to go at the end of the query.
if ( $res ) {
$row = $this->fetchRow( $res );
- $rows = ( isset( $row['rowcount'] ) ) ? $row['rowcount'] : 0;
+ $rows = ( isset( $row['rowcount'] ) ) ? (int)$row['rowcount'] : 0;
}
return $rows;
if ( $res ) {
$row = $this->fetchRow( $res );
- $rows = ( isset( $row['rowcount'] ) ) ? $row['rowcount'] : 0;
+ $rows = ( isset( $row['rowcount'] ) ) ? (int)$row['rowcount'] : 0;
}
return $rows;
* Returns a stdClass with source, pst and output members
*
* @param Content $content
- * @param int|null $revid
+ * @param Revision|int|null $revision Revision object. For backwards compatibility, a
+ * revision ID is also accepted, but this is deprecated.
* @param User|null $user
* @param string|null $serialFormat
* @param bool $useCache Check shared prepared edit cache
* @since 1.21
*/
public function prepareContentForEdit(
- Content $content, $revid = null, User $user = null, $serialFormat = null, $useCache = true
+ Content $content, $revision = null, User $user = null, $serialFormat = null, $useCache = true
) {
global $wgContLang, $wgUser, $wgAjaxEditStash;
+ if ( is_object( $revision ) ) {
+ $revid = $revision->getId();
+ } else {
+ $revid = $revision;
+ // This code path is deprecated, and nothing is known to
+ // use it, so performance here shouldn't be a worry.
+ if ( $revid !== null ) {
+ $revision = Revision::newFromId( $revid, Revision::READ_LATEST );
+ } else {
+ $revision = null;
+ }
+ }
+
$user = is_null( $user ) ? $wgUser : $user;
//XXX: check $user->getId() here???
if ( $cachedEdit ) {
$edit->output = $cachedEdit->output;
} else {
+ if ( $revision ) {
+ // We get here if vary-revision is set. This means that this page references
+ // itself (such as via self-transclusion). In this case, we need to make sure
+ // that any such self-references refer to the newly-saved revision, and not
+ // to the previous one, which could otherwise happen due to slave lag.
+ $oldCallback = $edit->popts->setCurrentRevisionCallback(
+ function ( $title, $parser = false ) use ( $revision, &$oldCallback ) {
+ if ( $title->equals( $revision->getTitle() ) ) {
+ return $revision;
+ } else {
+ return call_user_func(
+ $oldCallback,
+ $title,
+ $parser
+ );
+ }
+ }
+ );
+ }
$edit->output = $edit->pstContent
? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts )
: null;
// already pre-save transformed once.
if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
- $editInfo = $this->prepareContentForEdit( $content, $revision->getId(), $user );
+ $editInfo = $this->prepareContentForEdit( $content, $revision, $user );
} else {
wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" );
$editInfo = $this->mPreparedEdit;
Hooks::run( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
if ( Hooks::run( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
- if ( 0 == mt_rand( 0, 99 ) ) {
- // Flush old entries from the `recentchanges` table; we do this on
- // random requests so as to avoid an increase in writes for no good reason
- RecentChange::purgeExpiredChanges();
- }
+ // Flush old entries from the `recentchanges` table
+ JobQueueGroup::singleton()->push( RecentChangesUpdateJob::newPurgeJob() );
}
if ( !$this->exists() ) {
// Get the last edit not by this guy...
// Note: these may not be public values
- $user = intval( $current->getRawUser() );
- $user_text = $dbw->addQuotes( $current->getRawUserText() );
+ $user = intval( $current->getUser( Revision::RAW ) );
+ $user_text = $dbw->addQuotes( $current->getUserText( Revision::RAW ) );
$s = $dbw->selectRow( 'revision',
array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
array( 'rev_page' => $current->getPage(),