production.
=== Configuration changes in 1.28 ===
+* $wgSend404Code now affects status code of action=history if the page is not there.
* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
made by MediaWiki via a proxy. Relying on the http_proxy environment
variable is no longer supported.
==== Upgraded external libraries ====
* Updated es5-shim from v4.1.5 to v4.5.8
* Updated composer/semver from v1.4.1 to v1.4.2
+* Updated wikimedia/php-session-serializer from v1.0.3 to v1.0.4
==== New external libraries ====
* Added wikimedia/scoped-callback v1.0.0
==== Removed and replaced external libraries ====
=== Bug fixes in 1.28 ===
+* (T146496) action=history pages should return 404 HTTP error code if the page does not exist
* (T137264) SECURITY: XSS in unclosed internal links
* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
* (T133147) SECURITY: Require login to preview user CSS pages
"ext-xml": "*",
"liuggio/statsd-php-client": "1.0.18",
"mediawiki/at-ease": "1.1.0",
- "oojs/oojs-ui": "0.17.9",
+ "oojs/oojs-ui": "0.17.10",
"oyejorge/less.php": "1.7.0.10",
"php": ">=5.5.9",
"psr/log": "1.0.0",
"wikimedia/composer-merge-plugin": "1.3.1",
"wikimedia/html-formatter": "1.0.1",
"wikimedia/ip-set": "1.1.0",
- "wikimedia/php-session-serializer": "1.0.3",
+ "wikimedia/php-session-serializer": "1.0.4",
"wikimedia/relpath": "1.0.3",
"wikimedia/running-stat": "1.1.0",
"wikimedia/scoped-callback": "1.0.0",
// Fail nicely if article doesn't exist.
if ( !$this->page->exists() ) {
+ global $wgSend404Code;
+ if ( $wgSend404Code ) {
+ $out->setStatusCode( 404 );
+ }
$out->addWikiMsg( 'nohistory' );
# show deletion/move log if there is an entry
LogEventsList::showLogExtract(
$context->getTitle()->resetArticleID( 0 );
}
+ $contLang = $config->get( 'ContLang' );
$context->getOutput()->sendCacheControl();
header( "Content-Type: {$config->get( 'MimeType' )}; charset=UTF-8" );
- header( "Content-Language: {$config->get( 'LanguageCode' )}" );
+ header( "Content-Language: {$contLang->getHtmlCode()}" );
if ( $this->useGzip() ) {
if ( wfClientAcceptsGzip() ) {
header( 'Content-Encoding: gzip' );
// 1.28
[ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
+ [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
+ [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
];
}
'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
[ 'doRevisionPageRevIndexNonUnique' ],
[ 'doNonUniquePlTlIl' ],
+ [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
+ [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
];
}
// 1.28
[ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
+ [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
+ [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
// KEEP THIS AT THE BOTTOM!!
[ 'doRebuildDuplicateFunction' ],
[ 'addSequence', 'archive', false, 'archive_ar_id_seq' ],
[ 'addSequence', 'externallinks', false, 'externallinks_el_id_seq' ],
[ 'addSequence', 'watchlist', false, 'watchlist_wl_id_seq' ],
+ [ 'addSequence', 'change_tag', false, 'change_tag_ct_id_seq' ],
+ [ 'addSequence', 'tag_summary', false, 'tag_summary_ts_id_seq' ],
# new tables
[ 'addTable', 'category', 'patch-category.sql' ],
// 1.28
[ 'addPgIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
'( rc_namespace, rc_type, rc_patrolled, rc_timestamp )' ],
+ [ 'addPgField', 'change_tag', 'ct_id',
+ "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('change_tag_ct_id_seq')" ],
+ [ 'addPgField', 'tag_summary', 'ts_id',
+ "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('tag_summary_ts_id_seq')" ],
];
}
// 1.28
[ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
+ [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
+ [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
];
}
public function sourceFile(
$filename,
- $lineCallback = false,
- $resultCallback = false,
+ callable $lineCallback = null,
+ callable $resultCallback = null,
$fname = false,
- $inputCallback = false
+ callable $inputCallback = null
) {
MediaWiki\suppressWarnings();
$fp = fopen( $filename, 'r' );
public function sourceStream(
$fp,
- $lineCallback = false,
- $resultCallback = false,
+ callable $lineCallback = null,
+ callable $resultCallback = null,
$fname = __METHOD__,
- $inputCallback = false
+ callable $inputCallback = null
) {
$cmd = '';
* on object's error ignore settings).
*
* @param string $filename File name to open
- * @param bool|callable $lineCallback Optional function called before reading each line
- * @param bool|callable $resultCallback Optional function called for each MySQL result
+ * @param callable|null $lineCallback Optional function called before reading each line
+ * @param callable|null $resultCallback Optional function called for each MySQL result
* @param bool|string $fname Calling function name or false if name should be
* generated dynamically using $filename
- * @param bool|callable $inputCallback Optional function called for each
+ * @param callable|null $inputCallback Optional function called for each
* complete line sent
* @return bool|string
* @throws Exception
*/
public function sourceFile(
$filename,
- $lineCallback = false,
- $resultCallback = false,
+ callable $lineCallback = null,
+ callable $resultCallback = null,
$fname = false,
- $inputCallback = false
+ callable $inputCallback = null
);
/**
* on object's error ignore settings).
*
* @param resource $fp File handle
- * @param bool|callable $lineCallback Optional function called before reading each query
- * @param bool|callable $resultCallback Optional function called for each MySQL result
+ * @param callable|null $lineCallback Optional function called before reading each query
+ * @param callable|null $resultCallback Optional function called for each MySQL result
* @param string $fname Calling function name
- * @param bool|callable $inputCallback Optional function called for each complete query sent
+ * @param callable|null $inputCallback Optional function called for each complete query sent
* @return bool|string
*/
public function sourceStream(
$fp,
- $lineCallback = false,
- $resultCallback = false,
+ callable $lineCallback = null,
+ callable $resultCallback = null,
$fname = __METHOD__,
- $inputCallback = false
+ callable $inputCallback = null
);
/**
$this->baseLoadBalancerParams(),
[
'servers' => $this->makeServerArray( $template, $loads, $groupLoads ),
- 'loadMonitor' => $this->loadMonitorClass,
+ 'loadMonitor' => [ 'class' => $this->loadMonitorClass ],
'readOnlyReason' => $readOnlyReason
]
) );
: [];
$this->loadMonitorClass = isset( $conf['loadMonitorClass'] )
? $conf['loadMonitorClass']
- : null;
+ : 'LoadMonitor';
}
/**
$this->baseLoadBalancerParams(),
[
'servers' => $servers,
- 'loadMonitor' => $this->loadMonitorClass,
+ 'loadMonitor' => [ 'class' => $this->loadMonitorClass ],
]
) );
$this->initLoadBalancer( $lb );
private $mServers;
/** @var array[] Map of (local/foreignUsed/foreignFree => server index => IDatabase array) */
private $mConns;
- /** @var array Map of (server index => weight) */
+ /** @var float[] Map of (server index => weight) */
private $mLoads;
/** @var array[] Map of (group => server index => weight) */
private $mGroupLoads;
private $mAllowLagged;
/** @var integer Seconds to spend waiting on replica DB lag to resolve */
private $mWaitTimeout;
- /** @var string The LoadMonitor subclass name */
- private $mLoadMonitorClass;
+ /** @var array The LoadMonitor configuration */
+ private $loadMonitorConfig;
/** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
private $tableAliases = [];
/** @var ILoadMonitor */
- private $mLoadMonitor;
+ private $loadMonitor;
/** @var BagOStuff */
private $srvCache;
/** @var BagOStuff */
}
if ( isset( $params['loadMonitor'] ) ) {
- $this->mLoadMonitorClass = $params['loadMonitor'];
+ $this->loadMonitorConfig = $params['loadMonitor'];
} else {
- $master = reset( $params['servers'] );
- if ( isset( $master['type'] ) && $master['type'] === 'mysql' ) {
- $this->mLoadMonitorClass = 'LoadMonitorMySQL';
- } else {
- $this->mLoadMonitorClass = 'LoadMonitorNull';
- }
+ $this->loadMonitorConfig = [ 'class' => 'LoadMonitorNull' ];
}
foreach ( $params['servers'] as $i => $server ) {
* @return ILoadMonitor
*/
private function getLoadMonitor() {
- if ( !isset( $this->mLoadMonitor ) ) {
- $class = $this->mLoadMonitorClass;
- $this->mLoadMonitor = new $class( $this, $this->srvCache, $this->memCache );
- $this->mLoadMonitor->setLogger( $this->replLogger );
+ if ( !isset( $this->loadMonitor ) ) {
+ $class = $this->loadMonitorConfig['class'];
+ $this->loadMonitor = new $class(
+ $this, $this->srvCache, $this->memCache, $this->loadMonitorConfig );
+ $this->loadMonitor->setLogger( $this->replLogger );
}
- return $this->mLoadMonitor;
+ return $this->loadMonitor;
}
/**
* @param ILoadBalancer $lb LoadBalancer this instance serves
* @param BagOStuff $sCache Local server memory cache
* @param BagOStuff $cCache Local cluster memory cache
+ * @param array $options Options map
*/
- public function __construct( ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache );
+ public function __construct(
+ ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache, array $options = []
+ );
/**
* Perform pre-connection load ratio adjustment.
- * @param int[] &$loads
+ * @param int[] &$weightByServer Map of (server index => integer weight)
* @param string|bool $group The selected query group. Default: false
* @param string|bool $domain Default: false
*/
- public function scaleLoads( &$loads, $group = false, $domain = false );
+ public function scaleLoads( array &$weightByServer, $group = false, $domain = false );
/**
* Get an estimate of replication lag (in seconds) for each server
*
* @return array Map of (server index => float|int|bool)
*/
- public function getLagTimes( $serverIndexes, $domain );
+ public function getLagTimes( array $serverIndexes, $domain );
/**
* Clear any process and persistent cache of lag times
/** @var LoggerInterface */
protected $replLogger;
- public function __construct( ILoadBalancer $lb, BagOStuff $srvCache, BagOStuff $cache ) {
+ /** @var float Moving average ratio (e.g. 0.1 for 10% weight to new weight) */
+ private $movingAveRatio;
+
+ public function __construct(
+ ILoadBalancer $lb, BagOStuff $srvCache, BagOStuff $cache, array $options = []
+ ) {
$this->parent = $lb;
$this->srvCache = $srvCache;
$this->mainCache = $cache;
$this->replLogger = new \Psr\Log\NullLogger();
+
+ $this->movingAveRatio = isset( $options['movingAveRatio'] )
+ ? $options['movingAveRatio']
+ : 0.1;
}
public function setLogger( LoggerInterface $logger ) {
$this->replLogger = $logger;
}
- public function scaleLoads( &$loads, $group = false, $domain = false ) {
+ public function scaleLoads( array &$weightByServer, $group = false, $domain = false ) {
+ $states = $this->getServerStates( $weightByServer, $domain );
+ $coefficientsByServer = $states['weightScales'];
+ foreach ( $weightByServer as $i => $weight ) {
+ $weightByServer[$i] = $weight * $coefficientsByServer[$i];
+ }
+ }
+
+ public function getLagTimes( array $serverIndexes, $domain ) {
+ $states = $this->getServerStates( $serverIndexes, $domain );
+
+ return $states['lagTimes'];
}
- public function getLagTimes( $serverIndexes, $domain ) {
+ protected function getServerStates( array $serverIndexes, $domain ) {
if ( count( $serverIndexes ) == 1 && reset( $serverIndexes ) == 0 ) {
# Single server only, just return zero without caching
- return [ 0 => 0 ];
+ return [
+ 'lagTimes' => [ $this->parent->getWriterIndex() => 0 ],
+ 'weightScales' => [ $this->parent->getWriterIndex() => 1 ]
+ ];
}
- $key = $this->getLagTimeCacheKey();
+ $key = $this->getCacheKey();
# Randomize TTLs to reduce stampedes (4.0 - 5.0 sec)
$ttl = mt_rand( 4e6, 5e6 ) / 1e6;
# Keep keys around longer as fallbacks
$value = $this->srvCache->get( $key );
if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) {
$this->replLogger->debug( __METHOD__ . ": got lag times ($key) from local cache" );
- return $value['lagTimes']; // cache hit
+ return $value; // cache hit
}
$staleValue = $value ?: false;
$this->srvCache->set( $key, $value, $staleTTL );
$this->replLogger->debug( __METHOD__ . ": got lag times ($key) from main cache" );
- return $value['lagTimes']; // cache hit
+ return $value; // cache hit
}
$staleValue = $value ?: $staleValue;
} );
} elseif ( $staleValue ) {
# Could not acquire lock but an old cache exists, so use it
- return $staleValue['lagTimes'];
+ return $staleValue;
}
$lagTimes = [];
+ $weightScales = [];
+ $movAveRatio = $this->movingAveRatio;
foreach ( $serverIndexes as $i ) {
if ( $i == $this->parent->getWriterIndex() ) {
$lagTimes[$i] = 0; // master always has no lag
+ $weightScales[$i] = 1.0; // nominal weight
continue;
}
$close = true; // new connection
}
+ $lastWeight = isset( $staleValue['weightScales'][$i] )
+ ? $staleValue['weightScales'][$i]
+ : 1.0;
+ $coefficient = $this->getWeightScale( $i, $conn ?: null );
+ $newWeight = $movAveRatio * $coefficient + ( 1 - $movAveRatio ) * $lastWeight;
+
+ // Scale from 10% to 100% of nominal weight
+ $weightScales[$i] = max( $newWeight, .10 );
+
if ( !$conn ) {
$lagTimes[$i] = false;
$host = $this->parent->getServerName( $i );
- $this->replLogger->error( __METHOD__ . ": host $host (#$i) is unreachable" );
+ $this->replLogger->error( __METHOD__ . ": host $host is unreachable" );
continue;
}
$lagTimes[$i] = $conn->getLag();
if ( $lagTimes[$i] === false ) {
$host = $this->parent->getServerName( $i );
- $this->replLogger->error( __METHOD__ . ": host $host (#$i) is not replicating?" );
+ $this->replLogger->error( __METHOD__ . ": host $host is not replicating?" );
}
if ( $close ) {
}
# Add a timestamp key so we know when it was cached
- $value = [ 'lagTimes' => $lagTimes, 'timestamp' => microtime( true ) ];
+ $value = [
+ 'lagTimes' => $lagTimes,
+ 'weightScales' => $weightScales,
+ 'timestamp' => microtime( true )
+ ];
$this->mainCache->set( $key, $value, $staleTTL );
$this->srvCache->set( $key, $value, $staleTTL );
$this->replLogger->info( __METHOD__ . ": re-calculated lag times ($key)" );
- return $value['lagTimes'];
+ return $value;
+ }
+
+ /**
+ * @param integer $index Server index
+ * @param IDatabase|null $conn Connection handle or null on connection failure
+ * @return float
+ */
+ protected function getWeightScale( $index, IDatabase $conn = null ) {
+ return $conn ? 1.0 : 0.0;
}
public function clearCaches() {
- $key = $this->getLagTimeCacheKey();
+ $key = $this->getCacheKey();
$this->srvCache->delete( $key );
$this->mainCache->delete( $key );
}
- private function getLagTimeCacheKey() {
- $writerIndex = $this->parent->getWriterIndex();
+ private function getCacheKey() {
// Lag is per-server, not per-DB, so key on the master DB name
return $this->srvCache->makeGlobalKey(
'lag-times',
- $this->parent->getServerName( $writerIndex )
+ $this->parent->getServerName( $this->parent->getWriterIndex() )
);
}
}
* @ingroup Database
*/
class LoadMonitorMySQL extends LoadMonitor {
- public function scaleLoads( &$loads, $group = false, $domain = false ) {
- // @TODO: maybe use Threads_running/Threads_created ratio to guess load
- // and Queries/Uptime to guess if a server is warming up the buffer pool
+ /** @var float What buffer pool use ratio counts as "warm" (e.g. 0.5 for 50% usage) */
+ private $warmCacheRatio;
+
+ public function __construct(
+ ILoadBalancer $lb, BagOStuff $srvCache, BagOStuff $cache, array $options = []
+ ) {
+ parent::__construct( $lb, $srvCache, $cache, $options );
+
+ $this->warmCacheRatio = isset( $options['warmCacheRatio'] )
+ ? $options['warmCacheRatio']
+ : 0.0;
+ }
+
+ protected function getWeightScale( $index, IDatabase $conn = null ) {
+ if ( !$conn ) {
+ return 0.0;
+ }
+
+ $weight = 1.0;
+ if ( $this->warmCacheRatio > 0 ) {
+ $res = $conn->query( 'SHOW STATUS', false );
+ $s = $res ? $conn->fetchObject( $res ) : false;
+ if ( $s === false ) {
+ $host = $this->parent->getServerName( $index );
+ $this->replLogger->error( __METHOD__ . ": could not get status for $host" );
+ } else {
+ // http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html
+ if ( $s->Innodb_buffer_pool_pages_total > 0 ) {
+ $ratio = $s->Innodb_buffer_pool_pages_data / $s->Innodb_buffer_pool_pages_total;
+ } elseif ( $s->Qcache_total_blocks > 0 ) {
+ $ratio = 1.0 - $s->Qcache_free_blocks / $s->Qcache_total_blocks;
+ } else {
+ $ratio = 1.0;
+ }
+ // Stop caring once $ratio >= $this->warmCacheRatio
+ $weight *= min( $ratio / $this->warmCacheRatio, 1.0 );
+ }
+ }
+
+ return $weight;
}
}
use Psr\Log\LoggerInterface;
class LoadMonitorNull implements ILoadMonitor {
- public function __construct( ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache ) {
+ public function __construct(
+ ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache, array $options = []
+ ) {
}
public function setLogger( LoggerInterface $logger ) {
}
- public function scaleLoads( &$loads, $group = false, $domain = false ) {
+ public function scaleLoads( array &$loads, $group = false, $domain = false ) {
}
- public function getLagTimes( $serverIndexes, $domain ) {
+ public function getLagTimes( array $serverIndexes, $domain ) {
return array_fill_keys( $serverIndexes, 0 );
}
* @deprecated since 1.21, getContent() should be used instead.
*/
public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) {
- ContentHandler::deprecated( __METHOD__, '1.21' );
+ wfDeprecated( __METHOD__, '1.21' );
$this->loadLastEdit();
if ( $this->mLastRevision ) {
'text' => $ilLangName,
'title' => $ilTitle,
'class' => $class,
+ 'link-class' => 'interlanguage-link-target',
'lang' => $ilInterwikiCodeBCP47,
'hreflang' => $ilInterwikiCodeBCP47,
];
if ( !$title->equals( $oldTitle ) ) {
$oldTitleText = $oldTitle->getPrefixedText();
- $oldTitleText = $this->msg( 'rc-old-title' )->params( $oldTitleText )->escaped();
+ $oldTitleText = Html::rawElement(
+ 'span',
+ [ 'class' => 'mw-newpages-oldtitle' ],
+ $this->msg( 'rc-old-title' )->params( $oldTitleText )->escaped()
+ );
}
return "<li{$css}>{$time} {$dm}{$plink} {$hist} {$dm}{$length} "
"searchprofile-advanced-tooltip": "Search in custom namespaces",
"search-result-size": "$1 ({{PLURAL:$2|1 word|$2 words}})",
"search-result-category-size": "{{PLURAL:$1|1 member|$1 members}} ({{PLURAL:$2|1 subcategory|$2 subcategories}}, {{PLURAL:$3|1 file|$3 files}})",
- "search-redirect": "(redirect $1)",
+ "search-redirect": "(redirect from $1)",
"search-section": "(section $1)",
"search-category": "(category $1)",
"search-file-match": "(matches file content)",
"feedback-external-bug-report-button": "File a technical task",
"feedback-dialog-title": "Submit feedback",
"feedback-dialog-intro": "You can use the easy form below to submit your feedback. Your comment will be added to the page \"$1\", along with your username.",
- "feedback-error-title": "Error",
"feedback-error1": "Error: Unrecognized result from API",
"feedback-error2": "Error: Edit failed",
"feedback-error3": "Error: No response from API",
"feedback-external-bug-report-button": "A button for submitting an external technical bug report.",
"feedback-dialog-title": "Title of the feedback dialog",
"feedback-dialog-intro": "An introduction at the top of the feedback dialog. $1 - Feedback page link",
- "feedback-error-title": "{{Identical|Error}}",
"feedback-error1": "Error message, appears when an unknown error occurs submitting feedback",
"feedback-error2": "Error message, appears when we could not add feedback",
"feedback-error3": "Error message, appears when we lose our connection to the wiki",
--- /dev/null
+-- Primary key in change_tag table
+
+ALTER TABLE /*$wgDBprefix*/change_tag
+ ADD COLUMN ct_id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
+ ADD PRIMARY KEY (ct_id);
--- /dev/null
+-- Primary key in tag_summary table
+
+ALTER TABLE /*$wgDBprefix*/tag_summary
+ ADD COLUMN ts_id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
+ ADD PRIMARY KEY (ts_id);
cache|http://www.google.com/search?q=cache:$1|0|
commons|https://commons.wikimedia.org/wiki/$1|0|https://commons.wikimedia.org/w/api.php
dictionary|http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1|0|
-docbook|http://wiki.docbook.org/$1|0|
doi|http://dx.doi.org/$1|0|
drumcorpswiki|http://www.drumcorpswiki.com/$1|0|http://drumcorpswiki.com/api.php
dwjwiki|http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1|0|
foldoc|http://foldoc.org/?$1|0|
foxwiki|http://fox.wikis.com/wc.dll?Wiki~$1|0|
freebsdman|http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1|0|
-gej|http://www.esperanto.de/dej.malnova/aktivikio.pl?$1|0|
gentoo-wiki|http://gentoo-wiki.com/$1|0|
google|http://www.google.com/search?q=$1|0|
googlegroups|http://groups.google.com/groups?q=$1|0|
hammondwiki|http://www.dairiki.org/HammondWiki/$1|0|
hrwiki|http://www.hrwiki.org/wiki/$1|0|http://www.hrwiki.org/w/api.php
imdb|http://www.imdb.com/find?q=$1&tt=on|0|
-jargonfile|http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1|0|
kmwiki|http://kmwiki.wikispaces.com/$1|0|
linuxwiki|http://linuxwiki.de/$1|0|
lojban|http://mw.lojban.org/papri/$1|0|
lqwiki|http://wiki.linuxquestions.org/wiki/$1|0|
-lugkr|http://www.lug-kr.de/wiki/$1|0|
meatball|http://www.usemod.com/cgi-bin/mb.pl?$1|0|
mediawikiwiki|https://www.mediawiki.org/wiki/$1|0|https://www.mediawiki.org/w/api.php
-mediazilla|https://bugzilla.wikimedia.org/$1|0|
memoryalpha|http://en.memory-alpha.org/wiki/$1|0|http://en.memory-alpha.org/api.php
metawiki|http://sunir.org/apps/meta.pl?$1|0|
metawikimedia|https://meta.wikimedia.org/wiki/$1|0|https://meta.wikimedia.org/w/api.php
mw|https://www.mediawiki.org/wiki/$1|0|https://www.mediawiki.org/w/api.php
oeis|http://oeis.org/$1|0|
openwiki|http://openwiki.com/ow.asp?$1|0|
-ppr|http://c2.com/cgi/wiki?$1|0|
pythoninfo|http://wiki.python.org/moin/$1|0|
rfc|http://www.rfc-editor.org/rfc/rfc$1.txt|0|
s23wiki|http://s23.org/wiki/$1|0|http://s23.org/w/api.php
seattlewireless|http://seattlewireless.net/$1|0|
senseislibrary|http://senseis.xmp.net/?$1|0|
shoutwiki|http://www.shoutwiki.com/wiki/$1|0|http://www.shoutwiki.com/w/api.php
-sourcewatch|http://www.sourcewatch.org/index.php?title=$1|0|http://www.sourcewatch.org/api.php
squeak|http://wiki.squeak.org/squeak/$1|0|
-tejo|http://www.tejo.org/vikio/$1|0|
tmbw|http://www.tmbw.net/wiki/$1|0|http://tmbw.net/wiki/api.php
tmnet|http://www.technomanifestos.net/?$1|0|
theopedia|http://www.theopedia.com/$1|0|
twiki|http://twiki.org/cgi-bin/view/$1|0|
-uea|http://uea.org/vikio/index.php/$1|0|http://uea.org/vikio/api.php
uncyclopedia|http://en.uncyclopedia.co/wiki/$1|0|http://en.uncyclopedia.co/w/api.php
unreal|http://wiki.beyondunreal.com/$1|0|http://wiki.beyondunreal.com/w/api.php
usemod|http://www.usemod.com/cgi-bin/wiki.pl?$1|0|
-webseitzwiki|http://webseitz.fluxent.com/wiki/$1|0|
wiki|http://c2.com/cgi/wiki?$1|0|
wikia|http://www.wikia.com/wiki/$1|0|
wikibooks|https://en.wikibooks.org/wiki/$1|0|https://en.wikibooks.org/w/api.php
('cache','http://www.google.com/search?q=cache:$1',0,''),
('commons','https://commons.wikimedia.org/wiki/$1',0,'https://commons.wikimedia.org/w/api.php'),
('dictionary','http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1',0,''),
-('docbook','http://wiki.docbook.org/$1',0,''),
('doi','http://dx.doi.org/$1',0,''),
('drumcorpswiki','http://www.drumcorpswiki.com/$1',0,'http://drumcorpswiki.com/api.php'),
('dwjwiki','http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1',0,''),
('foldoc','http://foldoc.org/?$1',0,''),
('foxwiki','http://fox.wikis.com/wc.dll?Wiki~$1',0,''),
('freebsdman','http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1',0,''),
-('gej','http://www.esperanto.de/dej.malnova/aktivikio.pl?$1',0,''),
('gentoo-wiki','http://gentoo-wiki.com/$1',0,''),
('google','http://www.google.com/search?q=$1',0,''),
('googlegroups','http://groups.google.com/groups?q=$1',0,''),
('hammondwiki','http://www.dairiki.org/HammondWiki/$1',0,''),
('hrwiki','http://www.hrwiki.org/wiki/$1',0,'http://www.hrwiki.org/w/api.php'),
('imdb','http://www.imdb.com/find?q=$1&tt=on',0,''),
-('jargonfile','http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1',0,''),
('kmwiki','http://kmwiki.wikispaces.com/$1',0,''),
('linuxwiki','http://linuxwiki.de/$1',0,''),
('lojban','http://www.lojban.org/tiki/tiki-index.php?page=$1',0,''),
('lqwiki','http://wiki.linuxquestions.org/wiki/$1',0,''),
-('lugkr','http://www.lug-kr.de/wiki/$1',0,''),
('meatball','http://www.usemod.com/cgi-bin/mb.pl?$1',0,''),
('mediawikiwiki','https://www.mediawiki.org/wiki/$1',0,'https://www.mediawiki.org/w/api.php'),
-('mediazilla','https://bugzilla.wikimedia.org/$1',0,''),
('memoryalpha','http://en.memory-alpha.org/wiki/$1',0,'http://en.memory-alpha.org/api.php'),
('metawiki','http://sunir.org/apps/meta.pl?$1',0,''),
('metawikimedia','https://meta.wikimedia.org/wiki/$1',0,'https://meta.wikimedia.org/w/api.php'),
('mw','https://www.mediawiki.org/wiki/$1',0,'https://www.mediawiki.org/w/api.php'),
('oeis','http://oeis.org/$1',0,''),
('openwiki','http://openwiki.com/ow.asp?$1',0,''),
-('ppr','http://c2.com/cgi/wiki?$1',0,''),
('pythoninfo','http://wiki.python.org/moin/$1',0,''),
('rfc','http://www.rfc-editor.org/rfc/rfc$1.txt',0,''),
('s23wiki','http://s23.org/wiki/$1',0,'http://s23.org/w/api.php'),
('seattlewireless','http://seattlewireless.net/$1',0,''),
('senseislibrary','http://senseis.xmp.net/?$1',0,''),
('shoutwiki','http://www.shoutwiki.com/wiki/$1',0,'http://www.shoutwiki.com/w/api.php'),
-('sourcewatch','http://www.sourcewatch.org/index.php?title=$1',0,'http://www.sourcewatch.org/api.php'),
('squeak','http://wiki.squeak.org/squeak/$1',0,''),
-('tejo','http://www.tejo.org/vikio/$1',0,''),
('tmbw','http://www.tmbw.net/wiki/$1',0,'http://tmbw.net/wiki/api.php'),
('tmnet','http://www.technomanifestos.net/?$1',0,''),
('theopedia','http://www.theopedia.com/$1',0,''),
('twiki','http://twiki.org/cgi-bin/view/$1',0,''),
-('uea','http://uea.org/vikio/index.php/$1',0,'http://uea.org/vikio/api.php'),
('uncyclopedia','http://en.uncyclopedia.co/wiki/$1',0,'http://en.uncyclopedia.co/w/api.php'),
('unreal','http://wiki.beyondunreal.com/$1',0,'http://wiki.beyondunreal.com/w/api.php'),
('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0,''),
-('webseitzwiki','http://webseitz.fluxent.com/wiki/$1',0,''),
('wiki','http://c2.com/cgi/wiki?$1',0,''),
('wikia','http://www.wikia.com/wiki/$1',0,''),
('wikibooks','https://en.wikibooks.org/wiki/$1',0,'https://en.wikibooks.org/w/api.php'),
--- /dev/null
+-- Primary key in change_tag table
+
+ALTER TABLE /*_*/change_tag ADD ct_id INT IDENTITY;
+ALTER TABLE /*_*/change_tag ADD CONSTRAINT pk_change_tag PRIMARY KEY(ct_id)
--- /dev/null
+-- Primary key in tag_summary table
+
+ALTER TABLE /*_*/tag_summary ADD ts_id INT IDENTITY;
+ALTER TABLE /*_*/tag_summary ADD CONSTRAINT pk_tag_summary PRIMARY KEY(ts_id)
-- A table to track tags for revisions, logs and recent changes.
CREATE TABLE /*_*/change_tag (
+ ct_id int NOT NULL PRIMARY KEY IDENTITY,
-- RCID for the change
ct_rc_id int NULL REFERENCES /*_*/recentchanges(rc_id),
-- LOGID for the change
-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT
-- that only works on MySQL 4.1+
CREATE TABLE /*_*/tag_summary (
+ ts_id int NOT NULL PRIMARY KEY IDENTITY,
-- RCID for the change
ts_rc_id int NULL REFERENCES /*_*/recentchanges(rc_id),
-- LOGID for the change
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.change_tag ADD (
+ct_id NUMBER NOT NULL,
+);
+ALTER TABLE &mw_prefix.change_tag ADD CONSTRAINT &mw_prefix.change_tag_pk PRIMARY KEY (ct_id);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.tag_summary ADD (
+ts_id NUMBER NOT NULL,
+);
+ALTER TABLE &mw_prefix.tag_summary ADD CONSTRAINT &mw_prefix.tag_summary_pk PRIMARY KEY (ts_id);
ALTER TABLE &mw_prefix.updatelog ADD CONSTRAINT &mw_prefix.updatelog_pk PRIMARY KEY (ul_key);
CREATE TABLE &mw_prefix.change_tag (
+ ct_id NUMBER NOT NULL,
ct_rc_id NUMBER NULL,
ct_log_id NUMBER NULL,
ct_rev_id NUMBER NULL,
ct_tag VARCHAR2(255) NOT NULL,
ct_params BLOB NULL
);
+ALTER TABLE &mw_prefix.change_tag ADD CONSTRAINT &mw_prefix.change_tag_pk PRIMARY KEY (ct_id);
CREATE UNIQUE INDEX &mw_prefix.change_tag_u01 ON &mw_prefix.change_tag (ct_rc_id,ct_tag);
CREATE UNIQUE INDEX &mw_prefix.change_tag_u02 ON &mw_prefix.change_tag (ct_log_id,ct_tag);
CREATE UNIQUE INDEX &mw_prefix.change_tag_u03 ON &mw_prefix.change_tag (ct_rev_id,ct_tag);
CREATE INDEX &mw_prefix.change_tag_i01 ON &mw_prefix.change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
CREATE TABLE &mw_prefix.tag_summary (
+ ts_id NUMBER NOT NULL,
ts_rc_id NUMBER NULL,
ts_log_id NUMBER NULL,
ts_rev_id NUMBER NULL,
ts_tags BLOB NOT NULL
);
+ALTER TABLE &mw_prefix.tag_summary ADD CONSTRAINT &mw_prefix.tag_summary_pk PRIMARY KEY (ts_id);
CREATE UNIQUE INDEX &mw_prefix.tag_summary_u01 ON &mw_prefix.tag_summary (ts_rc_id);
CREATE UNIQUE INDEX &mw_prefix.tag_summary_u02 ON &mw_prefix.tag_summary (ts_log_id);
CREATE UNIQUE INDEX &mw_prefix.tag_summary_u03 ON &mw_prefix.tag_summary (ts_rev_id);
DROP SEQUENCE IF EXISTS archive_ar_id_seq CASCADE;
DROP SEQUENCE IF EXISTS externallinks_el_id_seq CASCADE;
DROP SEQUENCE IF EXISTS sites_site_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS change_tag_ct_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS tag_summary_ts_id_seq CASCADE;
DROP FUNCTION IF EXISTS page_deleted() CASCADE;
DROP FUNCTION IF EXISTS ts2_page_title() CASCADE;
DROP FUNCTION IF EXISTS ts2_page_text() CASCADE;
CREATE UNIQUE INDEX category_title ON category(cat_title);
CREATE INDEX category_pages ON category(cat_pages);
+CREATE SEQUENCE change_tag_ct_id_seq;
CREATE TABLE change_tag (
+ ct_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('change_tag_ct_id_seq'),
ct_rc_id INTEGER NULL,
ct_log_id INTEGER NULL,
ct_rev_id INTEGER NULL,
CREATE UNIQUE INDEX change_tag_rev_tag ON change_tag(ct_rev_id,ct_tag);
CREATE INDEX change_tag_tag_id ON change_tag(ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
+CREATE SEQUENCE tag_summary_ts_id_seq;
CREATE TABLE tag_summary (
- ts_rc_id INTEGER NULL,
- ts_log_id INTEGER NULL,
- ts_rev_id INTEGER NULL,
- ts_tags TEXT NOT NULL
+ ts_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('tag_summary_ts_id_seq'),
+ ts_rc_id INTEGER NULL,
+ ts_log_id INTEGER NULL,
+ ts_rev_id INTEGER NULL,
+ ts_tags TEXT NOT NULL
);
CREATE UNIQUE INDEX tag_summary_rc_id ON tag_summary(ts_rc_id);
CREATE UNIQUE INDEX tag_summary_log_id ON tag_summary(ts_log_id);
$this->error( "Unable to open input file", true );
}
- $error = $db->sourceStream( $file, false, [ $this, 'sqlPrintResult' ] );
+ $error = $db->sourceStream( $file, null, [ $this, 'sqlPrintResult' ] );
if ( $error !== true ) {
$this->error( $error, true );
} else {
--- /dev/null
+DROP TABLE IF EXISTS /*_*/change_tag_tmp;
+
+CREATE TABLE /*$wgDBprefix*/change_tag_tmp (
+ ct_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ ct_rc_id int NULL,
+ ct_log_id int NULL,
+ ct_rev_id int NULL,
+ ct_tag varchar(255) NOT NULL,
+ ct_params blob NULL
+);
+
+INSERT OR IGNORE INTO /*_*/change_tag_tmp (
+ ct_rc_id, ct_log_id, ct_rev_id, ct_tag, ct_params )
+ SELECT
+ ct_rc_id, ct_log_id, ct_rev_id, ct_tag, ct_params
+ FROM /*_*/change_tag;
+
+DROP TABLE /*_*/change_tag;
+
+ALTER TABLE /*_*/change_tag_tmp RENAME TO /*_*/change_tag;
+
+CREATE UNIQUE INDEX /*i*/change_tag_rc_tag ON /*_*/change_tag (ct_rc_id,ct_tag);
+CREATE UNIQUE INDEX /*i*/change_tag_log_tag ON /*_*/change_tag (ct_log_id,ct_tag);
+CREATE UNIQUE INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag (ct_rev_id,ct_tag);
+CREATE INDEX /*i*/change_tag_tag_id ON /*_*/change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
--- /dev/null
+DROP TABLE IF EXISTS /*_*/tag_summary_tmp;
+
+CREATE TABLE /*$wgDBprefix*/tag_summary_tmp (
+ ts_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ ts_rc_id int NULL,
+ ts_log_id int NULL,
+ ts_rev_id int NULL,
+ ts_tags blob NOT NULL
+);
+
+INSERT OR IGNORE INTO /*_*/tag_summary_tmp (
+ ts_rc_id, ts_log_id, ts_rev_id, ts_tags )
+ SELECT
+ ts_rc_id, ts_log_id, ts_rev_id, ts_tags
+ FROM /*_*/tag_summary;
+
+DROP TABLE /*_*/tag_summary;
+
+ALTER TABLE /*_*/tag_summary_tmp RENAME TO /*_*/tag_summary;
+
+CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id);
+CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id);
+CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id);
-- A table to track tags for revisions, logs and recent changes.
CREATE TABLE /*_*/change_tag (
+ ct_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
-- RCID for the change
ct_rc_id int NULL,
-- LOGID for the change
-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT
-- that only works on MySQL 4.1+
CREATE TABLE /*_*/tag_summary (
+ ts_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
-- RCID for the change
ts_rc_id int NULL,
-- LOGID for the change
'feedback-cancel',
'feedback-close',
'feedback-dialog-title',
- 'feedback-error-title',
'feedback-error1',
'feedback-error2',
'feedback-error3',
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-element-hidden {
display: none !important;
max-width: 100%;
padding: 0;
white-space: normal;
+ float: left;
+}
+.oo-ui-fieldsetLayout-group {
+ clear: both;
}
.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-help {
float: right;
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-element-hidden {
display: none !important;
max-width: 100%;
padding: 0;
white-space: normal;
+ float: left;
+}
+.oo-ui-fieldsetLayout-group {
+ clear: both;
}
.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-help {
float: right;
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
}
// Initialization
+ this.$group.addClass( 'oo-ui-fieldsetLayout-group' );
this.$element
.addClass( 'oo-ui-fieldsetLayout' )
.prepend( this.$label, this.$help, this.$icon, this.$group );
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-popupTool .oo-ui-popupWidget-popup,
.oo-ui-popupTool .oo-ui-popupWidget-anchor {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-tool.oo-ui-widget-enabled {
-webkit-transition: background-color 100ms;
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-draggableElement-handle,
.oo-ui-draggableElement-handle.oo-ui-widget {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-draggableElement-handle,
.oo-ui-draggableElement-handle.oo-ui-widget {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-actionWidget.oo-ui-pendingElement-pending {
background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:06Z
+ * Date: 2016-10-03T18:59:06Z
*/
.oo-ui-window {
background: transparent;
/*!
- * OOjs UI v0.17.9
+ * OOjs UI v0.17.10
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2016 OOjs UI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2016-09-13T18:30:02Z
+ * Date: 2016-10-03T18:59:01Z
*/
( function ( OO ) {
]
};
break;
- case 'error1':
- case 'error2':
- case 'error3':
- case 'error4':
- dialogConfig = {
- title: mw.msg( 'feedback-error-title' ),
- message: mw.msg( 'feedback-' + status ),
- actions: [
- {
- action: 'accept',
- label: mw.msg( 'feedback-close' ),
- flags: 'primary'
- }
- ]
- };
- break;
}
// Show the message dialog
}, function () {
fb.status = 'error4';
mw.log.warn( 'Feedback report failed because MessagePoster could not be fetched' );
- } ).always( function () {
+ } ).then( function () {
fb.close();
+ }, function () {
+ return fb.getErrorMessage();
} );
}, this );
}
return mw.Feedback.Dialog.parent.prototype.getActionProcess.call( this, action );
};
+ /**
+ * Returns an error message for the current status.
+ *
+ * @private
+ *
+ * @return {OO.ui.Error}
+ */
+ mw.Feedback.Dialog.prototype.getErrorMessage = function () {
+ switch ( this.status ) {
+ case 'error1':
+ case 'error2':
+ case 'error3':
+ case 'error4':
+ // Messages: feedback-error1, feedback-error2, feedback-error3, feedback-error4
+ return new OO.ui.Error( mw.msg( 'feedback-' + this.status ) );
+ }
+ };
+
/**
* Posts the message
*