* Updated cssjanus/cssjanus from 1.2.1 to 1.3.0.
* Updated wikimedia/at-ease from 1.2.0 to 2.0.0.
* Updated wikimedia/remex-html from 2.0.1 to 2.0.3.
+* Updated monolog/monolog from 1.22.1 to 1.24.0 (dev-only).
* …
==== Removed external libraries ====
* User::makeGroupLinkWiki(), deprecated in 1.29, has been removed. Use
UserGroupMembership::getLink() instead.
* SavepointPostgres, deprecated in 1.31, has been removed.
-* Output::sectionEditLinksEnabled(), ParserOutput::getEditSectionTokens,
- ::getTOCEnabled, ::setEditSectionTokens, ::setTOCEnabled, deprecated in 1.31,
- have been removed.
+* OutputPage::enableSectionEditLinks(), OutputPage::sectionEditLinksEnabled(),
+ ParserOptions::getEditSection(), ParserOptions::setEditSection(), and
+ ParserOutput::getEditSectionTokens, ::getTOCEnabled, ::setEditSectionTokens,
+ and ::setTOCEnabled, deprecated in 1.31, have been removed.
* EditPage::safeUnicodeInput() and ::safeUnicodeOutput(), deprecated in 1.30,
have been removed.
* Four methods in OutputPage, deprecated in 1.32, have been removed. You should
* The constant DB_SLAVE, deprecated in 1.28, has been removed. Use DB_REPLICA.
* Replacer, DoubleReplacer, HashtableReplacer and RegexlikeReplacer
(deprecated in 1.32) have been removed. Closures should be used instead.
+* OutputPage::addWikiText(), ::addWikiTextWithTitle(), ::addWikiTextTitleTidy(),
+ ::addWikiTextTidy(), ::addWikiTextTitle(), deprecated in 1.32, have been
+ removed.
+* The $wgUseKeyHeader configuration option and the OutputPage::getKeyHeader()
+ method, deprecated in 1.32, have been removed.
+* WebInstallerOutput::addWikiText(), deprecated in 1.32, has been removed.
+* Parser::fetchFile(), deprecated in 1.32, has been removed. Use the method
+ Parser::fetchFileAndTitle() instead.
+* The global function wfBCP47, deprecated in 1.31, has been removed.
* …
=== Deprecations in 1.34 ===
"jakub-onderka/php-parallel-lint": "0.9.2",
"justinrainbow/json-schema": "~5.2",
"mediawiki/mediawiki-codesniffer": "26.0.0",
- "monolog/monolog": "~1.22.1",
+ "monolog/monolog": "~1.24.0",
"nikic/php-parser": "3.1.5",
"seld/jsonlint": "1.7.1",
"nmred/kafka-php": "0.1.5",
*/
$wgUseESI = false;
-/**
- * Send the Key HTTP header for better caching.
- * See https://datatracker.ietf.org/doc/draft-ietf-httpbis-key/ for details.
- * @since 1.27
- * @deprecated in 1.32, the IETF spec expired without becoming a standard.
- */
-$wgUseKeyHeader = false;
-
/**
* Add X-Forwarded-Proto to the Vary and Key headers for API requests and
* RSS/Atom feeds. Use this if you have an SSL termination setup
return $val;
}
-/**
- * Get the normalised IETF language tag
- * See unit test for examples.
- * See mediawiki.language.bcp47 for the JavaScript implementation.
- *
- * @deprecated since 1.31, use LanguageCode::bcp47() directly.
- *
- * @param string $code The language code.
- * @return string The language code which complying with BCP 47 standards.
- */
-function wfBCP47( $code ) {
- wfDeprecated( __METHOD__, '1.31' );
- return LanguageCode::bcp47( $code );
-}
-
/**
* Get a specific cache object.
*
}
if ( !$foundVary ) {
header( 'Vary: Accept-Encoding' );
- global $wgUseKeyHeader;
- if ( $wgUseKeyHeader ) {
- header( 'Key: Accept-Encoding;match=gzip' );
- }
}
return $s;
}
private $mFollowPolicy = 'follow';
/**
- * @var array Headers that cause the cache to vary. Key is header name, value is an array of
- * options for the Key header.
+ * @var array Headers that cause the cache to vary. Key is header name,
+ * value should always be null. (Value was an array of options for
+ * the `Key` header, which was deprecated in 1.32 and removed in 1.34.)
*/
private $mVaryHeader = [
- 'Accept-Encoding' => [ 'match=gzip' ],
+ 'Accept-Encoding' => null,
];
/**
return $this->mImageTimeKeys;
}
- /**
- * Convert wikitext to HTML and add it to the buffer
- * Default assumes that the current page title will be used.
- *
- * @param string $text
- * @param bool $linestart Is this the start of a line?
- * @param bool $interface Is this text in the user interface language?
- * @throws MWException
- * @deprecated since 1.32 due to untidy output; use
- * addWikiTextAsInterface() if $interface is default value or true,
- * or else addWikiTextAsContent() if $interface is false.
- */
- public function addWikiText( $text, $linestart = true, $interface = true ) {
- wfDeprecated( __METHOD__, '1.32' );
- $title = $this->getTitle();
- if ( !$title ) {
- throw new MWException( 'Title is null' );
- }
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/false, $interface );
- }
-
/**
* Convert wikitext *in the user interface language* to HTML and
* add it to the buffer. The result will not be
if ( !$title ) {
throw new MWException( 'Title is null' );
}
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/true, /*interface*/true );
+ $this->addWikiTextTitleInternal( $text, $title, $linestart, /*interface*/true );
}
/**
) {
$this->addWikiTextTitleInternal(
$text, $this->getTitle(),
- /*linestart*/true, /*tidy*/true, /*interface*/true,
+ /*linestart*/true, /*interface*/true,
$wrapperClass
);
}
if ( !$title ) {
throw new MWException( 'Title is null' );
}
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/true, /*interface*/false );
- }
-
- /**
- * Add wikitext with a custom Title object
- *
- * @param string $text Wikitext
- * @param Title $title
- * @param bool $linestart Is this the start of a line?
- * @deprecated since 1.32 due to untidy output; use
- * addWikiTextAsInterface()
- */
- public function addWikiTextWithTitle( $text, Title $title, $linestart = true ) {
- wfDeprecated( __METHOD__, '1.32' );
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/false, /*interface*/false );
- }
-
- /**
- * Add wikitext *in content language* with a custom Title object.
- * Output will be tidy.
- *
- * @param string $text Wikitext in content language
- * @param Title $title
- * @param bool $linestart Is this the start of a line?
- * @deprecated since 1.32 to rename methods consistently; use
- * addWikiTextAsContent()
- */
- function addWikiTextTitleTidy( $text, Title $title, $linestart = true ) {
- wfDeprecated( __METHOD__, '1.32' );
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/true, /*interface*/false );
- }
-
- /**
- * Add wikitext *in content language*. Output will be tidy.
- *
- * @param string $text Wikitext in content language
- * @param bool $linestart Is this the start of a line?
- * @deprecated since 1.32 to rename methods consistently; use
- * addWikiTextAsContent()
- */
- public function addWikiTextTidy( $text, $linestart = true ) {
- wfDeprecated( __METHOD__, '1.32' );
- $title = $this->getTitle();
- if ( !$title ) {
- throw new MWException( 'Title is null' );
- }
- $this->addWikiTextTitleInternal( $text, $title, $linestart, /*tidy*/true, /*interface*/false );
- }
-
- /**
- * Add wikitext with a custom Title object.
- * Output is unwrapped.
- *
- * @param string $text Wikitext
- * @param Title $title
- * @param bool $linestart Is this the start of a line?
- * @param bool $tidy Whether to use tidy.
- * Setting this to false (or omitting it) is deprecated
- * since 1.32; all wikitext should be tidied.
- * For backwards-compatibility with prior MW releases,
- * you may wish to invoke this method but set $tidy=true;
- * this will result in equivalent output to the non-deprecated
- * addWikiTextAsContent()/addWikiTextAsInterface() methods.
- * @param bool $interface Whether it is an interface message
- * (for example disables conversion)
- * @deprecated since 1.32, use addWikiTextAsContent() or
- * addWikiTextAsInterface() (depending on $interface)
- */
- public function addWikiTextTitle( $text, Title $title, $linestart,
- $tidy = false, $interface = false
- ) {
- wfDeprecated( __METHOD__, '1.32' );
- return $this->addWikiTextTitleInternal( $text, $title, $linestart, $tidy, $interface );
+ $this->addWikiTextTitleInternal( $text, $title, $linestart, /*interface*/false );
}
/**
* @private
*/
private function addWikiTextTitleInternal(
- $text, Title $title, $linestart, $tidy, $interface, $wrapperClass = null
+ $text, Title $title, $linestart, $interface, $wrapperClass = null
) {
- if ( !$tidy ) {
- wfDeprecated( 'disabling tidy', '1.32' );
- }
-
$parserOutput = $this->parseInternal(
- $text, $title, $linestart, $tidy, $interface, /*language*/null
+ $text, $title, $linestart, true, $interface, /*language*/null
);
$this->addParserOutput( $parserOutput, [
* Add an HTTP header that will influence on the cache
*
* @param string $header Header name
- * @param string[]|null $option Options for the Key header. See
- * https://datatracker.ietf.org/doc/draft-fielding-http-key/
- * for the list of valid options.
+ * @param string[]|null $option Deprecated; formerly options for the
+ * Key header, deprecated in 1.32 and removed in 1.34. See
+ * https://datatracker.ietf.org/doc/draft-fielding-http-key/
+ * for the list of formerly-valid options.
*/
public function addVaryHeader( $header, array $option = null ) {
- if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
- $this->mVaryHeader[$header] = [];
+ if ( $option !== null && count( $option ) > 0 ) {
+ wfDeprecated( 'addVaryHeader $option is ignored', '1.34' );
}
- if ( !is_array( $option ) ) {
- $option = [];
+ if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
+ $this->mVaryHeader[$header] = null;
}
- $this->mVaryHeader[$header] =
- array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
}
/**
return 'Link: ' . implode( ',', $this->mLinkHeader );
}
- /**
- * Get a complete Key header
- *
- * @return string
- * @deprecated in 1.32; the IETF spec for this header expired w/o becoming
- * a standard.
- */
- public function getKeyHeader() {
- wfDeprecated( '$wgUseKeyHeader', '1.32' );
-
- $cvCookies = $this->getCacheVaryCookies();
-
- $cookiesOption = [];
- foreach ( $cvCookies as $cookieName ) {
- $cookiesOption[] = 'param=' . $cookieName;
- }
- $this->addVaryHeader( 'Cookie', $cookiesOption );
-
- foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
- $this->addVaryHeader( $header, $options );
- }
-
- $headers = [];
- foreach ( $this->mVaryHeader as $header => $option ) {
- $newheader = $header;
- if ( is_array( $option ) && count( $option ) > 0 ) {
- $newheader .= ';' . implode( ';', $option );
- }
- $headers[] = $newheader;
- }
- $key = 'Key: ' . implode( ',', $headers );
-
- return $key;
- }
-
/**
* T23672: Add Accept-Language to Vary and Key headers if there's no 'variant' parameter in GET.
*
$lang = $title->getPageLanguage();
if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
- $variants = $lang->getVariants();
- $aloption = [];
- foreach ( $variants as $variant ) {
- if ( $variant === $lang->getCode() ) {
- continue;
- }
-
- // XXX Note that this code is not strictly correct: we
- // do a case-insensitive match in
- // LanguageConverter::getHeaderVariant() while the
- // (abandoned, draft) spec for the `Key` header only
- // allows case-sensitive matches. To match the logic
- // in LanguageConverter::getHeaderVariant() we should
- // also be looking at fallback variants and deprecated
- // mediawiki-internal codes, as well as BCP 47
- // normalized forms.
-
- $aloption[] = "substr=$variant";
-
- // IE and some other browsers use BCP 47 standards in their Accept-Language header,
- // like "zh-CN" or "zh-Hant". We should handle these too.
- $variantBCP47 = LanguageCode::bcp47( $variant );
- if ( $variantBCP47 !== $variant ) {
- $aloption[] = "substr=$variantBCP47";
- }
- }
- $this->addVaryHeader( 'Accept-Language', $aloption );
+ $this->addVaryHeader( 'Accept-Language' );
}
}
# maintain different caches for logged-in users and non-logged in ones
$response->header( $this->getVaryHeader() );
- if ( $config->get( 'UseKeyHeader' ) ) {
- $response->header( $this->getKeyHeader() );
- }
-
if ( $this->mEnableClientCache ) {
if (
$config->get( 'UseCdn' ) &&
return $this->mEnableTOC;
}
- /**
- * Enables/disables section edit links, doesn't override __NOEDITSECTION__
- * @param bool $flag
- * @since 1.23
- * @deprecated since 1.31, use $poOptions to addParserOutput() instead.
- */
- public function enableSectionEditLinks( $flag = true ) {
- wfDeprecated( __METHOD__, '1.31' );
- }
-
/**
* Helper function to setup the PHP implementation of OOUI to use in this request.
*
// Set standard Vary headers so cache varies on cookies and such (T125283)
$response->header( $this->getOutput()->getVaryHeader() );
- if ( $config->get( 'UseKeyHeader' ) ) {
- $response->header( $this->getOutput()->getKeyHeader() );
- }
// Output may contain user-specific data;
// vary generated content for open sessions on private wikis
return;
}
- $useKeyHeader = $config->get( 'UseKeyHeader' );
if ( $this->mCacheMode == 'anon-public-user-private' ) {
$out->addVaryHeader( 'Cookie' );
$response->header( $out->getVaryHeader() );
- if ( $useKeyHeader ) {
- $response->header( $out->getKeyHeader() );
- if ( $out->haveCacheVaryCookies() ) {
- // Logged in, mark this request private
- $response->header( "Cache-Control: $privateCache" );
- return;
- }
- // Logged out, send normal public headers below
- } elseif ( MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent() ) {
+ if ( MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent() ) {
// Logged in or otherwise has session (e.g. anonymous users who have edited)
// Mark request private
$response->header( "Cache-Control: $privateCache" );
return;
- } // else no Key and anonymous, send public headers below
+ } // else anonymous, send public headers below
}
// Send public headers
$response->header( $out->getVaryHeader() );
- if ( $useKeyHeader ) {
- $response->header( $out->getKeyHeader() );
- }
// If nobody called setCacheMaxAge(), use the (s)maxage parameters
if ( !isset( $this->mCacheControl['s-maxage'] ) ) {
* @file
*/
use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\IDatabase;
/**
* $this->getPageTableFields().
*
* @param IDatabase $db
- * @param ResultWrapper $queryResult
+ * @param IResultWrapper $queryResult
*/
public function populateFromQueryResult( $db, $queryResult ) {
$this->initFromQueryResult( $queryResult );
/**
* Iterate through the result of the query on 'page' table,
* and for each row create and store title object and save any extra fields requested.
- * @param ResultWrapper $res DB Query result
+ * @param IResultWrapper $res DB Query result
* @param array $remaining Array of either pageID or ns/title elements (optional).
* If given, any missing items will go to $mMissingPageIDs and $mMissingTitles
* @param bool $processTitles Must be provided together with $remaining.
*/
use Wikimedia\Rdbms\IDatabase;
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
/**
* This is a base class for all Query modules.
* @param array|null &$hookData If set, the ApiQueryBaseBeforeQuery and
* ApiQueryBaseAfterQuery hooks will be called, and the
* ApiQueryBaseProcessRow hook will be expected.
- * @return ResultWrapper
+ * @return IResultWrapper
*/
protected function select( $method, $extraQuery = [], array &$hookData = null ) {
$tables = array_merge(
}
/**
- * Given a list of blocks, return a list blocks where each block either has a
- * unique ID or has ID null.
+ * Given a list of blocks, return a list of unique blocks.
+ *
+ * This usually means that each block has a unique ID. For a block with ID null,
+ * if it's an autoblock, it will be filtered out if the parent block is present;
+ * if not, it is assumed to be a unique system block, and kept.
*
* @param AbstractBlock[] $blocks
* @return AbstractBlock[]
*/
private function getUniqueBlocks( $blocks ) {
- $blockIds = [];
- $uniqueBlocks = [];
+ $systemBlocks = [];
+ $databaseBlocks = [];
+
foreach ( $blocks as $block ) {
- $id = $block->getId();
- if ( $id === null ) {
- $uniqueBlocks[] = $block;
- } elseif ( !isset( $blockIds[$id] ) ) {
- $uniqueBlocks[] = $block;
- $blockIds[$block->getId()] = true;
+ if ( $block instanceof SystemBlock ) {
+ $systemBlocks[] = $block;
+ } elseif ( $block->getType() === DatabaseBlock::TYPE_AUTO ) {
+ if ( !isset( $databaseBlocks[$block->getParentBlockId()] ) ) {
+ $databaseBlocks[$block->getParentBlockId()] = $block;
+ }
+ } else {
+ $databaseBlocks[$block->getId()] = $block;
}
}
- return $uniqueBlocks;
+
+ return array_merge( $systemBlocks, $databaseBlocks );
}
/**
return $this;
}
+ /**
+ * @since 1.34
+ * @return int|null If this is an autoblock, ID of the parent block; otherwise null
+ */
+ public function getParentBlockId() {
+ return $this->mParentBlockId;
+ }
+
/**
* Get/set a flag determining whether the master is used for reads
*
* @since 1.34
*/
class ServiceOptions {
+ private $keys = [];
private $options = [];
/**
* @throws InvalidArgumentException if one of $keys is not found in any of $sources
*/
public function __construct( array $keys, ...$sources ) {
+ $this->keys = $keys;
foreach ( $keys as $key ) {
foreach ( $sources as $source ) {
if ( $source instanceof Config ) {
* @param string[] $expectedKeys
*/
public function assertRequiredOptions( array $expectedKeys ) {
- $actualKeys = array_keys( $this->options );
- $extraKeys = array_diff( $actualKeys, $expectedKeys );
- $missingKeys = array_diff( $expectedKeys, $actualKeys );
- Assert::precondition( !$extraKeys && !$missingKeys,
- (
- $extraKeys
- ? 'Unsupported options passed: ' . implode( ', ', $extraKeys ) . '!'
- : ''
- ) . ( $extraKeys && $missingKeys ? ' ' : '' ) . (
- $missingKeys
- ? 'Required options missing: ' . implode( ', ', $missingKeys ) . '!'
- : ''
- )
- );
+ if ( $this->keys !== $expectedKeys ) {
+ $extraKeys = array_diff( $this->keys, $expectedKeys );
+ $missingKeys = array_diff( $expectedKeys, $this->keys );
+ Assert::precondition( !$extraKeys && !$missingKeys,
+ (
+ $extraKeys
+ ? 'Unsupported options passed: ' . implode( ', ', $extraKeys ) . '!'
+ : ''
+ ) . ( $extraKeys && $missingKeys ? ' ' : '' ) . (
+ $missingKeys
+ ? 'Required options missing: ' . implode( ', ', $missingKeys ) . '!'
+ : ''
+ )
+ );
+ }
}
/**
$this->flush();
}
- /**
- * @param string $text
- * @deprecated since 1.32; use addWikiTextAsInterface instead
- */
- public function addWikiText( $text ) {
- wfDeprecated( __METHOD__, '1.32' );
- $this->addWikiTextAsInterface( $text );
- }
-
/**
* @param string $text
* @since 1.32
'deps' => $deps ];
}
- /**
- * Fetch a file and its title and register a reference to it.
- * If 'broken' is a key in $options then the file will appear as a broken thumbnail.
- * @param Title $title
- * @param array $options Array of options to RepoGroup::findFile
- * @return File|bool
- * @deprecated since 1.32, use fetchFileAndTitle instead
- */
- public function fetchFile( $title, $options = [] ) {
- wfDeprecated( __METHOD__, '1.32' );
- return $this->fetchFileAndTitle( $title, $options )[0];
- }
-
/**
* Fetch a file and its title and register a reference to it.
* If 'broken' is a key in $options then the file will appear as a broken thumbnail.
return wfSetVar( $this->mTimestamp, $x );
}
- /**
- * Create "edit section" links?
- * @deprecated since 1.31, use ParserOutput::getText() options instead.
- * @return bool
- */
- public function getEditSection() {
- wfDeprecated( __METHOD__, '1.31' );
- return true;
- }
-
- /**
- * Create "edit section" links?
- * @deprecated since 1.31, use ParserOutput::getText() options instead.
- * @param bool|null $x New value (null is no change)
- * @return bool Old value
- */
- public function setEditSection( $x ) {
- wfDeprecated( __METHOD__, '1.31' );
- return true;
- }
-
/**
* Set the redirect target.
*
/**
* Feature flags to indicate to extensions that MediaWiki core supports and
* uses getText() stateless transforms.
+ *
+ * @since 1.31
*/
const SUPPORTS_STATELESS_TRANSFORMS = 1;
+
+ /**
+ * @since 1.31
+ */
const SUPPORTS_UNWRAP_TRANSFORM = 1;
/**
/**
* ResourceLoader module based on local JavaScript/CSS files.
+ *
+ * The following public methods can query the database:
+ *
+ * - getDefinitionSummary / … / ResourceLoaderModule::getFileDependencies.
+ * - getVersionHash / getDefinitionSummary / … / ResourceLoaderModule::getFileDependencies.
+ * - getStyles / ResourceLoaderModule::saveFileDependencies.
*/
class ResourceLoaderFileModule extends ResourceLoaderModule {
if ( is_string( $deprecationInfo ) ) {
$warning .= "\n" . $deprecationInfo;
}
- return Xml::encodeJsCall(
- 'mw.log.warn',
- [ $warning ]
- );
+ return 'mw.log.warn(' . ResourceLoader::encodeJsonForScript( $warning ) . ');';
} else {
return '';
}
* }
* @endcode
*
+ * Note that the $options parameter to addVaryHeader has been deprecated
+ * since 1.34, and should be `null` or an empty array.
+ *
* @protected For use by \MediaWiki\Session\SessionManager only
* @return array
*/
);
$download = Xml::element(
'a',
- [ 'href' => $services->getRepoGroup()->findFile( $filePage )->getUrl() ],
+ [ 'href' => $services->getRepoGroup()->getLocalRepo()->newFile( $filePage )->getUrl() ],
$imgfile
);
$download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
"history": "Page history",
"history_short": "History",
"history_small": "history",
- "updatedmarker": "updated since my last visit",
+ "updatedmarker": "updated since your last visit",
"printableversion": "Printable version",
"permalink": "Permanent link",
"print": "Print",
require_once __DIR__ . '/Maintenance.php';
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\IDatabase;
/**
}
/**
- * @param ResultWrapper $res
+ * @param IResultWrapper $res
* @param IDatabase $dbw
* @return null|int
*/
use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\IMaintainableDatabase;
/**
* @param string $name Prefix that is being made a namespace
* @param array $options Associative array of validated command-line options
*
- * @return ResultWrapper
+ * @return IResultWrapper
*/
private function getTargetList( $ns, $name, $options ) {
if (
use MediaWiki\Storage\SqlBlobStore;
use Wikimedia\Assert\Assert;
use Wikimedia\Rdbms\IDatabase;
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
require_once __DIR__ . '/Maintenance.php';
}
/**
- * @param ResultWrapper $rows
+ * @param IResultWrapper $rows
* @param int $startId
* @param string $table
* @return int|null
*/
- private function populateContentTablesForRowBatch( ResultWrapper $rows, $startId, $table ) {
+ private function populateContentTablesForRowBatch( IResultWrapper $rows, $startId, $table ) {
$this->beginTransaction( $this->dbw, __METHOD__ );
if ( $this->contentRowMap === null ) {
require_once __DIR__ . '/Maintenance.php';
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
/**
* Maintenance script that sends purge requests for pages edited in a date
*
* @todo move this elsewhere
*
- * @param ResultWrapper $res Query result sorted by $column (ascending)
+ * @param IResultWrapper $res Query result sorted by $column (ascending)
* @param string $column
* @param int $limit
* @return array (array of rows, string column value)
*/
- protected function pageableSortedRows( ResultWrapper $res, $column, $limit ) {
+ protected function pageableSortedRows( IResultWrapper $res, $column, $limit ) {
$rows = iterator_to_array( $res, false );
// Nothing to do
require_once __DIR__ . '/Maintenance.php';
use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\ResultWrapper;
+use Wikimedia\Rdbms\IResultWrapper;
use Wikimedia\Rdbms\IDatabase;
use Wikimedia\Rdbms\DBQueryError;
/**
* Print the results, callback for $db->sourceStream()
- * @param ResultWrapper|bool $res
+ * @param IResultWrapper|bool $res
* @param IDatabase $db
* @return int|null Number of rows selected or updated, or null if the query was unsuccessful.
*/
//
// Please extend the regex instead of adding new ones!
// And add a test case to startup.test.js
- !ua.match( /MSIE 10|webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$|googleweblight|PLAYSTATION|PlayStation/ )
+ !ua.match( /MSIE 10|webOS\/1\.[0-4]|SymbianOS|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$|googleweblight|PLAYSTATION|PlayStation/ )
);
}
'MediaWikiTestResult' => "$testDir/phpunit/MediaWikiTestResult.php",
'MediaWikiTestRunner' => "$testDir/phpunit/MediaWikiTestRunner.php",
'PHPUnit4And6Compat' => "$testDir/phpunit/PHPUnit4And6Compat.php",
- 'ResourceLoaderFileModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
+ 'ResourceLoaderFileModuleTestingSubclass' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'ResourceLoaderFileTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'ResourceLoaderTestCase' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'ResourceLoaderTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
}
}
+/**
+ * A more constrained and testable variant of ResourceLoaderFileModule.
+ *
+ * - Implements getLessVars() support.
+ * - Disables database persistance of discovered file dependencies.
+ */
class ResourceLoaderFileTestModule extends ResourceLoaderFileModule {
protected $lessVars = [];
public function getLessVars( ResourceLoaderContext $context ) {
return $this->lessVars;
}
+
+ /** @return array */
+ protected function getFileDependencies( ResourceLoaderContext $context ) {
+ // No-op
+ return [];
+ }
+
+ protected function saveFileDependencies( ResourceLoaderContext $context, $refs ) {
+ // No-op
+ }
}
-class ResourceLoaderFileModuleTestModule extends ResourceLoaderFileModule {
+class ResourceLoaderFileModuleTestingSubclass extends ResourceLoaderFileModule {
}
class EmptyResourceLoader extends ResourceLoader {
/**
* @dataProvider provideAddWikiText
- * @covers OutputPage::addWikiText
* @covers OutputPage::addWikiTextAsInterface
* @covers OutputPage::wrapWikiTextAsInterface
* @covers OutputPage::addWikiTextAsContent
- * @covers OutputPage::addWikiTextWithTitle
- * @covers OutputPage::addWikiTextTitle
- * @covers OutputPage::addWikiTextTidy
- * @covers OutputPage::addWikiTextTitleTidy
* @covers OutputPage::getHTML
*/
public function testAddWikiText( $method, array $args, $expected ) {
$op = $this->newInstance();
$this->assertSame( '', $op->getHTML() );
- $this->hideDeprecated( 'OutputPage::addWikiText' );
- $this->hideDeprecated( 'OutputPage::addWikiTextTitle' );
- $this->hideDeprecated( 'OutputPage::addWikiTextWithTitle' );
- $this->hideDeprecated( 'OutputPage::addWikiTextTidy' );
- $this->hideDeprecated( 'OutputPage::addWikiTextTitleTidy' );
- $this->hideDeprecated( 'disabling tidy' );
-
- if ( in_array(
- $method,
- [ 'addWikiTextWithTitle', 'addWikiTextTitleTidy', 'addWikiTextTitle' ]
- ) && count( $args ) >= 2 && $args[1] === null ) {
- // Special placeholder because we can't get the actual title in the provider
- $args[1] = $op->getTitle();
- }
if ( in_array(
$method,
[ 'addWikiTextAsInterface', 'addWikiTextAsContent' ]
public function provideAddWikiText() {
$tests = [
- 'addWikiText' => [
- // Not tidied; this API is deprecated.
- 'Simple wikitext' => [
- [ "'''Bold'''" ],
- "<p><b>Bold</b>\n</p>",
- ], 'List at start' => [
- [ '* List' ],
- "<ul><li>List</li></ul>\n",
- ], 'List not at start' => [
- [ '* Not a list', false ],
- '* Not a list',
- ], 'Non-interface' => [
- [ "'''Bold'''", true, false ],
- "<p><b>Bold</b>\n</p>",
- ], 'No section edit links' => [
- [ '== Title ==' ],
- "<h2><span class=\"mw-headline\" id=\"Title\">Title</span></h2>",
- ],
- ],
- 'addWikiTextWithTitle' => [
- // Untidied; this API is deprecated
- 'With title at start' => [
- [ '* {{PAGENAME}}', Title::newFromText( 'Talk:Some page' ) ],
- "<ul><li>Some page</li></ul>\n",
- ], 'With title at start' => [
- [ '* {{PAGENAME}}', Title::newFromText( 'Talk:Some page' ), false ],
- "* Some page",
- ],
- ],
'addWikiTextAsInterface' => [
- // Preferred interface: output is tidied
'Simple wikitext' => [
[ "'''Bold'''" ],
"<p><b>Bold</b>\n</p>",
],
],
'addWikiTextAsContent' => [
- // Preferred interface: output is tidied
'SpecialNewimages' => [
[ "<p lang='en' dir='ltr'>\nMy message" ],
'<p lang="en" dir="ltr">' . "\nMy message</p>"
],
];
- // Test all the others on addWikiTextTitle as well
- foreach ( $tests['addWikiText'] as $key => $val ) {
- $args = [ $val[0][0], null, $val[0][1] ?? true, false, $val[0][2] ?? true ];
- $tests['addWikiTextTitle']["$key (addWikiTextTitle)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- }
- foreach ( $tests['addWikiTextWithTitle'] as $key => $val ) {
- $args = [ $val[0][0], $val[0][1], $val[0][2] ?? true ];
- $tests['addWikiTextTitle']["$key (addWikiTextTitle)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- }
- foreach ( $tests['addWikiTextAsInterface'] as $key => $val ) {
- $args = [ $val[0][0], $val[0][2] ?? null, $val[0][1] ?? true, true, true ];
- $tests['addWikiTextTitle']["$key (addWikiTextTitle)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- }
- foreach ( $tests['addWikiTextAsContent'] as $key => $val ) {
- $args = [ $val[0][0], $val[0][2] ?? null, $val[0][1] ?? true, true, false ];
- $tests['addWikiTextTitle']["$key (addWikiTextTitle)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- }
- // addWikiTextTidy / addWikiTextTitleTidy were old aliases of
- // addWikiTextAsContent
- foreach ( $tests['addWikiTextAsContent'] as $key => $val ) {
- if ( count( $val[0] ) > 2 ) {
- $args = [ $val[0][0], $val[0][2], $val[0][1] ?? true ];
- $tests['addWikiTextTitleTidy']["$key (addWikiTextTitleTidy)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- } else {
- $args = [ $val[0][0], $val[0][1] ?? true ];
- $tests['addWikiTextTidy']["$key (addWikiTextTidy)"] =
- array_merge( [ $args ], array_slice( $val, 1 ) );
- }
- }
-
// We have to reformat our array to match what PHPUnit wants
$ret = [];
foreach ( $tests as $key => $subarray ) {
return $ret;
}
- /**
- * @covers OutputPage::addWikiText
- */
- public function testAddWikiTextNoTitle() {
- $this->hideDeprecated( 'OutputPage::addWikiText' );
- $this->setExpectedException( MWException::class, 'Title is null' );
-
- $op = $this->newInstance( [], null, 'notitle' );
- $op->addWikiText( 'a' );
- }
-
/**
* @covers OutputPage::addWikiTextAsInterface
*/
*
* @covers OutputPage::addVaryHeader
* @covers OutputPage::getVaryHeader
- * @covers OutputPage::getKeyHeader
*
* @param array[] $calls For each array, call addVaryHeader() with those arguments
* @param string[] $cookies Array of cookie names to vary on
* @param string $vary Text of expected Vary header (including the 'Vary: ')
* @param string $key Text of expected Key header (including the 'Key: ')
*/
- public function testVaryHeaders( array $calls, array $cookies, $vary, $key ) {
+ public function testVaryHeaders( array $calls, array $cookies, $vary ) {
// Get rid of default Vary fields
$op = $this->getMockBuilder( OutputPage::class )
->setConstructorArgs( [ new RequestContext() ] )
->will( $this->returnValue( $cookies ) );
TestingAccessWrapper::newFromObject( $op )->mVaryHeader = [];
- $this->hideDeprecated( '$wgUseKeyHeader' );
+ $this->hideDeprecated( 'addVaryHeader $option is ignored' );
foreach ( $calls as $call ) {
$op->addVaryHeader( ...$call );
}
$this->assertEquals( $vary, $op->getVaryHeader(), 'Vary:' );
- $this->assertEquals( $key, $op->getKeyHeader(), 'Key:' );
}
public function provideVaryHeaders() {
- // note: getKeyHeader() automatically adds Vary: Cookie
return [
'No header' => [
[],
[],
'Vary: ',
- 'Key: Cookie',
],
'Single header' => [
[
],
[],
'Vary: Cookie',
- 'Key: Cookie',
],
'Non-unique headers' => [
[
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie,Accept-Language',
],
'Two headers with single options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Accept-Language', [ 'substr=en' ] ],
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
],
'One header with multiple options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid', 'param=userId' ] ],
],
[],
'Vary: Cookie',
- 'Key: Cookie;param=phpsessid;param=userId',
],
'Duplicate option' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Cookie', [ 'param=phpsessid' ] ],
],
[],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
],
'Same header, different options' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=phpsessid' ] ],
[ 'Cookie', [ 'param=userId' ] ],
],
[],
'Vary: Cookie',
- 'Key: Cookie;param=phpsessid;param=userId',
],
'No header, vary cookies' => [
[],
[ 'cookie1', 'cookie2' ],
'Vary: Cookie',
- 'Key: Cookie;param=cookie1;param=cookie2',
],
'Cookie header with option plus vary cookies' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=cookie1' ] ],
],
[ 'cookie2', 'cookie3' ],
'Vary: Cookie',
- 'Key: Cookie;param=cookie1;param=cookie2;param=cookie3',
],
'Non-cookie header plus vary cookies' => [
[
],
[ 'cookie' ],
'Vary: Accept-Language, Cookie',
- 'Key: Accept-Language,Cookie;param=cookie',
],
'Cookie and non-cookie headers plus vary cookies' => [
+ // Options are deprecated since 1.34
[
[ 'Cookie', [ 'param=cookie1' ] ],
[ 'Accept-Language' ],
],
[ 'cookie2' ],
'Vary: Cookie, Accept-Language',
- 'Key: Cookie;param=cookie1;param=cookie2,Accept-Language',
],
];
}
/**
* @dataProvider provideAddAcceptLanguage
* @covers OutputPage::addAcceptLanguage
- * @covers OutputPage::getKeyHeader
*/
public function testAddAcceptLanguage(
- $code, array $variants, array $expected, array $options = []
+ $code, array $variants, $expected, array $options = []
) {
$req = new FauxRequest( in_array( 'varianturl', $options ) ? [ 'variant' => 'x' ] : [] );
$op = $this->newInstance( [], $req, in_array( 'notitle', $options ) ? 'notitle' : null );
// This will run addAcceptLanguage()
$op->sendCacheControl();
-
- $this->hideDeprecated( '$wgUseKeyHeader' );
- $keyHeader = $op->getKeyHeader();
-
- if ( !$expected ) {
- $this->assertFalse( strpos( 'Accept-Language', $keyHeader ) );
- return;
- }
-
- $keyHeader = explode( ' ', $keyHeader, 2 )[1];
- $keyHeader = explode( ',', $keyHeader );
-
- $acceptLanguage = null;
- foreach ( $keyHeader as $item ) {
- if ( strpos( $item, 'Accept-Language;' ) === 0 ) {
- $acceptLanguage = $item;
- break;
- }
- }
-
- $expectedString = 'Accept-Language;substr=' . implode( ';substr=', $expected );
- $this->assertSame( $expectedString, $acceptLanguage );
+ $this->assertSame( "Vary: $expected", $op->getVaryHeader() );
}
public function provideAddAcceptLanguage() {
return [
- 'No variants' => [ 'en', [ 'en' ], [] ],
- 'One simple variant' => [ 'en', [ 'en', 'en-x-piglatin' ], [ 'en-x-piglatin' ] ],
+ 'No variants' => [
+ 'en',
+ [ 'en' ],
+ 'Accept-Encoding, Cookie',
+ ],
+ 'One simple variant' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie, Accept-Language',
+ ],
'Multiple variants with BCP47 alternatives' => [
'zh',
[ 'zh', 'zh-hans', 'zh-cn', 'zh-tw' ],
- [ 'zh-hans', 'zh-Hans', 'zh-cn', 'zh-Hans-CN', 'zh-tw', 'zh-Hant-TW' ],
+ 'Accept-Encoding, Cookie, Accept-Language',
+ ],
+ 'No title' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie',
+ [ 'notitle' ]
+ ],
+ 'Variant in URL' => [
+ 'en',
+ [ 'en', 'en-x-piglatin' ],
+ 'Accept-Encoding, Cookie',
+ [ 'varianturl' ]
],
- 'No title' => [ 'en', [ 'en', 'en-x-piglatin' ], [], [ 'notitle' ] ],
- 'Variant in URL' => [ 'en', [ 'en', 'en-x-piglatin' ], [], [ 'varianturl' ] ],
];
}
use MediaWiki\Block\BlockManager;
use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Block\SystemBlock;
/**
* @group Blocking
],
];
}
+
+ /**
+ * @covers ::getUniqueBlocks
+ */
+ public function testGetUniqueBlocks() {
+ $blockId = 100;
+
+ $class = new ReflectionClass( BlockManager::class );
+ $method = $class->getMethod( 'getUniqueBlocks' );
+ $method->setAccessible( true );
+
+ $blockManager = $this->getBlockManager( [] );
+
+ $block = $this->getMockBuilder( DatabaseBlock::class )
+ ->setMethods( [ 'getId' ] )
+ ->getMock();
+ $block->expects( $this->any() )
+ ->method( 'getId' )
+ ->willReturn( $blockId );
+
+ $autoblock = $this->getMockBuilder( DatabaseBlock::class )
+ ->setMethods( [ 'getParentBlockId', 'getType' ] )
+ ->getMock();
+ $autoblock->expects( $this->any() )
+ ->method( 'getParentBlockId' )
+ ->willReturn( $blockId );
+ $autoblock->expects( $this->any() )
+ ->method( 'getType' )
+ ->willReturn( DatabaseBlock::TYPE_AUTO );
+
+ $blocks = [ $block, $block, $autoblock, new SystemBlock() ];
+
+ $this->assertSame( 2, count( $method->invoke( $blockManager, $blocks ) ) );
+ }
}
<?php
/**
- * @group Database
* @group ResourceLoader
*/
class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
}
);
$this->setService( 'SkinFactory', $skinFactory );
+
+ // This test is not expected to query any database
+ MediaWiki\MediaWikiServices::disableStorageBackend();
}
private static function getModules() {
$base = [
- 'localBasePath' => realpath( __DIR__ ),
+ 'localBasePath' => __DIR__,
];
return [
*/
public function testMixedCssAnnotations() {
$basePath = __DIR__ . '/../../data/css';
- $testModule = new ResourceLoaderFileModule( [
+ $testModule = new ResourceLoaderFileTestModule( [
'localBasePath' => $basePath,
'styles' => [ 'test.css' ],
] );
$testModule->setName( 'testing' );
- $expectedModule = new ResourceLoaderFileModule( [
+ $expectedModule = new ResourceLoaderFileTestModule( [
'localBasePath' => $basePath,
'styles' => [ 'expected.css' ],
] );
*/
public function testBomConcatenation() {
$basePath = __DIR__ . '/../../data/css';
- $testModule = new ResourceLoaderFileModule( [
+ $testModule = new ResourceLoaderFileTestModule( [
'localBasePath' => $basePath,
'styles' => [ 'bom.css' ],
] );
);
// Subclass
- $module = new ResourceLoaderFileModuleTestModule( $baseParams );
+ $module = new ResourceLoaderFileModuleTestingSubclass( $baseParams );
$this->assertNotEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
}, 5000, 'Expected rollback page to appear.' );
} );
- it( 'should perform rollback via GET request without asking the user to confirm', function () {
+ it.skip( 'should perform rollback via GET request without asking the user to confirm', function () {
var rollbackActionUrl = HistoryPage.rollbackLink.getAttribute( 'href' );
browser.url( rollbackActionUrl );