revision comparison pages using syntax such as [[Special:Diff/12345]],
[[Special:Diff/12345/prev]] or [[Special:Diff/12345/98765]].
* New user accounts' personal and talk pages are now watched by them by default.
+* Added SkinTemplateGetLanguageLink hook to allow changing the html of language
+ links.
=== Bug fixes in 1.23 ===
* (bug 41759) The "updated since last visit" markers (on history pages, recent
$sktemplate: SkinTemplate object
$nav_urls: array of tabs
+'SkinTemplateGetLanguageLink': After building the data for a language link from
+which the actual html is constructed.
+&$languageLink: array containing data about the link. The following keys can be
+ modified: href, text, title, class, lang, hreflang. Each of them is a string.
+$languageLinkTitle: Title object belonging to the external language link
+$title: Title object of the page the link belongs to
+
To alter the structured navigation links in SkinTemplates, there are three
hooks called in different spots:
wfProfileOut( $fname . '-exception' );
wfProfileIn( $fname . '-includes' );
-require_once "$IP/includes/GlobalFunctions.php";
require_once "$IP/includes/normal/UtfNormalUtil.php";
+require_once "$IP/includes/GlobalFunctions.php";
require_once "$IP/includes/normal/UtfNormalDefines.php";
wfProfileOut( $fname . '-includes' );
);
}
-$wgDeferredUpdateList = array(); // b/c
-
wfProfileOut( $fname . '-defaults2' );
wfProfileIn( $fname . '-misc1' );
}
wfProfileOut( $fname . '-misc1' );
-if ( !defined( 'MW_SETUP_NO_CACHE' ) ) {
- wfProfileIn( $fname . '-memcached' );
+wfProfileIn( $fname . '-memcached' );
- $wgMemc = wfGetMainCache();
- $messageMemc = wfGetMessageCacheStorage();
- $parserMemc = wfGetParserCacheStorage();
- $wgLangConvMemc = wfGetLangConverterCacheStorage();
+$wgMemc = wfGetMainCache();
+$messageMemc = wfGetMessageCacheStorage();
+$parserMemc = wfGetParserCacheStorage();
+$wgLangConvMemc = wfGetLangConverterCacheStorage();
- wfDebug( 'CACHES: ' . get_class( $wgMemc ) . '[main] ' .
- get_class( $messageMemc ) . '[message] ' .
- get_class( $parserMemc ) . "[parser]\n" );
+wfDebug( 'CACHES: ' . get_class( $wgMemc ) . '[main] ' .
+ get_class( $messageMemc ) . '[message] ' .
+ get_class( $parserMemc ) . "[parser]\n" );
- wfProfileOut( $fname . '-memcached' );
- # # Most of the config is out, some might want to run hooks here.
- wfRunHooks( 'SetupAfterCache' );
-}
+wfProfileOut( $fname . '-memcached' );
+
+# # Most of the config is out, some might want to run hooks here.
+wfRunHooks( 'SetupAfterCache' );
wfProfileIn( $fname . '-session' );
}
wfProfileOut( $fname . '-session' );
+wfProfileIn( $fname . '-globals' );
-if ( !defined( 'MW_SETUP_NO_CONTEXT' ) ) {
- wfProfileIn( $fname . '-globals' );
-
- $wgContLang = Language::factory( $wgLanguageCode );
- $wgContLang->initEncoding();
- $wgContLang->initContLang();
+$wgContLang = Language::factory( $wgLanguageCode );
+$wgContLang->initEncoding();
+$wgContLang->initContLang();
- // Now that variant lists may be available...
- $wgRequest->interpolateTitle();
- $wgUser = RequestContext::getMain()->getUser(); # BackCompat
+// Now that variant lists may be available...
+$wgRequest->interpolateTitle();
+$wgUser = RequestContext::getMain()->getUser(); # BackCompat
- /**
- * @var $wgLang Language
- */
- $wgLang = new StubUserLang;
+/**
+ * @var $wgLang Language
+ */
+$wgLang = new StubUserLang;
- /**
- * @var OutputPage
- */
- $wgOut = RequestContext::getMain()->getOutput(); # BackCompat
+/**
+ * @var OutputPage
+ */
+$wgOut = RequestContext::getMain()->getOutput(); # BackCompat
- /**
- * @var $wgParser Parser
- */
- $wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParserConf ) );
+/**
+ * @var $wgParser Parser
+ */
+$wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParserConf ) );
- if ( !is_object( $wgAuth ) ) {
- $wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' );
- wfRunHooks( 'AuthPluginSetup', array( &$wgAuth ) );
- }
+if ( !is_object( $wgAuth ) ) {
+ $wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' );
+ wfRunHooks( 'AuthPluginSetup', array( &$wgAuth ) );
+}
- # Placeholders in case of DB error
- $wgTitle = null;
+# Placeholders in case of DB error
+$wgTitle = null;
- wfProfileOut( $fname . '-globals' );
-}
+$wgDeferredUpdateList = array();
+wfProfileOut( $fname . '-globals' );
wfProfileIn( $fname . '-extensions' );
# Extension setup functions for extensions other than skins
}
$ilInterwikiCodeBCP47 = wfBCP47( $ilInterwikiCode );
- $languageLinks[] = array(
+ $languageLink = array(
'href' => $languageLinkTitle->getFullURL(),
'text' => $ilLangName,
'title' => $ilTitle,
'lang' => $ilInterwikiCodeBCP47,
'hreflang' => $ilInterwikiCodeBCP47,
);
+ wfRunHooks( 'SkinTemplateGetLanguageLink', array( &$languageLink, $languageLinkTitle, $this->getTitle() ) );
+ $languageLinks[] = $languageLink;
}
}
} elseif ( !$content instanceof TextContent ) {
// non-text content
wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
- . $content->getModel() . "` which is not supported via this interface." );
+ . $content->getModel() . "` which is not supported via this interface." );
die();
} else {
// want a section?
// Translate message to code, for backwards compatability
$code = ApiBase::$messageMap[$code]['code'];
}
+
return array( $code, $msg->inLanguage( 'en' )->useDatabase( false )->plain() );
}
self::addValues( $result, $this->getSpecialTitles(), 'special', 'title' );
}
if ( in_array( "missingIds", $invalidChecks ) ) {
- self::addValues( $result, $this->getMissingPageIDs(), 'missing', 'pageid' );
+ self::addValues( $result, $this->getMissingPageIDs(), 'missing', 'pageid' );
}
if ( in_array( "missingRevIds", $invalidChecks ) ) {
self::addValues( $result, $this->getMissingRevisionIDs(), 'missing', 'revid' );
if ( in_array( "interwikiTitles", $invalidChecks ) ) {
self::addValues( $result, $this->getInterwikiTitlesAsResult() );
}
+
return $result;
}
}
$expiryarray[$p[0]] = $exp;
}
- $resultProtections[] = array( $p[0] => $protections[$p[0]],
- 'expiry' => ( $expiryarray[$p[0]] == $db->getInfinity() ?
- 'infinite' :
- wfTimestamp( TS_ISO_8601, $expiryarray[$p[0]] ) ) );
+ $resultProtections[] = array(
+ $p[0] => $protections[$p[0]],
+ 'expiry' => ( $expiryarray[$p[0]] == $db->getInfinity()
+ ? 'infinite'
+ : wfTimestamp( TS_ISO_8601, $expiryarray[$p[0]] )
+ )
+ );
}
$cascade = $params['cascade'];
// prefix.
$this->dieUsageMsg( array( 'invalidtitle', $titlePart ) );
}
+
return substr( $t->getDbKey(), 0, -1 );
}
$this->setContinueEnumParameter( 'continue',
$params['continue'] !== null ? $params['continue'] : '0|0'
);
+
return;
}
}
// of anoncontributors
$this->setContinueEnumParameter( 'continue', $continuePages );
}
+
return;
}
} elseif ( $params['excluderights'] ) {
// We've reached the one extra which shows that
// there are additional pages to be had. Stop here...
$this->setContinueEnumParameter( 'continue', $row->page . '|' . $row->user );
+
return;
}
);
if ( !$fit ) {
$this->setContinueEnumParameter( 'continue', $row->page . '|' . $row->user );
+
return;
}
}
);
}
-
public function getDescription() {
return 'Get the list of logged-in contributors and ' .
'the count of anonymous contributors to a page';
protected function getInitialisedRepoGroup() {
$repoGroup = RepoGroup::singleton();
$repoGroup->initialiseRepos();
+
return $repoGroup;
}
$vcsVersion = $gitInfo->getHeadSHA1();
if ( $vcsVersion !== false ) {
$ret['vcs-system'] = 'git';
- $ret['vcs-version'] = $vcsVersion;
+ $ret['vcs-version'] = $vcsVersion;
$ret['vcs-url'] = $gitInfo->getHeadViewUrl();
$ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $gitInfo->getHeadCommitDate() );
} else {
$this->getResult()->setIndexedTagName( $warnings, 'w' );
$ret['warnings'] = $warnings;
}
+
return $ret;
}
$message['rendered'] = $msg->useDatabase( false )->inLanguage( 'en' )->plain();
$ret[] = $message;
}
+
return $ret;
}
if ( $compatibilityMode ) {
$this->dieStatus( $status );
}
- $res['error'] = $this->getErrorFromStatus( $status );
+ $res['error'] = $this->getErrorFromStatus( $status );
}
+
return $res;
}
-
/**
* Get a cached instance of an ApiPageSet object
* @return ApiPageSet
if ( $this->mPageSet === null ) {
$this->mPageSet = new ApiPageSet( $this );
}
+
return $this->mPageSet;
}
if ( $flags ) {
$result += $this->getPageSet()->getFinalParams( $flags );
}
+
return $result;
}
public function getParamDescription() {
$psModule = $this->getPageSet();
+
return $psModule->getParamDescription() + array(
'title' => 'The page to (un)watch. use titles instead',
'unwatch' => 'If set the page will be unwatched rather than watched',
unset( $data[$key] );
}
}
+
// The JSON format only supports messages, none of the other variables, so wrap the data
return array( 'messages' => $data );
}
public function endRecentChangesList() {
$out = $this->rclistOpen ? "</ul>\n" : '';
$out .= '</div>';
+
return $out;
}
*
* @file
*/
+
class OldChangesList extends ChangesList {
/**
* Format a line using the old system (aka without any javascript).
*
* @file
*/
+
class RCCacheEntry extends RecentChange {
public $curlink;
public $difflink;
*
* @since 1.23
*/
-
abstract class Config {
-
/**
* @param string $name configuration variable name without prefix
* @param string $prefix of the variable name
*/
public function set( $name, $value, $prefix = 'wg' ) {
$GLOBALS[$prefix . $name] = $value;
+
return Status::newGood();
}
}
*/
public function getRedirectTarget() {
list( $title, ) = $this->getRedirectTargetAndText();
+
return $title;
}
if ( $this->config === null ) {
$this->config = Config::factory();
}
+
return $this->config;
}
* @param string $delTable The table to delete from.
* @param string $joinTable The other table.
* @param string $delVar The variable to join on, in the first table.
- * @param string$joinVar The variable to join on, in the second table.
+ * @param string $joinVar The variable to join on, in the second table.
* @param array $conds Condition array of field names mapped to variables,
* ANDed together in the WHERE clause
* @param string $fname Calling function name (use __METHOD__) for logs/profiling
*/
protected function mysqlFieldType( $res, $n ) {
$field = $res->fetch_field_direct( $n );
+
return $field->type;
}
$job = new RefreshLinksJob(
$title,
array(
- 'table' => $table,
+ 'table' => $table,
'recursive' => true,
) + Job::newRootJobParams( // "overall" refresh links job info
"refreshlinks:{$table}:{$title->getPrefixedText()}"
*/
protected $mReducedLineNumbers = false;
- /** @var string Link to action=markpatrolled */
+ /** @var string Link to action=markpatrolled */
protected $mMarkPatrolledLink = null;
/** @var bool Show rev_deleted content if allowed */
$limit = 100; // use diff-multi-manyusers if too many users
$users = $this->mNewPage->getAuthorsBetween( $oldRev, $newRev, $limit );
$numUsers = count( $users );
- if( $numUsers == 1 && $users[0] == $newRev->getRawUserText() ) {
+
+ if ( $numUsers == 1 && $users[0] == $newRev->getRawUserText() ) {
$numUsers = 0; // special case to say "by the same user" instead of "by one other user"
}
/** @var string Path to file */
protected $path;
- /** @var string File SHA-1 in base 36 */
+ /** @var string File SHA-1 in base 36 */
protected $sha1Base36;
/**
protected $fileJournal;
/** Flags for supported features */
- const ATTR_HEADERS = 1;
+ const ATTR_HEADERS = 1;
const ATTR_METADATA = 2;
/**
*/
protected $backends = array();
- /** @var int Index of master backend */
+ /** @var int Index of master backend */
protected $masterIndex = -1;
/** @var int Bitfield */
public function getFileXAttributes( array $params ) {
$realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
return $this->backends[$this->masterIndex]->getFileXAttributes( $realParams );
}
wfProfileOut( __METHOD__ . '-miss-' . $this->name );
wfProfileOut( __METHOD__ . '-miss' );
$this->cheapCache->set( $path, 'xattr', array( 'map' => $fields, 'latest' => $latest ) );
+
return $fields;
}
*/
final protected static function normalizeXAttributes( array $xattr ) {
$newXAttr = array( 'headers' => array(), 'metadata' => array() );
+
foreach ( $xattr['headers'] as $name => $value ) {
$newXAttr['headers'][strtolower( $name )] = $value;
}
+
foreach ( $xattr['metadata'] as $name => $value ) {
$newXAttr['metadata'][strtolower( $name )] = $value;
}
+
return $newXAttr;
}
$n = count( $performOps );
if ( $n > self::MAX_BATCH_SIZE ) {
$status->fatal( 'backend-fail-batchsize', $n, self::MAX_BATCH_SIZE );
+
return $status;
}
$dst = $this->resolveHashKey( $params['dst'] );
if ( $dst === null ) {
$status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
return $status;
}
$this->files[$dst] = array(
- 'data' => $params['content'],
+ 'data' => $params['content'],
'mtime' => wfTimestamp( TS_MW, time() )
);
$dst = $this->resolveHashKey( $params['dst'] );
if ( $dst === null ) {
$status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
return $status;
}
wfRestoreWarnings();
if ( $data === false ) { // source doesn't exist?
$status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
+
return $status;
}
$this->files[$dst] = array(
- 'data' => $data,
+ 'data' => $data,
'mtime' => wfTimestamp( TS_MW, time() )
);
$src = $this->resolveHashKey( $params['src'] );
if ( $src === null ) {
$status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
return $status;
}
$dst = $this->resolveHashKey( $params['dst'] );
if ( $dst === null ) {
$status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
return $status;
}
if ( empty( $params['ignoreMissingSource'] ) ) {
$status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
}
+
return $status;
}
$this->files[$dst] = array(
- 'data' => $this->files[$src]['data'],
+ 'data' => $this->files[$src]['data'],
'mtime' => wfTimestamp( TS_MW, time() )
);
$src = $this->resolveHashKey( $params['src'] );
if ( $src === null ) {
$status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
return $status;
}
if ( empty( $params['ignoreMissingSource'] ) ) {
$status->fatal( 'backend-fail-delete', $params['src'] );
}
+
return $status;
}
if ( isset( $this->files[$src] ) ) {
return array(
'mtime' => $this->files[$src]['mtime'],
- 'size' => strlen( $this->files[$src]['data'] ),
+ 'size' => strlen( $this->files[$src]['data'] ),
);
}
}
$tmpFiles[$srcPath] = $fsFile;
}
+
return $tmpFiles;
}
$src = $this->resolveHashKey( $params['src'] );
if ( $src === null || !isset( $this->files[$src] ) ) {
$status->fatal( 'backend-fail-stream', $params['src'] );
+
return $status;
}
return true;
}
}
+
return false;
}
}
}
}
+
return array_keys( $dirs );
}
$files[] = $relPath;
}
}
+
return $files;
}
if ( $relPath === null ) {
return null; // invalid
}
+
return ( $relPath !== '' ) ? "$fullCont/$relPath" : $fullCont;
}
}
$headers = array();
// Normalize casing, and strip out illegal headers
- if ( isset( $params['headers'] ) ) {
+ if ( isset( $params['headers'] ) ) {
foreach ( $params['headers'] as $name => $value ) {
$name = strtolower( $name );
if ( preg_match( '/^content-(type|length)$/', $name ) ) {
$contentType = $this->getContentType( $params['dst'], $params['content'], null );
$reqs = array( array(
- 'method' => 'PUT',
- 'url' => array( $dstCont, $dstRel ),
+ 'method' => 'PUT',
+ 'url' => array( $dstCont, $dstRel ),
'headers' => array(
- 'content-length' => strlen( $params['content'] ),
- 'etag' => md5( $params['content'] ),
- 'content-type' => $contentType,
+ 'content-length' => strlen( $params['content'] ),
+ 'etag' => md5( $params['content'] ),
+ 'content-type' => $contentType,
'x-object-meta-sha1base36' => $sha1Hash
) + $this->sanitizeHdrs( $params ),
- 'body' => $params['content']
+ 'body' => $params['content']
) );
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
}
$reqs = array( array(
- 'method' => 'PUT',
- 'url' => array( $dstCont, $dstRel ),
+ 'method' => 'PUT',
+ 'url' => array( $dstCont, $dstRel ),
'headers' => array(
- 'content-length' => filesize( $params['src'] ),
- 'etag' => md5_file( $params['src'] ),
- 'content-type' => $contentType,
+ 'content-length' => filesize( $params['src'] ),
+ 'etag' => md5_file( $params['src'] ),
+ 'content-type' => $contentType,
'x-object-meta-sha1base36' => $sha1Hash
) + $this->sanitizeHdrs( $params ),
- 'body' => $handle // resource
+ 'body' => $handle // resource
) );
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
}
$reqs = array( array(
- 'method' => 'PUT',
- 'url' => array( $dstCont, $dstRel ),
+ 'method' => 'PUT',
+ 'url' => array( $dstCont, $dstRel ),
'headers' => array(
'x-copy-from' => '/' . rawurlencode( $srcCont ) .
'/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 201 ) {
// good
$reqs = array(
array(
- 'method' => 'PUT',
- 'url' => array( $dstCont, $dstRel ),
+ 'method' => 'PUT',
+ 'url' => array( $dstCont, $dstRel ),
'headers' => array(
'x-copy-from' => '/' . rawurlencode( $srcCont ) .
'/' . str_replace( "%2F", "/", rawurlencode( $srcRel ) )
);
if ( "{$srcCont}/{$srcRel}" !== "{$dstCont}/{$dstRel}" ) {
$reqs[] = array(
- 'method' => 'DELETE',
- 'url' => array( $srcCont, $srcRel ),
+ 'method' => 'DELETE',
+ 'url' => array( $srcCont, $srcRel ),
'headers' => array()
);
}
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $request['method'] === 'PUT' && $rcode === 201 ) {
// good
return $status;
}
- $reqs = array(
- array(
- 'method' => 'DELETE',
- 'url' => array( $srcCont, $srcRel ),
- 'headers' => array()
+ $reqs = array( array(
+ 'method' => 'DELETE',
+ 'url' => array( $srcCont, $srcRel ),
+ 'headers' => array()
) );
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 204 ) {
// good
$customHdrs = $this->sanitizeHdrs( $params ) + $stat['xattr']['headers'];
$reqs = array( array(
- 'method' => 'POST',
- 'url' => array( $srcCont, $srcRel ),
+ 'method' => 'POST',
+ 'url' => array( $srcCont, $srcRel ),
'headers' => $metaHdrs + $customHdrs
) );
$be = $this;
$method = __METHOD__;
- $handler = function( array $request, Status $status ) use ( $be, $method, $params ) {
+ $handler = function ( array $request, Status $status ) use ( $be, $method, $params ) {
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $request['response'];
if ( $rcode === 202 ) {
// good
return $status; // already there
} elseif ( $stat === null ) {
$status->fatal( 'backend-fail-internal', $this->name );
+
return $status;
}
return $status; // ok, nothing to do
} elseif ( !is_array( $stat ) ) {
$status->fatal( 'backend-fail-internal', $this->name );
+
return $status;
}
// (b) Check the file
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'HEAD',
- 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+ 'method' => 'HEAD',
+ 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
'headers' => $this->authTokenHeaders( $auth ) + $this->headersFromParams( $params )
) );
if ( $rcode === 200 || $rcode === 204 ) {
// Convert various random Swift dates to TS_MW
'mtime' => $this->convertSwiftDate( $rhdrs['last-modified'], TS_MW ),
// Empty objects actually return no content-length header in Ceph
- 'size' => isset( $rhdrs['content-length'] ) ? (int)$rhdrs['content-length'] : 0,
- 'sha1' => $rhdrs[ 'x-object-meta-sha1base36'],
- 'md5' => ctype_xdigit( $rhdrs['etag'] ) ? $rhdrs['etag'] : null,
+ 'size' => isset( $rhdrs['content-length'] ) ? (int)$rhdrs['content-length'] : 0,
+ 'sha1' => $rhdrs['x-object-meta-sha1base36'],
+ 'md5' => ctype_xdigit( $rhdrs['etag'] ) ? $rhdrs['etag'] : null,
'xattr' => array( 'metadata' => $metadata, 'headers' => $headers )
);
} elseif ( $rcode === 404 ) {
protected function convertSwiftDate( $ts, $format = TS_MW ) {
try {
$timestamp = new MWTimestamp( $ts );
+
return $timestamp->getTimestamp( $format );
} catch ( MWException $e ) {
throw new FileBackendError( $e->getMessage() );
$auth = $this->getAuthentication();
if ( !$auth ) {
$objHdrs['x-object-meta-sha1base36'] = false;
+
return $objHdrs; // failed
}
$objHdrs['x-object-meta-sha1base36'] = $hash;
list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $path );
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'POST',
- 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+ 'method' => 'POST',
+ 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
'headers' => $this->authTokenHeaders( $auth ) + $objHdrs
) );
if ( $rcode >= 200 && $rcode <= 299 ) {
$handle = fopen( 'php://temp', 'wb' );
if ( $handle ) {
$reqs[$path] = array(
- 'method' => 'GET',
- 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+ 'method' => 'GET',
+ 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
'headers' => $this->authTokenHeaders( $auth )
+ $this->headersFromParams( $params ),
- 'stream' => $handle,
+ 'stream' => $handle,
);
} else {
$data = false;
if ( $status->isOk() ) {
return ( count( $status->value ) );
}
+
return null; // error
}
$dirs[] = $object; // directories end in '/'
}
}
- // Recursive: list all dirs under $dir and its subdirs
} else {
- $getParentDir = function( $path ) {
+ // Recursive: list all dirs under $dir and its subdirs
+ $getParentDir = function ( $path ) {
return ( strpos( $path, '/' ) !== false ) ? dirname( $path ) : false;
};
+
// Get directory from last item of prior page
$lastDir = $getParentDir( $after ); // must be first page
$status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
+
if ( !$status->isOk() ) {
return $dirs; // error
}
+
$objects = $status->value;
+
foreach ( $objects as $object ) { // files
$objectDir = $getParentDir( $object ); // directory of object
+
if ( $objectDir !== false && $objectDir !== $dir ) {
// Swift stores paths in UTF-8, using binary sorting.
// See function "create_container_table" in common/db.py.
} else {
$status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
}
- // Recursive: list all files under $dir and its subdirs
} else {
+ // Recursive: list all files under $dir and its subdirs
if ( !empty( $params['adviseStat'] ) ) {
$status = $this->objectListing( $fullCont, 'info', $limit, $after, $prefix );
} else {
$status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
}
}
+
// Reformat this list into a list of (name, stat array or null) entries
if ( !$status->isOk() ) {
return $files; // error
}
+
$objects = $status->value;
$files = $this->buildFileObjectListing( $params, $dir, $objects );
+
// Page on the unfiltered object listing (what is returned may be filtered)
if ( count( $objects ) < $limit ) {
$after = INF; // avoid a second RTT
}
$stat = array(
// Convert various random Swift dates to TS_MW
- 'mtime' => $this->convertSwiftDate( $object->last_modified, TS_MW ),
- 'size' => (int)$object->bytes,
- 'md5' => ctype_xdigit( $object->hash ) ? $object->hash : null,
+ 'mtime' => $this->convertSwiftDate( $object->last_modified, TS_MW ),
+ 'size' => (int)$object->bytes,
+ 'md5' => ctype_xdigit( $object->hash ) ? $object->hash : null,
'latest' => false // eventually consistent
);
$names[] = array( $object->name, $stat );
$this->clearCache( array( $params['src'] ) );
$stat = $this->getFileStat( $params );
}
+
return $stat['xattr'];
} else {
return false;
$auth = $this->getAuthentication();
if ( !$auth || !is_array( $this->getContainerStat( $srcCont ) ) ) {
$status->fatal( 'backend-fail-stream', $params['src'] );
+
return $status;
}
$handle = fopen( 'php://output', 'wb' );
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'GET',
- 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+ 'method' => 'GET',
+ 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
'headers' => $this->authTokenHeaders( $auth )
+ $this->headersFromParams( $params ),
- 'stream' => $handle,
+ 'stream' => $handle,
) );
if ( $rcode >= 200 && $rcode <= 299 ) {
$handle = fopen( $tmpFile->getPath(), 'wb' );
if ( $handle ) {
$reqs[$path] = array(
- 'method' => 'GET',
- 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
+ 'method' => 'GET',
+ 'url' => $this->storageUrl( $auth, $srcCont, $srcRel ),
'headers' => $this->authTokenHeaders( $auth )
+ $this->headersFromParams( $params ),
- 'stream' => $handle,
+ 'stream' => $handle,
);
} else {
$tmpFile = null;
"GET\n{$expires}\n{$contPath}/{$srcRel}",
$this->swiftTempUrlKey
);
+
return "{$url}?temp_url_sig={$signature}&temp_url_expires={$expires}";
} else { // give S3 API URL for rgw
// Path for signature starts with the bucket
foreach ( $fileOpHandles as $index => $fileOpHandle ) {
$statuses[$index] = Status::newFatal( 'backend-fail-connect', $this->name );
}
+
return $statuses;
}
*/
protected function setContainerAccess( $container, array $readGrps, array $writeGrps ) {
$status = Status::newGood();
-
$auth = $this->getAuthentication();
+
if ( !$auth ) {
$status->fatal( 'backend-fail-connect', $this->name );
+
return $status;
}
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'POST',
- 'url' => $this->storageUrl( $auth, $container ),
+ 'method' => 'POST',
+ 'url' => $this->storageUrl( $auth, $container ),
'headers' => $this->authTokenHeaders( $auth ) + array(
- 'x-container-read' => implode( ',', $readGrps ),
+ 'x-container-read' => implode( ',', $readGrps ),
'x-container-write' => implode( ',', $writeGrps )
)
) );
}
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'HEAD',
- 'url' => $this->storageUrl( $auth, $container ),
+ 'method' => 'HEAD',
+ 'url' => $this->storageUrl( $auth, $container ),
'headers' => $this->authTokenHeaders( $auth )
) );
} else {
$this->onError( null, __METHOD__,
array( 'cont' => $container ), $rerr, $rcode, $rdesc );
+
return null;
}
}
$auth = $this->getAuthentication();
if ( !$auth ) {
$status->fatal( 'backend-fail-connect', $this->name );
+
return $status;
}
$writeGrps = array( $this->swiftUser ); // sanity
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'PUT',
- 'url' => $this->storageUrl( $auth, $container ),
+ 'method' => 'PUT',
+ 'url' => $this->storageUrl( $auth, $container ),
'headers' => $this->authTokenHeaders( $auth ) + array(
- 'x-container-read' => implode( ',', $readGrps ),
+ 'x-container-read' => implode( ',', $readGrps ),
'x-container-write' => implode( ',', $writeGrps )
)
) );
$auth = $this->getAuthentication();
if ( !$auth ) {
$status->fatal( 'backend-fail-connect', $this->name );
+
return $status;
}
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'DELETE',
- 'url' => $this->storageUrl( $auth, $container ),
+ 'method' => 'DELETE',
+ 'url' => $this->storageUrl( $auth, $container ),
'headers' => $this->authTokenHeaders( $auth )
) );
$auth = $this->getAuthentication();
if ( !$auth ) {
$status->fatal( 'backend-fail-connect', $this->name );
+
return $status;
}
}
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'GET',
- 'url' => $this->storageUrl( $auth, $fullCont ),
- 'query' => $query,
+ 'method' => 'GET',
+ 'url' => $this->storageUrl( $auth, $fullCont ),
+ 'query' => $query,
'headers' => $this->authTokenHeaders( $auth )
) );
$this->authSessionTimestamp = time() - ceil( $this->authTTL / 2 );
} else { // cache miss
list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
- 'method' => 'GET',
- 'url' => "{$this->swiftAuthUrl}/v1.0",
+ 'method' => 'GET',
+ 'url' => "{$this->swiftAuthUrl}/v1.0",
'headers' => array(
- 'x-auth-user' => $this->swiftUser, 'x-auth-key' => $this->swiftKey )
+ 'x-auth-user' => $this->swiftUser,
+ 'x-auth-key' => $this->swiftKey
+ )
) );
if ( $rcode >= 200 && $rcode <= 299 ) { // OK
$this->authCreds = array(
- 'auth_token' => $rhdrs['x-auth-token'],
+ 'auth_token' => $rhdrs['x-auth-token'],
'storage_url' => $rhdrs['x-storage-url']
);
$this->authSessionTimestamp = time();
} elseif ( $rcode === 401 ) {
$this->onError( null, __METHOD__, array(), "Authentication failed.", $rcode );
$this->authErrorTimestamp = time();
+
return null;
} else {
$this->onError( null, __METHOD__, array(), "HTTP return code: $rcode", $rcode );
$this->authErrorTimestamp = time();
+
return null;
}
}
}
+
return $this->authCreds;
}
if ( strlen( $object ) ) {
$parts[] = str_replace( "%2F", "/", rawurlencode( $object ) );
}
+
return implode( '/', $parts );
}
foreach ( $this->srvsByBucket[$bucket] as $lockSrv ) {
if ( !$this->isServerUp( $lockSrv ) ) {
$status->warning( 'lockmanager-fail-svr-release', $lockSrv );
- // Attempt to release the lock on this peer
} else {
+ // Attempt to release the lock on this peer
$status->merge( $this->freeLocksOnServer( $lockSrv, $pathsByType ) );
++$yesVotes; // success for this peer
// Normally the first peers form the quorum, and the others are ignored.
/** @var Array Map of zones to config */
protected $zones = array();
- /** @var string URL of thumb.php */
+ /** @var string URL of thumb.php */
protected $thumbScriptUrl;
/** @var bool Whether to skip media file transformation on parse and rely
*/
protected $abbrvThreshold;
- /** @var string The URL of the repo's favicon, if any */
+ /** @var string The URL of the repo's favicon, if any */
protected $favicon;
/**
$searchName = File::normalizeTitle( $title )->getDBkey(); // must be valid
if ( $flags & self::NAME_AND_TIME_ONLY ) {
$result[$searchName] = array(
- 'title' => $file->getTitle()->getDBkey(),
+ 'title' => $file->getTitle()->getDBkey(),
'timestamp' => $file->getTimestamp()
);
} else {
/** @var int Redownload thumbnail files after a month (86400*30) */
protected $fileCacheExpiry = 2592000;
- /** @var array */
+ /** @var array */
protected $mFileExists = array();
- /** @var array */
+ /** @var array */
private $mQueryCache = array();
/**
}
}
- $fileMatchesSearch = function( File $file, array $search ) {
+ $fileMatchesSearch = function ( File $file, array $search ) {
// Note: file name comparison done elsewhere (to handle redirects)
$user = ( !empty( $search['private'] ) && $search['private'] instanceof User )
? $search['private']
: null;
+
return (
$file->exists() &&
(
};
$repo = $this;
- $applyMatchingFiles = function( ResultWrapper $res, &$searchSet, &$finalFiles )
+ $applyMatchingFiles = function ( ResultWrapper $res, &$searchSet, &$finalFiles )
use ( $repo, $fileMatchesSearch, $flags )
{
global $wgContLang;
$dbKeysLook[] = $wgContLang->lcfirst( $file->getName() );
}
foreach ( $dbKeysLook as $dbKey ) {
- if ( isset( $searchSet[$dbKey])
+ if ( isset( $searchSet[$dbKey] )
&& $fileMatchesSearch( $file, $searchSet[$dbKey] )
) {
$finalFiles[$dbKey] = ( $flags & FileRepo::NAME_AND_TIME_ONLY )
foreach ( array_keys( $searchSet ) as $dbKey ) {
$imgNames[] = $this->getNameFromTitle( File::normalizeTitle( $dbKey ) );
}
+
if ( count( $imgNames ) ) {
$res = $dbr->select( 'image',
LocalFile::selectFields(), array( 'img_name' => $imgNames ), __METHOD__ );
);
}
}
+
if ( count( $oiConds ) ) {
$res = $dbr->select( 'oldimage',
OldLocalFile::selectFields(), $dbr->makeList( $oiConds, LIST_OR ), __METHOD__ );
if ( !empty( $search['ignoreRedirect'] ) ) {
continue;
}
+
$title = File::normalizeTitle( $dbKey );
$redir = $this->checkRedirect( $title ); // hopefully hits memcached
+
if ( $redir && $redir->getNamespace() == NS_FILE ) {
$file = $this->newFile( $redir );
if ( $file && $fileMatchesSearch( $file, $search ) ) {
$file->redirectedFrom( $title->getDBkey() );
if ( $flags & FileRepo::NAME_AND_TIME_ONLY ) {
$finalFiles[$dbKey] = array(
- 'title' => $file->getTitle()->getDBkey(),
+ 'title' => $file->getTitle()->getDBkey(),
'timestamp' => $file->getTimestamp()
);
} else {
*/
function getInfo() {
global $wgFavicon;
+
return array_merge( parent::getInfo(), array(
'favicon' => wfExpandUrl( $wgFavicon ),
) );
/** @var array */
protected $foreignInfo;
- /** @var ProcessCacheLRU */
+ /** @var ProcessCacheLRU */
protected $cache;
/** @var RepoGroup */
}
throw new MWException( "Unknown type '$type'." );
-
}
/**
/** @var Title|string|bool */
protected $title;
- /** @var string Text of last error */
+ /** @var string Text of last error */
protected $lastError;
- /** @var string Main part of the title, with underscores (Title::getDBkey) */
+ /** @var string Main part of the title, with underscores (Title::getDBkey) */
protected $redirected;
/** @var Title */
if ( !$handler ) {
return false;
}
+
return $handler->getCommonMetaArray( $this );
}
$this->assertRepoDefined();
return $this->repo->getZonePath( 'thumb' ) . '/' .
- $this->getArchiveThumbRel( $archiveName, $suffix );
+ $this->getArchiveThumbRel( $archiveName, $suffix );
}
/**
/** @var array List of file IDs to restore */
private $ids;
- /** @var bool Add all revisions of the file */
+ /** @var bool Add all revisions of the file */
private $all;
- /** @var bool Wether to remove all settings for suppressed fields */
+ /** @var bool Wether to remove all settings for suppressed fields */
private $unsuppress = false;
/**
/** @var Title */
protected $target;
- /** @var */
protected $cur;
- /** @var */
protected $olds;
- /** @var */
protected $oldCount;
- /** @var */
protected $archive;
/** @var DatabaseBase */
* @ingroup FileAbstraction
*/
class UnregisteredLocalFile extends File {
- /** @var Title */
+ /** @var Title */
protected $title;
/** @var string */
* @ingroup Media
*/
abstract class ImageGalleryBase extends ContextSource {
- /** @var array Gallery images */
+ /** @var array Gallery images */
protected $mImages;
- /** @var bool Whether to show the filesize in bytes in categories */
+ /** @var bool Whether to show the filesize in bytes in categories */
protected $mShowBytes;
/** @var bool Whether to show the filename. Default: true */
* @param string $html Additional HTML text to be shown. The name and size
* of the image are always shown.
* @param string $alt Alt text for the image
- * @param string $link Override image link (optional)
+ * @param string $link Override image link (optional)
* @param array $handlerOpts Array of options for image handler (aka page number)
*/
function insert( $title, $html = '', $alt = '', $link = '', $handlerOpts = array() ) {
$ret = array();
- foreach( $list as $key ) {
+ foreach ( $list as $key ) {
if ( in_array( $key, $boolAttribs ) ) {
if ( !empty( $this->mParams[$key] ) ) {
$ret[$key] = '';
if ( !$status->isOK() ) {
return $status;
}
- $status->value->insert( 'site_stats', array(
- 'ss_row_id' => 1,
- 'ss_total_views' => 0,
- 'ss_total_edits' => 0,
- 'ss_good_articles' => 0,
- 'ss_total_pages' => 0,
- 'ss_users' => 0,
- 'ss_images' => 0 ),
- __METHOD__, 'IGNORE' );
+ $status->value->insert(
+ 'site_stats',
+ array(
+ 'ss_row_id' => 1,
+ 'ss_total_views' => 0,
+ 'ss_total_edits' => 0,
+ 'ss_good_articles' => 0,
+ 'ss_total_pages' => 0,
+ 'ss_users' => 0,
+ 'ss_images' => 0
+ ),
+ __METHOD__, 'IGNORE'
+ );
return Status::newGood();
}
}
if ( $this->groupPermissions['*']['edit'] === false
&& $this->groupPermissions['*']['createaccount'] === false
- && $this->groupPermissions['*']['read'] !== false ) {
+ && $this->groupPermissions['*']['read'] !== false
+ ) {
$noFollow = "\n# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
. "# the general public and wish to apply nofollow to external links as a\n"
. "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
'patch-ufg_group-length-increase-255.sql' ),
//1.23
- array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
- array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
+ array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
+ array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
// KEEP THIS AT THE BOTTOM!!
array( 'doRebuildDuplicateFunction' ),
* @ingroup Deployment
* @since 1.17
*/
-
class PostgresUpdater extends DatabaseUpdater {
/**
array( 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ),
array( 'addIndex', 'logging', 'log_user_text_type_time',
'patch-logging_user_text_type_time_index.sql' ),
- array( 'addIndex', 'logging', 'log_user_text_time', 'patch-logging_user_text_time_index.sql' ),
+ array( 'addIndex', 'logging', 'log_user_text_time', 'patch-logging_user_text_time_index.sql' ),
array( 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ),
);
}
) {
// JS appears to be the only method that works consistently with IE7+
$this->addHtml( "\n<script>jQuery( function () { document.location = " .
- Xml::encodeJsVar( $lsUrl ) . "; } );</script>\n" );
+ Xml::encodeJsVar( $lsUrl ) . "; } );</script>\n" );
} else {
$this->parent->request->response()->header( "Refresh: 0;url=$lsUrl" );
}
}
/**
- * Gets the luser provided comment
+ * Gets the user provided comment
* @return string HTML
*/
public function getComment() {
'contribslink' => 'contribs',
'emaillink' => 'send email',
'autoblocker' => 'Autoblocked because your IP address has been recently used by "[[User:$1|$1]]".
-The reason given for $1\'s block is "<em>$2</em>"',
+The reason given for $1\'s block is "$2"',
'blocklogpage' => 'Block log',
'blocklog-showlog' => 'This user has been blocked previously.
The block log is provided below for reference:',
* @author Antoine Musso <hashar@free.fr>
*/
-define( 'MW_SETUP_NO_CACHE', 1 );
-define( 'MW_SETUP_NO_CONTEXT', 1 );
require_once __DIR__ . '/Maintenance.php';
/**
* Return false if fullscreen is not supported.
*/
setupFullscreen = function () {
- if ( document.fullscreenEnabled ||
- document.mozFullScreenEnabled ||
- document.webkitFullscreenEnabled ||
- document.msFullscreenEnabled
- ) {
+ if ( $.support.fullscreen ) {
// When the fullscreen mode is changed, trigger the
// fullscreen events (and when exiting,
// also remove the fullscreen class)
return this;
}
};
+
+ $.support.fullscreen = document.fullscreenEnabled ||
+ document.webkitFullscreenEnabled ||
+ document.mozFullScreenEnabled ||
+ document.msFullscreenEnabled;
}( jQuery ) );
/**
* Add the appropriate prefix to the accesskey shown in the tooltip.
- * If the nodeList parameter is given, only those nodes are updated;
- * otherwise, all the nodes that will probably have accesskeys by
- * default are updated.
+ *
+ * If the `$nodes` parameter is given, only those nodes are updated;
+ * otherwise, depending on browser support, we update either all elements
+ * with accesskeys on the page or a bunch of elements which are likely to
+ * have them on core skins.
*
* @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
*/
updateTooltipAccessKeys: function ( $nodes ) {
if ( !$nodes ) {
- // Rather than going into a loop of all anchor tags, limit to few elements that
- // contain the relevant anchor tags.
- // Input and label are rare enough that no such optimization is needed
- $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label' );
+ if ( document.querySelectorAll ) {
+ // If we're running on a browser where we can do this efficiently,
+ // just find all elements that have accesskeys. We can't use jQuery's
+ // polyfill for the selector since looping over all elements on page
+ // load might be too slow.
+ $nodes = $( document.querySelectorAll( '[accesskey]' ) );
+ } else {
+ // Otherwise go through some elements likely to have accesskeys rather
+ // than looping over all of them. Unfortunately this will not fully
+ // work for custom skins with different HTML structures. Input, label
+ // and button should be rare enough that no optimizations are needed.
+ $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
+ }
} else if ( !( $nodes instanceof $ ) ) {
$nodes = $( $nodes );
}