--- /dev/null
+*.sh eol=lf
* $wgPasswordSenderName has been removed and is no longer functional. To set a
custom mailer name, the system message 'emailsender' should be modified
(default: "{{SITENAME}}").
-* If you customized [[MediaWiki:Enotif body]] (the text of email notifications),
+* (bug 63269) Email notifications were not correctly handling the
+ [[MediaWiki:Helppage]] message being set to a full URL (the default).
+ If you customized [[MediaWiki:Enotif body]] (the text of email notifications),
you'll need to edit it locally to include the URL via the new variable
- $HELPPAGE instead of the parser functions fullurl and canonicalurl.
+ $HELPPAGE instead of the parser functions fullurl and canonicalurl; otherwise
+ you don't have to do anything.
* $wgDBAhandler was removed as the only class using it was also removed
* The 'max threads' setting was removed from $wgDBservers.
* Support for AdminSettings.php has been completely removed. All configuration
See the file UPGRADE for more detailed upgrade instructions.
-For notes on 1.21.x and older releases, see HISTORY.
+For notes on 1.22.x and older releases, see HISTORY.
== Online documentation ==
production.
=== Configuration changes in 1.24 ===
+* The server's canonical hostname is available as $wgServerName, which is
+ exposed in both mw.config and ApiQuerySiteInfo.
=== New features in 1.24 ===
* Added a new hook, "WhatLinksHereProps", to allow extensions to annotate
WhatLinksHere entries.
+* Added a new hook, "ContentGetParserOutput", to customize parser output for
+ a given content object.
+* Deprecated the hook "ShowRawCssJs", use "ContentGetParserOutput" instead.
* HTMLForm's HTMLTextField now supports the 'url' type.
* HTMLForm fields may now be dynamically hidden based on the values of other
fields in the form.
* HTMLForm now supports multiple copies of an input field or set of input
fields, e.g. the form may request "one or more usernames" without having to
have the user enter delimited list of names into a text field.
+* Added a new hook, "SidebarBeforeOutput", to allow to edit the structure of
+ the sidebar just before its display.
=== Bug fixes in 1.24 ===
* (bug 62258) A bug was fixed in File::getUnscaledThumb when a height
which used to collapse some sidebar elements by default.
* (bug 890) Links in Special:RecentChanges and Special:Watchlist no longer
follow redirects to their target pages.
+* Parser now dies early if called recursively, instead of producing subtle bugs.
=== Web API changes in 1.24 ===
* action=parse API now supports prop=modules, which provides the list of
* CLDRPluralRuleConverter_Operator to CLDRPluralRuleConverterOperator
* CLDRPluralRuleEvaluator_Range to CLDRPluralRuleEvaluatorRange
* CSSJanus_Tokenizer to CSSJanusTokenizer
+* RevDel_ArchiveItem to RevDelArchiveItem
+* RevDel_ArchiveList to RevDelArchiveList
+* RevDel_ArchivedFileItem to RevDelArchivedFileItem
+* RevDel_ArchivedFileList to RevDelArchivedFileList
+* RevDel_ArchivedRevisionItem to RevDelArchivedRevisionItem
+* RevDel_FileItem to RevDelFileItem
+* RevDel_FileList to RevDelFileList
+* RevDel_Item to RevDelItem
+* RevDel_List to RevDelList
+* RevDel_LogItem to RevDelLogItem
+* RevDel_LogList to RevDelLogList
+* RevDel_RevisionItem to RevDelRevisionItem
+* RevDel_RevisionList to RevDelRevisionList
+
+==== Removed classes ====
+* IPBlockForm - Use SpecialBlock directly
+* WatchlistEditor - Use SpecialEditWatchlist directly
== Compatibility ==
== Upgrading ==
-1.24 has several database changes since 1.22, and will not work without schema
+1.24 has several database changes since 1.23, and will not work without schema
updates. Note that due to changes to some very large tables like the revision
table, the schema update may take quite long (minutes on a medium sized site,
many hours on a large site).
See the file UPGRADE for more detailed upgrade instructions.
-For notes on 1.21.x and older releases, see HISTORY.
+For notes on 1.22.x and older releases, see HISTORY.
== Online documentation ==
Handler functions that modify $ok should generally return false to prevent further
hooks from further modifying $ok.
+'ContentGetParserOutput': Customize parser output for a given content object,
+called by AbstractContent::getParserOutput. May be used to override the normal
+model-specific rendering of page content.
+$content: The Content to render
+$title: Title of the page, as context
+$revId: The revision ID, as context
+$options: ParserOptions for rendering. To avoid confusing the parser cache,
+the output can only depend on parameters provided to this hook function, not on global state.
+$generateHtml: boolean, indicating whether full HTML should be generated. If false,
+generation of HTML may be skipped, but other information should still be present in the
+ParserOutput object.
+&$output: ParserOutput, to manipulate or replace
+
'ConvertContent': Called by AbstractContent::convert when a conversion to another
content model is requested.
$content: The Content object to be converted.
$article: The article object corresponding to the page
'ShowRawCssJs': Customise the output of raw CSS and JavaScript in page views.
-DEPRECATED, use the ContentHandler facility to handle CSS and JavaScript!
+DEPRECATED, use the ContentGetParserOutput hook instead!
$text: Text being shown
$title: Title of the custom script/stylesheet page
$output: Current OutputPage object
&$bar: Sidebar contents
Modify $bar to add or modify sidebar portlets.
+'SidebarBeforeOutput': Allows to edit sidebar just before its output by skins.
+$skin Skin object
+&$bar: Sidebar content
+Modify $bar to add or modify sidebar portlets.
+Warning: This hook is run on each display. You should consider to use 'SkinBuildSidebar' that is aggressively cached.
+
'SkinCopyrightFooter': Allow for site and per-namespace customization of
copyright notice.
$title: displayed page title
* Show a page view for a page formatted as CSS or JavaScript. To be called by
* Article::view() only.
*
- * This is hooked by SyntaxHighlight_GeSHi to do syntax highlighting of these
- * page views.
+ * This exists mostly to serve the deprecated ShowRawCssJs hook (used to customize these views).
+ * It has been replaced by the ContentGetParserOutput hook, which lets you do the same but with
+ * more flexibility.
*
* @param bool $showCacheHint Whether to show a message telling the user
* to clear the browser cache (default: true).
'ResourceLoaderWikiModule' => 'includes/resourceloader/ResourceLoaderWikiModule.php',
# includes/revisiondelete
- 'RevDel_ArchivedFileItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_ArchivedFileList' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_ArchivedRevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_ArchiveItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_ArchiveList' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_FileItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_FileList' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_Item' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
- 'RevDel_List' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
- 'RevDel_LogItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_LogList' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_RevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
- 'RevDel_RevisionList' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelArchivedFileItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelArchivedFileList' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelArchivedRevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelArchiveItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelArchiveList' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelFileItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelFileList' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelItem' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
+ 'RevDelList' => 'includes/revisiondelete/RevisionDeleteAbstracts.php',
+ 'RevDelLogItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelLogList' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelRevisionItem' => 'includes/revisiondelete/RevisionDelete.php',
+ 'RevDelRevisionList' => 'includes/revisiondelete/RevisionDelete.php',
'RevisionDeleter' => 'includes/revisiondelete/RevisionDeleter.php',
'RevisionDeleteUser' => 'includes/revisiondelete/RevisionDeleteUser.php',
'HTMLBlockedUsersItemSelect' => 'includes/specials/SpecialBlockList.php',
'ImageListPager' => 'includes/specials/SpecialListfiles.php',
'ImportReporter' => 'includes/specials/SpecialImport.php',
- 'IPBlockForm' => 'includes/specials/SpecialBlock.php',
'LinkSearchPage' => 'includes/specials/SpecialLinkSearch.php',
'ListredirectsPage' => 'includes/specials/SpecialListredirects.php',
'ListDuplicatedFilesPage' => 'includes/specials/SpecialListDuplicatedFiles.php',
'WantedFilesPage' => 'includes/specials/SpecialWantedfiles.php',
'WantedPagesPage' => 'includes/specials/SpecialWantedpages.php',
'WantedTemplatesPage' => 'includes/specials/SpecialWantedtemplates.php',
- 'WatchlistEditor' => 'includes/specials/SpecialEditWatchlist.php',
'WithoutInterwikiPage' => 'includes/specials/SpecialWithoutinterwiki.php',
# includes/templates
// Verified by native speakers
'be' => array( "Ё" ),
'be-tarask' => array( "Ё" ),
+ 'cy' => array( "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ),
'en' => array(),
+ 'fa' => array( "آ", "ء", "ه" ),
'fi' => array( "Å", "Ä", "Ö" ),
+ 'fr' => array(),
'hu' => array( "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ),
+ 'is' => array( "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ),
'it' => array(),
+ 'lv' => array( "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ),
'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
'pt' => array(),
'ru' => array(),
'ca' => array(),
'co' => array(),
'cs' => array( "Č", "Ch", "Ř", "Š", "Ž" ),
- 'cy' => array( "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ),
'da' => array( "Æ", "Ø", "Å" ),
'de' => array(),
'dsb' => array( "Č", "Ć", "Dź", "Ě", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ),
'es' => array( "Ñ" ),
'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü" ),
'eu' => array( "Ñ" ),
- 'fa' => array( "آ", "ء", "ه" ),
'fo' => array( "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ),
- 'fr' => array(),
'fur' => array( "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ),
'fy' => array(),
'ga' => array(),
'gl' => array( "Ch", "Ll", "Ñ" ),
'hr' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
'hsb' => array( "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ),
- 'is' => array( "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ),
'kk' => array( "Ү", "І" ),
'kl' => array( "Æ", "Ø", "Å" ),
'ku' => array( "Ç", "Ê", "Î", "Ş", "Û" ),
'la' => array(),
'lb' => array(),
'lt' => array( "Č", "Š", "Ž" ),
- 'lv' => array( "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ),
'mk' => array(),
'mo' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
'mt' => array( "Ċ", "Ġ", "Għ", "Ħ", "Ż" ),
*/
$wgCanonicalServer = false;
+/**
+ * Server name. This is automatically computed by parsing the bare
+ * hostname out of $wgCanonicalServer. It should not be customized.
+ * @since 1.24
+ */
+$wgServerName = false;
+
/************************************************************************//**
* @name Script path settings
* @{
* @{
*/
-$serverName = substr( $wgServer, strrpos( $wgServer, '/' ) + 1 );
/**
* Site admin email address.
+ *
+ * Defaults to "wikiadmin@{$wgServerName}".
*/
-$wgEmergencyContact = 'wikiadmin@' . $serverName;
+$wgEmergencyContact = false;
/**
* Password reminder email address.
*
* The address we should use as sender when a user is requesting his password.
+ *
+ * Defaults to "apache@{$wgServerName}".
*/
-$wgPasswordSender = 'apache@' . $serverName;
-
-unset( $serverName ); # Don't leak local variables to global scope
+$wgPasswordSender = false;
/**
* Password reminder name
*/
$wgSiteNotice = '';
-/**
- * A subtitle to add to the tagline, for skins that have it/
- */
-$wgExtraSubtitle = '';
-
/**
* If this is set, a "donate" link will appear in the sidebar. Set it to a URL.
*/
* Tracking categories allow pages with certain characteristics to be tracked.
* It works by adding any such page to a category automatically.
*
+ * A message with the suffix '-desc' should be added as a description message
+ * to have extra information on Special:TrackingCategories.
+ *
* @since 1.23
*/
$wgTrackingCategories = array(
$wgGroupPermissions['user']['move'] = true;
$wgGroupPermissions['user']['move-subpages'] = true;
$wgGroupPermissions['user']['move-rootuserpages'] = true; // can move root userpages
+$wgGroupPermissions['user']['move-categorypages'] = true;
$wgGroupPermissions['user']['movefile'] = true;
$wgGroupPermissions['user']['read'] = true;
$wgGroupPermissions['user']['edit'] = true;
$wgGroupPermissions['sysop']['move'] = true;
$wgGroupPermissions['sysop']['move-subpages'] = true;
$wgGroupPermissions['sysop']['move-rootuserpages'] = true;
+$wgGroupPermissions['sysop']['move-categorypages'] = true;
$wgGroupPermissions['sysop']['patrol'] = true;
$wgGroupPermissions['sysop']['autopatrol'] = true;
$wgGroupPermissions['sysop']['protect'] = true;
*
* @param array $handlerParams Associative array of media handler parameters, to be passed
* to transform(). Typical keys are "width" and "page".
- * @param string $time Timestamp of the file, set as false for current
+ * @param string|bool $time Timestamp of the file, set as false for current
* @param string $query Query params for desc url
* @param int|null $widthOption Used by the parser to remember the user preference thumbnailsize
* @since 1.20
* Allow external reads of TTL array
*
* @param int $id
- * @return array
+ * @return int
*/
static function getCacheTTL( $id ) {
if ( array_key_exists( $id, self::$mCacheTTLs ) ) {
public static function isMovable( $index ) {
global $wgAllowImageMoving;
- $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) || $index == NS_CATEGORY );
+ $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) );
/**
* @since 1.20
/**
* Get the HTML link to the revision text.
- * Overridden by RevDel_ArchiveItem.
+ * Overridden by RevDelArchiveItem.
* @return string
*/
protected function getRevisionLink() {
/**
* Get the HTML link to the diff.
- * Overridden by RevDel_ArchiveItem
+ * Overridden by RevDelArchiveItem
* @return string
*/
protected function getDiffLink() {
}
// Set various default paths sensibly...
+
if ( $wgScript === false ) {
$wgScript = "$wgScriptPath/index$wgScriptExtension";
}
wfProfileOut( $fname . '-includes' );
wfProfileIn( $fname . '-defaults2' );
+
+if ( $wgCanonicalServer === false ) {
+ $wgCanonicalServer = wfExpandUrl( $wgServer, PROTO_HTTP );
+}
+
+// Set server name
+$serverParts = wfParseUrl( $wgCanonicalServer );
+if ( $wgServerName !== false ) {
+ wfWarn( '$wgServerName should be derived from $wgCanonicalServer, not customized. Overwriting $wgServerName.' );
+}
+$wgServerName = $serverParts['host'];
+unset( $serverParts );
+
+// Set defaults for configuration variables
+// that are derived from the server name by default
+if ( $wgEmergencyContact === false ) {
+ $wgEmergencyContact = 'wikiadmin@' . $wgServerName;
+}
+
+if ( $wgPasswordSender === false ) {
+ $wgPasswordSender = 'apache@' . $wgServerName;
+}
+
if ( $wgSecureLogin && substr( $wgServer, 0, 2 ) !== '//' ) {
$wgSecureLogin = false;
wfWarn( 'Secure login was enabled on a server that only supports HTTP or HTTPS. Disabling secure login.' );
wfProfileOut( $fname . '-tempDir' );
}
-if ( $wgCanonicalServer === false ) {
- $wgCanonicalServer = wfExpandUrl( $wgServer, PROTO_HTTP );
-}
-
// $wgHTCPMulticastRouting got renamed to $wgHTCPRouting in MediaWiki 1.22
// ensure back compatibility.
if ( !$wgHTCPRouting && $wgHTCPMulticastRouting ) {
if ( $wgEnableSidebarCache ) {
$cachedsidebar = $wgMemc->get( $key );
if ( $cachedsidebar ) {
+ wfRunHooks( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
+
wfProfileOut( __METHOD__ );
return $cachedsidebar;
}
$wgMemc->set( $key, $bar, $wgSidebarCacheExpiry );
}
+ wfRunHooks( 'SidebarBeforeOutput', array( $this, &$bar ) );
+
wfProfileOut( __METHOD__ );
return $bar;
}
*/
function makeListItem( $key, $item, $options = array() ) {
if ( isset( $item['links'] ) ) {
- $html = '';
+ $links = array();
foreach ( $item['links'] as $linkKey => $link ) {
- $html .= $this->makeLink( $linkKey, $link, $options );
+ $links[] = $this->makeLink( $linkKey, $link, $options );
}
+ $html = implode( ' ', $links );
} else {
$link = $item;
// These keys are used by makeListItem and shouldn't be passed on to the link
}
return $t;
} else {
- $ret = null;
- return $ret;
+ return null;
}
}
$errors[] = array( 'movenotallowedfile' );
}
+ // Check if user is allowed to move category pages if it's a category page
+ if ( $this->mNamespace == NS_CATEGORY && !$user->isAllowed( 'move-categorypages' ) ) {
+ $errors[] = array( 'cant-move-category-page' );
+ }
+
if ( !$user->isAllowed( 'move' ) ) {
// User can't move anything
$userCanMove = User::groupHasPermission( 'user', 'move' );
&& $this->mNamespace == NS_USER && !$this->isSubpage() ) {
// Show user page-specific message only if the user can move other pages
$errors[] = array( 'cant-move-to-user-page' );
+ } elseif ( !$user->isAllowed( 'move-categorypages' )
+ && $this->mNamespace == NS_CATEGORY ) {
+ // Show category page-specific message only if the user can move other pages
+ $errors[] = array( 'cant-move-to-category-page' );
}
} elseif ( !$user->isAllowed( $action ) ) {
$errors[] = $this->missingPermissionError( $action, $short );
}
if ( $createRedirect ) {
- $contentHandler = ContentHandler::getForTitle( $this );
- $redirectContent = $contentHandler->makeRedirectContent( $nt,
- wfMessage( 'move-redirect-text' )->inContentLanguage()->plain() );
+ if ( $this->getNamespace() == NS_CATEGORY && !wfMessage( 'category-move-redirect-override' )->isDisabled() ) {
+ $redirectContent = new WikitextContent(
+ wfMessage( 'category-move-redirect-override' )->params( $nt->getPrefixedText() )->inContentLanguage()->plain() );
+ } else {
+ $contentHandler = ContentHandler::getForTitle( $this );
+ $redirectContent = $contentHandler->makeRedirectContent( $nt,
+ wfMessage( 'move-redirect-text' )->inContentLanguage()->plain() );
+ }
// NOTE: If this page's content model does not support redirects, $redirectContent will be null.
} else {
'minoredit',
'move',
'movefile',
+ 'move-categorypages',
'move-rootuserpages',
'move-subpages',
'nominornewtalk',
if ( $this->address ) {
if ( $this->name != '' && !wfIsWindows() ) {
global $wgEnotifUseRealName;
- $name = ( $wgEnotifUseRealName && $this->realName ) ? $this->realName : $this->name;
+ $name = ( $wgEnotifUseRealName && $this->realName !== '' ) ? $this->realName : $this->name;
$quoted = UserMailer::quotedPrintable( $name );
if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) {
$quoted = '"' . $quoted . '"';
$keys['$PAGEEDITOR_EMAIL'] = wfMessage( 'noemailtitle' )->inContentLanguage()->text();
} else {
- $keys['$PAGEEDITOR'] = $wgEnotifUseRealName ? $this->editor->getRealName() : $this->editor->getName();
+ $keys['$PAGEEDITOR'] = $wgEnotifUseRealName && $this->editor->getRealName() !== ''
+ ? $this->editor->getRealName() : $this->editor->getName();
$emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $this->editor->getName() );
$keys['$PAGEEDITOR_EMAIL'] = $emailPage->getCanonicalURL();
}
array( '$WATCHINGUSERNAME',
'$PAGEEDITDATE',
'$PAGEEDITTIME' ),
- array( $wgEnotifUseRealName ? $watchingUser->getRealName() : $watchingUser->getName(),
+ array( $wgEnotifUseRealName && $watchingUser->getRealName() !== ''
+ ? $watchingUser->getRealName() : $watchingUser->getName(),
$wgContLang->userDate( $this->timestamp, $watchingUser ),
$wgContLang->userTime( $this->timestamp, $watchingUser ) ),
$this->body );
return new FeedItem(
$title->getPrefixedText(),
$this->feedItemDesc( $revision ),
- $title->getFullURL(),
+ $title->getFullURL( array( 'diff' => $revision->getId() ) ),
$date,
$this->feedItemAuthor( $revision ),
$comments
class ApiFeedWatchlist extends ApiBase {
private $watchlistModule = null;
- private $linkToDiffs = false;
private $linkToSections = false;
/**
'meta' => 'siteinfo',
'siprop' => 'general',
'list' => 'watchlist',
- 'wlprop' => 'title|user|comment|timestamp',
+ 'wlprop' => 'title|user|comment|timestamp|ids',
'wldir' => 'older', // reverse order - from newest to oldest
'wlend' => $endTime, // stop at this time
'wllimit' => min( 50, $wgFeedLimit )
$fauxReqArr['wltype'] = $params['wltype'];
}
- // Support linking to diffs instead of article
- if ( $params['linktodiffs'] ) {
- $this->linkToDiffs = true;
- $fauxReqArr['wlprop'] .= '|ids';
- }
-
// Support linking directly to sections when possible
// (possible only if section name is present in comment)
if ( $params['linktosections'] ) {
private function createFeedItem( $info ) {
$titleStr = $info['title'];
$title = Title::newFromText( $titleStr );
- if ( $this->linkToDiffs && isset( $info['revid'] ) ) {
+ if ( isset( $info['revid'] ) ) {
$titleUrl = $title->getFullURL( array( 'diff' => $info['revid'] ) );
} else {
$titleUrl = $title->getFullURL();
ApiBase::PARAM_MIN => 1,
ApiBase::PARAM_MAX => 72,
),
- 'linktodiffs' => false,
'linktosections' => false,
);
if ( $flags ) {
return array(
'feedformat' => 'The format of the feed',
'hours' => 'List pages modified within this many hours from now',
- 'linktodiffs' => 'Link to change differences instead of article pages',
'linktosections' => 'Link directly to changed sections if possible',
'allrev' => $wldescr['allrev'],
'wlowner' => $wldescr['owner'],
public function getExamples() {
return array(
'api.php?action=feedwatchlist',
- 'api.php?action=feedwatchlist&allrev=&linktodiffs=&hours=6'
+ 'api.php?action=feedwatchlist&allrev=&hours=6'
);
}
$data['script'] = $GLOBALS['wgScript'];
$data['variantarticlepath'] = $GLOBALS['wgVariantArticlePath'];
$data['server'] = $GLOBALS['wgServer'];
+ $data['servername'] = $GLOBALS['wgServerName'];
$data['wikiid'] = wfWikiID();
$data['time'] = wfTimestamp( TS_ISO_8601, time() );
// by default we use pageset to extract the page to work on.
// title is still supported for backward compatibility
if ( !isset( $params['title'] ) ) {
- $pageSet->execute();
- $res = $pageSet->getInvalidTitlesAndRevisions( array(
- 'invalidTitles',
- 'special',
- 'missingIds',
- 'missingRevIds',
- 'interwikiTitles'
- ) );
-
- foreach ( $pageSet->getMissingTitles() as $title ) {
- $r = $this->watchTitle( $title, $user, $params );
- $r['missing'] = 1;
- $res[] = $r;
+ if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
+ $this->dieUsage(
+ "Cannot use 'entirewatchlist' at the same time as '{$pageSet->getDataSource()}'",
+ 'multisource'
+ );
}
- foreach ( $pageSet->getGoodTitles() as $title ) {
- $r = $this->watchTitle( $title, $user, $params );
- $res[] = $r;
+ if ( $params['entirewatchlist'] ) {
+ if ( !$params['unwatch'] ) {
+ $this->dieUsage(
+ "'entirewatchlist' option can only be used with 'unwatch' parameter.",
+ 'invalidparammix'
+ );
+ } else {
+ // We're going to do this in the database as a bulk operation
+ // instead of one at a time, so it doesn't time out on largeish lists.
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'watchlist', array( 'wl_user' => $user->getId() ), __METHOD__ );
+ $user->invalidateCache();
+ $res = array();
+ }
+ } else {
+ $pageSet->execute();
+ $res = $pageSet->getInvalidTitlesAndRevisions( array(
+ 'invalidTitles',
+ 'special',
+ 'missingIds',
+ 'missingRevIds',
+ 'interwikiTitles'
+ ) );
+
+ foreach ( $pageSet->getMissingTitles() as $title ) {
+ $r = $this->watchTitle( $title, $user, $params );
+ $r['missing'] = 1;
+ $res[] = $r;
+ }
+
+ foreach ( $pageSet->getGoodTitles() as $title ) {
+ $r = $this->watchTitle( $title, $user, $params );
+ $res[] = $r;
+ }
+ $this->getResult()->setIndexedTagName( $res, 'w' );
}
- $this->getResult()->setIndexedTagName( $res, 'w' );
} else {
// dont allow use of old title parameter with new pageset parameters.
$extraParams = array_keys( array_filter( $pageSet->extractRequestParams(), function ( $x ) {
ApiBase::PARAM_DEPRECATED => true
),
'unwatch' => false,
+ 'entirewatchlist' => false,
'uselang' => null,
'token' => array(
ApiBase::PARAM_TYPE => 'string',
return $psModule->getParamDescription() + array(
'title' => 'The page to (un)watch. use titles instead',
'unwatch' => 'If set the page will be unwatched rather than watched',
+ 'entirewatchlist' => 'Work on all watched pages without returning a list; can only be used together with \'unwatch\' option.',
'uselang' => 'Language to show the message in',
'token' => 'A token previously acquired via prop=info',
);
return $result;
}
+
+ /**
+ * Returns a ParserOutput object containing information derived from this content.
+ * Most importantly, unless $generateHtml was false, the return value contains an
+ * HTML representation of the content.
+ *
+ * Subclasses that want to control the parser output may override this, but it is
+ * preferred to override fillParserOutput() instead.
+ *
+ * Subclasses that override getParserOutput() itself should take care to call the
+ * ContentGetParserOutput hook.
+ *
+ * @since 1.24
+ *
+ * @param Title $title Context title for parsing
+ * @param int|null $revId Revision ID (for {{REVISIONID}})
+ * @param ParserOptions|null $options Parser options
+ * @param bool $generateHtml Whether or not to generate HTML
+ *
+ * @return ParserOutput Containing information derived from this content.
+ */
+ public function getParserOutput( Title $title, $revId = null,
+ ParserOptions $options = null, $generateHtml = true
+ ) {
+ if ( $options === null ) {
+ $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
+ }
+
+ $po = new ParserOutput();
+
+ if ( wfRunHooks( 'ContentGetParserOutput',
+ array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) {
+
+ $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po );
+ }
+
+ return $po;
+ }
+
+ /**
+ * Fills the provided ParserOutput with information derived from the content.
+ * Unless $generateHtml was false, this includes an HTML representation of the content.
+ *
+ * This is called by getParserOutput() after consulting the ContentGetParserOutput hook.
+ * Subclasses are expected to override this method (or getParserOutput(), if need be).
+ * Subclasses of TextContent should generally override getHtml() instead.
+ *
+ * This placeholder implementation always throws an exception.
+ *
+ * @since 1.24
+ *
+ * @param Title $title Context title for parsing
+ * @param int|null $revId Revision ID (for {{REVISIONID}})
+ * @param ParserOptions|null $options Parser options
+ * @param bool $generateHtml Whether or not to generate HTML
+ * @param ParserOutput &$output The output object to fill (reference).
+ *
+ * @throws MWException
+ */
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
+ // Don't make abstract, so subclasses that override getParserOutput() directly don't fail.
+ throw new MWException( 'Subclasses of AbstractContent must override fillParserOutput!' );
+ }
}
protected function getHtml() {
$html = "";
$html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
- $html .= $this->getHighlightHtml();
+ $html .= htmlspecialchars( $this->getNativeData() );
$html .= "\n</pre>\n";
return $html;
protected function getHtml() {
$html = "";
$html .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
- $html .= $this->getHighlightHtml();
+ $html .= htmlspecialchars( $this->getNativeData() );
$html .= "\n</pre>\n";
return $html;
}
/**
- * Returns a generic ParserOutput object, wrapping the HTML returned by
- * getHtml().
+ * Fills the provided ParserOutput object with information derived from the content.
+ * Unless $generateHtml was false, this includes an HTML representation of the content
+ * provided by getHtml().
+ *
+ * For content models listed in $wgTextModelsToParse, this method will call the MediaWiki
+ * wikitext parser on the text to extract any (wikitext) links, magic words, etc.
+ *
+ * Subclasses may override this to provide custom content processing.
+ * For custom HTML generation alone, it is sufficient to override getHtml().
*
* @param Title $title Context title for parsing
* @param int $revId Revision ID (for {{REVISIONID}})
* @param ParserOptions $options Parser options
* @param bool $generateHtml Whether or not to generate HTML
- *
- * @return ParserOutput Representing the HTML form of the text.
+ * @param ParserOutput $output The output object to fill (reference).
*/
- public function getParserOutput( Title $title, $revId = null,
- ParserOptions $options = null, $generateHtml = true ) {
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
global $wgParser, $wgTextModelsToParse;
- if ( !$options ) {
- //NOTE: use canonical options per default to produce cacheable output
- $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
- }
-
if ( in_array( $this->getModel(), $wgTextModelsToParse ) ) {
- // parse just to get links etc into the database
- $po = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId );
- } else {
- $po = new ParserOutput();
+ // parse just to get links etc into the database, HTML is replaced below.
+ $output = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId );
}
if ( $generateHtml ) {
$html = '';
}
- $po->setText( $html );
-
- return $po;
+ $output->setText( $html );
}
/**
* Generates an HTML version of the content, for display. Used by
- * getParserOutput() to construct a ParserOutput object.
+ * fillParserOutput() to provide HTML for the ParserOutput object.
+ *
+ * Subclasses may override this to provide a custom HTML rendering.
+ * If further information is to be derived from the content (such as
+ * categories), the fillParserOutput() method can be overridden instead.
*
- * This default implementation just calls getHighlightHtml(). Content
- * models that have another mapping to HTML (as is the case for markup
- * languages like wikitext) should override this method to generate the
- * appropriate HTML.
+ * For backwards-compatibility, this default implementation just calls
+ * getHighlightHtml().
*
* @return string An HTML representation of the content
*/
}
/**
- * Generates a syntax-highlighted version of the content, as HTML.
- * Used by the default implementation of getHtml().
+ * Generates an HTML version of the content, for display.
+ *
+ * This default implementation returns an HTML-escaped version
+ * of the raw text content.
*
- * @return string A HTML representation of the content's markup
+ * @note: The functionality of this method should really be implemented
+ * in getHtml(), and subclasses should override getHtml() if needed.
+ * getHighlightHtml() is kept around for backward compatibility with
+ * extensions that already override it.
+ *
+ * @deprecated since 1.24. Use getHtml() instead. In particular, subclasses overriding
+ * getHighlightHtml() should override getHtml() instead.
+ *
+ * @return string An HTML representation of the content
*/
protected function getHighlightHtml() {
- # TODO: make Highlighter interface, use highlighter here, if available
return htmlspecialchars( $this->getNativeData() );
}
* Returns a ParserOutput object resulting from parsing the content's text
* using $wgParser.
*
- * @since 1.21
- *
* @param Title $title
* @param int $revId Revision to pass to the parser (default: null)
* @param ParserOptions $options (default: null)
* @param bool $generateHtml (default: true)
- *
- * @return ParserOutput Representing the HTML form of the text
+ * @param &$output ParserOutput representing the HTML form of the text,
+ * may be manipulated or replaced.
*/
- public function getParserOutput( Title $title, $revId = null,
- ParserOptions $options = null, $generateHtml = true ) {
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
global $wgParser;
- if ( !$options ) {
- //NOTE: use canonical options per default to produce cacheable output
- $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
- }
-
list( $redir, $text ) = $this->getRedirectTargetAndText();
- $po = $wgParser->parse( $text, $title, $options, true, true, $revId );
+ $output = $wgParser->parse( $text, $title, $options, true, true, $revId );
// Add redirect indicator at the top
if ( $redir ) {
// Make sure to include the redirect link in pagelinks
- $po->addLink( $redir );
+ $output->addLink( $redir );
if ( $generateHtml ) {
$chain = $this->getRedirectChain();
- $po->setText(
+ $output->setText(
Article::getRedirectHeaderHtml( $title->getPageLanguage(), $chain, false ) .
- $po->getText()
+ $output->getText()
);
}
}
-
- return $po;
}
/**
* @ingroup Media
*/
abstract class ImageGalleryBase extends ContextSource {
- /** @var array Gallery images */
+ /**
+ * @var array Gallery images
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+ */
public $mImages;
- /** @var bool Whether to show the filesize in bytes in categories */
+ /**
+ * @var bool Whether to show the filesize in bytes in categories
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+ */
public $mShowBytes;
- /** @var bool Whether to show the filename. Default: true */
+ /**
+ * @var bool Whether to show the filename. Default: true
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+ */
public $mShowFilename;
- /** @var string Gallery mode. Default: traditional */
+ /**
+ * @var string Gallery mode. Default: traditional
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+ */
public $mMode;
- /** @var bool|string Gallery caption. Default: false */
+ /**
+ * @var bool|string Gallery caption. Default: false
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
+ */
public $mCaption = false;
/**
* @var bool Hide blacklisted images?
+ * @deprecated in 1.23 (was declared "var") and will be removed in 1.24
*/
public $mHideBadImages;
parent::__construct( $params );
# Per HTML5 spec, hidden fields cannot be 'required'
- # http://dev.w3.org/html5/spec/states-of-the-type-attribute.html#hidden-state
+ # http://www.w3.org/TR/html5/forms.html#hidden-state-%28type=hidden%29
unset( $this->mParams['required'] );
}
'_NamespaceType' => 'site-name',
'_AdminName' => '', // will be set later, when the user selects language
'_AdminPassword' => '',
- '_AdminPassword2' => '',
+ '_AdminPasswordConfirm' => '',
'_AdminEmail' => '',
'_Subscribe' => false,
'_SkipOptional' => 'continue',
array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
array( 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ),
+ array( 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ),
+ array( 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ),
//1.24
'label' => 'config-admin-password',
) ) .
$this->parent->getPasswordBox( array(
- 'var' => '_AdminPassword2',
+ 'var' => '_AdminPasswordConfirm',
'label' => 'config-admin-password-confirm'
) ) .
$this->parent->getTextBox( array(
public function submit() {
$retVal = true;
$this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType',
- '_AdminName', '_AdminPassword', '_AdminPassword2', '_AdminEmail',
+ '_AdminName', '_AdminPassword', '_AdminPasswordConfirm', '_AdminEmail',
'_Subscribe', '_SkipOptional', 'wgMetaNamespace' ) );
// Validate site name
# $user->getPasswordValidity just checks for $wgMinimalPasswordLength.
# This message is more specific and helpful.
$msg = 'config-admin-password-blank';
- } elseif ( $pwd !== $this->getVar( '_AdminPassword2' ) ) {
+ } elseif ( $pwd !== $this->getVar( '_AdminPasswordConfirm' ) ) {
$msg = 'config-admin-password-mismatch';
} elseif ( $valid !== true ) {
$msg = $valid;
if ( $msg !== false ) {
call_user_func_array( array( $this->parent, 'showError' ), (array)$msg );
$this->setVar( '_AdminPassword', '' );
- $this->setVar( '_AdminPassword2', '' );
+ $this->setVar( '_AdminPasswordConfirm', '' );
$retVal = false;
}
"config-help-restart": "是否要清除所有已輸入且儲存的資料,並重新開始安裝程序嗎?",
"config-restart": "是的,重新開始",
"config-welcome": "=== 環境檢查 ===\n現在會做基本的檢查,檢查環境是否符合 MediaWiki 安裝所需。\n若您要尋求如何完成安裝的協助,請記得提供以下訊息。",
- "config-copyright": "=== 版權聲明與授權條款 ===\n\n$1\n\n本程式為自由軟體;您可依據自由軟體基金會所發表的 GNU 通用公共授權條款規定,將本程式重新發佈與/或修改;無論您依據的是本授權條款的第二版或 (您可自行選擇) 之後的任何版本。\n\n本程式發佈的目的是希望可以提供幫助,但 <strong>不負任何擔保責任</strong>;亦無隱含對 <strong>適售性</strong> 或 <strong>特定用途的適用性</strong> 的情形擔保。詳情請參照GNU 通用公共授權。\n\n您應已隨本程式收到 <doclink href=\"Copying\">GNU 通用公共授權條款</doclink>;如果沒有,請信件通知自由軟體基金會,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或 [http://www.gnu.org/copyleft/gpl.html 線上閱讀]。",
+ "config-copyright": "=== 版權聲明與授權條款 ===\n\n$1\n\n本程式為自由軟體;您可依據自由軟體基金會所發表的 GNU 通用公共授權條款規定,將本程式重新發佈與/或修改;無論您依據的是本授權條款的第二版或 (您可自行選擇) 之後的任何版本。\n\n本程式發佈的目的是希望可以提供幫助,但 <strong>不負任何擔保責任</strong>;亦無隱含對 <strong>適售性</strong> 或 <strong>特定用途的適用性</strong> 的情形擔保。詳情請參照 GNU 通用公共授權。\n\n您應已隨本程式收到 <doclink href=\"Copying\">GNU 通用公共授權條款的副本</doclink>;如果沒有,請信件通知自由軟體基金會,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或 [http://www.gnu.org/copyleft/gpl.html 線上閱讀]。",
"config-sidebar": "* [www.mediawiki.org/wiki/MediaWiki/zh-hant MediaWiki 首頁]\n* [www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/zh 使用者指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/zh 管理者指南]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/zh-hant 常見問題集]\n----\n* <doclink href=Readme>讀我說明</doclink>\n* <doclink href=ReleaseNotes>發行說明</doclink>\n* <doclink href=Copying>版權聲明</doclink>\n* <doclink href=UpgradeDoc>升級</doclink>",
"config-env-good": "環境檢查已完成。\n您可以安裝 MediaWiki。",
"config-env-bad": "環境檢查已完成。\n您無法安裝 MediaWiki。",
'dstUrl' => $dstUrl,
);
+ if ( isset( $params['quality'] ) && $params['quality'] === 'low' ) {
+ $scalerParams['quality'] = 30;
+ }
+
# Determine scaler type
$scaler = self::getScalerType( $dstPath );
if ( !$image->mustRender() &&
$scalerParams['physicalWidth'] == $scalerParams['srcWidth']
&& $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
+ && !isset( $scalerParams['quality'] )
) {
# normaliseParams (or the user) wants us to return the unscaled image
if ( $flags & self::TRANSFORM_LATER ) {
wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
- $params = array(
+ $newParams = array(
'width' => $scalerParams['clientWidth'],
'height' => $scalerParams['clientHeight']
);
-
- return new ThumbnailImage( $image, $dstUrl, false, $params );
+ if ( isset( $params['quality'] ) ) {
+ $newParams['quality'] = $params['quality'];
+ }
+ return new ThumbnailImage( $image, $dstUrl, false, $newParams );
}
# Try to make a target path for the thumbnail
} elseif ( $mto ) {
return $mto;
} else {
- $params = array(
+ $newParams = array(
'width' => $scalerParams['clientWidth'],
'height' => $scalerParams['clientHeight']
);
-
- return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
+ if ( isset( $params['quality'] ) ) {
+ $newParams['quality'] = $params['quality'];
+ }
+ return new ThumbnailImage( $image, $dstUrl, $dstPath, $newParams );
}
}
$animation_post = array();
$decoderHint = array();
if ( $params['mimeType'] == 'image/jpeg' ) {
- $quality = array( '-quality', '80' ); // 80%
+ $qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
+ $quality = array( '-quality', $qualityVal ?: '80' ); // 80%
# Sharpening, see bug 6193
if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
/ ( $params['srcWidth'] + $params['srcHeight'] )
list( $radius, $sigma ) = explode( 'x', $wgSharpenParameter );
$im->sharpenImage( $radius, $sigma );
}
- $im->setCompressionQuality( 80 );
+ $qualityVal = isset( $params['quality'] ) ? (string) $params['quality'] : null;
+ $im->setCompressionQuality( $qualityVal ?: 80 );
} elseif ( $params['mimeType'] == 'image/png' ) {
$im->setCompressionQuality( 95 );
} elseif ( $params['mimeType'] == 'image/gif' ) {
# input routine for this.
$typemap = array(
- 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ),
- 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor',
+ 'image/gif' => array( 'imagecreatefromgif', 'palette', false, 'imagegif' ),
+ 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', true,
array( __CLASS__, 'imageJpegWrapper' ) ),
- 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ),
- 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ),
- 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ),
+ 'image/png' => array( 'imagecreatefrompng', 'bits', false, 'imagepng' ),
+ 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', false, 'imagewbmp' ),
+ 'image/xbm' => array( 'imagecreatefromxbm', 'palette', false, 'imagexbm' ),
);
+
if ( !isset( $typemap[$params['mimeType']] ) ) {
$err = 'Image type not supported';
wfDebug( "$err\n" );
return $this->getMediaTransformError( $params, $errMsg );
}
- list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']];
+ list( $loader, $colorStyle, $useQuality, $saveType ) = $typemap[$params['mimeType']];
if ( !function_exists( $loader ) ) {
$err = "Incomplete GD library configuration: missing function $loader";
imagesavealpha( $dst_image, true );
- call_user_func( $saveType, $dst_image, $params['dstPath'] );
+ $funcParams = array( $dst_image, $params['dstPath'] );
+ if ( $useQuality && isset( $params['quality'] ) ) {
+ $funcParams[] = $params['quality'];
+ }
+ call_user_func_array( $saveType, $funcParams );
+
imagedestroy( $dst_image );
imagedestroy( $src_image );
return $cache;
}
- static function imageJpegWrapper( $dst_image, $thumbPath ) {
+ // FIXME: transformImageMagick() & transformImageMagickExt() uses JPEG quality 80, here it's 95?
+ static function imageJpegWrapper( $dst_image, $thumbPath, $quality = 95 ) {
imageinterlace( $dst_image );
- imagejpeg( $dst_image, $thumbPath, 95 );
+ imagejpeg( $dst_image, $thumbPath, $quality );
}
/**
* @ingroup Media
*/
class JpegHandler extends ExifBitmapHandler {
+
+ function normaliseParams( $image, &$params ) {
+ if ( !parent::normaliseParams( $image, $params ) ) {
+ return false;
+ }
+ if ( isset( $params['quality'] ) && !self::validateQuality( $params['quality'] ) ) {
+ return false;
+ }
+ return true;
+ }
+
+ function validateParam( $name, $value ) {
+ if ( $name === 'quality' ) {
+ return self::validateQuality( $value );
+ } else {
+ return parent::validateParam( $name, $value );
+ }
+ }
+
+ /** Validate and normalize quality value to be between 1 and 100 (inclusive).
+ * @param int $value quality value, will be converted to integer or 0 if invalid
+ * @return bool true if the value is valid
+ */
+ private static function validateQuality( $value ) {
+ return $value === 'low';
+ }
+
+ function makeParamString( $params ) {
+ // Prepend quality as "qValue-". This has to match parseParamString() below
+ $res = parent::makeParamString( $params );
+ if ( $res && isset( $params['quality'] ) ) {
+ $res = "q{$params['quality']}-$res";
+ }
+ return $res;
+ }
+
+ function parseParamString( $str ) {
+ // $str contains "qlow-200px" or "200px" strings because thumb.php would strip the filename
+ // first - check if the string begins with "qlow-", and if so, treat it as quality.
+ // Pass the first portion, or the whole string if "qlow-" not found, to the parent
+ // The parsing must match the makeParamString() above
+ $res = false;
+ $m = false;
+ if ( preg_match( '/q([^-]+)-(.*)$/', $str, $m ) ) {
+ $v = $m[1];
+ if ( self::validateQuality( $v ) ) {
+ $res = parent::parseParamString( $m[2] );
+ if ( $res ) {
+ $res['quality'] = $v;
+ }
+ }
+ } else {
+ $res = parent::parseParamString( $str );
+ }
+ return $res;
+ }
+
+ function getScriptParams( $params ) {
+ $res = parent::getScriptParams( $params );
+ if ( isset( $params['quality'] ) ) {
+ $res['quality'] = $params['quality'];
+ }
+ return $res;
+ }
+
function getMetadata( $image, $filename ) {
try {
$meta = BitmapMetadataHandler::Jpeg( $filename );
*/
public $mUsedOptions;
- var $mVersion = Parser::VERSION, # Compatibility check
- $mCacheTime = '', # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
- $mCacheExpiry = null, # Seconds after which the object should expire, use 0 for uncachable. Used in ParserCache.
- $mContainsOldMagic, # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
- $mCacheRevisionId = null; # Revision ID that was parsed
+ /** @var string Compatibility check */
+ protected $mVersion = Parser::VERSION;
+
+ /** @var string Time when this object was generated, or -1 for uncacheable. Used in ParserCache. */
+ protected $mCacheTime = '';
+
+ /**
+ * @var int Seconds after which the object should expire, use 0 for uncachable.
+ * Used in ParserCache.
+ */
+ protected $mCacheExpiry = null;
+
+ /** @var bool Boolean variable indicating if the input contained variables like {{CURRENTDAY}} */
+ protected $mContainsOldMagic;
+
+ /** @var int Revision ID that was parsed */
+ protected $mCacheRevisionId = null;
/**
* @return string TS_MW timestamp
*/
public function expired( $touched ) {
global $wgCacheEpoch;
- return !$this->isCacheable() || // parser says it's uncacheable
- $this->getCacheTime() < $touched ||
- $this->getCacheTime() <= $wgCacheEpoch ||
- $this->getCacheTime() < wfTimestamp( TS_MW, time() - $this->getCacheExpiry() ) || // expiry period has passed
- !isset( $this->mVersion ) ||
- version_compare( $this->mVersion, Parser::VERSION, "lt" );
+
+ return !$this->isCacheable() // parser says it's uncacheable
+ || $this->getCacheTime() < $touched
+ || $this->getCacheTime() <= $wgCacheEpoch
+ || $this->getCacheTime() <
+ wfTimestamp( TS_MW, time() - $this->getCacheExpiry() ) // expiry period has passed
+ || !isset( $this->mVersion )
+ || version_compare( $this->mVersion, Parser::VERSION, "lt" );
}
/**
$parser->setFunctionHook( 'displaytitle', array( __CLASS__, 'displaytitle' ), SFH_NO_HASH );
}
if ( $wgAllowSlowParserFunctions ) {
- $parser->setFunctionHook( 'pagesinnamespace', array( __CLASS__, 'pagesinnamespace' ), SFH_NO_HASH );
+ $parser->setFunctionHook(
+ 'pagesinnamespace',
+ array( __CLASS__, 'pagesinnamespace' ),
+ SFH_NO_HASH
+ );
}
}
static function intFunction( $parser, $part1 = '' /*, ... */ ) {
if ( strval( $part1 ) !== '' ) {
$args = array_slice( func_get_args(), 2 );
- $message = wfMessage( $part1, $args )->inLanguage( $parser->getOptions()->getUserLangObj() )->plain();
+ $message = wfMessage( $part1, $args )
+ ->inLanguage( $parser->getOptions()->getUserLangObj() )->plain();
+
return array( $message, 'noparse' => false );
} else {
return array( 'found' => false );
// only requested titles that normalize to the actual title are allowed through
// if $wgRestrictDisplayTitle is true (it is by default)
// mimic the escaping process that occurs in OutputPage::setPageTitle
- $text = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $text, $htmlTagsCallback, array(), array(), $bad ) );
+ $text = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags(
+ $text,
+ $htmlTagsCallback,
+ array(),
+ array(),
+ $bad
+ ) );
$title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
if ( !$wgRestrictDisplayTitle ) {
$parser->mOutput->setDisplayTitle( $text );
- } elseif ( $title instanceof Title && !$title->hasFragment() && $title->equals( $parser->mTitle ) ) {
+ } elseif ( $title instanceof Title
+ && !$title->hasFragment()
+ && $title->equals( $parser->mTitle )
+ ) {
$parser->mOutput->setDisplayTitle( $text );
}
}
}
- // Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}} or {{filepath|300|nowiki}}
- // or {{filepath|300px}}, {{filepath|200x300px}}, {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}
+ // Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}}
+ // or {{filepath|300|nowiki}} or {{filepath|300px}}, {{filepath|200x300px}},
+ // {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}.
public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) {
$file = wfFindFile( $name );
* @ingroup Parser
*/
class DateFormatter {
- var $mSource, $mTarget;
- var $monthNames = '', $rxDM, $rxMD, $rxDMY, $rxYDM, $rxMDY, $rxYMD;
+ protected $mSource;
- var $regexes, $pDays, $pMonths, $pYears;
- var $rules, $xMonths, $preferences;
+ protected $mTarget;
+
+ /** @var string */
+ protected $monthNames = '';
+
+ /** @todo Are these unused? */
+ private $rxDM;
+ private $rxMD;
+ private $rxDMY;
+ private $rxYDM;
+ private $rxMDY;
+ private $rxYMD;
+
+ /** @var array */
+ protected $regexes;
+
+ /** @todo Are these unused? */
+ private $pDays;
+ private $pMonths;
+ private $pYears;
+
+ /** @var array */
+ protected $rules;
+
+ /** @var array */
+ protected $xMonths;
+
+ /** @var array */
+ protected $preferences;
+
+ /** @var bool */
+ protected $mLinked;
protected $lang;
$bits = array();
$key = $this->keys[$this->mSource];
- for ( $p = 0; $p < strlen( $key ); $p++ ) {
+ $keyLength = strlen( $key );
+ for ( $p = 0; $p < $keyLength; $p++ ) {
if ( $key[$p] != ' ' ) {
$bits[$key[$p]] = $matches[$p + 1];
}
$bits['d'] = sprintf( '%02d', $bits['j'] );
}
- for ( $p = 0; $p < strlen( $format ); $p++ ) {
+ $formatLength = strlen( $format );
+ for ( $p = 0; $p < $formatLength; $p++ ) {
$char = $format[$p];
switch ( $char ) {
case 'd': # ISO day of month
* @ingroup Parser
*/
class LinkHolderArray {
- var $internals = array(), $interwikis = array();
- var $size = 0;
- var $parent;
+ /** @var array */
+ public $internals = array();
+
+ /** @var array */
+ public $interwikis = array();
+
+ /** @var int */
+ protected $size = 0;
+
+ /** @var Parser */
+ protected $parent;
+
+ /** @var int */
protected $tempIdOffset;
function __construct( $parent ) {
$res = $dbr->select(
'page',
- array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_len', 'page_latest' ),
+ array( 'page_id', 'page_namespace', 'page_title',
+ 'page_is_redirect', 'page_len', 'page_latest' ),
$dbr->makeList( $where, LIST_OR ),
__METHOD__
);
// construct query
$dbr = wfGetDB( DB_SLAVE );
$varRes = $dbr->select( 'page',
- array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_len', 'page_latest' ),
+ array( 'page_id', 'page_namespace', 'page_title',
+ 'page_is_redirect', 'page_len', 'page_latest' ),
$linkBatch->constructSet( 'page', $dbr ),
__METHOD__
);
const TOC_START = '<mw:toc>';
const TOC_END = '</mw:toc>';
- # Persistent:
- var $mTagHooks = array();
- var $mTransparentTagHooks = array();
- var $mFunctionHooks = array();
- var $mFunctionSynonyms = array( 0 => array(), 1 => array() );
- var $mFunctionTagHooks = array();
- var $mStripList = array();
- var $mDefaultStripList = array();
- var $mVarCache = array();
- var $mImageParams = array();
- var $mImageParamsMagicArray = array();
- var $mMarkerIndex = 0;
- var $mFirstCall = true;
+ # Persistent
- # Initialised by initialiseVariables()
+ /** @var array */
+ public $mTagHooks = array();
- /**
- * @var MagicWordArray
- */
- var $mVariables;
+ /** @var array */
+ public $mTransparentTagHooks = array();
+
+ /** @var array */
+ public $mFunctionHooks = array();
+
+ /** @var array */
+ protected $mFunctionSynonyms = array( 0 => array(), 1 => array() );
+
+ /** @var array */
+ protected $mFunctionTagHooks = array();
+
+ /** @var array */
+ protected $mStripList = array();
/**
- * @var MagicWordArray
+ * @var array
+ * @todo Unused?
*/
- var $mSubstWords;
- var $mConf, $mPreprocessor, $mExtLinkBracketedRegex, $mUrlProtocols; # Initialised in constructor
+ private $mDefaultStripList = array();
+
+ /** @var array */
+ protected $mVarCache = array();
+
+ /** @var array */
+ protected $mImageParams = array();
+
+ /** @var array */
+ protected $mImageParamsMagicArray = array();
+
+ /** @var int */
+ public $mMarkerIndex = 0;
+
+ /** @var bool */
+ protected $mFirstCall = true;
+
+ # Initialised by initialiseVariables()
+
+ /** @var MagicWordArray */
+ public $mVariables;
+
+ /** @var MagicWordArray */
+ protected $mSubstWords;
+
+ # Initialised in constructor
+
+ /** @var array */
+ protected $mConf;
+
+ /** @var Parser */
+ public $mPreprocessor;
+
+ /** @var string */
+ protected $mExtLinkBracketedRegex;
+
+ /** @var string */
+ protected $mUrlProtocols;
# Cleared with clearState():
- /**
- * @var ParserOutput
- */
- var $mOutput;
- var $mAutonumber, $mDTopen;
+
+ /** @var ParserOutput */
+ public $mOutput;
+
+ /** @var int */
+ protected $mAutonumber;
+
+ /** @var bool */
+ protected $mDTopen;
+
+ /** @var StripState */
+ public $mStripState;
/**
- * @var StripState
+ * @var array
+ * @todo Unused?
*/
- var $mStripState;
+ private $mIncludeCount;
- var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
/**
- * @var LinkHolderArray
+ * @var bool
+ * @todo Unused?
*/
- var $mLinkHolders;
+ private $mArgStack;
- var $mLinkID;
- var $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth;
- var $mDefaultSort;
- var $mTplExpandCache; # empty-frame expansion cache
- var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
- var $mExpensiveFunctionCount; # number of expensive parser function calls
- var $mShowToc, $mForceTocPosition;
+ /** @var string */
+ protected $mLastSection;
- /**
- * @var User
- */
- var $mUser; # User object; only used when doing pre-save transform
+ /** @var bool */
+ protected $mInPre;
+
+ /** @var LinkHolderArray */
+ protected $mLinkHolders;
+
+ /** @var int */
+ protected $mLinkID;
+
+ /** @var array */
+ protected $mIncludeSizes;
+
+ /** @var int */
+ public $mPPNodeCount;
+
+ /** @var int */
+ public $mGeneratedPPNodeCount;
+
+ /** @var int */
+ public $mHighestExpansionDepth;
+
+ /** @var bool|string */
+ protected $mDefaultSort;
+
+ /** @var array Empty-frame expansion cache */
+ protected $mTplExpandCache;
+
+ /** @var array */
+ protected $mTplRedirCache;
+
+ /** @var array */
+ protected $mTplDomCache;
+
+ /** @var array */
+ public $mHeadings;
+
+ /** @var array */
+ protected $mDoubleUnderscores;
+
+ /** @var int Number of expensive parser function calls */
+ protected $mExpensiveFunctionCount;
+
+ /** @var bool */
+ protected $mShowToc;
+
+ /** @var bool */
+ protected $mForceTocPosition;
+
+ /** @var User User object; only used when doing pre-save transform */
+ protected $mUser;
# Temporary
# These are variables reset at least once per parse regardless of $clearState
- /**
- * @var ParserOptions
- */
- var $mOptions;
+ /** @var ParserOptions */
+ public $mOptions;
- /**
- * @var Title
- */
- var $mTitle; # Title context, used for self-link rendering and similar things
- var $mOutputType; # Output type, one of the OT_xxx constants
- var $ot; # Shortcut alias, see setOutputType()
- var $mRevisionObject; # The revision object of the specified revision ID
- var $mRevisionId; # ID to display in {{REVISIONID}} tags
- var $mRevisionTimestamp; # The timestamp of the specified revision ID
- var $mRevisionUser; # User to display in {{REVISIONUSER}} tag
- var $mRevisionSize; # Size to display in {{REVISIONSIZE}} variable
- var $mRevIdForTs; # The revision ID which was used to fetch the timestamp
- var $mInputSize = false; # For {{PAGESIZE}} on current page.
+ /** @var Title Title context, used for self-link rendering and similar things */
+ public $mTitle;
+
+ /** @var array Shortcut alias, see setOutputType() */
+ public $ot;
+
+ /** @var string The timestamp of the specified revision ID */
+ public $mRevisionTimestamp;
+
+ /** @var string */
+ public $mUniqPrefix;
/**
- * @var string
+ * @var boolean Recursive call protection.
+ * This variable should be treated as if it were private.
*/
- var $mUniqPrefix;
+ public $mInParse = false;
+
+ /** @var int Output type, one of the OT_xxx constants */
+ protected $mOutputType;
+
+ /** @var Revision The revision object of the specified revision ID */
+ protected $mRevisionObject;
+
+ /** @var int ID to display in {{REVISIONID}} tags */
+ protected $mRevisionId;
+
+ /** @var string User to display in {{REVISIONUSER}} tag */
+ protected $mRevisionUser;
+
+ /** @var int Size to display in {{REVISIONSIZE}} variable */
+ protected $mRevisionSize;
+
+ /** @var bool|int For {{PAGESIZE}} on current page. */
+ protected $mInputSize = false;
/**
* @var array Array with the language name of each language link (i.e. the
* interwiki prefix) in the key, value arbitrary. Used to avoid sending
* duplicate language links to the ParserOutput.
*/
- var $mLangLinkLanguages;
+ protected $mLangLinkLanguages;
+
+ /**
+ * @var int The revision ID which was used to fetch the timestamp
+ * @todo Unused?
+ */
+ private $mRevIdForTs;
/**
* Constructor
* Allow extensions to clean up when the parser is cloned
*/
function __clone() {
+ $this->mInParse = false;
wfRunHooks( 'ParserCloned', array( $this ) );
}
* @param int $revid Number to pass in {{REVISIONID}}
* @return ParserOutput A ParserOutput
*/
- public function parse( $text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null ) {
+ public function parse( $text, Title $title, ParserOptions $options,
+ $linestart = true, $clearState = true, $revid = null
+ ) {
/**
* First pass--just handle <nowiki> sections, pass the rest off
* to internalParse() which does all the real work.
wfProfileIn( __METHOD__ );
wfProfileIn( $fname );
+ if ( $clearState ) {
+ $magicScopeVariable = $this->lock();
+ }
+
$this->startParse( $title, $options, self::OT_HTML, $clearState );
$this->mInputSize = strlen( $text );
*/
function preprocess( $text, Title $title = null, ParserOptions $options, $revid = null ) {
wfProfileIn( __METHOD__ );
+ $magicScopeVariable = $this->lock();
$this->startParse( $title, $options, self::OT_PREPROCESS, true );
if ( $revid !== null ) {
$this->mRevisionId = $revid;
$text = $msg->params( $params )->plain();
# Parser (re)initialisation
+ $magicScopeVariable = $this->lock();
$this->startParse( $title, $options, self::OT_PLAIN, true );
$flags = PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES;
array_push( $tr_history, false );
array_push( $td_history, false );
array_push( $last_tag_history, '' );
- } elseif ( $first_character === '|' || $first_character === '!' || substr( $line, 0, 2 ) === '|+' ) {
+ } elseif ( $first_character === '|'
+ || $first_character === '!'
+ || substr( $line, 0, 2 ) === '|+'
+ ) {
# This might be cell elements, td, th or captions
if ( substr( $line, 0, 2 ) === '|+' ) {
$first_character = '+';
}
wfRunHooks( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
- $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ), false, array_keys( $this->mTransparentTagHooks ) );
+ $text = Sanitizer::removeHTMLtags(
+ $text,
+ array( &$this, 'attributeStripCallback' ),
+ false,
+ array_keys( $this->mTransparentTagHooks )
+ );
wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
# Tables need to come after variable replacement for things to work
$bits = preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
if ( $bits === false ) {
wfProfileOut( __METHOD__ );
- throw new MWException( "PCRE needs to be compiled with --enable-unicode-properties in order for MediaWiki to function" );
+ throw new MWException( "PCRE needs to be compiled with "
+ . "--enable-unicode-properties in order for MediaWiki to function" );
}
$s = array_shift( $bits );
} else {
$imagematch = false;
}
+
if ( $this->mOptions->getAllowExternalImages()
- || ( $imagesexception && $imagematch ) ) {
+ || ( $imagesexception && $imagematch )
+ ) {
if ( preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
# Image found
$text = Linker::makeExternalImage( $url );
}
}
if ( !$text && $this->mOptions->getEnableImageWhitelist()
- && preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
- $whitelist = explode( "\n", wfMessage( 'external_image_whitelist' )->inContentLanguage()->text() );
+ && preg_match( self::EXT_IMAGE_REGEX, $url )
+ ) {
+ $whitelist = explode(
+ "\n",
+ wfMessage( 'external_image_whitelist' )->inContentLanguage()->text()
+ );
+
foreach ( $whitelist as $entry ) {
# Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments
if ( strpos( $entry, '#' ) === 0 || $entry === '' ) {
$useSubpages = $this->areSubpagesAllowed();
wfProfileOut( __METHOD__ . '-setup' );
+ // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
# Loop for each link
for ( ; $line !== false && $line !== null; $a->next(), $line = $a->current() ) {
+ // @codingStandardsIgnoreStart
+
# Check for excessive memory usage
if ( $holders->isBig() ) {
# Too big
$m[1] = str_replace( array( '<', '>' ), array( '<', '>' ), rawurldecode( $m[1] ) );
}
$trail = $m[3];
- } elseif ( preg_match( $e1_img, $line, $m ) ) { # Invalid, but might be an image with a link in its caption
+ } elseif ( preg_match( $e1_img, $line, $m ) ) {
+ # Invalid, but might be an image with a link in its caption
$might_be_img = true;
$text = $m[2];
if ( strpos( $m[1], '%' ) !== false ) {
if ( $noforce ) {
# Interwikis
wfProfileIn( __METHOD__ . "-interwiki" );
- if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' ) ) {
+ if ( $iw && $this->mOptions->getInterwikiMagic()
+ && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' )
+ ) {
// XXX: the above check prevents links to sites with identifiers that are not language codes
# Bug 24502: filter duplicates
wfProfileIn( __METHOD__ . "-paragraph" );
# No prefix (not in list)--go to paragraph mode
# XXX: use a stack for nestable elements like span, table and div
- $openmatch = preg_match( '/(?:<table|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<dl|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
+ $openmatch = preg_match(
+ '/(?:<table|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|'
+ . '<p|<ul|<ol|<dl|<li|<\\/tr|<\\/td|<\\/th)/iS',
+ $t
+ );
$closematch = preg_match(
- '/(?:<\\/table|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|' .
- '<td|<th|<\\/?blockquote|<\\/?div|<hr|<\\/pre|<\\/p|<\\/mw:|' . $this->mUniqPrefix . '-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS', $t );
+ '/(?:<\\/table|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'
+ . '<td|<th|<\\/?blockquote|<\\/?div|<hr|<\\/pre|<\\/p|<\\/mw:|'
+ . $this->mUniqPrefix
+ . '-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS',
+ $t
+ );
+
if ( $openmatch or $closematch ) {
$paragraphStack = false;
# TODO bug 5718: paragraph closed
}
$inBlockElem = !$closematch;
} elseif ( !$inBlockElem && !$this->mInPre ) {
- if ( ' ' == substr( $t, 0, 1 ) and ( $this->mLastSection === 'pre' || trim( $t ) != '' ) and !$inBlockquote ) {
+ if ( ' ' == substr( $t, 0, 1 )
+ && ( $this->mLastSection === 'pre' || trim( $t ) != '' )
+ && !$inBlockquote
+ ) {
# pre
if ( $this->mLastSection !== 'pre' ) {
$paragraphStack = false;
* @return string
*/
function getVariableValue( $index, $frame = false ) {
- global $wgContLang, $wgSitename, $wgServer;
+ global $wgContLang, $wgSitename, $wgServer, $wgServerName;
global $wgArticlePath, $wgScriptPath, $wgStylePath;
if ( is_null( $this->mTitle ) ) {
$value = wfEscapeWikiText( $this->mTitle->getRootText() );
break;
case 'rootpagenamee':
- $value = wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $this->mTitle->getRootText() ) ) );
+ $value = wfEscapeWikiText( wfUrlEncode( str_replace(
+ ' ',
+ '_',
+ $this->mTitle->getRootText()
+ ) ) );
break;
case 'basepagename':
$value = wfEscapeWikiText( $this->mTitle->getBaseText() );
break;
case 'basepagenamee':
- $value = wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $this->mTitle->getBaseText() ) ) );
+ $value = wfEscapeWikiText( wfUrlEncode( str_replace(
+ ' ',
+ '_',
+ $this->mTitle->getBaseText()
+ ) ) );
break;
case 'talkpagename':
if ( $this->mTitle->canTalk() ) {
$value = $this->mTitle->getNamespace();
break;
case 'talkspace':
- $value = $this->mTitle->canTalk() ? str_replace( '_', ' ', $this->mTitle->getTalkNsText() ) : '';
+ $value = $this->mTitle->canTalk()
+ ? str_replace( '_', ' ', $this->mTitle->getTalkNsText() )
+ : '';
break;
case 'talkspacee':
$value = $this->mTitle->canTalk() ? wfUrlencode( $this->mTitle->getTalkNsText() ) : '';
$value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'w' ) );
break;
case 'localdayname':
- $value = $pageLang->getWeekdayName( (int)MWTimestamp::getLocalInstance( $ts )->format( 'w' ) + 1 );
+ $value = $pageLang->getWeekdayName(
+ (int)MWTimestamp::getLocalInstance( $ts )->format( 'w' ) + 1
+ );
break;
case 'localyear':
$value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'Y' ), true );
break;
case 'localtime':
- $value = $pageLang->time( MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' ), false, false );
+ $value = $pageLang->time(
+ MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' ),
+ false,
+ false
+ );
break;
case 'localhour':
$value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'H' ), true );
case 'server':
return $wgServer;
case 'servername':
- $serverParts = wfParseUrl( $wgServer );
- return $serverParts && isset( $serverParts['host'] ) ? $serverParts['host'] : $wgServer;
+ return $wgServerName;
case 'scriptpath':
return $wgScriptPath;
case 'stylepath':
break;
default:
$ret = null;
- wfRunHooks( 'ParserGetVariableValueSwitch', array( &$this, &$this->mVarCache, &$index, &$ret, &$frame ) );
+ wfRunHooks(
+ 'ParserGetVariableValueSwitch',
+ array( &$this, &$this->mVarCache, &$index, &$ret, &$frame )
+ );
+
return $ret;
}
if ( $frame === false ) {
$frame = $this->getPreprocessor()->newFrame();
} elseif ( !( $frame instanceof PPFrame ) ) {
- wfDebug( __METHOD__ . " called using plain parameters instead of a PPFrame instance. Creating custom frame.\n" );
+ wfDebug( __METHOD__ . " called using plain parameters instead of "
+ . "a PPFrame instance. Creating custom frame.\n" );
$frame = $this->getPreprocessor()->newCustomFrame( $frame );
}
wfProfileIn( __METHOD__ );
wfProfileIn( __METHOD__ . '-setup' );
- # Flags
- $found = false; # $text has been filled
- $nowiki = false; # wiki markup in $text should be escaped
- $isHTML = false; # $text is HTML, armour it against wikitext transformation
- $forceRawInterwiki = false; # Force interwiki transclusion to be done in raw mode not rendered
- $isChildObj = false; # $text is a DOM node needing expansion in a child frame
- $isLocalObj = false; # $text is a DOM node needing expansion in the current frame
+ // Flags
+
+ // $text has been filled
+ $found = false;
+ // wiki markup in $text should be escaped
+ $nowiki = false;
+ // $text is HTML, armour it against wikitext transformation
+ $isHTML = false;
+ // Force interwiki transclusion to be done in raw mode not rendered
+ $forceRawInterwiki = false;
+ // $text is a DOM node needing expansion in a child frame
+ $isChildObj = false;
+ // $text is a DOM node needing expansion in the current frame
+ $isLocalObj = false;
# Title object, where $text came from
$title = false;
$originalTitle = $part1;
# $args is a list of argument nodes, starting from index 0, not including $part1
- # @todo FIXME: If piece['parts'] is null then the call to getLength() below won't work b/c this $args isn't an object
+ # @todo FIXME: If piece['parts'] is null then the call to getLength()
+ # below won't work b/c this $args isn't an object
$args = ( null == $piece['parts'] ) ? array() : $piece['parts'];
wfProfileOut( __METHOD__ . '-setup' );
// "uselang" will have no effect since the Language object
// is forced to the one defined in ParserOptions.
$pageArgs = array();
- for ( $i = 0; $i < $args->getLength(); $i++ ) {
+ $argsLength = $args->getLength();
+ for ( $i = 0; $i < $argsLength; $i++ ) {
$bits = $args->item( $i )->splitArg();
if ( strval( $bits['index'] ) === '' ) {
$name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) );
preg_replace( '/^:/', '', $originalTitle );
$text = "[[:$originalTitle]]";
}
- $text .= $this->insertStripItem( '<!-- WARNING: template omitted, post-expand include size too large -->' );
+ $text .= $this->insertStripItem( '<!-- WARNING: template omitted, '
+ . 'post-expand include size too large -->' );
$this->limitationWarn( 'post-expand-template-inclusion' );
}
* @return array ( string or false, Title )
*/
function fetchTemplateAndTitle( $title ) {
- $templateCb = $this->mOptions->getTemplateCallback(); # Defaults to Parser::statelessFetchTemplate()
+ // Defaults to Parser::statelessFetchTemplate()
+ $templateCb = $this->mOptions->getTemplateCallback();
$stuff = call_user_func( $templateCb, $title, $this );
$text = $stuff['text'];
$finalTitle = isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title;
$status = $req->execute(); // Status object
if ( $status->isOK() ) {
$text = $req->getContent();
- } elseif ( $req->getStatus() != 200 ) { // Though we failed to fetch the content, this status is useless.
- return wfMessage( 'scarytranscludefailed-httpstatus', $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
+ } elseif ( $req->getStatus() != 200 ) {
+ // Though we failed to fetch the content, this status is useless.
+ return wfMessage( 'scarytranscludefailed-httpstatus' )
+ ->params( $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
} else {
return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
}
$name = $frame->expand( $params['name'] );
$attrText = !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] );
$content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] );
- $marker = "{$this->mUniqPrefix}-$name-" . sprintf( '%08X', $this->mMarkerIndex++ ) . self::MARKER_SUFFIX;
+ $marker = "{$this->mUniqPrefix}-$name-"
+ . sprintf( '%08X', $this->mMarkerIndex++ ) . self::MARKER_SUFFIX;
$isFunctionTag = isset( $this->mFunctionTagHooks[strtolower( $name )] ) &&
( $this->ot['html'] || $this->ot['pre'] );
if ( isset( $this->mDoubleUnderscores['notoc'] ) && !$this->mForceTocPosition ) {
$this->mShowToc = false;
}
- if ( isset( $this->mDoubleUnderscores['hiddencat'] ) && $this->mTitle->getNamespace() == NS_CATEGORY ) {
+ if ( isset( $this->mDoubleUnderscores['hiddencat'] )
+ && $this->mTitle->getNamespace() == NS_CATEGORY
+ ) {
$this->addTrackingCategory( 'hidden-category-category' );
}
# (bug 8068) Allow control over whether robots index a page.
# Get all headlines for numbering them and adding funky stuff like [edit]
# links - this is for later, but we need the number of headlines right now
$matches = array();
- $numMatches = preg_match_all( '/<H(?P<level>[1-6])(?P<attrib>.*?' . '>)\s*(?P<header>[\s\S]*?)\s*<\/H[1-6] *>/i', $text, $matches );
+ $numMatches = preg_match_all(
+ '/<H(?P<level>[1-6])(?P<attrib>.*?' . '>)\s*(?P<header>[\s\S]*?)\s*<\/H[1-6] *>/i',
+ $text,
+ $matches
+ );
# if there are fewer than 4 headlines in the article, do not show TOC
# unless it's been explicitly enabled.
# We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from <span>,
# to allow setting directionality in toc items.
$tocline = preg_replace(
- array( '#<(?!/?(span|sup|sub|i|b)(?: [^>]*)?>).*?' . '>#', '#<(/?(?:span(?: dir="(?:rtl|ltr)")?|sup|sub|i|b))(?: .*?)?' . '>#' ),
+ array(
+ '#<(?!/?(span|sup|sub|i|b)(?: [^>]*)?>).*?' . '>#',
+ '#<(/?(?:span(?: dir="(?:rtl|ltr)")?|sup|sub|i|b))(?: .*?)?' . '>#'
+ ),
array( '', '<$1>' ),
$safeHeadline
);
# Don't number the heading if it is the only one (looks silly)
if ( count( $matches[3] ) > 1 && $this->mOptions->getNumberHeadings() ) {
# the two are different if the line contains a link
- $headline = Html::element( 'span', array( 'class' => 'mw-headline-number' ), $numbering ) . ' ' . $headline;
+ $headline = Html::element(
+ 'span',
+ array( 'class' => 'mw-headline-number' ),
+ $numbering
+ ) . ' ' . $headline;
}
# Create the anchor for linking from the TOC to the section
# that sections inside <includeonly> should be counted.
$editlinkArgs = array( $titleText, "T-$sectionIndex"/*, null */ );
} else {
- $editlinkArgs = array( $this->mTitle->getPrefixedText(), $sectionIndex, $headlineHint );
+ $editlinkArgs = array(
+ $this->mTitle->getPrefixedText(),
+ $sectionIndex,
+ $headlineHint
+ );
}
- // We use a bit of pesudo-xml for editsection markers. The language converter is run later on
- // Using a UNIQ style marker leads to the converter screwing up the tokens when it converts stuff
- // And trying to insert strip tags fails too. At this point all real inputted tags have already been escaped
- // so we don't have to worry about a user trying to input one of these markers directly.
- // We use a page and section attribute to stop the language converter from converting these important bits
- // of data, but put the headline hint inside a content block because the language converter is supposed to
+ // We use a bit of pesudo-xml for editsection markers. The
+ // language converter is run later on. Using a UNIQ style marker
+ // leads to the converter screwing up the tokens when it
+ // converts stuff. And trying to insert strip tags fails too. At
+ // this point all real inputted tags have already been escaped,
+ // so we don't have to worry about a user trying to input one of
+ // these markers directly. We use a page and section attribute
+ // to stop the language converter from converting these
+ // important bits of data, but put the headline hint inside a
+ // content block because the language converter is supposed to
// be able to convert that piece of data.
$editlink = '<mw:editsection page="' . htmlspecialchars( $editlinkArgs[0] );
$editlink .= '" section="' . htmlspecialchars( $editlinkArgs[1] ) . '"';
* @param bool $clearState Whether to clear the parser state first
* @return string The altered wiki markup
*/
- public function preSaveTransform( $text, Title $title, User $user, ParserOptions $options, $clearState = true ) {
+ public function preSaveTransform( $text, Title $title, User $user,
+ ParserOptions $options, $clearState = true
+ ) {
+ if ( $clearState ) {
+ $magicScopeVariable = $this->lock();
+ }
$this->startParse( $title, $options, self::OT_WIKI, $clearState );
$this->setUser( $user );
$tc = '[' . Title::legalChars() . ']';
$nc = '[ _0-9A-Za-z\x80-\xff-]'; # Namespaces can use non-ascii!
- $p1 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\))\\|]]/"; # [[ns:page (context)|]]
- $p4 = "/\[\[(:?$nc+:|:|)($tc+?)( ?($tc+))\\|]]/"; # [[ns:page(context)|]] (double-width brackets, added in r40257)
- $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\)|)((?:, |,)$tc+|)\\|]]/"; # [[ns:page (context), context|]] (using either single or double-width comma)
- $p2 = "/\[\[\\|($tc+)]]/"; # [[|page]] (reverse pipe trick: add context from page title)
+ // [[ns:page (context)|]]
+ $p1 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\))\\|]]/";
+ // [[ns:page(context)|]] (double-width brackets, added in r40257)
+ $p4 = "/\[\[(:?$nc+:|:|)($tc+?)( ?($tc+))\\|]]/";
+ // [[ns:page (context), context|]] (using either single or double-width comma)
+ $p3 = "/\[\[(:?$nc+:|:|)($tc+?)( ?\\($tc+\\)|)((?:, |,)$tc+|)\\|]]/";
+ // [[|page]] (reverse pipe trick: add context from page title)
+ $p2 = "/\[\[\\|($tc+)]]/";
# try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]"
$text = preg_replace( $p1, '[[\\1\\2\\3|\\2]]', $text );
$nickText = wfEscapeWikiText( $nickname );
$msgName = $user->isAnon() ? 'signature-anon' : 'signature';
- return wfMessage( $msgName, $userText, $nickText )->inContentLanguage()->title( $this->getTitle() )->text();
+ return wfMessage( $msgName, $userText, $nickText )->inContentLanguage()
+ ->title( $this->getTitle() )->text();
}
/**
public function cleanSig( $text, $parsing = false ) {
if ( !$parsing ) {
global $wgTitle;
+ $magicScopeVariable = $this->lock();
$this->startParse( $wgTitle, new ParserOptions, self::OT_PREPROCESS, true );
}
* @param int $outputType
* @param bool $clearState
*/
- public function startExternalParse( Title $title = null, ParserOptions $options, $outputType, $clearState = true ) {
+ public function startExternalParse( Title $title = null, ParserOptions $options,
+ $outputType, $clearState = true
+ ) {
$this->startParse( $title, $options, $outputType, $clearState );
}
* @param int $outputType
* @param bool $clearState
*/
- private function startParse( Title $title = null, ParserOptions $options, $outputType, $clearState = true ) {
+ private function startParse( Title $title = null, ParserOptions $options,
+ $outputType, $clearState = true
+ ) {
$this->setTitle( $title );
$this->mOptions = $options;
$this->setOutputType( $outputType );
* @return array
*/
function getTags() {
- return array_merge( array_keys( $this->mTransparentTagHooks ), array_keys( $this->mTagHooks ), array_keys( $this->mFunctionTagHooks ) );
+ return array_merge(
+ array_keys( $this->mTransparentTagHooks ),
+ array_keys( $this->mTagHooks ),
+ array_keys( $this->mFunctionTagHooks )
+ );
}
/**
list( $element, $content, $params, $tag ) = $data;
$tagName = strtolower( $element );
if ( isset( $this->mTransparentTagHooks[$tagName] ) ) {
- $output = call_user_func_array( $this->mTransparentTagHooks[$tagName], array( $content, $params, $this ) );
+ $output = call_user_func_array(
+ $this->mTransparentTagHooks[$tagName],
+ array( $content, $params, $this )
+ );
} else {
$output = $tag;
}
*/
private function extractSections( $text, $section, $mode, $newText = '' ) {
global $wgTitle; # not generally used but removes an ugly failure mode
+
+ $magicScopeVariable = $this->lock();
$this->startParse( $wgTitle, new ParserOptions, self::OT_PLAIN, true );
$outText = '';
$frame = $this->getPreprocessor()->newFrame();
* @return string
*/
function testSrvus( $text, Title $title, ParserOptions $options, $outputType = self::OT_HTML ) {
+ $magicScopeVariable = $this->lock();
$this->startParse( $title, $options, $outputType, true );
$text = $this->replaceVariables( $text );
}
return $parsedWidthParam;
}
+
+ /**
+ * Lock the current instance of the parser.
+ *
+ * This is meant to stop someone from calling the parser
+ * recursively and messing up all the strip state.
+ *
+ * @throws MWException If parser is in a parse
+ * @return ScopedCallback The lock will be released once the return value goes out of scope.
+ */
+ protected function lock() {
+ if ( $this->mInParse ) {
+ throw new MWException( "Parser state cleared while parsing. "
+ . "Did you call Parser::parse recursively?" );
+ }
+ $this->mInParse = true;
+
+ $that = $this;
+ $recursiveCheck = new ScopedCallback( function() use ( $that ) {
+ $that->mInParse = false;
+ } );
+
+ return $recursiveCheck;
+ }
}
if ( !$useOutdated && $optionsKey->expired( $article->getTouched() ) ) {
wfIncrStats( "pcache_miss_expired" );
$cacheTime = $optionsKey->getCacheTime();
- wfDebug( "Parser options key expired, touched " . $article->getTouched() . ", epoch $wgCacheEpoch, cached $cacheTime\n" );
+ wfDebug( "Parser options key expired, touched " . $article->getTouched()
+ . ", epoch $wgCacheEpoch, cached $cacheTime\n" );
return false;
} elseif ( $optionsKey->isDifferentRevision( $article->getLatest() ) ) {
wfIncrStats( "pcache_miss_revid" );
$usedOptions = ParserOptions::legacyOptions();
}
- return $this->getParserOutputKey( $article, $popts->optionsHash( $usedOptions, $article->getTitle() ) );
+ return $this->getParserOutputKey(
+ $article,
+ $popts->optionsHash( $usedOptions, $article->getTitle() )
+ );
}
/**
if ( !$useOutdated && $value->expired( $touched ) ) {
wfIncrStats( "pcache_miss_expired" );
$cacheTime = $value->getCacheTime();
- wfDebug( "ParserOutput key expired, touched $touched, epoch $wgCacheEpoch, cached $cacheTime\n" );
+ wfDebug( "ParserOutput key expired, touched $touched, "
+ . "epoch $wgCacheEpoch, cached $cacheTime\n" );
$value = false;
} elseif ( $value->isDifferentRevision( $article->getLatest() ) ) {
wfIncrStats( "pcache_miss_revid" );
/**
* \brief Set options of the Parser
*
- * All member variables are supposed to be private in theory, although in practise this is not the case.
+ * All member variables are supposed to be private in theory, although in
+ * practise this is not the case.
*
* @ingroup Parser
*/
class ParserOptions {
+ /** @var bool Parsing the page for a "preview" operation? */
+ public $mIsPreview = false;
- /**
- * Interlanguage links are removed and returned in an array
- */
- var $mInterwikiMagic;
+ /** @var bool Interlanguage links are removed and returned in an array */
+ protected $mInterwikiMagic;
- /**
- * Allow external images inline?
- */
- var $mAllowExternalImages;
+ /** @var bool Allow external images inline? */
+ protected $mAllowExternalImages;
- /**
- * If not, any exception?
- */
- var $mAllowExternalImagesFrom;
+ /** @var string|array If not, any exception? */
+ protected $mAllowExternalImagesFrom;
- /**
- * If not or it doesn't match, should we check an on-wiki whitelist?
- */
- var $mEnableImageWhitelist;
+ /** @var bool If not or it doesn't match, should we check an on-wiki whitelist? */
+ protected $mEnableImageWhitelist;
- /**
- * Date format index
- */
- var $mDateFormat = null;
+ /** @var string Date format index */
+ protected $mDateFormat = null;
- /**
- * Create "edit section" links?
- */
- var $mEditSection = true;
+ /** @var bool Create "edit section" links? */
+ protected $mEditSection = true;
- /**
- * Allow inclusion of special pages?
- */
- var $mAllowSpecialInclusion;
+ /** @var bool Allow inclusion of special pages? */
+ protected $mAllowSpecialInclusion;
- /**
- * Use tidy to cleanup output HTML?
- */
- var $mTidy = false;
+ /** @var bool Use tidy to cleanup output HTML? */
+ protected $mTidy = false;
/**
- * Which lang to call for PLURAL and GRAMMAR
+ * @var bool Which lang to call for PLURAL and GRAMMAR
+ * @todo FIXME: This comment doesn't appear to be correct.
+ * Should be this? Whether this is an interface message.
*/
- var $mInterfaceMessage = false;
+ protected $mInterfaceMessage = false;
- /**
- * Overrides $mInterfaceMessage with arbitrary language
- */
- var $mTargetLanguage = null;
+ /** @var string|Language Overrides $mInterfaceMessage with arbitrary language */
+ protected $mTargetLanguage = null;
- /**
- * Maximum size of template expansions, in bytes
- */
- var $mMaxIncludeSize;
+ /** @var int Maximum size of template expansions, in bytes */
+ protected $mMaxIncludeSize;
- /**
- * Maximum number of nodes touched by PPFrame::expand()
- */
- var $mMaxPPNodeCount;
+ /** @var int Maximum number of nodes touched by PPFrame::expand() */
+ protected $mMaxPPNodeCount;
- /**
- * Maximum number of nodes generated by Preprocessor::preprocessToObj()
- */
- var $mMaxGeneratedPPNodeCount;
+ /** @var int Maximum number of nodes generated by Preprocessor::preprocessToObj() */
+ protected $mMaxGeneratedPPNodeCount;
- /**
- * Maximum recursion depth in PPFrame::expand()
- */
- var $mMaxPPExpandDepth;
+ /** @var int Maximum recursion depth in PPFrame::expand() */
+ protected $mMaxPPExpandDepth;
- /**
- * Maximum recursion depth for templates within templates
- */
- var $mMaxTemplateDepth;
+ /** @var int Maximum recursion depth for templates within templates */
+ protected $mMaxTemplateDepth;
- /**
- * Maximum number of calls per parse to expensive parser functions
- */
- var $mExpensiveParserFunctionLimit;
+ /** @var int Maximum number of calls per parse to expensive parser functions */
+ protected $mExpensiveParserFunctionLimit;
- /**
- * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
- */
- var $mRemoveComments = true;
+ /** @var bool Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS */
+ protected $mRemoveComments = true;
- /**
- * Callback for template fetching. Used as first argument to call_user_func().
- */
- var $mTemplateCallback =
- array( 'Parser', 'statelessFetchTemplate' );
+ /** @var array Callback for template fetching. Used as first argument to call_user_func(). */
+ protected $mTemplateCallback = array( 'Parser', 'statelessFetchTemplate' );
- /**
- * Enable limit report in an HTML comment on output
- */
- var $mEnableLimitReport = false;
+ /** @var bool Enable limit report in an HTML comment on output */
+ protected $mEnableLimitReport = false;
- /**
- * Timestamp used for {{CURRENTDAY}} etc.
- */
- var $mTimestamp;
+ /** @var string Timestamp used for {{CURRENTDAY}} etc. */
+ protected $mTimestamp;
- /**
- * Target attribute for external links
- */
- var $mExternalLinkTarget;
+ /** @var bool|string Target attribute for external links */
+ protected $mExternalLinkTarget;
/**
- * Clean up signature texts?
+ * @var bool Clean up signature texts?
*
* 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
* 2) Substitute all transclusions
*/
- var $mCleanSignatures;
+ protected $mCleanSignatures;
- /**
- * Transform wiki markup when saving the page?
- */
- var $mPreSaveTransform = true;
+ /** @var bool Transform wiki markup when saving the page? */
+ protected $mPreSaveTransform = true;
- /**
- * Whether content conversion should be disabled
- */
- var $mDisableContentConversion;
+ /** @var bool Whether content conversion should be disabled */
+ protected $mDisableContentConversion;
- /**
- * Whether title conversion should be disabled
- */
- var $mDisableTitleConversion;
+ /** @var bool Whether title conversion should be disabled */
+ protected $mDisableTitleConversion;
- /**
- * Automatically number headings?
- */
- var $mNumberHeadings;
+ /** @var string Automatically number headings? */
+ protected $mNumberHeadings;
- /**
- * Thumb size preferred by the user.
- */
- var $mThumbSize;
+ /** @var string Thumb size preferred by the user. */
+ protected $mThumbSize;
- /**
- * Maximum article size of an article to be marked as "stub"
- */
+ /** @var Language Language object of the User language. */
+ protected $mUserLang;
+
+ /** @var User Stored user object */
+ protected $mUser;
+
+ /** @var bool Parsing the page for a "preview" operation on a single section? */
+ protected $mIsSectionPreview = false;
+
+ /** @var bool Parsing the printable version of the page? */
+ protected $mIsPrintable = false;
+
+ /** @var string Extra key that should be present in the caching key. */
+ protected $mExtraKey = '';
+
+ /** @var callable Function to be called when an option is accessed. */
+ protected $onAccessCallback = null;
+
+ /** @var int Maximum article size of an article to be marked as "stub" */
private $mStubThreshold;
- /**
- * Language object of the User language.
- */
- var $mUserLang;
+ function getInterwikiMagic() {
+ return $this->mInterwikiMagic;
+ }
- /**
- * @var User
- * Stored user object
- */
- var $mUser;
+ function getAllowExternalImages() {
+ return $this->mAllowExternalImages;
+ }
- /**
- * Parsing the page for a "preview" operation?
- */
- var $mIsPreview = false;
+ function getAllowExternalImagesFrom() {
+ return $this->mAllowExternalImagesFrom;
+ }
- /**
- * Parsing the page for a "preview" operation on a single section?
- */
- var $mIsSectionPreview = false;
+ function getEnableImageWhitelist() {
+ return $this->mEnableImageWhitelist;
+ }
- /**
- * Parsing the printable version of the page?
- */
- var $mIsPrintable = false;
+ function getEditSection() {
+ return $this->mEditSection;
+ }
- /**
- * Extra key that should be present in the caching key.
- */
- var $mExtraKey = '';
+ function getNumberHeadings() {
+ $this->optionUsed( 'numberheadings' );
- /**
- * Function to be called when an option is accessed.
- */
- protected $onAccessCallback = null;
+ return $this->mNumberHeadings;
+ }
+
+ function getAllowSpecialInclusion() {
+ return $this->mAllowSpecialInclusion;
+ }
+
+ function getTidy() {
+ return $this->mTidy;
+ }
+
+ function getInterfaceMessage() {
+ return $this->mInterfaceMessage;
+ }
+
+ function getTargetLanguage() {
+ return $this->mTargetLanguage;
+ }
+
+ function getMaxIncludeSize() {
+ return $this->mMaxIncludeSize;
+ }
+
+ function getMaxPPNodeCount() {
+ return $this->mMaxPPNodeCount;
+ }
+
+ function getMaxGeneratedPPNodeCount() {
+ return $this->mMaxGeneratedPPNodeCount;
+ }
+
+ function getMaxPPExpandDepth() {
+ return $this->mMaxPPExpandDepth;
+ }
+
+ function getMaxTemplateDepth() {
+ return $this->mMaxTemplateDepth;
+ }
- function getInterwikiMagic() { return $this->mInterwikiMagic; }
- function getAllowExternalImages() { return $this->mAllowExternalImages; }
- function getAllowExternalImagesFrom() { return $this->mAllowExternalImagesFrom; }
- function getEnableImageWhitelist() { return $this->mEnableImageWhitelist; }
- function getEditSection() { return $this->mEditSection; }
- function getNumberHeadings() { $this->optionUsed( 'numberheadings' );
- return $this->mNumberHeadings; }
- function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; }
- function getTidy() { return $this->mTidy; }
- function getInterfaceMessage() { return $this->mInterfaceMessage; }
- function getTargetLanguage() { return $this->mTargetLanguage; }
- function getMaxIncludeSize() { return $this->mMaxIncludeSize; }
- function getMaxPPNodeCount() { return $this->mMaxPPNodeCount; }
- function getMaxGeneratedPPNodeCount() { return $this->mMaxGeneratedPPNodeCount; }
- function getMaxPPExpandDepth() { return $this->mMaxPPExpandDepth; }
- function getMaxTemplateDepth() { return $this->mMaxTemplateDepth; }
/* @since 1.20 */
- function getExpensiveParserFunctionLimit() { return $this->mExpensiveParserFunctionLimit; }
- function getRemoveComments() { return $this->mRemoveComments; }
- function getTemplateCallback() { return $this->mTemplateCallback; }
- function getEnableLimitReport() { return $this->mEnableLimitReport; }
- function getCleanSignatures() { return $this->mCleanSignatures; }
- function getExternalLinkTarget() { return $this->mExternalLinkTarget; }
- function getDisableContentConversion() { return $this->mDisableContentConversion; }
- function getDisableTitleConversion() { return $this->mDisableTitleConversion; }
- function getThumbSize() { $this->optionUsed( 'thumbsize' );
- return $this->mThumbSize; }
- function getStubThreshold() { $this->optionUsed( 'stubthreshold' );
- return $this->mStubThreshold; }
-
- function getIsPreview() { return $this->mIsPreview; }
- function getIsSectionPreview() { return $this->mIsSectionPreview; }
- function getIsPrintable() { $this->optionUsed( 'printable' );
- return $this->mIsPrintable; }
- function getUser() { return $this->mUser; }
- function getPreSaveTransform() { return $this->mPreSaveTransform; }
+ function getExpensiveParserFunctionLimit() {
+ return $this->mExpensiveParserFunctionLimit;
+ }
+
+ function getRemoveComments() {
+ return $this->mRemoveComments;
+ }
+
+ function getTemplateCallback() {
+ return $this->mTemplateCallback;
+ }
+
+ function getEnableLimitReport() {
+ return $this->mEnableLimitReport;
+ }
+
+ function getCleanSignatures() {
+ return $this->mCleanSignatures;
+ }
+
+ function getExternalLinkTarget() {
+ return $this->mExternalLinkTarget;
+ }
+
+ function getDisableContentConversion() {
+ return $this->mDisableContentConversion;
+ }
+
+ function getDisableTitleConversion() {
+ return $this->mDisableTitleConversion;
+ }
+
+ function getThumbSize() {
+ $this->optionUsed( 'thumbsize' );
+
+ return $this->mThumbSize;
+ }
+
+ function getStubThreshold() {
+ $this->optionUsed( 'stubthreshold' );
+
+ return $this->mStubThreshold;
+ }
+
+ function getIsPreview() {
+ return $this->mIsPreview;
+ }
+
+ function getIsSectionPreview() {
+ return $this->mIsSectionPreview;
+ }
+
+ function getIsPrintable() {
+ $this->optionUsed( 'printable' );
+
+ return $this->mIsPrintable;
+ }
+
+ function getUser() {
+ return $this->mUser;
+ }
+
+ function getPreSaveTransform() {
+ return $this->mPreSaveTransform;
+ }
function getDateFormat() {
$this->optionUsed( 'dateformat' );
return $this->getUserLangObj()->getCode();
}
- function setInterwikiMagic( $x ) { return wfSetVar( $this->mInterwikiMagic, $x ); }
- function setAllowExternalImages( $x ) { return wfSetVar( $this->mAllowExternalImages, $x ); }
- function setAllowExternalImagesFrom( $x ) { return wfSetVar( $this->mAllowExternalImagesFrom, $x ); }
- function setEnableImageWhitelist( $x ) { return wfSetVar( $this->mEnableImageWhitelist, $x ); }
- function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); }
- function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); }
- function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); }
- function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); }
- function setTidy( $x ) { return wfSetVar( $this->mTidy, $x ); }
+ function setInterwikiMagic( $x ) {
+ return wfSetVar( $this->mInterwikiMagic, $x );
+ }
+
+ function setAllowExternalImages( $x ) {
+ return wfSetVar( $this->mAllowExternalImages, $x );
+ }
+
+ function setAllowExternalImagesFrom( $x ) {
+ return wfSetVar( $this->mAllowExternalImagesFrom, $x );
+ }
+
+ function setEnableImageWhitelist( $x ) {
+ return wfSetVar( $this->mEnableImageWhitelist, $x );
+ }
+
+ function setDateFormat( $x ) {
+ return wfSetVar( $this->mDateFormat, $x );
+ }
+
+ function setEditSection( $x ) {
+ return wfSetVar( $this->mEditSection, $x );
+ }
+
+ function setNumberHeadings( $x ) {
+ return wfSetVar( $this->mNumberHeadings, $x );
+ }
+
+ function setAllowSpecialInclusion( $x ) {
+ return wfSetVar( $this->mAllowSpecialInclusion, $x );
+ }
+
+ function setTidy( $x ) {
+ return wfSetVar( $this->mTidy, $x );
+ }
/** @deprecated since 1.19 */
- function setSkin( $x ) { wfDeprecated( __METHOD__, '1.19' ); }
- function setInterfaceMessage( $x ) { return wfSetVar( $this->mInterfaceMessage, $x ); }
- function setTargetLanguage( $x ) { return wfSetVar( $this->mTargetLanguage, $x, true ); }
- function setMaxIncludeSize( $x ) { return wfSetVar( $this->mMaxIncludeSize, $x ); }
- function setMaxPPNodeCount( $x ) { return wfSetVar( $this->mMaxPPNodeCount, $x ); }
- function setMaxGeneratedPPNodeCount( $x ) { return wfSetVar( $this->mMaxGeneratedPPNodeCount, $x ); }
- function setMaxTemplateDepth( $x ) { return wfSetVar( $this->mMaxTemplateDepth, $x ); }
+ function setSkin( $x ) {
+ wfDeprecated( __METHOD__, '1.19' );
+ }
+
+ function setInterfaceMessage( $x ) {
+ return wfSetVar( $this->mInterfaceMessage, $x );
+ }
+
+ function setTargetLanguage( $x ) {
+ return wfSetVar( $this->mTargetLanguage, $x, true );
+ }
+
+ function setMaxIncludeSize( $x ) {
+ return wfSetVar( $this->mMaxIncludeSize, $x );
+ }
+
+ function setMaxPPNodeCount( $x ) {
+ return wfSetVar( $this->mMaxPPNodeCount, $x );
+ }
+
+ function setMaxGeneratedPPNodeCount( $x ) {
+ return wfSetVar( $this->mMaxGeneratedPPNodeCount, $x );
+ }
+
+ function setMaxTemplateDepth( $x ) {
+ return wfSetVar( $this->mMaxTemplateDepth, $x );
+ }
+
/* @since 1.20 */
- function setExpensiveParserFunctionLimit( $x ) { return wfSetVar( $this->mExpensiveParserFunctionLimit, $x ); }
- function setRemoveComments( $x ) { return wfSetVar( $this->mRemoveComments, $x ); }
- function setTemplateCallback( $x ) { return wfSetVar( $this->mTemplateCallback, $x ); }
- function enableLimitReport( $x = true ) { return wfSetVar( $this->mEnableLimitReport, $x ); }
- function setTimestamp( $x ) { return wfSetVar( $this->mTimestamp, $x ); }
- function setCleanSignatures( $x ) { return wfSetVar( $this->mCleanSignatures, $x ); }
- function setExternalLinkTarget( $x ) { return wfSetVar( $this->mExternalLinkTarget, $x ); }
- function disableContentConversion( $x = true ) { return wfSetVar( $this->mDisableContentConversion, $x ); }
- function disableTitleConversion( $x = true ) { return wfSetVar( $this->mDisableTitleConversion, $x ); }
- function setUserLang( $x ) {
+ function setExpensiveParserFunctionLimit( $x ) {
+ return wfSetVar( $this->mExpensiveParserFunctionLimit, $x );
+ }
+
+ function setRemoveComments( $x ) {
+ return wfSetVar( $this->mRemoveComments, $x );
+ }
+
+ function setTemplateCallback( $x ) {
+ return wfSetVar( $this->mTemplateCallback, $x );
+ }
+
+ function enableLimitReport( $x = true ) {
+ return wfSetVar( $this->mEnableLimitReport, $x );
+ }
+
+ function setTimestamp( $x ) {
+ return wfSetVar( $this->mTimestamp, $x );
+ }
+
+ function setCleanSignatures( $x ) {
+ return wfSetVar( $this->mCleanSignatures, $x );
+ }
+
+ function setExternalLinkTarget( $x ) {
+ return wfSetVar( $this->mExternalLinkTarget, $x );
+ }
+
+ function disableContentConversion( $x = true ) {
+ return wfSetVar( $this->mDisableContentConversion, $x );
+ }
+
+ function disableTitleConversion( $x = true ) {
+ return wfSetVar( $this->mDisableTitleConversion, $x );
+ }
+
+ function setUserLang( $x ) {
if ( is_string( $x ) ) {
$x = Language::factory( $x );
}
+
return wfSetVar( $this->mUserLang, $x );
}
- function setThumbSize( $x ) { return wfSetVar( $this->mThumbSize, $x ); }
- function setStubThreshold( $x ) { return wfSetVar( $this->mStubThreshold, $x ); }
- function setPreSaveTransform( $x ) { return wfSetVar( $this->mPreSaveTransform, $x ); }
- function setIsPreview( $x ) { return wfSetVar( $this->mIsPreview, $x ); }
- function setIsSectionPreview( $x ) { return wfSetVar( $this->mIsSectionPreview, $x ); }
- function setIsPrintable( $x ) { return wfSetVar( $this->mIsPrintable, $x ); }
+ function setThumbSize( $x ) {
+ return wfSetVar( $this->mThumbSize, $x );
+ }
+
+ function setStubThreshold( $x ) {
+ return wfSetVar( $this->mStubThreshold, $x );
+ }
+
+ function setPreSaveTransform( $x ) {
+ return wfSetVar( $this->mPreSaveTransform, $x );
+ }
+
+ function setIsPreview( $x ) {
+ return wfSetVar( $this->mIsPreview, $x );
+ }
+
+ function setIsSectionPreview( $x ) {
+ return wfSetVar( $this->mIsSectionPreview, $x );
+ }
+
+ function setIsPrintable( $x ) {
+ return wfSetVar( $this->mIsPrintable, $x );
+ }
/**
* Extra key that should be present in the parser cache key.
* @return array
*/
public static function legacyOptions() {
- return array( 'stubthreshold', 'numberheadings', 'userlang', 'thumbsize', 'editsection', 'printable' );
+ return array(
+ 'stubthreshold',
+ 'numberheadings',
+ 'userlang',
+ 'thumbsize',
+ 'editsection',
+ 'printable'
+ );
}
/**
* @ingroup Parser
*/
class ParserOutput extends CacheTime {
- var $mText, # The output text
- $mLanguageLinks, # List of the full text of language links, in the order they appear
- $mCategories, # Map of category names to sort keys
- $mTitleText, # title text of the chosen language variant
- $mLinks = array(), # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken.
- $mTemplates = array(), # 2-D map of NS/DBK to ID for the template references. ID=zero for broken.
- $mTemplateIds = array(), # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken.
- $mImages = array(), # DB keys of the images used, in the array key only
- $mFileSearchOptions = array(), # DB keys of the images used mapped to sha1 and MW timestamp
- $mExternalLinks = array(), # External link URLs, in the key only
- $mInterwikiLinks = array(), # 2-D map of prefix/DBK (in keys only) for the inline interwiki links in the document.
- $mNewSection = false, # Show a new section link?
- $mHideNewSection = false, # Hide the new section link?
- $mNoGallery = false, # No gallery on category page? (__NOGALLERY__)
- $mHeadItems = array(), # Items to put in the <head> section
- $mModules = array(), # Modules to be loaded by the resource loader
- $mModuleScripts = array(), # Modules of which only the JS will be loaded by the resource loader
- $mModuleStyles = array(), # Modules of which only the CSSS will be loaded by the resource loader
- $mModuleMessages = array(), # Modules of which only the messages will be loaded by the resource loader
- $mJsConfigVars = array(), # JavaScript config variable for mw.config combined with this page
- $mOutputHooks = array(), # Hook tags as per $wgParserOutputHooks
- $mWarnings = array(), # Warning text to be returned to the user. Wikitext formatted, in the key only
- $mSections = array(), # Table of contents
- $mEditSectionTokens = false, # prefix/suffix markers if edit sections were output as tokens
- $mProperties = array(), # Name/value pairs to be cached in the DB
- $mTOCHTML = '', # HTML of the TOC
- $mTimestamp, # Timestamp of the revision
- $mTOCEnabled = true; # Whether TOC should be shown, can't override __NOTOC__
- private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change.
- private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
- private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
- private $mExtensionData = array(); # extra data used by extensions
- private $mLimitReportData = array(); # Parser limit report data
- private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
-
- const EDITSECTION_REGEX = '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
+ /** @var string The output text */
+ public $mText;
+
+ /** @var array List of the full text of language links; in the order they appear */
+ public $mLanguageLinks;
+
+ /** @var array Map of category names to sort keys */
+ public $mCategories;
+
+ /** @var array DB keys of the images used; in the array key only */
+ public $mImages = array();
+
+ /** @var array Modules to be loaded by the resource loader */
+ public $mModules = array();
+
+ /** @var array Name/value pairs to be cached in the DB */
+ public $mProperties = array();
+
+ /** @var string Title text of the chosen language variant */
+ protected $mTitleText;
+
+ /** @var array 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken. */
+ protected $mLinks = array();
+
+ /** @var array 2-D map of NS/DBK to ID for the template references. ID=zero for broken. */
+ protected $mTemplates = array();
+
+ /** @var array 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken. */
+ protected $mTemplateIds = array();
+
+ /** @var array DB keys of the images used mapped to sha1 and MW timestamp */
+ protected $mFileSearchOptions = array();
+
+ /** @var array External link URLs; in the key only */
+ protected $mExternalLinks = array();
+
+ /**
+ * @var array 2-D map of prefix/DBK (in keys only) for the inline interwiki
+ * links in the document.
+ */
+ protected $mInterwikiLinks = array();
+
+ /** @var bool Show a new section link? */
+ protected $mNewSection = false;
+
+ /** @var bool Hide the new section link? */
+ protected $mHideNewSection = false;
+
+ /** @var bool No gallery on category page? (__NOGALLERY__) */
+ public $mNoGallery = false;
+
+ /** @var array Items to put in the <head> section */
+ protected $mHeadItems = array();
+
+ /** @var array Modules of which only the JS will be loaded by the resource loader */
+ protected $mModuleScripts = array();
+
+ /** @var array Modules of which only the CSSS will be loaded by the resource loader */
+ protected $mModuleStyles = array();
+
+ /** @var array Modules of which only the messages will be loaded by the resource loader */
+ protected $mModuleMessages = array();
+
+ /** @var array JavaScript config variable for mw.config combined with this page */
+ protected $mJsConfigVars = array();
+
+ /** @var array Hook tags as per $wgParserOutputHooks */
+ protected $mOutputHooks = array();
+
+ /** @var array Warning text to be returned to the user. Wikitext formatted; in the key only */
+ protected $mWarnings = array();
+
+ /** @var array Table of contents */
+ protected $mSections = array();
+
+ /** @var bool Prefix/suffix markers if edit sections were output as tokens */
+ protected $mEditSectionTokens = false;
+
+ /** @var string HTML of the TOC */
+ protected $mTOCHTML = '';
+
+ /** @var string Timestamp of the revision */
+ protected $mTimestamp;
+
+ /** @var bool Whether TOC should be shown, can't override __NOTOC__ */
+ protected $mTOCEnabled = true;
+
+ /** @var string 'index' or 'noindex'? Any other value will result in no change. */
+ private $mIndexPolicy = '';
+
+ /** @var array List of ParserOptions (stored in the keys) */
+ private $mAccessedOptions = array();
+
+ /** @var array List of DataUpdate, used to save info from the page somewhere else. */
+ private $mSecondaryDataUpdates = array();
+
+ /** @var array Extra data used by extensions */
+ private $mExtensionData = array();
+
+ /** @var array Parser limit report data */
+ private $mLimitReportData = array();
+
+ /** @var array Timestamps for getTimeSinceStart() */
+ private $mParseStartTime = array();
+
+ const EDITSECTION_REGEX =
+ '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
function __construct( $text = '', $languageLinks = array(), $categoryLinks = array(),
$containsOldMagic = false, $titletext = ''
return call_user_func_array( array( $skin, 'doEditSectionLink' ), $args );
}
- function &getLanguageLinks() { return $this->mLanguageLinks; }
- function getInterwikiLinks() { return $this->mInterwikiLinks; }
- function getCategoryLinks() { return array_keys( $this->mCategories ); }
- function &getCategories() { return $this->mCategories; }
- function getTitleText() { return $this->mTitleText; }
- function getSections() { return $this->mSections; }
- function getEditSectionTokens() { return $this->mEditSectionTokens; }
- function &getLinks() { return $this->mLinks; }
- function &getTemplates() { return $this->mTemplates; }
- function &getTemplateIds() { return $this->mTemplateIds; }
- function &getImages() { return $this->mImages; }
- function &getFileSearchOptions() { return $this->mFileSearchOptions; }
- function &getExternalLinks() { return $this->mExternalLinks; }
- function getNoGallery() { return $this->mNoGallery; }
- function getHeadItems() { return $this->mHeadItems; }
- function getModules() { return $this->mModules; }
- function getModuleScripts() { return $this->mModuleScripts; }
- function getModuleStyles() { return $this->mModuleStyles; }
- function getModuleMessages() { return $this->mModuleMessages; }
+ function &getLanguageLinks() {
+ return $this->mLanguageLinks;
+ }
+
+ function getInterwikiLinks() {
+ return $this->mInterwikiLinks;
+ }
+
+ function getCategoryLinks() {
+ return array_keys( $this->mCategories );
+ }
+
+ function &getCategories() {
+ return $this->mCategories;
+ }
+
+ function getTitleText() {
+ return $this->mTitleText;
+ }
+
+ function getSections() {
+ return $this->mSections;
+ }
+
+ function getEditSectionTokens() {
+ return $this->mEditSectionTokens;
+ }
+
+ function &getLinks() {
+ return $this->mLinks;
+ }
+
+ function &getTemplates() {
+ return $this->mTemplates;
+ }
+
+ function &getTemplateIds() {
+ return $this->mTemplateIds;
+ }
+
+ function &getImages() {
+ return $this->mImages;
+ }
+
+ function &getFileSearchOptions() {
+ return $this->mFileSearchOptions;
+ }
+
+ function &getExternalLinks() {
+ return $this->mExternalLinks;
+ }
+
+ function getNoGallery() {
+ return $this->mNoGallery;
+ }
+
+ function getHeadItems() {
+ return $this->mHeadItems;
+ }
+
+ function getModules() {
+ return $this->mModules;
+ }
+
+ function getModuleScripts() {
+ return $this->mModuleScripts;
+ }
+
+ function getModuleStyles() {
+ return $this->mModuleStyles;
+ }
+
+ function getModuleMessages() {
+ return $this->mModuleMessages;
+ }
+
/** @since 1.23 */
- function getJsConfigVars() { return $this->mJsConfigVars; }
- function getOutputHooks() { return (array)$this->mOutputHooks; }
- function getWarnings() { return array_keys( $this->mWarnings ); }
- function getIndexPolicy() { return $this->mIndexPolicy; }
- function getTOCHTML() { return $this->mTOCHTML; }
- function getTimestamp() { return $this->mTimestamp; }
- function getLimitReportData() { return $this->mLimitReportData; }
- function getTOCEnabled() { return $this->mTOCEnabled; }
-
- function setText( $text ) { return wfSetVar( $this->mText, $text ); }
- function setLanguageLinks( $ll ) { return wfSetVar( $this->mLanguageLinks, $ll ); }
- function setCategoryLinks( $cl ) { return wfSetVar( $this->mCategories, $cl ); }
-
- function setTitleText( $t ) { return wfSetVar( $this->mTitleText, $t ); }
- function setSections( $toc ) { return wfSetVar( $this->mSections, $toc ); }
- function setEditSectionTokens( $t ) { return wfSetVar( $this->mEditSectionTokens, $t ); }
- function setIndexPolicy( $policy ) { return wfSetVar( $this->mIndexPolicy, $policy ); }
- function setTOCHTML( $tochtml ) { return wfSetVar( $this->mTOCHTML, $tochtml ); }
- function setTimestamp( $timestamp ) { return wfSetVar( $this->mTimestamp, $timestamp ); }
- function setTOCEnabled( $flag ) { return wfSetVar( $this->mTOCEnabled, $flag ); }
-
- function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; }
- function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; }
- function addWarning( $s ) { $this->mWarnings[$s] = 1; }
+ function getJsConfigVars() {
+ return $this->mJsConfigVars;
+ }
+
+ function getOutputHooks() {
+ return (array)$this->mOutputHooks;
+ }
+
+ function getWarnings() {
+ return array_keys( $this->mWarnings );
+ }
+
+ function getIndexPolicy() {
+ return $this->mIndexPolicy;
+ }
+
+ function getTOCHTML() {
+ return $this->mTOCHTML;
+ }
+
+ function getTimestamp() {
+ return $this->mTimestamp;
+ }
+
+ function getLimitReportData() {
+ return $this->mLimitReportData;
+ }
+
+ function getTOCEnabled() {
+ return $this->mTOCEnabled;
+ }
+
+ function setText( $text ) {
+ return wfSetVar( $this->mText, $text );
+ }
+
+ function setLanguageLinks( $ll ) {
+ return wfSetVar( $this->mLanguageLinks, $ll );
+ }
+
+ function setCategoryLinks( $cl ) {
+ return wfSetVar( $this->mCategories, $cl );
+ }
+
+ function setTitleText( $t ) {
+ return wfSetVar( $this->mTitleText, $t );
+ }
+
+ function setSections( $toc ) {
+ return wfSetVar( $this->mSections, $toc );
+ }
+
+ function setEditSectionTokens( $t ) {
+ return wfSetVar( $this->mEditSectionTokens, $t );
+ }
+
+ function setIndexPolicy( $policy ) {
+ return wfSetVar( $this->mIndexPolicy, $policy );
+ }
+
+ function setTOCHTML( $tochtml ) {
+ return wfSetVar( $this->mTOCHTML, $tochtml );
+ }
+
+ function setTimestamp( $timestamp ) {
+ return wfSetVar( $this->mTimestamp, $timestamp );
+ }
+
+ function setTOCEnabled( $flag ) {
+ return wfSetVar( $this->mTOCEnabled, $flag );
+ }
+
+ function addCategory( $c, $sort ) {
+ $this->mCategories[$c] = $sort;
+ }
+
+ function addLanguageLink( $t ) {
+ $this->mLanguageLinks[] = $t;
+ }
+
+ function addWarning( $s ) {
+ $this->mWarnings[$s] = 1;
+ }
function addOutputHook( $hook, $data = false ) {
$this->mOutputHooks[] = array( $hook, $data );
* extracted from the page's content, including a LinksUpdate object for all links stored in
* this ParserOutput object.
*
- * @note: Avoid using this method directly, use ContentHandler::getSecondaryDataUpdates() instead! The content
- * handler may provide additional update objects.
+ * @note Avoid using this method directly, use ContentHandler::getSecondaryDataUpdates()
+ * instead! The content handler may provide additional update objects.
*
* @since 1.20
*
/**
* @ingroup Parser
*/
-class Parser_DiffTest
-{
- var $parsers, $conf;
- var $shortOutput = false;
+class Parser_DiffTest {
+ /** @var array */
+ protected $parsers;
- var $dtUniqPrefix;
+ /** @var array */
+ protected $conf;
+
+ /** @var bool */
+ protected $shortOutput = false;
+
+ /** @var string */
+ protected $dtUniqPrefix;
function __construct( $conf ) {
if ( !isset( $conf['parsers'] ) ) {
function newFrame();
/**
- * Create a new custom frame for programmatic use of parameter replacement as used in some extensions
+ * Create a new custom frame for programmatic use of parameter replacement
+ * as used in some extensions.
*
* @param array $args
*
function newCustomFrame( $args );
/**
- * Create a new custom node for programmatic use of parameter replacement as used in some extensions
+ * Create a new custom node for programmatic use of parameter replacement
+ * as used in some extensions.
*
* @param array $values
*/
* @ingroup Parser
*/
class Preprocessor_DOM implements Preprocessor {
+ /** @var Parser */
+ public $parser;
- /**
- * @var Parser
- */
- var $parser;
-
- var $memoryLimit;
+ protected $memoryLimit;
const CACHE_VERSION = 1;
foreach ( $values as $k => $val ) {
if ( is_int( $k ) ) {
- $xml .= "<part><name index=\"$k\"/><value>" . htmlspecialchars( $val ) . "</value></part>";
+ $xml .= "<part><name index=\"$k\"/><value>"
+ . htmlspecialchars( $val ) . "</value></part>";
} else {
- $xml .= "<part><name>" . htmlspecialchars( $k ) . "</name>=<value>" . htmlspecialchars( $val ) . "</value></part>";
+ $xml .= "<part><name>" . htmlspecialchars( $k )
+ . "</name>=<value>" . htmlspecialchars( $val ) . "</value></part>";
}
}
*
* @param string $text The text to parse
* @param int $flags Bitwise combination of:
- * Parser::PTD_FOR_INCLUSION Handle "<noinclude>" and "<includeonly>" as if the text is being
- * included. Default is to assume a direct page view.
+ * Parser::PTD_FOR_INCLUSION Handle "<noinclude>" and "<includeonly>"
+ * as if the text is being included. Default
+ * is to assume a direct page view.
*
* The generated DOM tree must depend only on the input text and the flags.
* The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
if ( !$result ) {
// Try running the XML through UtfNormal to get rid of invalid characters
$xml = UtfNormal::cleanUp( $xml );
- // 1 << 19 == XML_PARSE_HUGE, needed so newer versions of libxml2 don't barf when the XML is >256 levels deep
+ // 1 << 19 == XML_PARSE_HUGE, needed so newer versions of libxml2
+ // don't barf when the XML is >256 levels deep.
$result = $dom->loadXML( $xml, 1 << 19 );
}
if ( $result ) {
$ignoredTags = array( 'includeonly', '/includeonly' );
$ignoredElements = array( 'noinclude' );
$xmlishElements[] = 'noinclude';
- if ( strpos( $text, '<onlyinclude>' ) !== false && strpos( $text, '</onlyinclude>' ) !== false ) {
+ if ( strpos( $text, '<onlyinclude>' ) !== false
+ && strpos( $text, '</onlyinclude>' ) !== false
+ ) {
$enableOnlyinclude = true;
}
} else {
$stack = new PPDStack;
$searchBase = "[{<\n"; #}
- $revText = strrev( $text ); // For fast reverse searches
+ // For fast reverse searches
+ $revText = strrev( $text );
$lengthText = strlen( $text );
- $i = 0; # Input pointer, starts out pointing to a pseudo-newline before the start
- $accum =& $stack->getAccum(); # Current accumulator
+ // Input pointer, starts out pointing to a pseudo-newline before the start
+ $i = 0;
+ // Current accumulator
+ $accum =& $stack->getAccum();
$accum = '<root>';
- $findEquals = false; # True to find equals signs in arguments
- $findPipe = false; # True to take notice of pipe characters
+ // True to find equals signs in arguments
+ $findEquals = false;
+ // True to take notice of pipe characters
+ $findPipe = false;
$headingIndex = 1;
- $inHeading = false; # True if $i is inside a possible heading
- $noMoreGT = false; # True if there are no more greater-than (>) signs right of $i
- $findOnlyinclude = $enableOnlyinclude; # True to ignore all input up to the next <onlyinclude>
- $fakeLineStart = true; # Do a line-start run without outputting an LF character
+ // True if $i is inside a possible heading
+ $inHeading = false;
+ // True if there are no more greater-than (>) signs right of $i
+ $noMoreGT = false;
+ // True to ignore all input up to the next <onlyinclude>
+ $findOnlyinclude = $enableOnlyinclude;
+ // Do a line-start run without outputting an LF character
+ $fakeLineStart = true;
while ( true ) {
//$this->memCheck();
if ( $found == 'angle' ) {
$matches = false;
// Handle </onlyinclude>
- if ( $enableOnlyinclude && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>' ) {
+ if ( $enableOnlyinclude
+ && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>'
+ ) {
$findOnlyinclude = true;
continue;
}
// Handle ignored tags
if ( in_array( $lowerName, $ignoredTags ) ) {
- $accum .= '<ignore>' . htmlspecialchars( substr( $text, $i, $tagEndPos - $i + 1 ) ) . '</ignore>';
+ $accum .= '<ignore>'
+ . htmlspecialchars( substr( $text, $i, $tagEndPos - $i + 1 ) )
+ . '</ignore>';
$i = $tagEndPos + 1;
continue;
}
$count = strspn( $text, '=', $i, 6 );
if ( $count == 1 && $findEquals ) {
- // DWIM: This looks kind of like a name/value separator
- // Let's let the equals handler have it and break the potential heading
- // This is heuristic, but AFAICT the methods for completely correct disambiguation are very complex.
+ // DWIM: This looks kind of like a name/value separator.
+ // Let's let the equals handler have it and break the
+ // potential heading. This is heuristic, but AFAICT the
+ // methods for completely correct disambiguation are very
+ // complex.
} elseif ( $count > 0 ) {
$piece = array(
'open' => "\n",
// A heading must be open, otherwise \n wouldn't have been in the search list
assert( '$piece->open == "\n"' );
$part = $piece->getCurrentPart();
- // Search back through the input to see if it has a proper close
- // Do this using the reversed string since the other solutions (end anchor, etc.) are inefficient
+ // Search back through the input to see if it has a proper close.
+ // Do this using the reversed string since the other solutions
+ // (end anchor, etc.) are inefficient.
$wsLength = strspn( $revText, " \t", $lengthText - $i );
$searchStart = $i - $wsLength;
if ( isset( $part->commentEnd ) && $searchStart - 1 == $part->commentEnd ) {
* @ingroup Parser
*/
class PPDStack {
- var $stack, $rootAccum;
+ /** @var array */
+ public $stack;
- /**
- * @var PPDStack
- */
- var $top;
- var $out;
- var $elementClass = 'PPDStackElement';
+ /** @var string */
+ public $rootAccum;
+
+ /** @var bool|PPDStack */
+ public $top;
+
+ /** @var */
+ public $out;
- static $false = false;
+ /** @var string */
+ protected $elementClass = 'PPDStackElement';
+
+ protected static $false = false;
function __construct() {
$this->stack = array();
* @ingroup Parser
*/
class PPDStackElement {
- var $open, // Opening character (\n for heading)
- $close, // Matching closing character
- $count, // Number of opening characters found (number of "=" for heading)
- $parts, // Array of PPDPart objects describing pipe-separated parts.
- $lineStart; // True if the open char appeared at the start of the input line. Not set for headings.
+ /** @var string Opening character (\n for heading) */
+ public $open;
+
+ /** @var string Matching closing character */
+ public $close;
+
+ /** @var int Number of opening characters found (number of "=" for heading) */
+ public $count;
+
+ /** @var array PPDPart objects describing pipe-separated parts. */
+ public $parts;
- var $partClass = 'PPDPart';
+ /**
+ * @var bool True if the open char appeared at the start of the input line.
+ * Not set for headings.
+ */
+ public $lineStart;
+
+ /** @var string */
+ protected $partClass = 'PPDPart';
function __construct( $data = array() ) {
$class = $this->partClass;
* @ingroup Parser
*/
class PPDPart {
- var $out; // Output accumulator string
+ /** @var string */
+ public $out;
// Optional member variables:
// eqpos Position of equals sign in output accumulator
* @ingroup Parser
*/
class PPFrame_DOM implements PPFrame {
+ /** @var array */
+ public $titleCache;
/**
- * @var Preprocessor
+ * @var array Hashtable listing templates which are disallowed for expansion
+ * in this frame, having been encountered previously in parent frames.
*/
- var $preprocessor;
+ public $loopCheckHash;
/**
- * @var Parser
+ * @var int Recursion depth of this frame, top = 0.
+ * Note that this is NOT the same as expansion depth in expand()
*/
- var $parser;
+ public $depth;
- /**
- * @var Title
- */
- var $title;
- var $titleCache;
+ /** @var Preprocessor */
+ protected $preprocessor;
- /**
- * Hashtable listing templates which are disallowed for expansion in this frame,
- * having been encountered previously in parent frames.
- */
- var $loopCheckHash;
+ /** @var Parser */
+ protected $parser;
- /**
- * Recursion depth of this frame, top = 0
- * Note that this is NOT the same as expansion depth in expand()
- */
- var $depth;
+ /** @var Title */
+ protected $title;
/**
* Construct a new preprocessor frame.
) {
$out .= '';
} elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
- # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
- # Not in RECOVER_COMMENTS mode (extractSections) though
+ # Add a strip marker in PST mode so that pstPass2() can
+ # run some old-fashioned regexes on the result.
+ # Not in RECOVER_COMMENTS mode (extractSections) though.
$out .= $this->parser->insertStripItem( $contextNode->textContent );
} else {
# Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
# OT_WIKI will only respect <ignore> in substed templates.
# The other output types respect it unless NO_IGNORE is set.
# extractSections() sets NO_IGNORE and so never respects it.
- if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) || ( $flags & PPFrame::NO_IGNORE ) ) {
+ if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] )
+ || ( $flags & PPFrame::NO_IGNORE )
+ ) {
$out .= $contextNode->textContent;
} else {
$out .= '';
* @ingroup Parser
*/
class PPTemplateFrame_DOM extends PPFrame_DOM {
- var $numberedArgs, $namedArgs;
+ /** @var PPFrame_DOM */
+ public $parent;
- /**
- * @var PPFrame_DOM
- */
- var $parent;
- var $numberedExpansionCache, $namedExpansionCache;
+ /** @var array */
+ protected $numberedArgs;
+
+ /** @var array */
+ protected $namedArgs;
+
+ /** @var array */
+ protected $numberedExpansionCache;
+
+ /** @var string[] */
+ protected $namedExpansionCache;
/**
* @param Preprocessor $preprocessor
* @param array $namedArgs
* @param Title $title
*/
- function __construct( $preprocessor, $parent = false, $numberedArgs = array(), $namedArgs = array(), $title = false ) {
+ function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
+ $namedArgs = array(), $title = false
+ ) {
parent::__construct( $preprocessor );
$this->parent = $parent;
}
if ( !isset( $this->numberedExpansionCache[$index] ) ) {
# No trimming for unnamed arguments
- $this->numberedExpansionCache[$index] = $this->parent->expand( $this->numberedArgs[$index], PPFrame::STRIP_COMMENTS );
+ $this->numberedExpansionCache[$index] = $this->parent->expand(
+ $this->numberedArgs[$index],
+ PPFrame::STRIP_COMMENTS
+ );
}
return $this->numberedExpansionCache[$index];
}
* @ingroup Parser
*/
class PPCustomFrame_DOM extends PPFrame_DOM {
- var $args;
+ protected $args;
function __construct( $preprocessor, $args ) {
parent::__construct( $preprocessor );
* @ingroup Parser
*/
class PPNode_DOM implements PPNode {
+ /** @var DOMElement */
+ public $node;
- /**
- * @var DOMElement
- */
- var $node;
- var $xpath;
+ /** @var DOMXPath */
+ protected $xpath;
function __construct( $node, $xpath = false ) {
$this->node = $node;
* @ingroup Parser
*/
class Preprocessor_Hash implements Preprocessor {
- /**
- * @var Parser
- */
- var $parser;
+ /** @var Parser */
+ public $parser;
const CACHE_VERSION = 1;
// Check cache.
global $wgMemc, $wgPreprocessorCacheThreshold;
- $cacheable = $wgPreprocessorCacheThreshold !== false && strlen( $text ) > $wgPreprocessorCacheThreshold;
+ $cacheable = $wgPreprocessorCacheThreshold !== false
+ && strlen( $text ) > $wgPreprocessorCacheThreshold;
+
if ( $cacheable ) {
wfProfileIn( __METHOD__ . '-cacheable' );
$ignoredTags = array( 'includeonly', '/includeonly' );
$ignoredElements = array( 'noinclude' );
$xmlishElements[] = 'noinclude';
- if ( strpos( $text, '<onlyinclude>' ) !== false && strpos( $text, '</onlyinclude>' ) !== false ) {
+ if ( strpos( $text, '<onlyinclude>' ) !== false
+ && strpos( $text, '</onlyinclude>' ) !== false
+ ) {
$enableOnlyinclude = true;
}
} else {
$stack = new PPDStack_Hash;
$searchBase = "[{<\n";
- $revText = strrev( $text ); // For fast reverse searches
+ // For fast reverse searches
+ $revText = strrev( $text );
$lengthText = strlen( $text );
- $i = 0; # Input pointer, starts out pointing to a pseudo-newline before the start
- $accum =& $stack->getAccum(); # Current accumulator
- $findEquals = false; # True to find equals signs in arguments
- $findPipe = false; # True to take notice of pipe characters
+ // Input pointer, starts out pointing to a pseudo-newline before the start
+ $i = 0;
+ // Current accumulator
+ $accum =& $stack->getAccum();
+ // True to find equals signs in arguments
+ $findEquals = false;
+ // True to take notice of pipe characters
+ $findPipe = false;
$headingIndex = 1;
- $inHeading = false; # True if $i is inside a possible heading
- $noMoreGT = false; # True if there are no more greater-than (>) signs right of $i
- $findOnlyinclude = $enableOnlyinclude; # True to ignore all input up to the next <onlyinclude>
- $fakeLineStart = true; # Do a line-start run without outputting an LF character
+ // True if $i is inside a possible heading
+ $inHeading = false;
+ // True if there are no more greater-than (>) signs right of $i
+ $noMoreGT = false;
+ // True to ignore all input up to the next <onlyinclude>
+ $findOnlyinclude = $enableOnlyinclude;
+ // Do a line-start run without outputting an LF character
+ $fakeLineStart = true;
while ( true ) {
//$this->memCheck();
if ( $found == 'angle' ) {
$matches = false;
// Handle </onlyinclude>
- if ( $enableOnlyinclude && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>' ) {
+ if ( $enableOnlyinclude
+ && substr( $text, $i, strlen( '</onlyinclude>' ) ) == '</onlyinclude>'
+ ) {
$findOnlyinclude = true;
continue;
}
$count = strspn( $text, '=', $i, 6 );
if ( $count == 1 && $findEquals ) {
- // DWIM: This looks kind of like a name/value separator
- // Let's let the equals handler have it and break the potential heading
- // This is heuristic, but AFAICT the methods for completely correct disambiguation are very complex.
+ // DWIM: This looks kind of like a name/value separator.
+ // Let's let the equals handler have it and break the potential
+ // heading. This is heuristic, but AFAICT the methods for
+ // completely correct disambiguation are very complex.
} elseif ( $count > 0 ) {
$piece = array(
'open' => "\n",
// A heading must be open, otherwise \n wouldn't have been in the search list
assert( '$piece->open == "\n"' );
$part = $piece->getCurrentPart();
- // Search back through the input to see if it has a proper close
- // Do this using the reversed string since the other solutions (end anchor, etc.) are inefficient
+ // Search back through the input to see if it has a proper close.
+ // Do this using the reversed string since the other solutions
+ // (end anchor, etc.) are inefficient.
$wsLength = strspn( $revText, " \t", $lengthText - $i );
$searchStart = $i - $wsLength;
if ( isset( $part->commentEnd ) && $searchStart - 1 == $part->commentEnd ) {
* @ingroup Parser
*/
class PPDAccum_Hash {
- var $firstNode, $lastNode;
+ public $firstNode;
+
+ public $lastNode;
function __construct() {
$this->firstNode = $this->lastNode = false;
* @ingroup Parser
*/
class PPFrame_Hash implements PPFrame {
-
/**
- * @var Parser
+ * @var int Recursion depth of this frame, top = 0
+ * Note that this is NOT the same as expansion depth in expand()
*/
- var $parser;
+ public $depth;
- /**
- * @var Preprocessor
- */
- var $preprocessor;
+ /** @var Parser */
+ protected $parser;
- /**
- * @var Title
- */
- var $title;
- var $titleCache;
+ /** @var Preprocessor */
+ protected $preprocessor;
- /**
- * Hashtable listing templates which are disallowed for expansion in this frame,
- * having been encountered previously in parent frames.
- */
- var $loopCheckHash;
+ /** @var Title */
+ protected $title;
+
+ /** @var array */
+ protected $titleCache;
/**
- * Recursion depth of this frame, top = 0
- * Note that this is NOT the same as expansion depth in expand()
+ * @var array Hashtable listing templates which are disallowed for
+ * expansion in this frame, having been encountered previously in
+ * parent frames.
*/
- var $depth;
+ protected $loopCheckHash;
/**
* Construct a new preprocessor frame.
# Double-brace expansion
$bits = $contextNode->splitTemplate();
if ( $flags & PPFrame::NO_TEMPLATES ) {
- $newIterator = $this->virtualBracketedImplode( '{{', '|', '}}', $bits['title'], $bits['parts'] );
+ $newIterator = $this->virtualBracketedImplode(
+ '{{', '|', '}}',
+ $bits['title'],
+ $bits['parts']
+ );
} else {
$ret = $this->parser->braceSubstitution( $bits, $this );
if ( isset( $ret['object'] ) ) {
# Triple-brace expansion
$bits = $contextNode->splitTemplate();
if ( $flags & PPFrame::NO_ARGS ) {
- $newIterator = $this->virtualBracketedImplode( '{{{', '|', '}}}', $bits['title'], $bits['parts'] );
+ $newIterator = $this->virtualBracketedImplode(
+ '{{{', '|', '}}}',
+ $bits['title'],
+ $bits['parts']
+ );
} else {
$ret = $this->parser->argSubstitution( $bits, $this );
if ( isset( $ret['object'] ) ) {
) {
$out .= '';
} elseif ( $this->parser->ot['wiki'] && !( $flags & PPFrame::RECOVER_COMMENTS ) ) {
- # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
- # Not in RECOVER_COMMENTS mode (extractSections) though
+ # Add a strip marker in PST mode so that pstPass2() can
+ # run some old-fashioned regexes on the result.
+ # Not in RECOVER_COMMENTS mode (extractSections) though.
$out .= $this->parser->insertStripItem( $contextNode->firstChild->value );
} else {
# Recover the literal comment in RECOVER_COMMENTS and pre+no-remove
# OT_WIKI will only respect <ignore> in substed templates.
# The other output types respect it unless NO_IGNORE is set.
# extractSections() sets NO_IGNORE and so never respects it.
- if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) || ( $flags & PPFrame::NO_IGNORE ) ) {
+ if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] )
+ || ( $flags & PPFrame::NO_IGNORE )
+ ) {
$out .= $contextNode->firstChild->value;
} else {
//$out .= '';
* @ingroup Parser
*/
class PPTemplateFrame_Hash extends PPFrame_Hash {
- var $numberedArgs, $namedArgs, $parent;
- var $numberedExpansionCache, $namedExpansionCache;
+ /** @var array */
+ protected $numberedArgs;
+
+ /** @var array */
+ protected $namedArgs;
+
+ /** @var bool|PPFrame */
+ protected $parent;
+
+ /** @var array */
+ protected $numberedExpansionCache;
+
+ /** @var */
+ protected $namedExpansionCache;
/**
* @param Preprocessor $preprocessor
* @param array $namedArgs
* @param Title $title
*/
- function __construct( $preprocessor, $parent = false, $numberedArgs = array(), $namedArgs = array(), $title = false ) {
+ function __construct( $preprocessor, $parent = false, $numberedArgs = array(),
+ $namedArgs = array(), $title = false
+ ) {
parent::__construct( $preprocessor );
$this->parent = $parent;
}
if ( !isset( $this->numberedExpansionCache[$index] ) ) {
# No trimming for unnamed arguments
- $this->numberedExpansionCache[$index] = $this->parent->expand( $this->numberedArgs[$index], PPFrame::STRIP_COMMENTS );
+ $this->numberedExpansionCache[$index] = $this->parent->expand(
+ $this->numberedArgs[$index],
+ PPFrame::STRIP_COMMENTS
+ );
}
return $this->numberedExpansionCache[$index];
}
* @ingroup Parser
*/
class PPCustomFrame_Hash extends PPFrame_Hash {
- var $args;
+ /** @var array */
+ protected $args;
function __construct( $preprocessor, $args ) {
parent::__construct( $preprocessor );
* @ingroup Parser
*/
class PPNode_Hash_Tree implements PPNode {
- var $name, $firstChild, $lastChild, $nextSibling;
+ public $name;
+
+ public $firstChild;
+
+ public $lastChild;
+
+ public $nextSibling;
function __construct( $name ) {
$this->name = $name;
* @ingroup Parser
*/
class PPNode_Hash_Text implements PPNode {
- var $value, $nextSibling;
+ public $value;
+
+ public $nextSibling;
function __construct( $value ) {
if ( is_object( $value ) ) {
return $this->nextSibling;
}
- function getChildren() { return false; }
- function getFirstChild() { return false; }
- function getChildrenOfType( $name ) { return false; }
- function getLength() { return false; }
- function item( $i ) { return false; }
- function getName() { return '#text'; }
- function splitArg() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitExt() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitHeading() { throw new MWException( __METHOD__ . ': not supported' ); }
+ function getChildren() {
+ return false;
+ }
+
+ function getFirstChild() {
+ return false;
+ }
+
+ function getChildrenOfType( $name ) {
+ return false;
+ }
+
+ function getLength() {
+ return false;
+ }
+
+ function item( $i ) {
+ return false;
+ }
+
+ function getName() {
+ return '#text';
+ }
+
+ function splitArg() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitExt() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitHeading() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
}
/**
* @ingroup Parser
*/
class PPNode_Hash_Array implements PPNode {
- var $value, $nextSibling;
+ public $value;
+
+ public $nextSibling;
function __construct( $value ) {
$this->value = $value;
return $this->value[$i];
}
- function getName() { return '#nodelist'; }
+ function getName() {
+ return '#nodelist';
+ }
function getNextSibling() {
return $this->nextSibling;
}
- function getChildren() { return false; }
- function getFirstChild() { return false; }
- function getChildrenOfType( $name ) { return false; }
- function splitArg() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitExt() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitHeading() { throw new MWException( __METHOD__ . ': not supported' ); }
+ function getChildren() {
+ return false;
+ }
+
+ function getFirstChild() {
+ return false;
+ }
+
+ function getChildrenOfType( $name ) {
+ return false;
+ }
+
+ function splitArg() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitExt() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitHeading() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
}
/**
* @ingroup Parser
*/
class PPNode_Hash_Attr implements PPNode {
- var $name, $value, $nextSibling;
+ /** @var string */
+ public $name;
+
+ /** @var string */
+ public $value;
+
+ public $nextSibling;
function __construct( $name, $value ) {
$this->name = $name;
return $this->nextSibling;
}
- function getChildren() { return false; }
- function getFirstChild() { return false; }
- function getChildrenOfType( $name ) { return false; }
- function getLength() { return false; }
- function item( $i ) { return false; }
- function splitArg() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitExt() { throw new MWException( __METHOD__ . ': not supported' ); }
- function splitHeading() { throw new MWException( __METHOD__ . ': not supported' ); }
+ function getChildren() {
+ return false;
+ }
+
+ function getFirstChild() {
+ return false;
+ }
+
+ function getChildrenOfType( $name ) {
+ return false;
+ }
+
+ function getLength() {
+ return false;
+ }
+
+ function item( $i ) {
+ return false;
+ }
+
+ function splitArg() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitExt() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
+
+ function splitHeading() {
+ throw new MWException( __METHOD__ . ': not supported' );
+ }
}
abstract public function release();
}
+// @codingStandardsIgnoreStart Squiz.Classes.ValidClassName.NotCamelCaps
class PoolCounter_Stub extends PoolCounter {
+ // @codingStandardsIgnoreEnd
+
public function __construct() {
/* No parameters needed */
}
* Also this should be on a server plenty of RAM for the working set to avoid evictions.
* Evictions could temporarily allow wait queues to double in size or temporarily cause
* pools to appear as full when they are not. Using volatile-ttl and bumping memory-samples
- * and redis.conf can be helpful otherwise.
+ * in redis.conf can be helpful otherwise.
*
* @ingroup Redis
* @since 1.23
if ( $poolCounter->slot !== null ) {
$poolCounter->release();
}
- } catch ( Exception $e ) {}
+ } catch ( Exception $e ) {
+ }
}
}
}
/** @var TransactionProfiler */
protected $trxProfiler;
- /** @var Profiler */
- public static $__instance = null; // do not call this outside Profiler and ProfileSection
+ // @codingStandardsIgnoreStart PSR2.Classes.PropertyDeclaration.Underscore
+ /** @var Profiler Do not call this outside Profiler and ProfileSection */
+ public static $__instance = null;
+ // @codingStandardsIgnoreEnd
/**
* @param array $params
if ( $useTrx ) {
$dbw->commit();
}
- } catch ( DBError $e ) {}
+ } catch ( DBError $e ) {
+ }
}
}
public function isStub() {
return true;
}
+
public function isPersistent() {
return false;
}
- public function profileIn( $fn ) {}
- public function profileOut( $fn ) {}
- public function getOutput() {}
- public function close() {}
- public function logData() {}
- public function getCurrentSection() { return ''; }
- public function transactionWritingIn( $server, $db, $id = '' ) {}
- public function transactionWritingOut( $server, $db, $id = '' ) {}
- public function getRawData() { return array(); }
+
+ public function profileIn( $fn ) {
+ }
+
+ public function profileOut( $fn ) {
+ }
+
+ public function getOutput() {
+ }
+
+ public function close() {
+ }
+
+ public function logData() {
+ }
+
+ public function getCurrentSection() {
+ return '';
+ }
+
+ public function transactionWritingIn( $server, $db, $id = '' ) {
+ }
+
+ public function transactionWritingOut( $server, $db, $id = '' ) {
+ }
+
+ public function getRawData() {
+ return array();
+ }
}
if ( $attribs['rc_type'] == RC_LOG ) {
$targetText = $rc->getTitle()->getPrefixedText();
- $comment = self::cleanupForIRC( str_replace( "[[$targetText]]", "[[\00302$targetText\00310]]", $actionComment ) );
+ $comment = self::cleanupForIRC( str_replace(
+ "[[$targetText]]",
+ "[[\00302$targetText\00310]]",
+ $actionComment
+ ) );
$flag = $attribs['rc_log_action'];
} else {
$comment = self::cleanupForIRC( $attribs['rc_comment'] );
$flag = '';
- if ( !$attribs['rc_patrolled'] && ( $wgUseRCPatrol || $attribs['rc_type'] == RC_NEW && $wgUseNPPatrol ) ) {
+ if ( !$attribs['rc_patrolled']
+ && ( $wgUseRCPatrol || $attribs['rc_type'] == RC_NEW && $wgUseNPPatrol )
+ ) {
$flag .= '!';
}
- $flag .= ( $attribs['rc_type'] == RC_NEW ? "N" : "" ) . ( $attribs['rc_minor'] ? "M" : "" ) . ( $attribs['rc_bot'] ? "B" : "" );
+ $flag .= ( $attribs['rc_type'] == RC_NEW ? "N" : "" )
+ . ( $attribs['rc_minor'] ? "M" : "" ) . ( $attribs['rc_bot'] ? "B" : "" );
}
if ( $feed['add_interwiki_prefix'] === true && $wgLocalInterwikis ) {
* @see RCFeedFormatter::getLine
*/
public function getLine( array $feed, RecentChange $rc, $actionComment ) {
- global $wgCanonicalServer, $wgScriptPath;
+ global $wgCanonicalServer, $wgServerName, $wgScriptPath;
$attrib = $rc->getAttributes();
$packet = array(
}
$packet['server_url'] = $wgCanonicalServer;
+ $packet['server_name'] = $wgServerName;
+
$packet['server_script_path'] = $wgScriptPath ?: '/';
$packet['wiki'] = wfWikiID();
* https://www.mediawiki.org/wiki/ResourceLoader
*/
class ResourceLoader {
-
- /**
- * @var int
- */
+ /** @var int */
protected static $filterCacheVersion = 7;
- /**
- * @var array
- */
+
+ /** @var array */
protected static $requiredSourceProperties = array( 'loadScript' );
- /**
- * @var array Module name/ResourceLoaderModule object pairs
- */
+ /** @var array Module name/ResourceLoaderModule object pairs */
protected $modules = array();
- /**
- * @var array Associative array mapping module name to info associative array
- */
+ /** @var array Associative array mapping module name to info associative array */
protected $moduleInfos = array();
/**
*/
protected $testModuleNames = array();
- /**
- * @var array e.g. array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) )
- */
+ /** @var array e.g. array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) ) */
protected $sources = array();
- /**
- * @var bool
- */
+ /** @var bool */
protected $hasErrors = false;
/**
wfProfileIn( __METHOD__ );
// Add 'local' source first
- $this->addSource( 'local', array( 'loadScript' => $wgLoadScript, 'apiScript' => wfScript( 'api' ) ) );
+ $this->addSource(
+ 'local',
+ array( 'loadScript' => $wgLoadScript, 'apiScript' => wfScript( 'api' ) )
+ );
// Add other sources
$this->addSource( $wgResourceLoaderSources );
// Check $name for validity
if ( !self::isValidModuleName( $name ) ) {
wfProfileOut( __METHOD__ );
- throw new MWException( "ResourceLoader module name '$name' is invalid, see ResourceLoader::isValidModuleName()" );
+ throw new MWException( "ResourceLoader module name '$name' is invalid, "
+ . "see ResourceLoader::isValidModuleName()" );
}
// Attach module
global $IP, $wgEnableJavaScriptTest;
if ( $wgEnableJavaScriptTest !== true ) {
- throw new MWException( 'Attempt to register JavaScript test modules but <code>$wgEnableJavaScriptTest</code> is false. Edit your <code>LocalSettings.php</code> to enable it.' );
+ throw new MWException( 'Attempt to register JavaScript test modules '
+ . 'but <code>$wgEnableJavaScriptTest</code> is false. '
+ . 'Edit your <code>LocalSettings.php</code> to enable it.' );
}
wfProfileIn( __METHOD__ );
$module['dependencies'][] = 'test.mediawiki.qunit.testrunner';
}
- $testModules['qunit'] = ( include "$IP/tests/qunit/QUnitTestResources.php" ) + $testModules['qunit'];
+ $testModules['qunit'] =
+ ( include "$IP/tests/qunit/QUnitTestResources.php" ) + $testModules['qunit'];
foreach ( $testModules as $id => $names ) {
// Register test modules
* @return array
*/
public function getTestModuleNames( $framework = 'all' ) {
- /// @todo api siteinfo prop testmodulenames modulenames
+ /** @todo api siteinfo prop testmodulenames modulenames */
if ( $framework == 'all' ) {
return $this->testModuleNames;
- } elseif ( isset( $this->testModuleNames[$framework] ) && is_array( $this->testModuleNames[$framework] ) ) {
+ } elseif ( isset( $this->testModuleNames[$framework] )
+ && is_array( $this->testModuleNames[$framework] )
+ ) {
return $this->testModuleNames[$framework];
} else {
return array();
$blobs = MessageBlobStore::get( $this, $modules, $context->getLanguage() );
} catch ( Exception $e ) {
MWExceptionHandler::logException( $e );
- wfDebugLog( 'resourceloader', __METHOD__ . ": pre-fetching blobs from MessageBlobStore failed: $e" );
+ wfDebugLog(
+ 'resourceloader',
+ __METHOD__ . ": pre-fetching blobs from MessageBlobStore failed: $e"
+ );
$this->hasErrors = true;
// Add exception to the output as a comment
$exceptions .= self::formatException( $e );
$scripts = $module->getScriptURLsForDebug( $context );
} else {
$scripts = $module->getScript( $context );
- // rtrim() because there are usually a few line breaks after the last ';'.
- // A new line at EOF, a new line added by ResourceLoaderFileModule::readScriptFiles, etc.
- if ( is_string( $scripts ) && strlen( $scripts ) && substr( rtrim( $scripts ), -1 ) !== ';' ) {
+ // rtrim() because there are usually a few line breaks
+ // after the last ';'. A new line at EOF, a new line
+ // added by ResourceLoaderFileModule::readScriptFiles, etc.
+ if ( is_string( $scripts )
+ && strlen( $scripts )
+ && substr( rtrim( $scripts ), -1 ) !== ';'
+ ) {
// Append semicolon to prevent weird bugs caused by files not
// terminating their statements right (bug 27054)
$scripts .= ";\n";
* @param string $script JavaScript code
* @return string
*/
- public static function makeCustomLoaderScript( $name, $version, $dependencies, $group, $source, $script ) {
+ public static function makeCustomLoaderScript( $name, $version, $dependencies,
+ $group, $source, $script
+ ) {
$script = str_replace( "\n", "\n\t", trim( $script ) );
return Xml::encodeJsCall(
"( function ( name, version, dependencies, group, source ) {\n\t$script\n} )",
* @param array $extraQuery Extra query parameters to add
* @return string URL to load.php. May be protocol-relative (if $wgLoadScript is procol-relative)
*/
- public static function makeLoaderURL( $modules, $lang, $skin, $user = null, $version = null, $debug = false, $only = null,
- $printable = false, $handheld = false, $extraQuery = array() ) {
+ public static function makeLoaderURL( $modules, $lang, $skin, $user = null,
+ $version = null, $debug = false, $only = null, $printable = false,
+ $handheld = false, $extraQuery = array()
+ ) {
global $wgLoadScript;
+
$query = self::makeLoaderQuery( $modules, $lang, $skin, $user, $version, $debug,
$only, $printable, $handheld, $extraQuery
);
*
* @return array
*/
- public static function makeLoaderQuery( $modules, $lang, $skin, $user = null, $version = null, $debug = false, $only = null,
- $printable = false, $handheld = false, $extraQuery = array() ) {
+ public static function makeLoaderQuery( $modules, $lang, $skin, $user = null,
+ $version = null, $debug = false, $only = null, $printable = false,
+ $handheld = false, $extraQuery = array()
+ ) {
$query = array(
'modules' => self::makePackedModulesString( $modules ),
'lang' => $lang,
* of a specific loader request
*/
class ResourceLoaderContext {
-
/* Protected Members */
protected $resourceLoader;
}
/**
- * Return a dummy ResourceLoaderContext object suitable for passing into things that don't "really" need a context
+ * Return a dummy ResourceLoaderContext object suitable for passing into
+ * things that don't "really" need a context.
* @return ResourceLoaderContext
*/
public static function newDummyContext() {
* ResourceLoader module based on local JavaScript/CSS files.
*/
class ResourceLoaderFileModule extends ResourceLoaderModule {
-
/* Protected Members */
/** @var string Local base path, see __construct() */
protected $localBasePath = '';
+
/** @var string Remote base path, see __construct() */
protected $remoteBasePath = '';
+
/**
* @var array List of paths to JavaScript files to always include
* @par Usage:
* @endcode
*/
protected $scripts = array();
+
/**
* @var array List of JavaScript files to include when using a specific language
* @par Usage:
* @endcode
*/
protected $languageScripts = array();
+
/**
* @var array List of JavaScript files to include when using a specific skin
* @par Usage:
* @endcode
*/
protected $skinScripts = array();
+
/**
* @var array List of paths to JavaScript files to include in debug mode
* @par Usage:
* @endcode
*/
protected $debugScripts = array();
+
/**
* @var array List of paths to JavaScript files to include in the startup module
* @par Usage:
* @endcode
*/
protected $loaderScripts = array();
+
/**
* @var array List of paths to CSS files to always include
* @par Usage:
* @endcode
*/
protected $styles = array();
+
/**
* @var array List of paths to CSS files to include when using specific skins
* @par Usage:
* @endcode
*/
protected $skinStyles = array();
+
/**
* @var array List of modules this module depends on
* @par Usage:
* @endcode
*/
protected $dependencies = array();
+
/**
* @var array List of message keys used by this module
* @par Usage:
* @endcode
*/
protected $messages = array();
+
/** @var string Name of group to load this module in */
protected $group;
+
/** @var string Position on the page to load this module at */
protected $position = 'bottom';
+
/** @var bool Link to raw files in debug mode */
protected $debugRaw = true;
+
/** @var bool Whether mw.loader.state() call should be omitted */
protected $raw = false;
+
protected $targets = array( 'desktop' );
/**
* @endcode
*/
protected $modifiedTime = array();
+
/**
* @var array Place where readStyleFile() tracks file dependencies
* @par Usage:
$result = $compiler->cachedCompile( $source );
if ( !is_array( $result ) ) {
- throw new MWException( 'LESS compiler result has type ' . gettype( $result ) . '; array expected.' );
+ throw new MWException( 'LESS compiler result has type '
+ . gettype( $result ) . '; array expected.' );
}
$this->localFileRefs += array_keys( $result['files'] );
* Abstraction for resource loader modules, with name registration and maxage functionality.
*/
abstract class ResourceLoaderModule {
-
# Type of resource
const TYPE_SCRIPTS = 'scripts';
const TYPE_STYLES = 'styles';
/**
* Helper method for calculating when this module's definition summary was last changed.
*
+ * @since 1.23
+ *
* @return int UNIX timestamp or 0 if no definition summary was provided
* by getDefinitionSummary()
*/
return $data;
}
- wfDebugLog( 'resourceloader', __METHOD__ . ": New definition hash for module {$this->getName()} in context {$context->getHash()}: $hash." );
+ wfDebugLog( 'resourceloader', __METHOD__ . ": New definition hash for module "
+ . "{$this->getName()} in context {$context->getHash()}: $hash." );
$timestamp = time();
$cache->set( $key, $timestamp );
* contain arrays and scalars as values (avoid object instances) which means
* it requires abstraction.
*
+ * @since 1.23
+ *
* @return array|null
*/
public function getDefinitionSummary( ResourceLoaderContext $context ) {
}
global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension,
- $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang,
- $wgVariantArticlePath, $wgActionPaths, $wgVersion,
+ $wgArticlePath, $wgScriptPath, $wgServer, $wgServerName,
+ $wgContLang, $wgVariantArticlePath, $wgActionPaths, $wgVersion,
$wgEnableAPI, $wgEnableWriteAPI, $wgDBname,
$wgSitename, $wgFileExtensions, $wgExtensionAssetsPath,
$wgCookiePrefix, $wgResourceLoaderMaxQueryLength,
// becoming [] instead of {} in JS (bug 34604)
'wgActionPaths' => (object)$wgActionPaths,
'wgServer' => $wgServer,
+ 'wgServerName' => $wgServerName,
'wgUserLanguage' => $context->getLanguage(),
'wgContentLanguage' => $wgContLang->getCode(),
'wgVersion' => $wgVersion,
* 'archive' table for traditionally-deleted revisions that have an
* ar_rev_id saved.
*
- * See RevDel_RevisionItem and RevDel_ArchivedRevisionItem for items.
+ * See RevDelRevisionItem and RevDelArchivedRevisionItem for items.
*/
-class RevDel_RevisionList extends RevDel_List {
- var $currentRevId;
+class RevDelRevisionList extends RevDelList {
+ /** @var int */
+ protected $currentRevId;
public function getType() {
return 'revision';
}
// Check if any requested revisions are available fully deleted.
- $archived = $db->select( array( 'archive' ), '*',
+ $archived = $db->select( array( 'archive' ), Revision::selectArchiveFields(),
array(
'ar_rev_id' => $ids
),
public function newItem( $row ) {
if ( isset( $row->rev_id ) ) {
- return new RevDel_RevisionItem( $this, $row );
+ return new RevDelRevisionItem( $this, $row );
} elseif ( isset( $row->ar_rev_id ) ) {
- return new RevDel_ArchivedRevisionItem( $this, $row );
+ return new RevDelArchivedRevisionItem( $this, $row );
} else {
// This shouldn't happen. :)
- throw new MWException( 'Invalid row type in RevDel_RevisionList' );
+ throw new MWException( 'Invalid row type in RevDelRevisionList' );
}
}
/**
* Item class for a live revision table row
*/
-class RevDel_RevisionItem extends RevDel_Item {
- var $revision;
+class RevDelRevisionItem extends RevDelItem {
+ protected $revision;
public function __construct( $list, $row ) {
parent::__construct( $list, $row );
/**
* Get the HTML link to the revision text.
- * Overridden by RevDel_ArchiveItem.
+ * Overridden by RevDelArchiveItem.
* @return string
*/
protected function getRevisionLink() {
/**
* Get the HTML link to the diff.
- * Overridden by RevDel_ArchiveItem
+ * Overridden by RevDelArchiveItem
* @return string
*/
protected function getDiffLink() {
/**
* List for archive table items, i.e. revisions deleted via action=delete
*/
-class RevDel_ArchiveList extends RevDel_RevisionList {
+class RevDelArchiveList extends RevDelRevisionList {
public function getType() {
return 'archive';
}
foreach ( $this->ids as $id ) {
$timestamps[] = $db->timestamp( $id );
}
- return $db->select( 'archive', '*',
+ return $db->select( 'archive', Revision::selectArchiveFields(),
array(
'ar_namespace' => $this->title->getNamespace(),
'ar_title' => $this->title->getDBkey(),
}
public function newItem( $row ) {
- return new RevDel_ArchiveItem( $this, $row );
+ return new RevDelArchiveItem( $this, $row );
}
public function doPreCommitUpdates() {
/**
* Item class for a archive table row
*/
-class RevDel_ArchiveItem extends RevDel_RevisionItem {
+class RevDelArchiveItem extends RevDelRevisionItem {
public function __construct( $list, $row ) {
- RevDel_Item::__construct( $list, $row );
+ RevDelItem::__construct( $list, $row );
$this->revision = Revision::newFromArchiveRow( $row,
array( 'page' => $this->list->title->getArticleID() ) );
}
/**
* Item class for a archive table row by ar_rev_id -- actually
- * used via RevDel_RevisionList.
+ * used via RevDelRevisionList.
*/
-class RevDel_ArchivedRevisionItem extends RevDel_ArchiveItem {
+class RevDelArchivedRevisionItem extends RevDelArchiveItem {
public function __construct( $list, $row ) {
- RevDel_Item::__construct( $list, $row );
+ RevDelItem::__construct( $list, $row );
$this->revision = Revision::newFromArchiveRow( $row,
array( 'page' => $this->list->title->getArticleID() ) );
/**
* List for oldimage table items
*/
-class RevDel_FileList extends RevDel_List {
+class RevDelFileList extends RevDelList {
+ /** @var array */
+ protected $storeBatch;
+
+ /** @var array */
+ protected $deleteBatch;
+
+ /** @var array */
+ protected $cleanupBatch;
+
public function getType() {
return 'oldimage';
}
return File::DELETED_FILE;
}
- var $storeBatch, $deleteBatch, $cleanupBatch;
-
/**
* @param DatabaseBase $db
* @return mixed
}
public function newItem( $row ) {
- return new RevDel_FileItem( $this, $row );
+ return new RevDelFileItem( $this, $row );
}
public function clearFileOps() {
/**
* Item class for an oldimage table row
*/
-class RevDel_FileItem extends RevDel_Item {
-
- /**
- * @var File
- */
- var $file;
+class RevDelFileItem extends RevDelItem {
+ /** @var File */
+ protected $file;
public function __construct( $list, $row ) {
parent::__construct( $list, $row );
/**
* Get the link to the file.
- * Overridden by RevDel_ArchivedFileItem.
+ * Overridden by RevDelArchivedFileItem.
* @return string
*/
protected function getLink() {
/**
* List for filearchive table items
*/
-class RevDel_ArchivedFileList extends RevDel_FileList {
+class RevDelArchivedFileList extends RevDelFileList {
public function getType() {
return 'filearchive';
}
}
public function newItem( $row ) {
- return new RevDel_ArchivedFileItem( $this, $row );
+ return new RevDelArchivedFileItem( $this, $row );
}
}
/**
* Item class for a filearchive table row
*/
-class RevDel_ArchivedFileItem extends RevDel_FileItem {
+class RevDelArchivedFileItem extends RevDelFileItem {
public function __construct( $list, $row ) {
- RevDel_Item::__construct( $list, $row );
+ RevDelItem::__construct( $list, $row );
$this->file = ArchivedFile::newFromRow( $row );
}
/**
* List for logging table items
*/
-class RevDel_LogList extends RevDel_List {
+class RevDelLogList extends RevDelList {
public function getType() {
return 'logging';
}
*/
public function doQuery( $db ) {
$ids = array_map( 'intval', $this->ids );
- return $db->select( 'logging', '*',
+ return $db->select( 'logging', array(
+ 'log_id',
+ 'log_type',
+ 'log_action',
+ 'log_timestamp',
+ 'log_user',
+ 'log_user_text',
+ 'log_namespace',
+ 'log_title',
+ 'log_page',
+ 'log_comment',
+ 'log_params',
+ 'log_deleted'
+ ),
array( 'log_id' => $ids ),
__METHOD__,
array( 'ORDER BY' => 'log_id DESC' )
}
public function newItem( $row ) {
- return new RevDel_LogItem( $this, $row );
+ return new RevDelLogItem( $this, $row );
}
public function getSuppressBit() {
/**
* Item class for a logging table row
*/
-class RevDel_LogItem extends RevDel_Item {
+class RevDelLogItem extends RevDelItem {
public function getIdField() {
return 'log_id';
}
// User links and action text
$action = $formatter->getActionText();
// Comment
- $comment = $this->list->getLanguage()->getDirMark() . Linker::commentBlock( $this->row->log_comment );
+ $comment = $this->list->getLanguage()->getDirMark()
+ . Linker::commentBlock( $this->row->log_comment );
+
if ( LogEventsList::isDeleted( $this->row, LogPage::DELETED_COMMENT ) ) {
$comment = '<span class="history-deleted">' . $comment . '</span>';
}
'type' => $logEntry->getType(),
'action' => $logEntry->getSubtype(),
);
- $ret += $logEntry->isDeleted( LogPage::DELETED_USER ) ? array( 'userhidden' => '' ) : array();
- $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT ) ? array( 'commenthidden' => '' ) : array();
- $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION ) ? array( 'actionhidden' => '' ) : array();
+ $ret += $logEntry->isDeleted( LogPage::DELETED_USER )
+ ? array( 'userhidden' => '' )
+ : array();
+ $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT )
+ ? array( 'commenthidden' => '' )
+ : array();
+ $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION )
+ ? array( 'actionhidden' => '' )
+ : array();
if ( LogEventsList::userCan( $this->row, LogPage::DELETED_ACTION, $user ) ) {
ApiQueryLogEvents::addLogParams(
/**
* Abstract base class for a list of deletable items. The list class
* needs to be able to make a query from a set of identifiers to pull
- * relevant rows, to return RevDel_Item subclasses wrapping them, and
+ * relevant rows, to return RevDelItem subclasses wrapping them, and
* to wrap bulk update operations.
*/
-abstract class RevDel_List extends RevisionListBase {
+abstract class RevDelList extends RevisionListBase {
function __construct( IContextSource $context, Title $title, array $ids ) {
parent::__construct( $context, $title );
$this->ids = $ids;
$status->itemStatuses = array();
}
+ // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
for ( $this->reset(); $this->current(); $this->next() ) {
+ // @codingStandardsIgnoreEnd
$item = $this->current();
unset( $missing[$item->getId()] );
/**
* Abstract base class for deletable items
*/
-abstract class RevDel_Item extends RevisionItemBase {
+abstract class RevDelItem extends RevisionItemBase {
/**
* Returns true if the item is "current", and the operation to set the given
* bits can't be executed for that reason
class RevisionDeleter {
/** List of known revdel types, with their corresponding list classes */
private static $allowedTypes = array(
- 'revision' => 'RevDel_RevisionList',
- 'archive' => 'RevDel_ArchiveList',
- 'oldimage' => 'RevDel_FileList',
- 'filearchive' => 'RevDel_ArchivedFileList',
- 'logging' => 'RevDel_LogList',
+ 'revision' => 'RevDelRevisionList',
+ 'archive' => 'RevDelArchiveList',
+ 'oldimage' => 'RevDelFileList',
+ 'filearchive' => 'RevDelArchivedFileList',
+ 'logging' => 'RevDelLogList',
);
/** Type map to support old log entries */
* @param IContextSource $context
* @param Title $title
* @param array $ids
- * @return RevDel_List
+ * @return RevDelList
*/
public static function createList( $typeName, IContextSource $context, Title $title, array $ids ) {
$typeName = self::getCanonicalTypeName( $typeName );
* @ingroup Search
*/
class SearchEngine {
- var $limit = 10;
- var $offset = 0;
- var $prefix = '';
- var $searchTerms = array();
- var $namespaces = array( NS_MAIN );
+ /** @var string */
+ public $prefix = '';
+
+ /** @var int[] */
+ public $namespaces = array( NS_MAIN );
+
+ /** @var int */
+ protected $limit = 10;
+
+ /** @var int */
+ protected $offset = 0;
+
+ /** @var array|string */
+ protected $searchTerms = array();
+
+ /** @var bool */
protected $showSuggestion = true;
/** @var array Feature values */
}
/**
- * Transform search term in cases when parts of the query came as different GET params (when supported)
- * e.g. for prefix queries: search=test&prefix=Main_Page/Archive -> test prefix:Main Page/Archive
+ * Transform search term in cases when parts of the query came as different
+ * GET params (when supported), e.g. for prefix queries:
+ * search=test&prefix=Main_Page/Archive -> test prefix:Main Page/Archive
*/
function transformSearchTerm( $term ) {
return $term;
$allSearchTerms = array( $searchterm );
if ( $wgContLang->hasVariants() ) {
- $allSearchTerms = array_merge( $allSearchTerms, $wgContLang->autoConvertToAllVariants( $searchterm ) );
+ $allSearchTerms = array_merge(
+ $allSearchTerms,
+ $wgContLang->autoConvertToAllVariants( $searchterm )
+ );
}
$titleResult = null;
*/
public static function getOpenSearchTemplate() {
global $wgOpenSearchTemplate, $wgCanonicalServer;
+
if ( $wgOpenSearchTemplate ) {
return $wgOpenSearchTemplate;
} else {
if ( !$ns ) {
$ns = "0";
}
- return $wgCanonicalServer . wfScript( 'api' ) . '?action=opensearch&search={searchTerms}&namespace=' . $ns;
+
+ return $wgCanonicalServer . wfScript( 'api' )
+ . '?action=opensearch&search={searchTerms}&namespace=' . $ns;
}
}
* @ingroup Search
*/
class SearchHighlighter {
- var $mCleanWikitext = true;
+ protected $mCleanWikitext = true;
function __construct( $cleanupWikitext = true ) {
$this->mCleanWikitext = $cleanupWikitext;
* @param array $terms Terms to highlight (unescaped)
* @param int $contextlines
* @param int $contextchars
- * @return tring
+ * @return string
*/
public function highlightText( $text, $terms, $contextlines, $contextchars ) {
- global $wgContLang;
- global $wgSearchHighlightBoundaries;
+ global $wgContLang, $wgSearchHighlightBoundaries;
+
$fname = __METHOD__;
if ( $text == '' ) {
foreach ( $terms as $index => $term ) {
// manually do upper/lowercase stuff for utf-8 since PHP won't do it
if ( preg_match( '/[\x80-\xff]/', $term ) ) {
- $terms[$index] = preg_replace_callback( '/./us', array( $this, 'caseCallback' ), $terms[$index] );
+ $terms[$index] = preg_replace_callback(
+ '/./us',
+ array( $this, 'caseCallback' ),
+ $terms[$index]
+ );
} else {
$terms[$index] = $term;
}
if ( $len < $targetchars - 20 ) {
// complete this line
if ( $len < strlen( $all[$index] ) ) {
- $extended[$index] = $this->extract( $all[$index], $offsets[$index], $offsets[$index] + $targetchars, $offsets[$index] );
+ $extended[$index] = $this->extract(
+ $all[$index],
+ $offsets[$index],
+ $offsets[$index] + $targetchars,
+ $offsets[$index]
+ );
$len = strlen( $extended[$index] );
}
foreach ( $snippets as $index => $line ) {
if ( $last == - 1 ) {
$extract .= $line; // first line
- } elseif ( $last + 1 == $index && $offsets[$last] + strlen( $snippets[$last] ) >= strlen( $all[$last] ) ) {
+ } elseif ( $last + 1 == $index
+ && $offsets[$last] + strlen( $snippets[$last] ) >= strlen( $all[$last] )
+ ) {
$extract .= " " . $line; // continous lines
} else {
$extract .= '<b> ... </b>' . $line;
$s = max( 0, $point - $tolerance );
$l = min( strlen( $text ), $point + $tolerance ) - $s;
$m = array();
- if ( preg_match( '/[ ,.!?~!@#$%^&*\(\)+=\-\\\|\[\]"\'<>]/', substr( $text, $s, $l ), $m, PREG_OFFSET_CAPTURE ) ) {
+
+ if ( preg_match(
+ '/[ ,.!?~!@#$%^&*\(\)+=\-\\\|\[\]"\'<>]/',
+ substr( $text, $s, $l ),
+ $m,
+ PREG_OFFSET_CAPTURE
+ ) ) {
return $m[0][1] + $s + $offset;
} else {
// check if point is on a valid first UTF8 char
}
$char = ord( $text[$point] );
}
+
return $point;
}
$text = preg_replace( "/\\{\\{([^|]+?)\\}\\}/", "", $text );
$text = preg_replace( "/\\{\\{([^|]+\\|)(.*?)\\}\\}/", "\\2", $text );
$text = preg_replace( "/\\[\\[([^|]+?)\\]\\]/", "\\1", $text );
- $text = preg_replace_callback( "/\\[\\[([^|]+\\|)(.*?)\\]\\]/", array( $this, 'linkReplace' ), $text );
+ $text = preg_replace_callback(
+ "/\\[\\[([^|]+\\|)(.*?)\\]\\]/",
+ array( $this, 'linkReplace' ),
+ $text
+ );
// $text = preg_replace("/\\[\\[([^|]+\\|)(.*?)\\]\\]/", "\\2", $text);
$text = preg_replace( "/<\/?[^>]+>/", "", $text );
$text = preg_replace( "/'''''/", "", $text );
* @access public
*/
function searchText( $term ) {
- $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), true ) ) );
+ $resultSet = $this->db->resultObject(
+ $this->db->query( $this->getQuery( $this->filter( $term ), true ) )
+ );
+
return new SqlSearchResultSet( $resultSet, $this->searchTerms );
}
* @access public
*/
function searchTitle( $term ) {
- $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
+ $resultSet = $this->db->resultObject(
+ $this->db->query( $this->getQuery( $this->filter( $term ), false ) )
+ );
+
return new SqlSearchResultSet( $resultSet, $this->searchTerms );
}
* @ingroup Search
*/
class SearchMySQL extends SearchDatabase {
- var $strictMatching = true;
- static $mMinSearchLength;
+ protected $strictMatching = true;
+
+ private static $mMinSearchLength;
/**
* Parse the user's query and transform it into an SQL fragment which will
*/
function parseQuery( $filteredText, $fulltext ) {
global $wgContLang;
+
$lc = $this->legalSearchChars(); // Minus format chars
$searchon = '';
$this->searchTerms = array();
if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
$filteredText, $m, PREG_SET_ORDER ) ) {
foreach ( $m as $bits ) {
- @list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
+ wfSuppressWarnings();
+ list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
+ wfRestoreWarnings();
if ( $nonQuoted != '' ) {
$term = $nonQuoted;
* @ingroup Search
*/
class SearchOracle extends SearchDatabase {
-
private $reservedWords = array(
'ABOUT' => 1,
'ACCUM' => 1,
return new SqlSearchResultSet( false, '' );
}
- $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), true ) ) );
+ $resultSet = $this->db->resultObject(
+ $this->db->query( $this->getQuery( $this->filter( $term ), true ) )
+ );
+
return new SqlSearchResultSet( $resultSet, $this->searchTerms );
}
return new SqlSearchResultSet( false, '' );
}
- $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
+ $resultSet = $this->db->resultObject(
+ $this->db->query( $this->getQuery( $this->filter( $term ), false ) )
+ );
+
return new SqlSearchResultSet( $resultSet, $this->searchTerms );
}
if ( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
$filteredText, $m, PREG_SET_ORDER ) ) {
foreach ( $m as $bits ) {
- @list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
+ wfSuppressWarnings();
+ list( /* all */, $modifier, $term, $nonQuoted, $wildcard ) = $bits;
+ wfRestoreWarnings();
if ( $nonQuoted != '' ) {
$term = $nonQuoted;
* @ingroup Site
*/
class MediaWikiSite extends Site {
-
const PATH_FILE = 'file_path';
const PATH_PAGE = 'page_path';
}
/**
- * Returns the normalized form of the given page title, using the normalization rules of the given site.
- * If the given title is a redirect, the redirect weill be resolved and the redirect target is returned.
+ * Returns the normalized form of the given page title, using the
+ * normalization rules of the given site. If the given title is a redirect,
+ * the redirect weill be resolved and the redirect target is returned.
*
- * @note : This actually makes an API request to the remote site, so beware that this function is slow and depends
- * on an external service.
+ * @note This actually makes an API request to the remote site, so beware
+ * that this function is slow and depends on an external service.
*
- * @note : If MW_PHPUNIT_TEST is defined, the call to the external site is skipped, and the title
- * is normalized using the local normalization rules as implemented by the Title class.
+ * @note If MW_PHPUNIT_TEST is defined, the call to the external site is
+ * skipped, and the title is normalized using the local normalization
+ * rules as implemented by the Title class.
*
* @see Site::normalizePageName
*
// Go on call the external site
if ( defined( 'MW_PHPUNIT_TEST' ) ) {
- // If the code is under test, don't call out to other sites, just normalize locally.
- // Note: this may cause results to be inconsistent with the actual normalization used by the respective remote site!
+ // If the code is under test, don't call out to other sites, just
+ // normalize locally.
+ // Note: this may cause results to be inconsistent with the actual
+ // normalization used by the respective remote site!
$t = Title::newFromText( $pageName );
return $t->getPrefixedText();
$page = static::extractPageRecord( $data, $pageName );
if ( isset( $page['missing'] ) ) {
- wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for a missing page title! " . $ret );
+ wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for a missing page title! "
+ . $ret );
return false;
}
if ( isset( $page['invalid'] ) ) {
- wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for an invalid page title! " . $ret );
+ wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for an invalid page title! "
+ . $ret );
return false;
}
return $filePath;
}
-
}
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class Site implements Serializable {
-
const TYPE_UNKNOWN = 'unknown';
const TYPE_MEDIAWIKI = 'mediawiki';
}
/**
- * Returns the main path type, that is the type of the path that should generally be used to construct links
- * to the target site.
+ * Returns the main path type, that is the type of the path that should
+ * generally be used to construct links to the target site.
*
- * This default implementation returns Site::PATH_LINK as the default path type. Subclasses can override this
- * to define a different default path type, or return false to disable site links.
+ * This default implementation returns Site::PATH_LINK as the default path
+ * type. Subclasses can override this to define a different default path
+ * type, or return false to disable site links.
*
* @since 1.21
*
* @return string[]
*/
public function getInterwikiIds() {
- return array_key_exists( self::ID_INTERWIKI, $this->localIds ) ? $this->localIds[self::ID_INTERWIKI] : array();
+ return array_key_exists( self::ID_INTERWIKI, $this->localIds )
+ ? $this->localIds[self::ID_INTERWIKI]
+ : array();
}
/**
* @return string[]
*/
public function getNavigationIds() {
- return array_key_exists( self::ID_EQUIVALENT, $this->localIds ) ? $this->localIds[self::ID_EQUIVALENT] : array();
+ return array_key_exists( self::ID_EQUIVALENT, $this->localIds )
+ ? $this->localIds[self::ID_EQUIVALENT] :
+ array();
}
/**
$this->setForward( $fields['forward'] );
$this->setInternalId( $fields['internalid'] );
}
-
}
/**
* @deprecated
*/
-class SiteObject extends Site {}
+class SiteObject extends Site {
+}
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class SiteList extends GenericArrayObject {
-
/**
* Internal site identifiers pointing to their sites offset value.
*
return $serializationData;
}
-
}
/**
* @deprecated
*/
-class SiteArray extends SiteList {}
+class SiteArray extends SiteList {
+}
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class SiteSQLStore implements SiteStore {
-
/**
* @since 1.21
*
}
if ( $siteRow->hasField( 'language' ) ) {
- $site->setLanguageCode( $siteRow->getField( 'language' ) === '' ? null : $siteRow->getField( 'language' ) );
+ $site->setLanguageCode( $siteRow->getField( 'language' ) === ''
+ ? null
+ : $siteRow->getField( 'language' )
+ );
}
if ( $siteRow->hasField( 'source' ) ) {
public function getSiteGroup( $group ) {
return $this->getSites()->getGroup( $group );
}
-
}
global $wgRecentChangesFlags;
$user = $context->getUser();
# The legend showing what the letters and stuff mean
- $legend = Xml::openElement( 'dl' ) . "\n";
+ $legend = Html::openElement( 'dl' ) . "\n";
# Iterates through them and gets the messages for both letter and tooltip
$legendItems = $wgRecentChangesFlags;
- if ( !$user->useRCPatrol() ) {
+ if ( !( $user->useRCPatrol() || $user->useNPPatrol() ) ) {
unset( $legendItems['unpatrolled'] );
}
- foreach ( $legendItems as $key => $legendInfo ) { # generate items of the legend
- $label = $legendInfo['title'];
- $letter = $legendInfo['letter'];
- $cssClass = isset( $legendInfo['class'] ) ? $legendInfo['class'] : $key;
+ foreach ( $legendItems as $key => $item ) { # generate items of the legend
+ $label = $item['title'];
+ $letter = $item['letter'];
+ $cssClass = isset( $item['class'] ) ? $item['class'] : $key;
- $legend .= Xml::element( 'dt',
+ $legend .= Html::element( 'dt',
array( 'class' => $cssClass ), $context->msg( $letter )->text()
) . "\n";
if ( $key === 'newpage' ) {
- $legend .= Xml::openElement( 'dd' );
+ $legend .= Html::openElement( 'dd' );
$legend .= $context->msg( $label )->escaped();
$legend .= ' ' . $context->msg( 'recentchanges-legend-newpage' )->parse();
- $legend .= Xml::closeElement( 'dd' ) . "\n";
+ $legend .= Html::closeElement( 'dd' ) . "\n";
} else {
- $legend .= Xml::element( 'dd', array(),
+ $legend .= Html::element( 'dd', array(),
$context->msg( $label )->text()
) . "\n";
}
}
# (+-123)
- $legend .= Xml::tags( 'dt',
+ $legend .= Html::rawElement( 'dt',
array( 'class' => 'mw-plusminus-pos' ),
$context->msg( 'recentchanges-legend-plusminus' )->parse()
) . "\n";
- $legend .= Xml::element(
+ $legend .= Html::element(
'dd',
array( 'class' => 'mw-changeslist-legend-plusminus' ),
$context->msg( 'recentchanges-label-plusminus' )->text()
) . "\n";
- $legend .= Xml::closeElement( 'dl' ) . "\n";
+ $legend .= Html::closeElement( 'dl' ) . "\n";
# Collapsibility
$legend =
* Return categorised listable special pages which are available
* for the current user, but not for everyone
*
+ * @param User|null $user User object to use or null for $wgUser
* @return array ( string => Specialpage )
*/
- public static function getRestrictedPages() {
- global $wgUser;
+ public static function getRestrictedPages( User $user = null ) {
$pages = array();
+ if ( $user === null ) {
+ global $wgUser;
+ $user = $wgUser;
+ }
foreach ( self::getList() as $name => $rec ) {
$page = self::getPage( $name );
if (
$page->isListed()
&& $page->isRestricted()
- && $page->userCanExecute( $wgUser )
+ && $page->userCanExecute( $user )
) {
$pages[$name] = $page;
}
* @ingroup SpecialPage
*/
class ActiveUsersPager extends UsersPager {
-
/**
* @var FormOptions
*/
$self = $this->getTitle();
$limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
- $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); # Form tag
+ # Form tag
+ $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
$out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n";
$out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
+ # Username field
$out .= Xml::inputLabel( $this->msg( 'activeusers-from' )->text(),
- 'username', 'offset', 20, $this->requestedUser, array( 'tabindex' => 1 ) ) . '<br />';# Username field
+ 'username', 'offset', 20, $this->requestedUser, array( 'tabindex' => 1 ) ) . '<br />';
$out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(),
'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ), array( 'tabindex' => 2 ) );
- $out .= Xml::checkLabel( $this->msg( 'activeusers-hidesysops' )->text(),
- 'hidesysops', 'hidesysops', $this->opts->getValue( 'hidesysops' ), array( 'tabindex' => 3 ) ) . '<br />';
-
- $out .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text(), array( 'tabindex' => 4 ) ) . "\n";# Submit button and form bottom
+ $out .= Xml::checkLabel(
+ $this->msg( 'activeusers-hidesysops' )->text(),
+ 'hidesysops',
+ 'hidesysops',
+ $this->opts->getValue( 'hidesysops' ),
+ array( 'tabindex' => 3 )
+ ) . '<br />';
+
+ # Submit button and form bottom
+ $out .= Xml::submitButton(
+ $this->msg( 'allpagessubmit' )->text(),
+ array( 'tabindex' => 4 )
+ ) . "\n";
$out .= Xml::closeElement( 'fieldset' );
$out .= Xml::closeElement( 'form' );
$this->getSkin()->setRelevantUser( $this->target );
}
- list( $this->previousTarget, /*...*/ ) = Block::parseTarget( $request->getVal( 'wpPreviousTarget' ) );
+ list( $this->previousTarget, /*...*/ ) =
+ Block::parseTarget( $request->getVal( 'wpPreviousTarget' ) );
$this->requestedHideUser = $request->getBool( 'wpHideUser' );
}
'Target' => array(
'type' => 'text',
'label-message' => 'ipaddressorusername',
- 'tabindex' => '1',
'id' => 'mw-bi-target',
'size' => '45',
'autofocus' => true,
'type' => !count( $suggestedDurations ) ? 'text' : 'selectorother',
'label-message' => 'ipbexpiry',
'required' => true,
- 'tabindex' => '2',
'options' => $suggestedDurations,
'other' => $this->msg( 'ipbother' )->text(),
'default' => $this->msg( 'ipb-default-expiry' )->inContentLanguage()->text(),
# Link to unblock the specified user, or to a blank unblock form
if ( $this->target instanceof User ) {
- $message = $this->msg( 'ipb-unblock-addr', wfEscapeWikiText( $this->target->getName() ) )->parse();
+ $message = $this->msg(
+ 'ipb-unblock-addr',
+ wfEscapeWikiText( $this->target->getName() )
+ )->parse();
$list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
} else {
$message = $this->msg( 'ipb-unblock' )->parse();
/**
* Determine the target of the block, and the type of target
- * TODO: should be in Block.php?
+ * @todo Should be in Block.php?
* @param string $par subpage parameter passed to setup, or data value from
* the HTMLForm
* @param WebRequest $request Optionally try and get data from a request too
# Can't watch a rangeblock
if ( $type != Block::TYPE_RANGE && $data['Watch'] ) {
- WatchAction::doWatch( Title::makeTitle( NS_USER, $target ), $performer, WatchedItem::IGNORE_USER_RIGHTS );
+ WatchAction::doWatch(
+ Title::makeTitle( NS_USER, $target ),
+ $performer,
+ WatchedItem::IGNORE_USER_RIGHTS
+ );
}
# Block constructor sanitizes certain block options on insert
return 'users';
}
}
-
-# BC @since 1.18
-class IPBlockForm extends SpecialBlock {
-}
* @ingroup SpecialPage
*/
class SpecialBlockList extends SpecialPage {
+ protected $target;
- protected $target, $options;
+ protected $options;
function __construct() {
parent::__construct( 'BlockList' );
foreach ( $otherBlockLink as $link ) {
$list .= Html::rawElement( 'li', array(), $link ) . "\n";
}
- $out->addHTML( Html::rawElement( 'ul', array( 'class' => 'mw-ipblocklist-otherblocks' ), $list ) . "\n" );
+ $out->addHTML( Html::rawElement(
+ 'ul',
+ array( 'class' => 'mw-ipblocklist-otherblocks' ),
+ $list
+ ) . "\n" );
}
}
}
// Let folks pick an explicit limit not from our list, as long as it's a real numbr.
- if ( !in_array( $value, $this->mParams['options'] ) && $value == intval( $value ) && $value > 0 ) {
+ if ( !in_array( $value, $this->mParams['options'] )
+ && $value == intval( $value )
+ && $value > 0
+ ) {
// This adds the explicitly requested limit value to the drop-down,
// then makes sure it's sorted correctly so when we output the list
// later, the custom option doesn't just show up last.
- $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] = intval( $value );
+ $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] =
+ intval( $value );
asort( $this->mParams['options'] );
}
* @ingroup SpecialPage
*/
class SpecialBookSources extends SpecialPage {
-
/**
* ISBN passed to the page, if any
*/
$this->getOutput()->addHTML( $this->makeForm() );
if ( strlen( $this->isbn ) > 0 ) {
if ( !self::isValidISBN( $this->isbn ) ) {
- $this->getOutput()->wrapWikiMsg( "<div class=\"error\">\n$1\n</div>", 'booksources-invalid-isbn' );
+ $this->getOutput()->wrapWikiMsg(
+ "<div class=\"error\">\n$1\n</div>",
+ 'booksources-invalid-isbn'
+ );
}
$this->showList();
}
global $wgScript;
$form = Html::openElement( 'fieldset' ) . "\n";
- $form .= Html::element( 'legend', array(), $this->msg( 'booksources-search-legend' )->text() ) . "\n";
+ $form .= Html::element(
+ 'legend',
+ array(),
+ $this->msg( 'booksources-search-legend' )->text()
+ ) . "\n";
$form .= Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) . "\n";
$form .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) . "\n";
- $form .= '<p>' . Xml::inputLabel( $this->msg( 'booksources-isbn' )->text(), 'isbn', 'isbn', 20, $this->isbn, array( 'autofocus' => true ) );
+ $form .= '<p>' . Xml::inputLabel(
+ $this->msg( 'booksources-isbn' )->text(),
+ 'isbn',
+ 'isbn',
+ 20,
+ $this->isbn,
+ array( 'autofocus' => true )
+ );
$form .= ' ' . Xml::submitButton( $this->msg( 'booksources-go' )->text() ) . "</p>\n";
$form .= Html::closeElement( 'form' ) . "\n";
$form .= Html::closeElement( 'fieldset' ) . "\n";
* @ingroup SpecialPage
*/
class BrokenRedirectsPage extends QueryPage {
-
function __construct( $name = 'BrokenRedirects' ) {
parent::__construct( $name );
}
);
}
- $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( $links ) )->escaped();
+ $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
+ ->pipeList( $links ) )->escaped();
$out .= " {$arr} {$to}";
return $out;
* @since 1.20
*/
abstract class SpecialCachedPage extends SpecialPage implements ICacheHelper {
-
/**
* CacheHelper object to which we forward the non-SpecialPage specific caching work.
* Initialized in startCache.
* @param string|null $key
*/
public function addCachedHTML( $computeFunction, $args = array(), $key = null ) {
- $this->getOutput()->addHTML( $this->cacheHelper->getCachedValue( $computeFunction, $args, $key ) );
+ $this->getOutput()->addHTML( $this->cacheHelper->getCachedValue(
+ $computeFunction,
+ $args,
+ $key
+ ) );
}
/**
}
/**
- * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
+ * Sets the time to live for the cache, in seconds or a unix timestamp
+ * indicating the point of expiry.
*
* @since 1.20
*
* @ingroup SpecialPage
*/
class SpecialChangeEmail extends UnlistedSpecialPage {
-
/**
* Users password
* @var string
$throttleCount = LoginForm::incLoginThrottle( $user->getName() );
if ( $throttleCount === true ) {
$lang = $this->getLanguage();
- $this->error( array( 'changeemail-throttled', $lang->formatDuration( $wgPasswordAttemptThrottle['seconds'] ) ) );
+ $this->error( array(
+ 'changeemail-throttled',
+ $lang->formatDuration( $wgPasswordAttemptThrottle['seconds'] )
+ ) );
return false;
}
global $wgRequirePasswordforEmailChange;
- if ( $wgRequirePasswordforEmailChange && !$user->checkTemporaryPassword( $pass ) && !$user->checkPassword( $pass ) ) {
+ if ( $wgRequirePasswordforEmailChange
+ && !$user->checkTemporaryPassword( $pass )
+ && !$user->checkPassword( $pass )
+ ) {
$this->error( 'wrongpassword' );
return false;
* @ingroup SpecialPage
*/
class SpecialChangePassword extends FormSpecialPage {
-
- protected $mUserName, $mDomain;
+ protected $mUserName;
+ protected $mDomain;
// Optional Wikitext Message to show above the password change form
protected $mPreTextMessage = null;
return false;
}
-
if ( $request->getCheck( 'wpCancel' ) ) {
$titleObj = Title::newFromText( $request->getVal( 'returnto' ) );
if ( !$titleObj instanceof Title ) {
# Show user names for /newbies as there may be different users.
# Note that we already excluded rows with hidden user names.
if ( $this->contribs == 'newbie' ) {
- $userlink = ' . . ' . $lang->getDirMark() . Linker::userLink( $rev->getUser(), $rev->getUserText() );
+ $userlink = ' . . ' . $lang->getDirMark()
+ . Linker::userLink( $rev->getUser(), $rev->getUserText() );
$userlink .= ' ' . $this->msg( 'parentheses' )->rawParams(
Linker::userTalkLink( $rev->getUser(), $rev->getUserText() ) )->escaped() . ' ';
} else {
*/
class SpecialCreateAccount extends SpecialRedirectToSpecial {
function __construct() {
- parent::__construct( 'CreateAccount', 'Userlogin', 'signup', array( 'returnto', 'returntoquery', 'uselang' ) );
+ parent::__construct(
+ 'CreateAccount',
+ 'Userlogin',
+ 'signup',
+ array( 'returnto', 'returntoquery', 'uselang' )
+ );
}
// No reason to hide this link on Special:Specialpages
$out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
}
break;
+ case self::EDIT_CLEAR:
+ $out->setPageTitle( $this->msg( 'watchlistedit-clear-title' ) );
+ $form = $this->getClearForm();
+ if ( $form->show() ) {
+ $out->addHTML( $this->successMessage );
+ $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
+ }
+ break;
case self::EDIT_NORMAL:
default:
return true;
}
+ public function submitClear( $data ) {
+ $current = $this->getWatchlist();
+ $this->clearWatchlist();
+ $this->getUser()->invalidateCache();
+ $this->successMessage = $this->msg( 'watchlistedit-clear-done' )->parse();
+ $this->successMessage .= ' ' . $this->msg( 'watchlistedit-clear-removed' )
+ ->numParams( count( $current ) )->parse();
+ $this->showTitles( $current, $this->successMessage );
+
+ return true;
+}
+
/**
* Print out a list of linked titles
*
$talk = $this->msg( 'talkpagelinktext' )->escaped();
// Do a batch existence check
$batch = new LinkBatch();
+ if (count($titles) >= 100) {
+ $output = wfMessage( 'watchlistedit-too-many' )->parse();
+ return;
+ }
foreach ( $titles as $title ) {
if ( !$title instanceof Title ) {
$title = Title::newFromText( $title );
$context->setTitle( $this->getPageTitle() ); // Remove subpage
$form = new EditWatchlistNormalHTMLForm( $fields, $context );
$form->setSubmitTextMsg( 'watchlistedit-normal-submit' );
- # Used message keys: 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit'
+ # Used message keys:
+ # 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit'
$form->setSubmitTooltip( 'watchlistedit-normal-submit' );
$form->setWrapperLegendMsg( 'watchlistedit-normal-legend' );
$form->addHeaderText( $this->msg( 'watchlistedit-normal-explain' )->parse() );
);
}
- wfRunHooks( 'WatchlistEditorBuildRemoveLine', array( &$tools, $title, $title->isRedirect(), $this->getSkin() ) );
+ wfRunHooks(
+ 'WatchlistEditorBuildRemoveLine',
+ array( &$tools, $title, $title->isRedirect(), $this->getSkin() )
+ );
return $link . " (" . $this->getLanguage()->pipeList( $tools ) . ")";
}
return $form;
}
+ /**
+ * Get a form for clearing the watchlist
+ *
+ * @return HTMLForm
+ */
+ protected function getClearForm() {
+ $context = new DerivativeContext( $this->getContext() );
+ $context->setTitle( $this->getPageTitle( 'clear' ) ); // Reset subpage
+ $form = new HTMLForm( array(), $context );
+ $form->setSubmitTextMsg( 'watchlistedit-clear-submit' );
+ # Used message keys: 'accesskey-watchlistedit-clear-submit', 'tooltip-watchlistedit-clear-submit'
+ $form->setSubmitTooltip( 'watchlistedit-clear-submit' );
+ $form->setWrapperLegendMsg( 'watchlistedit-clear-legend' );
+ $form->addHeaderText( $this->msg( 'watchlistedit-clear-explain' )->parse() );
+ $form->setSubmitCallback( array( $this, 'submitClear' ) );
+
+ return $form;
+ }
+
/**
* Determine whether we are editing the watchlist, and if so, what
* kind of editing operation
switch ( $mode ) {
case 'clear':
case self::EDIT_CLEAR:
+ return self::EDIT_CLEAR;
case 'raw':
case self::EDIT_RAW:
return self::EDIT_RAW;
'view' => array( 'Watchlist', false ),
'edit' => array( 'EditWatchlist', false ),
'raw' => array( 'EditWatchlist', 'raw' ),
+ 'clear' => array( 'EditWatchlist', 'clear' ),
);
foreach ( $modes as $mode => $arr ) {
}
}
-# B/C since 1.18
-class WatchlistEditor extends SpecialEditWatchlist {
-}
-
/**
* Extend HTMLForm purely so we can have a more sane way of getting the section headers
*/
) . '<br />';
}
- // Enable this when we can do something useful exporting/importing image information. :)
- //$form .= Xml::checkLabel( $this->msg( 'export-images' )->text(), 'images', 'wpExportImages', false ) . '<br />';
+ /* Enable this when we can do something useful exporting/importing image information.
+ $form .= Xml::checkLabel(
+ $this->msg( 'export-images' )->text(),
+ 'images',
+ 'wpExportImages',
+ false
+ ) . '<br />';
+ */
$form .= Xml::checkLabel(
$this->msg( 'export-download' )->text(),
'wpDownload',
* @return array
*/
private function getPageLinks( $inputPages, $pageSet, $depth ) {
+ // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
for ( ; $depth > 0; --$depth ) {
+ // @codingStandardsIgnoreEnd
$pageSet = $this->getLinks(
$inputPages, $pageSet, 'pagelinks',
array( 'namespace' => 'pl_namespace', 'title' => 'pl_title' ),
$sourceName = $request->getVal( "source" );
$this->logcomment = $request->getText( 'log-comment' );
- $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $request->getIntOrNull( 'pagelink-depth' );
+ $this->pageLinkDepth = $wgExportMaxLinkDepth == 0
+ ? 0
+ : $request->getIntOrNull( 'pagelink-depth' );
$this->rootpage = $request->getText( 'rootpage' );
$user = $this->getUser();
</tr>
<tr>
<td class='mw-label'>" .
- Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage-upload' ) .
+ Xml::label(
+ $this->msg( 'import-interwiki-rootpage' )->text(),
+ 'mw-interwiki-rootpage-upload'
+ ) .
"</td>
<td class='mw-input'>" .
Xml::input( 'rootpage', 50, $this->rootpage,
}
function reportNotice( $msg, array $params ) {
- $this->getOutput()->addHTML( Html::element( 'li', array(), $this->msg( $msg, $params )->text() ) );
+ $this->getOutput()->addHTML(
+ Html::element( 'li', array(), $this->msg( $msg, $params )->text() )
+ );
}
function reportLogItem( /* ... */ ) {
$detail = $this->msg( 'import-logentry-upload-detail' )->numParams(
$successCount )->inContentLanguage()->text();
if ( $this->reason ) {
- $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason;
+ $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
+ . $this->reason;
}
$log->addEntry( 'upload', $title, $detail, array(), $this->getUser() );
} else {
$detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams(
$successCount )->params( $interwiki )->inContentLanguage()->text();
if ( $this->reason ) {
- $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->reason;
+ $detail .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
+ . $this->reason;
}
$log->addEntry( 'interwiki', $title, $detail, array(), $this->getUser() );
}
$comment = $detail; // quick
$dbw = wfGetDB( DB_MASTER );
$latest = $title->getLatestRevID();
- $nullRevision = Revision::newNullRevision( $dbw, $title->getArticleID(), $comment, true, $this->getUser() );
+ $nullRevision = Revision::newNullRevision(
+ $dbw,
+ $title->getArticleID(),
+ $comment,
+ true,
+ $this->getUser()
+ );
+
if ( !is_null( $nullRevision ) ) {
$nullRevision->insertOn( $dbw );
$page = WikiPage::factory( $title );
# Update page record
$page->updateRevisionOn( $dbw, $nullRevision );
- wfRunHooks( 'NewRevisionFromEditComplete', array( $page, $nullRevision, $latest, $this->getUser() ) );
+ wfRunHooks(
+ 'NewRevisionFromEditComplete',
+ array( $page, $nullRevision, $latest, $this->getUser() )
+ );
}
} else {
$this->getOutput()->addHTML( "<li>" . Linker::linkKnown( $title ) . " " .
* @ingroup SpecialPage
*/
class SpecialJavaScriptTest extends SpecialPage {
-
/**
- * @var $frameworks Array: Mapping of framework ids and their initilizer methods
+ * @var array Mapping of framework ids and their initilizer methods
* in this class. If a framework is requested but not in this array,
* the 'unknownframework' error is served.
*/
- static $frameworks = array(
+ private static $frameworks = array(
'qunit' => 'initQUnitTesting',
);
* @ingroup SpecialPage Pager
*/
class ImageListPager extends TablePager {
- var $mFieldNames = null;
+ protected $mFieldNames = null;
+
// Subclasses should override buildQueryConds instead of using $mQueryConds variable.
- var $mQueryConds = array();
- var $mUserName = null;
- var $mSearch = '';
- var $mIncluding = false;
- var $mShowAll = false;
- var $mTableName = 'image';
+ protected $mQueryConds = array();
+
+ protected $mUserName = null;
+
+ protected $mSearch = '';
+
+ protected $mIncluding = false;
+
+ protected $mShowAll = false;
+
+ protected $mTableName = 'image';
function __construct( IContextSource $context, $userName = null, $search = '',
$including = false, $showAll = false
function reallyDoQuery( $offset, $limit, $asc ) {
$prevTableName = $this->mTableName;
$this->mTableName = 'image';
- list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo( $offset, $limit, $asc );
+ list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
+ $this->buildQueryInfo( $offset, $limit, $asc );
$imageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
$this->mTableName = $prevTableName;
}
$this->mIndexField = 'oi_' . substr( $this->mIndexField, 4 );
- list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo( $offset, $limit, $asc );
+ list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
+ $this->buildQueryInfo( $offset, $limit, $asc );
$oldimageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
$this->mTableName = $prevTableName;
}
}
}
+
+ // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
for ( ; $i < $limit && $topRes1; $i++ ) {
+ // @codingStandardsIgnoreEnd
$resultArray[] = $topRes1;
$topRes1 = $res1->next();
}
+
+ // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
for ( ; $i < $limit && $topRes2; $i++ ) {
+ // @codingStandardsIgnoreEnd
$resultArray[] = $topRes2;
$topRes2 = $res2->next();
}
* @author Petr Kadlec <mormegil@centrum.cz>
*/
class SpecialListGroupRights extends SpecialPage {
- /**
- * Constructor
- */
function __construct() {
parent::__construct( 'Listgrouprights' );
}
$addgroups = isset( $wgAddGroups[$group] ) ? $wgAddGroups[$group] : array();
$removegroups = isset( $wgRemoveGroups[$group] ) ? $wgRemoveGroups[$group] : array();
$addgroupsSelf = isset( $wgGroupsAddToSelf[$group] ) ? $wgGroupsAddToSelf[$group] : array();
- $removegroupsSelf = isset( $wgGroupsRemoveFromSelf[$group] ) ? $wgGroupsRemoveFromSelf[$group] : array();
+ $removegroupsSelf = isset( $wgGroupsRemoveFromSelf[$group] )
+ ? $wgGroupsRemoveFromSelf[$group]
+ : array();
$id = $group == '*' ? false : Sanitizer::escapeId( $group );
- $out->addHTML( Html::rawElement( 'tr', array( 'id' => $id ),
- "
+ $out->addHTML( Html::rawElement( 'tr', array( 'id' => $id ), "
<td>$grouppage$grouplink</td>
<td>" .
$this->formatPermissions( $permissions, $revoke, $addgroups, $removegroups,
* @ingroup SpecialPage
*/
class SpecialLockdb extends FormSpecialPage {
- var $reason = '';
+ protected $reason = '';
public function __construct() {
parent::__construct( 'Lockdb', 'siteadmin' );
$type = $opts->getValue( 'type' );
if ( !LogPage::isLogType( $type ) ) {
$opts->setValue( 'type', '' );
- } elseif ( isset( $wgLogRestrictions[$type] ) && !$this->getUser()->isAllowed( $wgLogRestrictions[$type] ) ) {
+ } elseif ( isset( $wgLogRestrictions[$type] )
+ && !$this->getUser()->isAllowed( $wgLogRestrictions[$type] )
+ ) {
throw new PermissionsError( $wgLogRestrictions[$type] );
}
* @ingroup SpecialPage
*/
class SpecialMergeHistory extends SpecialPage {
- var $mAction, $mTarget, $mDest, $mTimestamp, $mTargetID, $mDestID, $mComment;
+ /** @var string */
+ protected $mAction;
- /**
- * @var Title
- */
- var $mTargetObj, $mDestObj;
+ /** @var string */
+ protected $mTarget;
+
+ /** @var string */
+ protected $mDest;
+
+ /** @var string */
+ protected $mTimestamp;
+
+ /** @var int */
+ protected $mTargetID;
+
+ /** @var int */
+ protected $mDestID;
+
+ /** @var string */
+ protected $mComment;
+
+ /** @var bool Was posted? */
+ protected $mMerge;
+
+ /** @var bool Was submitted? */
+ protected $mSubmitted;
+
+ /** @var Title */
+ protected $mTargetObj;
+
+ /** @var Title */
+ protected $mDestObj;
public function __construct() {
parent::__construct( 'MergeHistory', 'mergehistory' );
}
$this->mComment = $request->getText( 'wpComment' );
- $this->mMerge = $request->wasPosted() && $this->getUser()->matchEditToken( $request->getVal( 'wpEditToken' ) );
+ $this->mMerge = $request->wasPosted()
+ && $this->getUser()->matchEditToken( $request->getVal( 'wpEditToken' ) );
+
// target page
if ( $this->mSubmitted ) {
$this->mTargetObj = Title::newFromURL( $this->mTarget );
<tr>
<td> </td>
<td class="mw-submit">' .
- Xml::submitButton( $this->msg( 'mergehistory-submit' )->text(), array( 'name' => 'merge', 'id' => 'mw-merge-submit' ) ) .
+ Xml::submitButton(
+ $this->msg( 'mergehistory-submit' )->text(),
+ array( 'name' => 'merge', 'id' => 'mw-merge-submit' )
+ ) .
'</td>
</tr>' .
Xml::closeElement( 'table' ) .
$comment = Linker::revComment( $rev );
return Html::rawElement( 'li', array(),
- $this->msg( 'mergehistory-revisionrow' )->rawParams( $checkBox, $last, $pageLink, $userLink, $stxt, $comment )->escaped() );
+ $this->msg( 'mergehistory-revisionrow' )
+ ->rawParams( $checkBox, $last, $pageLink, $userLink, $stxt, $comment )->escaped() );
}
function merge() {
}
class MergeHistoryPager extends ReverseChronologicalPager {
- public $mForm, $mConds;
+ /** @var IContextSource */
+ public $mForm;
+
+ /** @var array */
+ public $mConds;
function __construct( $form, $conds = array(), $source, $dest ) {
$this->mForm = $form;
* @ingroup SpecialPage
*/
class MovePageForm extends UnlistedSpecialPage {
- /**
- * Objects
- * @var Title
- */
- var $oldTitle, $newTitle;
- // Text input
- var $reason;
+ /** @var Title */
+ protected $oldTitle;
+
+ /** @var Title */
+ protected $newTitle;
+
+
+ /** @var string Text input */
+ protected $reason;
+
// Checks
- var $moveTalk, $deleteAndMove, $moveSubpages, $fixRedirects, $leaveRedirect, $moveOverShared;
+
+ /** @var bool */
+ protected $moveTalk;
+
+ /** @var bool */
+ protected $deleteAndMove;
+
+ /** @var bool */
+ protected $moveSubpages;
+
+ /** @var bool */
+ protected $fixRedirects;
+
+ /** @var bool */
+ protected $leaveRedirect;
+
+ /** @var bool */
+ protected $moveOverShared;
private $watch = false;
"<div class=\"error mw-moveuserpage-warning\">\n$1\n</div>",
'moveuserpage-warning'
);
+ } elseif ( $this->oldTitle->getNamespace() == NS_CATEGORY ) {
+ $out->wrapWikiMsg(
+ "<div class=\"error mw-movecategorypage-warning\">\n$1\n</div>",
+ 'movecategorypage-warning'
+ );
}
$out->addWikiMsg( $wgFixDoubleRedirects ?
);
$newLink = Linker::linkKnown( $newSubpage );
- $extraOutput[] = $this->msg( 'movepage-page-moved' )->rawParams( $oldLink, $newLink )->escaped();
+ $extraOutput[] = $this->msg( 'movepage-page-moved' )
+ ->rawParams( $oldLink, $newLink )->escaped();
++$count;
if ( $count >= $wgMaximumMovedPages ) {
- $extraOutput[] = $this->msg( 'movepage-max-pages' )->numParams( $wgMaximumMovedPages )->escaped();
+ $extraOutput[] = $this->msg( 'movepage-max-pages' )
+ ->numParams( $wgMaximumMovedPages )->escaped();
break;
}
} else {
$oldLink = Linker::linkKnown( $oldSubpage );
$newLink = Linker::link( $newSubpage );
- $extraOutput[] = $this->msg( 'movepage-page-unmoved' )->rawParams( $oldLink, $newLink )->escaped();
+ $extraOutput[] = $this->msg( 'movepage-page-unmoved' )
+ ->rawParams( $oldLink, $newLink )->escaped();
}
}
}
/**
* @var ImageGallery
*/
- var $gallery;
+ protected $gallery;
function __construct( IContextSource $context, $par = null ) {
$this->like = $context->getRequest()->getText( 'like' );
* @ingroup SpecialPage
*/
class SpecialNewpages extends IncludableSpecialPage {
- // Stored objects
-
/**
* @var FormOptions
*/
protected $opts;
protected $customFilters;
- // Some internal settings
protected $showNavigation = false;
public function __construct() {
$oldTitleText = $this->msg( 'rc-old-title' )->params( $oldTitleText )->escaped();
}
- return "<li{$css}>{$time} {$dm}{$plink} {$hist} {$dm}{$length} {$dm}{$ulink} {$comment} {$tagDisplay} {$oldTitleText}</li>\n";
+ return "<li{$css}>{$time} {$dm}{$plink} {$hist} {$dm}{$length} "
+ . "{$dm}{$ulink} {$comment} {$tagDisplay} {$oldTitleText}</li>\n";
}
/**
* @ingroup SpecialPage
*/
class SpecialProtectedpages extends SpecialPage {
-
protected $IdLevel = 'level';
protected $IdType = 'type';
);
} else {
$username = UserCache::singleton()->getProp( $value, 'name' );
- if ( LogEventsList::userCanBitfield( $row->log_deleted, LogPage::DELETED_USER, $this->getUser() ) ) {
+ if ( LogEventsList::userCanBitfield(
+ $row->log_deleted,
+ LogPage::DELETED_USER,
+ $this->getUser()
+ ) ) {
if ( $username === false ) {
$formatted = htmlspecialchars( $value );
} else {
$this->msg( 'protectedpages-unknown-reason' )->escaped()
);
} else {
- if ( LogEventsList::userCanBitfield( $row->log_deleted, LogPage::DELETED_COMMENT, $this->getUser() ) ) {
+ if ( LogEventsList::userCanBitfield(
+ $row->log_deleted,
+ LogPage::DELETED_COMMENT,
+ $this->getUser()
+ ) ) {
$formatted = Linker::formatComment( $value !== null ? $value : '' );
} else {
$formatted = $this->msg( 'rev-deleted-comment' )->escaped();
/** @var array UI Labels about the current type */
private $typeLabels;
- /** @var RevDel_List RevDel_List object, storing the list of items to be deleted/undeleted */
+ /** @var RevDelList RevDelList object, storing the list of items to be deleted/undeleted */
private $revDelList;
/** @var bool Whether user is allowed to perform the action */
// $this->ids = array_map( 'intval', $this->ids );
$this->ids = array_unique( array_filter( $this->ids ) );
- if ( $request->getVal( 'action' ) == 'historysubmit' || $request->getVal( 'action' ) == 'revisiondelete' ) {
+ if ( $request->getVal( 'action' ) == 'historysubmit'
+ || $request->getVal( 'action' ) == 'revisiondelete'
+ ) {
// For show/hide form submission from history page
// Since we are access through index.php?title=XXX&action=historysubmit
// getFullTitle() will contain the target title and not our title
$this->mIsAllowed = $user->isAllowed( RevisionDeleter::getRestriction( $this->typeName ) );
# Allow the list type to adjust the passed target
- $this->targetObj = RevisionDeleter::suggestTarget( $this->typeName, $this->targetObj, $this->ids );
+ $this->targetObj = RevisionDeleter::suggestTarget(
+ $this->typeName,
+ $this->targetObj,
+ $this->ids
+ );
$this->otherReason = $request->getVal( 'wpReason' );
# We need a target page!
/**
* Show a deleted file version requested by the visitor.
- * TODO Mostly copied from Special:Undelete. Refactor.
+ * @todo Mostly copied from Special:Undelete. Refactor.
* @param string $archiveName
*/
protected function tryShowFile( $archiveName ) {
# a user without appropriate permissions can toddle off and
# nab the image, and Squid will serve it
$this->getRequest()->response()->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
- $this->getRequest()->response()->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
+ $this->getRequest()->response()->header(
+ 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate'
+ );
$this->getRequest()->response()->header( 'Pragma: no-cache' );
$key = $oimage->getStorageKey();
/**
* Get the list object for this request
- * @return RevDel_List
+ * @return RevDelList
*/
protected function getList() {
if ( is_null( $this->revDelList ) ) {
$numRevisions = 0;
// Live revisions...
$list = $this->getList();
+ // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
for ( $list->reset(); $list->current(); $list->next() ) {
+ // @codingStandardsIgnoreEnd
$item = $list->current();
+
if ( !$item->canView() ) {
if ( !$this->submitClicked ) {
throw new PermissionsError( 'suppressrevision' );
}
$userAllowed = false;
}
+
$numRevisions++;
$this->getOutput()->addHTML( $item->getHTML() );
}
Xml::label( $this->msg( 'revdelete-otherreason' )->text(), 'wpReason' ) .
'</td>' .
'<td class="mw-input">' .
- Xml::input( 'wpReason', 60, $this->otherReason, array( 'id' => 'wpReason', 'maxlength' => 100 ) ) .
+ Xml::input(
+ 'wpReason',
+ 60,
+ $this->otherReason,
+ array( 'id' => 'wpReason', 'maxlength' => 100 )
+ ) .
'</td>' .
"</tr><tr>\n" .
'<td></td>' .
*/
protected function addUsageText() {
// Messages: revdelete-text-text, revdelete-text-file, logdelete-text
- $this->getOutput()->wrapWikiMsg( "<strong>$1</strong>\n$2", $this->typeLabels['text'], 'revdelete-text-others' );
+ $this->getOutput()->wrapWikiMsg(
+ "<strong>$1</strong>\n$2", $this->typeLabels['text'],
+ 'revdelete-text-others'
+ );
+
if ( $this->getUser()->isAllowed( 'suppressrevision' ) ) {
$this->getOutput()->addWikiMsg( 'revdelete-suppress-text' );
}
+
if ( $this->mIsAllowed ) {
$this->getOutput()->addWikiMsg( 'revdelete-confirm' );
}
if ( $list->length() == 1 ) {
$list->reset();
$bitfield = $list->current()->getBits(); // existing field
+
if ( $this->submitClicked ) {
$bitfield = RevisionDeleter::extractBitfield( $this->extractBitParams(), $bitfield );
}
+
foreach ( $this->checks as $item ) {
// Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
// revdelete-hide-comment, revdelete-hide-user, revdelete-hide-restricted
list( $message, $name, $field ) = $item;
- $innerHTML = Xml::checkLabel( $this->msg( $message )->text(), $name, $name, $bitfield & $field );
+ $innerHTML = Xml::checkLabel(
+ $this->msg( $message )->text(),
+ $name,
+ $name,
+ $bitfield & $field
+ );
+
if ( $field == Revision::DELETED_RESTRICTED ) {
$innerHTML = "<b>$innerHTML</b>";
}
+
$line = Xml::tags( 'td', array( 'class' => 'mw-input' ), $innerHTML );
$html .= "<tr>$line</tr>\n";
}
} else {
// Otherwise, use tri-state radios
$html .= '<tr>';
- $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-same' )->escaped() . '</th>';
- $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-unset' )->escaped() . '</th>';
- $html .= '<th class="mw-revdel-checkbox">' . $this->msg( 'revdelete-radio-set' )->escaped() . '</th>';
+ $html .= '<th class="mw-revdel-checkbox">'
+ . $this->msg( 'revdelete-radio-same' )->escaped() . '</th>';
+ $html .= '<th class="mw-revdel-checkbox">'
+ . $this->msg( 'revdelete-radio-unset' )->escaped() . '</th>';
+ $html .= '<th class="mw-revdel-checkbox">'
+ . $this->msg( 'revdelete-radio-set' )->escaped() . '</th>';
$html .= "<th></th></tr>\n";
foreach ( $this->checks as $item ) {
// Messages: revdelete-hide-text, revdelete-hide-image, revdelete-hide-name,
return false;
}
$bitParams = $this->extractBitParams();
- $listReason = $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' ); // from dropdown
+ // from dropdown
+ $listReason = $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' );
$comment = $listReason;
if ( $comment != 'other' && $this->otherReason != '' ) {
// Entry from drop down menu + additional comment
- $comment .= $this->msg( 'colon-separator' )->inContentLanguage()->text() . $this->otherReason;
+ $comment .= $this->msg( 'colon-separator' )->inContentLanguage()->text()
+ . $this->otherReason;
} elseif ( $comment == 'other' ) {
$comment = $this->otherReason;
}
# Can the user set this field?
- if ( $bitParams[Revision::DELETED_RESTRICTED] == 1 && !$this->getUser()->isAllowed( 'suppressrevision' ) ) {
+ if ( $bitParams[Revision::DELETED_RESTRICTED] == 1
+ && !$this->getUser()->isAllowed( 'suppressrevision' )
+ ) {
throw new PermissionsError( 'suppressrevision' );
}
# If the save went through, go to success message...
protected function success() {
// Messages: revdelete-success, logdelete-success
$this->getOutput()->setPageTitle( $this->msg( 'actioncomplete' ) );
- $this->getOutput()->wrapWikiMsg( "<span class=\"success\">\n$1\n</span>", $this->typeLabels['success'] );
+ $this->getOutput()->wrapWikiMsg(
+ "<span class=\"success\">\n$1\n</span>",
+ $this->typeLabels['success']
+ );
$this->wasSaved = true;
$this->revDelList->reloadFromMaster();
$this->showForm();
}
/**
- * Do the write operations. Simple wrapper for RevDel_*List::setVisibility().
+ * Do the write operations. Simple wrapper for RevDel*List::setVisibility().
* @param int $bitfield
* @param string $reason
* @param Title $title
// Constant-time signature verification
// http://www.emerose.com/timing-attacks-explained
- // @todo: make a common method for this
+ // @todo Make a common method for this
if ( !is_string( $rSig ) || strlen( $rSig ) !== strlen( $cSig ) ) {
$verified = false;
} else {
$result = 0;
- for ( $i = 0; $i < strlen( $cSig ); $i++ ) {
+ $cSigLength = strlen( $cSig );
+ for ( $i = 0; $i < $cSigLength; $i++ ) {
$result |= ord( $cSig[$i] ) ^ ord( $rSig[$i] );
}
$verified = ( $result == 0 );
$out->addHTML(
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, $this->msg( 'search-external' )->text() ) .
- Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), $this->msg( 'searchdisabled' )->text() ) .
+ Xml::element(
+ 'p',
+ array( 'class' => 'mw-searchdisabled' ),
+ $this->msg( 'searchdisabled' )->text()
+ ) .
$this->msg( 'googlesearch' )->rawParams(
htmlspecialchars( $term ),
'UTF-8',
$stParams
);
- $this->didYouMeanHtml = '<div class="searchdidyoumean">' . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
+ $this->didYouMeanHtml = '<div class="searchdidyoumean">'
+ . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
}
if ( !wfRunHooks( 'SpecialSearchResultsPrepend', array( $this, $out, $term ) ) ) {
// Show the create link ahead
$this->showCreateLink( $title, $num, $titleMatches, $textMatches );
if ( $totalRes > $this->limit || $this->offset ) {
- $prevnext = $this->getLanguage()->viewPrevNext( $this->getPageTitle(), $this->offset, $this->limit,
+ $prevnext = $this->getLanguage()->viewPrevNext(
+ $this->getPageTitle(),
+ $this->offset,
+ $this->limit,
$this->powerSearchOptions() + array( 'search' => $term ),
max( $titleMatchesNum, $textMatchesNum ) < $this->limit
);
} else {
$messageName = 'searchmenu-new-nocreate';
}
- $params = array( $messageName, wfEscapeWikiText( $title->getPrefixedText() ), Message::numParam( $num ) );
+ $params = array(
+ $messageName,
+ wfEscapeWikiText( $title->getPrefixedText() ),
+ Message::numParam( $num )
+ );
wfRunHooks( 'SpecialSearchCreateLink', array( $title, &$params ) );
// Extensions using the hook might still return an empty $messageName
&$score, &$size, &$date, &$related,
&$html
) ) ) {
- $html = "<li><div class='mw-search-result-heading'>{$link} {$redirect} {$section} {$fileMatch}</div> {$extract}\n" .
+ $html = "<li><div class='mw-search-result-heading'>" .
+ "{$link} {$redirect} {$section} {$fileMatch}</div> {$extract}\n" .
"<div class='mw-search-result-data'>{$score}{$size} - {$date}{$related}</div>" .
"</li>\n";
}
// work out custom project captions
$customCaptions = array();
- $customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() ); // format per line <iwprefix>:<caption>
+ // format per line <iwprefix>:<caption>
+ $customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() );
foreach ( $customLines as $line ) {
$parts = explode( ":", $line, 2 );
if ( count( $parts ) == 2 ) { // validate line
}
}
-
- // TODO: should support paging in a non-confusing way (not sure how though, maybe via ajax)..
+ // @todo Should support paging in a non-confusing way (not sure how though, maybe via ajax)..
$out .= "</ul></div>\n";
// convert the whole thing to desired language variant
// Normalize the name so that silly things don't cause "invalid username"
// errors. User::newFromName does some rather strict checking, rejecting
- // e.g. leading/trailing/multiple spaces.
+ // e.g. leading/trailing/multiple spaces. But first we need to reject
+ // usernames that would be treated as titles with a fragment part.
+ if ( strpos( $this->mUsername, '#' ) !== false ) {
+ return Status::newFatal( 'noname' );
+ }
$title = Title::makeTitleSafe( NS_USER, $this->mUsername );
if ( !is_object( $title ) ) {
return Status::newFatal( 'noname' );
if ( $mode !== false ) {
if ( $mode === SpecialEditWatchlist::EDIT_RAW ) {
$title = SpecialPage::getTitleFor( 'EditWatchlist', 'raw' );
+ } elseif ( $mode === SpecialEditWatchlist::EDIT_CLEAR ) {
+ $title = SpecialPage::getTitleFor( 'EditWatchlist', 'clear' );
} else {
$title = SpecialPage::getTitleFor( 'EditWatchlist' );
}
<?php
+// @codingStandardsIgnoreFile
/**
* Template used when there is no LocalSettings.php file.
*
<?php
+// @codingStandardsIgnoreFile
/**
* Html form for account creation (since 1.22 with VForm appearance).
*
*/
class UsercreateTemplate extends BaseTemplate {
-
/**
* Extensions (AntiSpoof and TitleBlacklist) call this in response to
* UserCreateForm hook to add checkboxes to the create account form.
<?php
+// @codingStandardsIgnoreFile
/**
* Html form for user login (since 1.22 with VForm appearance).
*
protected $mBlackListedExtensions;
protected $mJavaDetected, $mSVGNSError;
- protected static $safeXmlEncodings = array( 'UTF-8', 'ISO-8859-1', 'ISO-8859-2', 'UTF-16', 'UTF-32' );
+ protected static $safeXmlEncodings = array(
+ 'UTF-8',
+ 'ISO-8859-1',
+ 'ISO-8859-2',
+ 'UTF-16',
+ 'UTF-32'
+ );
const SUCCESS = 0;
const OK = 0;
return $permission;
}
}
+
return true;
}
// Upload handlers. Should probably just be a global.
- static $uploadHandlers = array( 'Stash', 'File', 'Url' );
+ private static $uploadHandlers = array( 'Stash', 'File', 'Url' );
/**
* Create a form of UploadBase depending on wpSourceType and initializes it
$handler = new $className;
$handler->initializeFromRequest( $request );
+
return $handler;
}
return false;
}
- public function __construct() {}
+ public function __construct() {
+ }
/**
* Returns the upload type. Should be overridden by child classes
wfProfileIn( __METHOD__ );
$repo = RepoGroup::singleton()->getLocalRepo();
if ( $repo->isVirtualUrl( $srcPath ) ) {
- // @todo just make uploads work with storage paths
- // UploadFromStash loads files via virtual URLs
+ /** @todo Just make uploads work with storage paths UploadFromStash
+ * loads files via virtual URLs.
+ */
$tmpFile = $repo->getLocalCopy( $srcPath );
if ( $tmpFile ) {
$tmpFile->bind( $this ); // keep alive with $this
$path = $srcPath;
}
wfProfileOut( __METHOD__ );
+
return $path;
}
*/
if ( $this->isEmptyFile() ) {
wfProfileOut( __METHOD__ );
+
return array( 'status' => self::EMPTY_FILE );
}
$maxSize = self::getMaxUploadSize( $this->getSourceType() );
if ( $this->mFileSize > $maxSize ) {
wfProfileOut( __METHOD__ );
+
return array(
'status' => self::FILE_TOO_LARGE,
'max' => $maxSize,
$verification = $this->verifyFile();
if ( $verification !== true ) {
wfProfileOut( __METHOD__ );
+
return array(
'status' => self::VERIFICATION_ERROR,
'details' => $verification
$result = $this->validateName();
if ( $result !== true ) {
wfProfileOut( __METHOD__ );
+
return $result;
}
array( $this->mDestName, $this->mTempPath, &$error ) )
) {
wfProfileOut( __METHOD__ );
+
return array( 'status' => self::HOOK_ABORTED, 'error' => $error );
}
wfProfileOut( __METHOD__ );
+
return array( 'status' => self::OK );
}
$result['blacklistedExt'] = $this->mBlackListedExtensions;
}
}
+
return $result;
}
$this->mDestName = $this->getLocalFile()->getName();
global $wgMimeTypeBlacklist;
if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
wfProfileOut( __METHOD__ );
+
return array( 'filetype-badmime', $mime );
}
foreach ( $ieTypes as $ieType ) {
if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
wfProfileOut( __METHOD__ );
+
return array( 'filetype-bad-ie-mime', $ieType );
}
}
}
wfProfileOut( __METHOD__ );
+
return true;
}
$status = $this->verifyPartialFile();
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
+
return $status;
}
# XXX: Missing extension will be caught by validateName() via getTitle()
if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
wfProfileOut( __METHOD__ );
+
return array( 'filetype-mime-mismatch', $this->mFinalExtension, $mime );
}
}
if ( !$handlerStatus->isOK() ) {
$errors = $handlerStatus->getErrorsArray();
wfProfileOut( __METHOD__ );
+
return reset( $errors );
}
}
wfRunHooks( 'UploadVerifyFile', array( $this, $mime, &$status ) );
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
+
return $status;
}
wfDebug( __METHOD__ . ": all clear; passing.\n" );
wfProfileOut( __METHOD__ );
+
return true;
}
$status = $this->verifyMimeType( $mime );
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
+
return $status;
}
if ( !$wgDisableUploadScriptChecks ) {
if ( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) {
wfProfileOut( __METHOD__ );
+
return array( 'uploadscripted' );
}
if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
$svgStatus = $this->detectScriptInSvg( $this->mTempPath );
if ( $svgStatus !== false ) {
wfProfileOut( __METHOD__ );
+
return $svgStatus;
}
}
$error = reset( $errors );
if ( $error[0] !== 'zip-wrong-format' ) {
wfProfileOut( __METHOD__ );
+
return $error;
}
}
if ( $this->mJavaDetected ) {
wfProfileOut( __METHOD__ );
+
return array( 'uploadjava' );
}
}
$virus = $this->detectVirus( $this->mTempPath );
if ( $virus ) {
wfProfileOut( __METHOD__ );
+
return array( 'uploadvirus', $virus );
}
wfProfileOut( __METHOD__ );
+
return true;
}
}
/**
- * Alias for verifyTitlePermissions. The function was originally 'verifyPermissions'
- * but that suggests it's checking the user, when it's really checking the title + user combination.
+ * Alias for verifyTitlePermissions. The function was originally
+ * 'verifyPermissions', but that suggests it's checking the user, when it's
+ * really checking the title + user combination.
+ *
* @param User $user User object to verify the permissions against
* @return mixed An array as returned by getUserPermissionsErrors or true
* in case the user has proper permissions.
if ( $permErrors || $permErrorsUpload || $permErrorsCreate ) {
$permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsUpload, $permErrors ) );
$permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsCreate, $permErrors ) );
+
return $permErrors;
}
if ( $this->mDesiredDestName != $filename && $comparableName != $filename ) {
$warnings['badfilename'] = $filename;
// Debugging for bug 62241
- wfDebugLog( 'upload', "Filename: '$filename', mDesiredDestName: '$this->mDesiredDestName', comparableName: '$comparableName'" );
+ wfDebugLog( 'upload', "Filename: '$filename', mDesiredDestName: "
+ . "'$this->mDesiredDestName', comparableName: '$comparableName'" );
}
// Check whether the file extension is on the unwanted list
}
wfProfileOut( __METHOD__ );
+
return $warnings;
}
if ( $status->isGood() ) {
if ( $watch ) {
- WatchAction::doWatch( $this->getLocalFile()->getTitle(), $user, WatchedItem::IGNORE_USER_RIGHTS );
+ WatchAction::doWatch(
+ $this->getLocalFile()->getTitle(),
+ $user,
+ WatchedItem::IGNORE_USER_RIGHTS
+ );
}
wfRunHooks( 'UploadComplete', array( &$this ) );
}
wfProfileOut( __METHOD__ );
+
return $status;
}
if ( strlen( $this->mFilteredName ) > 240 ) {
$this->mTitleError = self::FILENAME_TOO_LONG;
$this->mTitle = null;
+
return $this->mTitle;
}
if ( is_null( $nt ) ) {
$this->mTitleError = self::ILLEGAL_FILENAME;
$this->mTitle = null;
+
return $this->mTitle;
}
$this->mFilteredName = $nt->getDBkey();
if ( $this->mFinalExtension == '' ) {
$this->mTitleError = self::FILETYPE_MISSING;
$this->mTitle = null;
+
return $this->mTitle;
} elseif ( $blackListedExtensions ||
- ( $wgCheckFileExtensions && $wgStrictFileExtensions &&
- !$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) ) ) {
+ ( $wgCheckFileExtensions && $wgStrictFileExtensions &&
+ !$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) )
+ ) {
$this->mBlackListedExtensions = $blackListedExtensions;
$this->mTitleError = self::FILETYPE_BADTYPE;
$this->mTitle = null;
+
return $this->mTitle;
}
if ( wfIsWindows() && !preg_match( '/^[\x0-\x7f]*$/', $nt->getText() ) ) {
$this->mTitleError = self::WINDOWS_NONASCII_FILENAME;
$this->mTitle = null;
+
return $this->mTitle;
}
# If there was more than one "extension", reassemble the base
# filename to prevent bogus complaints about length
if ( count( $ext ) > 1 ) {
- for ( $i = 0; $i < count( $ext ) - 1; $i++ ) {
+ $iterations = count( $ext ) - 1;
+ for ( $i = 0; $i < $iterations; $i++ ) {
$partname .= '.' . $ext[$i];
}
}
if ( strlen( $partname ) < 1 ) {
$this->mTitleError = self::MIN_LENGTH_PARTNAME;
$this->mTitle = null;
+
return $this->mTitle;
}
$this->mTitle = $nt;
+
return $this->mTitle;
}
$nt = $this->getTitle();
$this->mLocalFile = is_null( $nt ) ? null : wfLocalFile( $nt );
}
+
return $this->mLocalFile;
}
/**
- * If the user does not supply all necessary information in the first upload form submission (either by accident or
- * by design) then we may want to stash the file temporarily, get more information, and publish the file later.
+ * If the user does not supply all necessary information in the first upload
+ * form submission (either by accident or by design) then we may want to
+ * stash the file temporarily, get more information, and publish the file
+ * later.
*
- * This method will stash a file in a temporary directory for later processing, and save the necessary descriptive info
- * into the database.
- * This method returns the file object, which also has a 'fileKey' property which can be passed through a form or
- * API request to find this stashed file again.
+ * This method will stash a file in a temporary directory for later
+ * processing, and save the necessary descriptive info into the database.
+ * This method returns the file object, which also has a 'fileKey' property
+ * which can be passed through a form or API request to find this stashed
+ * file again.
*
* @param User $user
* @return UploadStashFile Stashed file
$this->mLocalFile = $file;
wfProfileOut( __METHOD__ );
+
return $file;
}
/**
- * Stash a file in a temporary directory, returning a key which can be used to find the file again. See stashFile().
+ * Stash a file in a temporary directory, returning a key which can be used
+ * to find the file again. See stashFile().
*
* @return string File key
*/
public static function splitExtensions( $filename ) {
$bits = explode( '.', $filename );
$basename = array_shift( $bits );
+
return array( $basename, $bits );
}
if ( !$magic->isRecognizableExtension( $extension ) ) {
wfDebug( __METHOD__ . ": passing file with unknown detected mime type; " .
"unrecognized extension '$extension', can't verify\n" );
+
return true;
} else {
wfDebug( __METHOD__ . ": rejecting file with unknown detected mime type; " .
"recognized extension '$extension', so probably invalid file\n" );
+
return false;
}
}
if ( $match === null ) {
if ( $magic->getTypesForExtension( $extension ) !== null ) {
wfDebug( __METHOD__ . ": No extension known for $mime, but we know a mime for $extension\n" );
+
return false;
} else {
wfDebug( __METHOD__ . ": no file extension known for mime type $mime, passing file\n" );
+
return true;
}
} elseif ( $match === true ) {
wfDebug( __METHOD__ . ": mime type $mime matches extension $extension, passing file\n" );
- #TODO: if it's a bitmap, make sure PHP or ImageMagic resp. can handle it!
+ /** @todo If it's a bitmap, make sure PHP or ImageMagick resp. can handle it! */
return true;
-
} else {
- wfDebug( __METHOD__ . ": mime type $mime mismatches file extension $extension, rejecting file\n" );
+ wfDebug( __METHOD__
+ . ": mime type $mime mismatches file extension $extension, rejecting file\n" );
+
return false;
}
}
if ( !$chunk ) {
wfProfileOut( __METHOD__ );
+
return false;
}
$chunk = trim( $chunk );
- # @todo FIXME: Convert from UTF-16 if necessary!
+ /** @todo FIXME: Convert from UTF-16 if necessary! */
wfDebug( __METHOD__ . ": checking for embedded scripts and HTML stuff\n" );
# check for HTML doctype
if ( preg_match( "/<!DOCTYPE *X?HTML/i", $chunk ) ) {
wfProfileOut( __METHOD__ );
+
return true;
}
if ( $extension == 'svg' || strpos( $mime, 'image/svg' ) === 0 ) {
if ( self::checkXMLEncodingMissmatch( $file ) ) {
wfProfileOut( __METHOD__ );
+
return true;
}
}
'<a href',
'<body',
'<head',
- '<html', #also in safari
+ '<html', #also in safari
'<img',
'<pre',
'<script', #also in safari
if ( false !== strpos( $chunk, $tag ) ) {
wfDebug( __METHOD__ . ": found something that may make it be mistaken for html: $tag\n" );
wfProfileOut( __METHOD__ );
+
return true;
}
}
if ( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found script types\n" );
wfProfileOut( __METHOD__ );
+
return true;
}
if ( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found html-style script urls\n" );
wfProfileOut( __METHOD__ );
+
return true;
}
if ( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found css-style script urls\n" );
wfProfileOut( __METHOD__ );
+
return true;
}
wfDebug( __METHOD__ . ": no scripts found\n" );
wfProfileOut( __METHOD__ );
+
return false;
}
&& !in_array( strtoupper( $encMatch[1] ), self::$safeXmlEncodings )
) {
wfDebug( __METHOD__ . ": Found unsafe XML encoding '{$encMatch[1]}'\n" );
+
return true;
}
} elseif ( preg_match( "!<\?xml\b!si", $contents ) ) {
// Start of XML declaration without an end in the first $wgSVGMetadataCutoff
// bytes. There shouldn't be a legitimate reason for this to happen.
wfDebug( __METHOD__ . ": Unmatched XML declaration start\n" );
+
return true;
} elseif ( substr( $contents, 0, 4 ) == "\x4C\x6F\xA7\x94" ) {
// EBCDIC encoded XML
wfDebug( __METHOD__ . ": EBCDIC Encoded XML\n" );
+
return true;
}
wfSuppressWarnings();
$str = iconv( $encoding, 'UTF-8', $contents );
wfRestoreWarnings();
- if ( $str != '' && preg_match( "!<\?xml\b(.*?)\?>!si", $str, $matches ) ) {
+ if ( $str != '' && preg_match( "!<\?xml\b(.*?)\?>!si", $str, $matches ) ) {
if ( preg_match( $encodingRegex, $matches[1], $encMatch )
&& !in_array( strtoupper( $encMatch[1] ), self::$safeXmlEncodings )
) {
wfDebug( __METHOD__ . ": Found unsafe XML encoding '{$encMatch[1]}'\n" );
+
return true;
}
} elseif ( $str != '' && preg_match( "!<\?xml\b!si", $str ) ) {
// Start of XML declaration without an end in the first $wgSVGMetadataCutoff
// bytes. There shouldn't be a legitimate reason for this to happen.
wfDebug( __METHOD__ . ": Unmatched XML declaration start\n" );
+
return true;
}
}
if ( $this->mSVGNSError ) {
return array( 'uploadscriptednamespace', $this->mSVGNSError );
}
+
return array( 'uploadscripted' );
}
+
return false;
}
if ( preg_match( '/xml-stylesheet/i', $target ) ) {
return true;
}
+
return false;
}
if ( !in_array( $namespace, $validNamespaces ) ) {
wfDebug( __METHOD__ . ": Non-svg namespace '$namespace' in uploaded file.\n" );
- // @TODO return a status object to a closure in XmlTypeCheck, for MW1.21+
+ /** @todo Return a status object to a closure in XmlTypeCheck, for MW1.21+ */
$this->mSVGNSError = $namespace;
+
return true;
}
*/
if ( $strippedElement == 'script' ) {
wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" );
+
return true;
}
- # e.g., <svg xmlns="http://www.w3.org/2000/svg"> <handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler> </svg>
+ # e.g., <svg xmlns="http://www.w3.org/2000/svg">
+ # <handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler> </svg>
if ( $strippedElement == 'handler' ) {
wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" );
+
return true;
}
# SVG reported in Feb '12 that used xml:stylesheet to generate javascript block
if ( $strippedElement == 'stylesheet' ) {
wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" );
+
return true;
}
# Block iframes, in case they pass the namespace check
if ( $strippedElement == 'iframe' ) {
wfDebug( __METHOD__ . ": iframe in uploaded file.\n" );
+
return true;
}
$value = strtolower( $value );
if ( substr( $stripped, 0, 2 ) == 'on' ) {
- wfDebug( __METHOD__ . ": Found event-handler attribute '$attrib'='$value' in uploaded file.\n" );
+ wfDebug( __METHOD__
+ . ": Found event-handler attribute '$attrib'='$value' in uploaded file.\n" );
+
return true;
}
# href with javascript target
if ( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) {
- wfDebug( __METHOD__ . ": Found script in href attribute '$attrib'='$value' in uploaded file.\n" );
+ wfDebug( __METHOD__
+ . ": Found script in href attribute '$attrib'='$value' in uploaded file.\n" );
+
return true;
}
# href with embedded svg as target
if ( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) {
- wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+ wfDebug( __METHOD__ . ": Found href to embedded svg "
+ . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+
return true;
}
# href with embedded (text/xml) svg as target
if ( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) {
- wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+ wfDebug( __METHOD__ . ": Found href to embedded svg "
+ . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+
return true;
}
# use set/animate to add event-handler attribute to parent
- if ( ( $strippedElement == 'set' || $strippedElement == 'animate' ) && $stripped == 'attributename' && substr( $value, 0, 2 ) == 'on' ) {
- wfDebug( __METHOD__ . ": Found svg setting event-handler attribute with \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
+ if ( ( $strippedElement == 'set' || $strippedElement == 'animate' )
+ && $stripped == 'attributename'
+ && substr( $value, 0, 2 ) == 'on'
+ ) {
+ wfDebug( __METHOD__ . ": Found svg setting event-handler attribute with "
+ . "\"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
+
return true;
}
# use set to add href attribute to parent element
- if ( $strippedElement == 'set' && $stripped == 'attributename' && strpos( $value, 'href' ) !== false ) {
+ if ( $strippedElement == 'set'
+ && $stripped == 'attributename'
+ && strpos( $value, 'href' ) !== false
+ ) {
wfDebug( __METHOD__ . ": Found svg setting href attribute '$value' in uploaded file.\n" );
+
return true;
}
# use set to add a remote / data / script target to an element
- if ( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
+ if ( $strippedElement == 'set'
+ && $stripped == 'to'
+ && preg_match( '!(http|https|data|script):!sim', $value )
+ ) {
wfDebug( __METHOD__ . ": Found svg setting attribute to '$value' in uploaded file.\n" );
+
return true;
}
# use handler attribute with remote / data / script
if ( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
- wfDebug( __METHOD__ . ": Found svg setting handler with remote/data/script '$attrib'='$value' in uploaded file.\n" );
+ wfDebug( __METHOD__ . ": Found svg setting handler with remote/data/script "
+ . "'$attrib'='$value' in uploaded file.\n" );
+
return true;
}
# use CSS styles to bring in remote code
# catch url("http:..., url('http:..., url(http:..., but not url("#..., url('#..., url(#....
- if ( $stripped == 'style' && preg_match_all( '!((?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*["\']?\s*[^#]+.*?\))!sim', $value, $matches ) ) {
+ $tagsList = "font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke";
+ if ( $stripped == 'style'
+ && preg_match_all(
+ '!((?:' . $tagsList . ')\s*:\s*url\s*\(\s*["\']?\s*[^#]+.*?\))!sim',
+ $value,
+ $matches
+ )
+ ) {
foreach ( $matches[1] as $match ) {
- if ( !preg_match( '!(?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) {
- wfDebug( __METHOD__ . ": Found svg setting a style with remote url '$attrib'='$value' in uploaded file.\n" );
+ if ( !preg_match( '!(?:' . $tagsList . ')\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) {
+ wfDebug( __METHOD__ . ": Found svg setting a style with "
+ . "remote url '$attrib'='$value' in uploaded file.\n" );
+
return true;
}
}
}
# image filters can pull in url, which could be svg that executes scripts
- if ( $strippedElement == 'image' && $stripped == 'filter' && preg_match( '!url\s*\(!sim', $value ) ) {
- wfDebug( __METHOD__ . ": Found image filter with url: \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
+ if ( $strippedElement == 'image'
+ && $stripped == 'filter'
+ && preg_match( '!url\s*\(!sim', $value )
+ ) {
+ wfDebug( __METHOD__ . ": Found image filter with url: "
+ . "\"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
+
return true;
}
-
}
return false; //No scripts detected
$parts = explode( ':', strtolower( $element ) );
$name = array_pop( $parts );
$ns = implode( ':', $parts );
+
return array( $ns, $name );
}
private function stripXmlNamespace( $name ) {
// 'http://www.w3.org/2000/svg:script' -> 'script'
$parts = explode( ':', strtolower( $name ) );
+
return array_pop( $parts );
}
if ( !$wgAntivirus ) {
wfDebug( __METHOD__ . ": virus scanner disabled\n" );
wfProfileOut( __METHOD__ );
+
return null;
}
$wgOut->wrapWikiMsg( "<div class=\"error\">\n$1\n</div>",
array( 'virus-badscanner', $wgAntivirus ) );
wfProfileOut( __METHOD__ );
+
return wfMessage( 'virus-unknownscanner' )->text() . " $wgAntivirus";
}
# scan failed (code was mapped to false by $exitCodeMap)
wfDebug( __METHOD__ . ": failed to scan $file (code $exitCode).\n" );
- $output = $wgAntivirusRequired ? wfMessage( 'virus-scanfailed', array( $exitCode ) )->text() : null;
+ $output = $wgAntivirusRequired
+ ? wfMessage( 'virus-scanfailed', array( $exitCode ) )->text()
+ : null;
} elseif ( $mappedCode === AV_SCAN_ABORTED ) {
# scan failed because filetype is unknown (probably imune)
wfDebug( __METHOD__ . ": unsupported file type $file (code $exitCode).\n" );
}
wfProfileOut( __METHOD__ );
+
return $output;
}
// Check for files with the same name but a different extension
$similarFiles = RepoGroup::singleton()->getLocalRepo()->findFilesByPrefix(
- "{$partname}.", 1 );
+ "{$partname}.", 1 );
if ( count( $similarFiles ) ) {
return array(
'warning' => 'exists-normalized',
if ( self::isThumbName( $file->getName() ) ) {
# Check for filenames like 50px- or 180px-, these are mostly thumbnails
- $nt_thb = Title::newFromText( substr( $partname, strpos( $partname, '-' ) + 1 ) . '.' . $extension, NS_FILE );
+ $nt_thb = Title::newFromText(
+ substr( $partname, strpos( $partname, '-' ) + 1 ) . '.' . $extension,
+ NS_FILE
+ );
$file_thb = wfLocalFile( $nt_thb );
if ( $file_thb->exists() ) {
return array(
public static function isThumbName( $filename ) {
$n = strrpos( $filename, '.' );
$partname = $n ? substr( $filename, 0, $n ) : $filename;
+
return (
- substr( $partname, 3, 3 ) == 'px-' ||
- substr( $partname, 2, 3 ) == 'px-'
- ) &&
- preg_match( "/[0-9]{2}/", substr( $partname, 0, 2 ) );
+ substr( $partname, 3, 3 ) == 'px-' ||
+ substr( $partname, 2, 3 ) == 'px-'
+ ) &&
+ preg_match( "/[0-9]{2}/", substr( $partname, 0, 2 ) );
}
/**
$blacklist[] = trim( $line );
}
}
+
return $blacklist;
}
/**
* Gets image info about the file just uploaded.
*
- * Also has the effect of setting metadata to be an 'indexed tag name' in returned API result if
- * 'metadata' was requested. Oddly, we have to pass the "result" object down just so it can do that
- * with the appropriate format, presumably.
+ * Also has the effect of setting metadata to be an 'indexed tag name' in
+ * returned API result if 'metadata' was requested. Oddly, we have to pass
+ * the "result" object down just so it can do that with the appropriate
+ * format, presumably.
*
* @param ApiResult $result
* @return array Image info
*/
public function getImageInfo( $result ) {
$file = $this->getLocalFile();
- // TODO This cries out for refactoring. We really want to say $file->getAllInfo(); here.
- // Perhaps "info" methods should be moved into files, and the API should just wrap them in queries.
+ /** @todo This cries out for refactoring.
+ * We really want to say $file->getAllInfo(); here.
+ * Perhaps "info" methods should be moved into files, and the API should
+ * just wrap them in queries.
+ */
if ( $file instanceof UploadStashFile ) {
$imParam = ApiQueryStashImageInfo::getPropertyNames();
$info = ApiQueryStashImageInfo::getInfo( $file, array_flip( $imParam ), $result );
$imParam = ApiQueryImageInfo::getPropertyNames();
$info = ApiQueryImageInfo::getInfo( $file, array_flip( $imParam ), $result );
}
+
return $info;
}
public function convertVerifyErrorToStatus( $error ) {
$code = $error['status'];
unset( $code['status'] );
+
return Status::newFatal( $this->getVerificationErrorCode( $code ), $error );
}
// Update db table to reflect initial "chunk" state
$this->updateChunkStatus();
+
return $this->mLocalFile;
}
if ( $ret['status'] !== UploadBase::OK ) {
wfDebugLog( 'fileconcatenate', "Verification failed for chunked upload" );
$status->fatal( $this->getVerificationErrorCode( $ret['status'] ) );
+
return $status;
}
*/
public function performUpload( $comment, $pageText, $watch, $user ) {
$rv = parent::performUpload( $comment, $pageText, $watch, $user );
+
return $rv;
}
*/
function getVirtualChunkLocation( $index ) {
return $this->repo->getVirtualUrl( 'temp' ) .
- '/' .
- $this->repo->getHashPath(
- $this->getChunkFileKey( $index )
- ) .
- $this->getChunkFileKey( $index );
+ '/' .
+ $this->repo->getHashPath(
+ $this->getChunkFileKey( $index )
+ ) .
+ $this->getChunkFileKey( $index );
}
/**
$status = Status::newFatal( 'invalid-chunk-offset' );
}
}
+
return $status;
}
*/
private function updateChunkStatus() {
wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" .
- $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
+ $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
$dbw = $this->repo->getMasterDb();
// Use a quick transaction since we will upload the full temp file into shared
if ( $this->mChunkIndex !== null ) {
return $this->mChunkIndex;
}
+
return 0;
}
if ( $this->mOffset !== null ) {
return $this->mOffset;
}
+
return 0;
}
$this->repo->getZonePath( 'temp' ) . "/{$hashPath}{$fileKey}" );
// Check for error in stashing the chunk:
- if ( ! $storeStatus->isOK() ) {
+ if ( !$storeStatus->isOK() ) {
$error = $storeStatus->getErrorsArray();
$error = reset( $error );
- if ( ! count( $error ) ) {
+ if ( !count( $error ) ) {
$error = $storeStatus->getWarningsArray();
$error = reset( $error );
- if ( ! count( $error ) ) {
+ if ( !count( $error ) ) {
$error = array( 'unknown', 'no error recorded' );
}
}
throw new UploadChunkFileException( "Error storing file in '$chunkPath': " .
implode( '; ', $error ) );
}
+
return $storeStatus;
}
if ( $index === null ) {
$index = $this->getChunkIndex();
}
+
return $this->mFileKey . '.' . $index;
}
* @author Bryan Tong Minh
*/
class UploadFromFile extends UploadBase {
-
/**
* @var WebRequestUpload
*/
// replace mLocalFile with an instance of UploadStashFile, which adds some methods
// that are useful for stashed files.
$this->mLocalFile = parent::stashFile( $user );
+
return $this->mLocalFile;
}
public function performUpload( $comment, $pageText, $watch, $user ) {
$rv = parent::performUpload( $comment, $pageText, $watch, $user );
$this->unsaveUploadedFile();
+
return $rv;
}
}
if ( !$user->isAllowed( 'upload_by_url' ) ) {
return 'upload_by_url';
}
+
return parent::isAllowed( $user );
}
*/
public static function isEnabled() {
global $wgAllowCopyUploads;
+
return $wgAllowCopyUploads && parent::isEnabled();
}
}
*/
}
+
return $valid;
}
wfRunHooks( 'IsUploadAllowedFromUrl', array( $url, &$allowed ) );
self::$allowedUrls[$url] = $allowed;
}
+
return self::$allowedUrls[$url];
}
global $wgUser;
$url = $request->getVal( 'wpUploadFileURL' );
+
return !empty( $url )
&& Http::isValidURI( $url )
&& $wgUser->isAllowed( 'upload_by_url' );
if ( !$this->mAsync ) {
return $this->reallyFetchFile( $httpOptions );
}
+
return Status::newGood();
}
protected function makeTemporaryFile() {
$tmpFile = TempFSFile::factory( 'URL' );
$tmpFile->bind( $this );
+
return $tmpFile->getPath();
}
$this->mRemoveTempFile = true;
$this->mFileSize = 0;
- $options = $httpOptions + array(
- 'followRedirects' => true,
- );
+ $options = $httpOptions + array( 'followRedirects' => true );
+
if ( $wgCopyUploadProxy !== false ) {
$options['proxy'] = $wgCopyUploadProxy;
}
+
if ( $wgCopyUploadTimeout && !isset( $options['timeout'] ) ) {
$options['timeout'] = $wgCopyUploadTimeout;
}
if ( $this->mAsync ) {
return array( 'status' => UploadBase::OK );
}
+
return parent::verifyUpload();
}
public function checkWarnings() {
if ( $this->mAsync ) {
$this->mIgnoreWarnings = false;
+
return array();
}
+
return parent::checkWarnings();
}
if ( $this->mAsync ) {
return true;
}
+
return parent::verifyTitlePermissions( $user );
}
) );
$job->initializeSessionData();
JobQueueGroup::singleton()->push( $job );
+
return $sessionKey;
}
-
}
/**
* UploadStash is intended to accomplish a few things:
- * - enable applications to temporarily stash files without publishing them to the wiki.
- * - Several parts of MediaWiki do this in similar ways: UploadBase, UploadWizard, and FirefoggChunkedExtension
- * And there are several that reimplement stashing from scratch, in idiosyncratic ways. The idea is to unify them all here.
- * Mostly all of them are the same except for storing some custom fields, which we subsume into the data array.
- * - enable applications to find said files later, as long as the db table or temp files haven't been purged.
- * - enable the uploading user (and *ONLY* the uploading user) to access said files, and thumbnails of said files, via a URL.
- * We accomplish this using a database table, with ownership checking as you might expect. See SpecialUploadStash, which
- * implements a web interface to some files stored this way.
+ * - Enable applications to temporarily stash files without publishing them to
+ * the wiki.
+ * - Several parts of MediaWiki do this in similar ways: UploadBase,
+ * UploadWizard, and FirefoggChunkedExtension.
+ * And there are several that reimplement stashing from scratch, in
+ * idiosyncratic ways. The idea is to unify them all here.
+ * Mostly all of them are the same except for storing some custom fields,
+ * which we subsume into the data array.
+ * - Enable applications to find said files later, as long as the db table or
+ * temp files haven't been purged.
+ * - Enable the uploading user (and *ONLY* the uploading user) to access said
+ * files, and thumbnails of said files, via a URL. We accomplish this using
+ * a database table, with ownership checking as you might expect. See
+ * SpecialUploadStash, which implements a web interface to some files stored
+ * this way.
*
- * UploadStash right now is *mostly* intended to show you one user's slice of the entire stash. The user parameter is only optional
- * because there are few cases where we clean out the stash from an automated script. In the future we might refactor this.
+ * UploadStash right now is *mostly* intended to show you one user's slice of
+ * the entire stash. The user parameter is only optional because there are few
+ * cases where we clean out the stash from an automated script. In the future we
+ * might refactor this.
*
* UploadStash represents the entire stash of temporary files.
* UploadStashFile is a filestore for the actual physical disk files.
- * UploadFromStash extends UploadBase, and represents a single stashed file as it is moved from the stash to the regular file repository
+ * UploadFromStash extends UploadBase, and represents a single stashed file as
+ * it is moved from the stash to the regular file repository
*
* @ingroup Upload
*/
class UploadStash {
-
// Format of the key for files -- has to be suitable as a filename itself (e.g. ab12cd34ef.jpg)
const KEY_FORMAT_REGEX = '/^[\w-\.]+\.\w*$/';
/**
* Get a file and its metadata from the stash.
- * The noAuth param is a bit janky but is required for automated scripts which clean out the stash.
+ * The noAuth param is a bit janky but is required for automated scripts
+ * which clean out the stash.
*
* @param string $key Key under which file information is stored
* @param bool $noAuth (optional) Don't check authentication. Used by maintenance scripts.
* @return UploadStashFile
*/
public function getFile( $key, $noAuth = false ) {
- if ( ! preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
+ if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
throw new UploadStashBadPathException( "key '$key' is not in a proper format" );
}
if ( !isset( $this->fileMetadata[$key] ) ) {
if ( !$this->fetchFileMetadata( $key ) ) {
- // If nothing was received, it's likely due to replication lag. Check the master to see if the record is there.
+ // If nothing was received, it's likely due to replication lag.
+ // Check the master to see if the record is there.
$this->fetchFileMetadata( $key, DB_MASTER );
}
}
}
- if ( ! $this->files[$key]->exists() ) {
+ if ( !$this->files[$key]->exists() ) {
wfDebug( __METHOD__ . " tried to get file at $key, but it doesn't exist\n" );
throw new UploadStashBadPathException( "path doesn't exist" );
}
if ( !$noAuth ) {
if ( $this->fileMetadata[$key]['us_user'] != $this->userId ) {
- throw new UploadStashWrongOwnerException( "This file ($key) doesn't belong to the current user." );
+ throw new UploadStashWrongOwnerException( "This file ($key) doesn't "
+ . "belong to the current user." );
}
}
*/
public function getMetadata( $key ) {
$this->getFile( $key );
+
return $this->fileMetadata[$key];
}
*/
public function getFileProps( $key ) {
$this->getFile( $key );
+
return $this->fileProps[$key];
}
/**
- * Stash a file in a temp directory and record that we did this in the database, along with other metadata.
+ * Stash a file in a temp directory and record that we did this in the
+ * database, along with other metadata.
*
* @param string $path Path to file you want stashed
- * @param string $sourceType The type of upload that generated this file (currently, I believe, 'file' or null)
+ * @param string $sourceType The type of upload that generated this file
+ * (currently, I believe, 'file' or null)
* @throws UploadStashBadPathException
* @throws UploadStashFileException
* @throws UploadStashNotLoggedInException
$pathWithGoodExtension = $path;
}
- // If no key was supplied, make one. a mysql insertid would be totally reasonable here, except
- // that for historical reasons, the key is this random thing instead. At least it's not guessable.
+ // If no key was supplied, make one. a mysql insertid would be totally
+ // reasonable here, except that for historical reasons, the key is this
+ // random thing instead. At least it's not guessable.
//
- // some things that when combined will make a suitably unique key.
+ // Some things that when combined will make a suitably unique key.
// see: http://www.jwz.org/doc/mid.html
list( $usec, $sec ) = explode( ' ', microtime() );
$usec = substr( $usec, 2 );
$this->fileProps[$key] = $fileProps;
- if ( ! preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
+ if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
throw new UploadStashBadPathException( "key '$key' is not in a proper format" );
}
// if not already in a temporary area, put it there
$storeStatus = $this->repo->storeTemp( basename( $pathWithGoodExtension ), $path );
- if ( ! $storeStatus->isOK() ) {
- // It is a convention in MediaWiki to only return one error per API exception, even if multiple errors
- // are available. We use reset() to pick the "first" thing that was wrong, preferring errors to warnings.
- // This is a bit lame, as we may have more info in the $storeStatus and we're throwing it away, but to fix it means
+ if ( !$storeStatus->isOK() ) {
+ // It is a convention in MediaWiki to only return one error per API
+ // exception, even if multiple errors are available. We use reset()
+ // to pick the "first" thing that was wrong, preferring errors to
+ // warnings. This is a bit lame, as we may have more info in the
+ // $storeStatus and we're throwing it away, but to fix it means
// redesigning API errors significantly.
- // $storeStatus->value just contains the virtual URL (if anything) which is probably useless to the caller
+ // $storeStatus->value just contains the virtual URL (if anything)
+ // which is probably useless to the caller.
$error = $storeStatus->getErrorsArray();
$error = reset( $error );
- if ( ! count( $error ) ) {
+ if ( !count( $error ) ) {
$error = $storeStatus->getWarningsArray();
$error = reset( $error );
- if ( ! count( $error ) ) {
+ if ( !count( $error ) ) {
$error = array( 'unknown', 'no error recorded' );
}
}
- // at this point, $error should contain the single "most important" error, plus any parameters.
+ // At this point, $error should contain the single "most important"
+ // error, plus any parameters.
$errorMsg = array_shift( $error );
- throw new UploadStashFileException( "Error storing file in '$path': " . wfMessage( $errorMsg, $error )->text() );
+ throw new UploadStashFileException( "Error storing file in '$path': "
+ . wfMessage( $errorMsg, $error )->text() );
}
$stashPath = $storeStatus->value;
// fetch the current user ID
if ( !$this->isLoggedIn ) {
- throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' );
+ throw new UploadStashNotLoggedInException( __METHOD__
+ . ' No user is logged in, files must belong to users' );
}
// insert the file metadata into the db.
__METHOD__
);
- // store the insertid in the class variable so immediate retrieval (possibly laggy) isn't necesary.
+ // store the insertid in the class variable so immediate retrieval
+ // (possibly laggy) isn't necesary.
$this->fileMetadata[$key]['us_id'] = $dbw->insertId();
# create the UploadStashFile object for this file.
*/
public function clear() {
if ( !$this->isLoggedIn ) {
- throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' );
+ throw new UploadStashNotLoggedInException( __METHOD__
+ . ' No user is logged in, files must belong to users' );
}
wfDebug( __METHOD__ . ' clearing all rows for user ' . $this->userId . "\n" );
* Remove a particular file from the stash. Also removes it from the repo.
*
* @param string $key
- * @throws UploadStashNoSuchKeyException|UploadStashNotLoggedInException|UploadStashWrongOwnerException
+ * @throws UploadStashNoSuchKeyException|UploadStashNotLoggedInException
+ * @throws UploadStashWrongOwnerException
* @return bool Success
*/
public function removeFile( $key ) {
if ( !$this->isLoggedIn ) {
- throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' );
+ throw new UploadStashNotLoggedInException( __METHOD__
+ . ' No user is logged in, files must belong to users' );
}
$dbw = $this->repo->getMasterDb();
- // this is a cheap query. it runs on the master so that this function still works when there's lag.
- // it won't be called all that often.
+ // this is a cheap query. it runs on the master so that this function
+ // still works when there's lag. It won't be called all that often.
$row = $dbw->selectRow(
'uploadstash',
'us_user',
}
if ( $row->us_user != $this->userId ) {
- throw new UploadStashWrongOwnerException( "Can't delete: the file ($key) doesn't belong to this user." );
+ throw new UploadStashWrongOwnerException( "Can't delete: "
+ . "the file ($key) doesn't belong to this user." );
}
return $this->removeFileNoAuth( $key );
__METHOD__
);
- // TODO: look into UnregisteredLocalFile and find out why the rv here is sometimes wrong (false when file was removed)
- // for now, ignore.
+ /** @todo Look into UnregisteredLocalFile and find out why the rv here is
+ * sometimes wrong (false when file was removed). For now, ignore.
+ */
$this->files[$key]->remove();
unset( $this->files[$key] );
*/
public function listFiles() {
if ( !$this->isLoggedIn ) {
- throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' );
+ throw new UploadStashNotLoggedInException( __METHOD__
+ . ' No user is logged in, files must belong to users' );
}
$dbr = $this->repo->getSlaveDb();
// put it in a web accesible directory.
return '';
}
+
return $extension;
}
throw new UploadStashZeroLengthFileException( "File is zero length" );
}
$this->files[$key] = $file;
+
return true;
}
}
protected $url;
/**
- * A LocalFile wrapper around a file that has been temporarily stashed, so we can do things like create thumbnails for it
- * Arguably UnregisteredLocalFile should be handling its own file repo but that class is a bit retarded currently
+ * A LocalFile wrapper around a file that has been temporarily stashed,
+ * so we can do things like create thumbnails for it. Arguably
+ * UnregisteredLocalFile should be handling its own file repo but that
+ * class is a bit retarded currently.
*
* @param FileRepo $repo Repository where we should find the path
* @param string $path Path to file
if ( $repo->isVirtualUrl( $path ) ) {
$path = $repo->resolveVirtualUrl( $path );
} else {
-
- // check if path appears to be sane, no parent traversals, and is in this repo's temp zone.
+ // check if path appears to be sane, no parent traversals,
+ // and is in this repo's temp zone.
$repoTempPath = $repo->getZonePath( 'temp' );
- if ( ( ! $repo->validateFilename( $path ) ) ||
- ( strpos( $path, $repoTempPath ) !== 0 ) ) {
- wfDebug( "UploadStash: tried to construct an UploadStashFile from a file that should already exist at '$path', but path is not valid\n" );
+ if ( ( !$repo->validateFilename( $path ) ) ||
+ ( strpos( $path, $repoTempPath ) !== 0 )
+ ) {
+ wfDebug( "UploadStash: tried to construct an UploadStashFile "
+ . "from a file that should already exist at '$path', but path is not valid\n" );
throw new UploadStashBadPathException( 'path is not valid' );
}
// check if path exists! and is a plain file.
- if ( ! $repo->fileExists( $path ) ) {
- wfDebug( "UploadStash: tried to construct an UploadStashFile from a file that should already exist at '$path', but path is not found\n" );
+ if ( !$repo->fileExists( $path ) ) {
+ wfDebug( "UploadStash: tried to construct an UploadStashFile from "
+ . "a file that should already exist at '$path', but path is not found\n" );
throw new UploadStashFileNotFoundException( 'cannot find path, or not a plain file' );
}
}
/**
* A method needed by the file transforming and scaling routines in File.php
* We do not necessarily care about doing the description at this point
- * However, we also can't return the empty string, as the rest of MediaWiki demands this (and calls to imagemagick
- * convert require it to be there)
+ * However, we also can't return the empty string, as the rest of MediaWiki
+ * demands this (and calls to imagemagick convert require it to be there)
*
* @return string Dummy value
*/
* The actual argument is the result of thumbName although we seem to have
* buggy code elsewhere that expects a boolean 'suffix'
*
- * @param string $thumbName Name of thumbnail (e.g. "120px-123456.jpg" ), or false to just get the path
- * @return string Path thumbnail should take on filesystem, or containing directory if thumbname is false
+ * @param string $thumbName Name of thumbnail (e.g. "120px-123456.jpg" ),
+ * or false to just get the path
+ * @return string Path thumbnail should take on filesystem, or containing
+ * directory if thumbname is false
*/
public function getThumbPath( $thumbName = false ) {
$path = dirname( $this->path );
if ( $thumbName !== false ) {
$path .= "/$thumbName";
}
+
return $path;
}
}
/**
- * Helper function -- given a 'subpage', return the local URL e.g. /wiki/Special:UploadStash/subpage
+ * Helper function -- given a 'subpage', return the local URL,
+ * e.g. /wiki/Special:UploadStash/subpage
* @param string $subPage
* @return string Local URL for this subpage in the Special:UploadStash space.
*/
/**
* Get a URL to access the thumbnail
* This is required because the model of how files work requires that
- * the thumbnail urls be predictable. However, in our model the URL is not based on the filename
- * (that's hidden in the db)
+ * the thumbnail urls be predictable. However, in our model the URL is
+ * not based on the filename (that's hidden in the db)
*
- * @param string $thumbName Basename of thumbnail file -- however, we don't want to use the file exactly
+ * @param string $thumbName Basename of thumbnail file -- however, we don't
+ * want to use the file exactly
* @return string URL to access thumbnail, or URL with partial path
*/
public function getThumbUrl( $thumbName = false ) {
wfDebug( __METHOD__ . " getting for $thumbName \n" );
+
return $this->getSpecialUrl( 'thumb/' . $this->getUrlName() . '/' . $thumbName );
}
* @return string Base url name, like '120px-123456.jpg'
*/
public function getUrlName() {
- if ( ! $this->urlName ) {
+ if ( !$this->urlName ) {
$this->urlName = $this->fileKey;
}
+
return $this->urlName;
}
if ( !isset( $this->url ) ) {
$this->url = $this->getSpecialUrl( 'file/' . $this->getUrlName() );
}
+
return $this->url;
}
/**
- * Parent classes use this method, for no obvious reason, to return the path (relative to wiki root, I assume).
- * But with this class, the URL is unrelated to the path.
+ * Parent classes use this method, for no obvious reason, to return the path
+ * (relative to wiki root, I assume). But with this class, the URL is
+ * unrelated to the path.
*
* @return string Url
*/
}
/**
- * Getter for file key (the unique id by which this file's location & metadata is stored in the db)
+ * Getter for file key (the unique id by which this file's location &
+ * metadata is stored in the db)
*
* @return string File key
*/
public function exists() {
return $this->repo->fileExists( $this->path );
}
+}
+
+class UploadStashException extends MWException {
+}
+
+class UploadStashNotAvailableException extends UploadStashException {
+}
+
+class UploadStashFileNotFoundException extends UploadStashException {
+}
+
+class UploadStashBadPathException extends UploadStashException {
+}
+
+class UploadStashFileException extends UploadStashException {
+}
+
+class UploadStashZeroLengthFileException extends UploadStashException {
+}
+
+class UploadStashNotLoggedInException extends UploadStashException {
+}
+
+class UploadStashWrongOwnerException extends UploadStashException {
+}
+class UploadStashNoSuchKeyException extends UploadStashException {
}
-class UploadStashException extends MWException {};
-class UploadStashNotAvailableException extends UploadStashException {};
-class UploadStashFileNotFoundException extends UploadStashException {};
-class UploadStashBadPathException extends UploadStashException {};
-class UploadStashFileException extends UploadStashException {};
-class UploadStashZeroLengthFileException extends UploadStashException {};
-class UploadStashNotLoggedInException extends UploadStashException {};
-class UploadStashWrongOwnerException extends UploadStashException {};
-class UploadStashNoSuchKeyException extends UploadStashException {};
* @return int|bool The item index of the lower bound, or false if the target value
* sorts before all items.
*/
- public static function findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target ) {
+ public static function findLowerBound( $valueCallback, $valueCount,
+ $comparisonCallback, $target
+ ) {
if ( $valueCount === 0 ) {
return false;
}
* Exception for Cdb errors.
* This explicitly doesn't subclass MWException to encourage reuse.
*/
-class CdbException extends Exception {}
+class CdbException extends Exception {
+}
*/
class CdbReaderPHP extends CdbReader {
/** The filename */
- var $fileName;
+ protected $fileName;
/* number of hash slots searched under this key */
- var $loop;
+ protected $loop;
/* initialized if loop is nonzero */
- var $khash;
+ protected $khash;
/* initialized if loop is nonzero */
- var $kpos;
+ protected $kpos;
/* initialized if loop is nonzero */
- var $hpos;
+ protected $hpos;
/* initialized if loop is nonzero */
- var $hslots;
+ protected $hslots;
/* initialized if findNext() returns true */
- var $dpos;
+ protected $dpos;
/* initialized if cdb_findnext() returns 1 */
- var $dlen;
+ protected $dlen;
/**
* @param $fileName string
* CDB writer class
*/
class CdbWriterPHP extends CdbWriter {
- var $hplist;
- var $numentries, $pos;
+ protected $hplist;
+
+ protected $numentries;
+
+ protected $pos;
/**
* @param $fileName string
if ( ( $flags & self::QUICK_VOLATILE ) && PHP_SAPI !== 'cli' ) {
try {
$cache = ObjectCache::newAccelerator( array() );
- } catch ( MWException $e ) {} // not supported
+ } catch ( MWException $e ) {
+ // not supported
+ }
}
if ( $cache ) {
$counter = $cache->incr( $bucket, $count );
$data[0] = 'Offset';
}
- $minDiff = 0;
if ( $data[0] == 'System' || $tz == '' ) {
- # Global offset in minutes.
- if ( isset( $wgLocalTZoffset ) ) {
- $minDiff = $wgLocalTZoffset;
- }
+ # Global offset in minutes.
+ $minDiff = $wgLocalTZoffset;
} elseif ( $data[0] == 'Offset' ) {
$minDiff = intval( $data[1] );
} else {
global $wgDisableLangConversion, $wgDisableTitleConversion, $wgRequest;
$isredir = $wgRequest->getText( 'redirect', 'yes' );
$action = $wgRequest->getText( 'action' );
+ if ( $action == 'edit' && $wgRequest->getBool( 'redlink' ) ) {
+ $action = 'view';
+ }
$linkconvert = $wgRequest->getText( 'linkconvert', 'yes' );
$disableLinkConversion = $wgDisableLangConversion
|| $wgDisableTitleConversion;
"accmailtext": "[[User talk:$1|$1]]-ৰ কাৰণে যাদৃচ্ছিকভাৱে উৎপন্ন কৰা গুপ্তশব্দ $2লৈ পঠোৱা হ'ল । \nএই নতুন একাউন্টত প্ৰৱেশ কৰি ''[[Special:ChangePassword|গুপ্তশব্দ সলনি কৰক]]'' পৃষ্ঠাখনত শব্দতো সলনি কৰি ল’ব পাৰিব ।",
"newarticle": "(নতুন)",
"newarticletext": "আপুনি বিচৰা প্ৰবন্ধটো বিচাৰি পোৱা নগ'ল।\n\nইচ্ছা কৰিলে আপুনিয়েই এই প্ৰবন্ধটো লিখা আৰম্ভ কৰিব পাৰে। [$1 ইয়াত] সহায় পাব।\n\nআপুনি যদি ইয়ালৈ ভুলতে আহিছে, তেনেহলে আপোনাৰ ব্ৰাওজাৰৰ '''BACK''' বুটামত টিপা মাৰক।",
- "anontalkpagetext": "----''à¦\8fà¦\87à¦\96ন à¦\86লà§\8bà¦\9aনা পà§\83ষà§\8dঠা বà§\87নামà§\80 সদসà§\8dযৰ বাবà§\87, যিয়à§\87 নিà¦\9cা à¦\8fà¦\95াà¦\89নà§\8dà¦\9f সà§\83ষà§\8dà¦\9fি à¦\95ৰা নাà¦\87 বা যিয়à§\87 সà§\87à¦\87 à¦\8fà¦\95াà¦\89নà§\8dà¦\9f বà§\8dযৱহাৰ নà¦\95ৰà§\87 ।\nà¦\8fতà§\87à¦\95à§\87 à¦\86মি তà§\87à¦\96à§\87তসà¦\95লà¦\95 à¦\86à¦\87-পি ঠিà¦\95নাৰà§\87 à¦\9aিনাà¦\95à§\8dত à¦\95ৰিবলà§\88 বাধà§\8dয ।\nসà§\87à¦\87 à¦\8fà¦\95à§\87à¦\87 à¦\86à¦\87-পি ঠিà¦\95না à¦\85নà§\87à¦\95à§\87à¦\87 বà§\8dযৱহাৰ à¦\95ৰিব পাৰà§\87 ।\nআপুনি যদি এজন বেনামী সদস্য আৰু যদি আপুনি অনুভৱ কৰে যে আপোনাৰ প্ৰতি অপ্ৰাসঙ্গিক মন্তব্য কৰা হৈছে, তেনেহলে আন বেনামী সদস্যৰ পৰা পৃথক কৰিবলৈ \n[[Special:UserLogin/signup|একাউন্ট সৃষ্টি কৰক]] বা [[Special:UserLogin|প্ৰৱেশ কৰক]] ।''",
+ "anontalkpagetext": "----''à¦\8fà¦\87à¦\96ন à¦\86লà§\8bà¦\9aনা পà§\83ষà§\8dঠা বà§\87নামà§\80 সদসà§\8dযৰ বাবà§\87, যিয়à§\87 নিà¦\9cা à¦\8fà¦\95াà¦\89ণà§\8dà¦\9f সà§\83ষà§\8dà¦\9fি à¦\95ৰা নাà¦\87 বা যিয়à§\87 সà§\87à¦\87 à¦\8fà¦\95াà¦\89ণà§\8dà¦\9f বà§\8dযৱহাৰ নà¦\95ৰà§\87।\nà¦\8fতà§\87à¦\95à§\87 à¦\86মি তà§\87à¦\96à§\87তসà¦\95লà¦\95 à¦\86à¦\87-পি ঠিà¦\95নাৰà§\87 à¦\9aিনাà¦\95à§\8dত à¦\95ৰিবলà§\88 বাধà§\8dয।\nসà§\87à¦\87 à¦\8fà¦\95à§\87à¦\87 à¦\86à¦\87-পি ঠিà¦\95না à¦\85নà§\87à¦\95à§\87à¦\87 বà§\8dযৱহাৰ à¦\95ৰিব পাৰà§\87।\nআপুনি যদি এজন বেনামী সদস্য আৰু যদি আপুনি অনুভৱ কৰে যে আপোনাৰ প্ৰতি অপ্ৰাসঙ্গিক মন্তব্য কৰা হৈছে, তেনেহলে আন বেনামী সদস্যৰ পৰা পৃথক কৰিবলৈ \n[[Special:UserLogin/signup|একাউন্ট সৃষ্টি কৰক]] বা [[Special:UserLogin|প্ৰৱেশ কৰক]] ।''",
"noarticletext": "এই পৃষ্ঠাত বৰ্তমান কোনো পাঠ্য নাই ।\nআপুনি আন পৃষ্ঠাত [[Special:Search/{{PAGENAME}}| এই শিৰোনামা অনুসন্ধান কৰিব পাৰে]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} সম্পৰ্কীয় অভিলেখ অনুসন্ধান কৰিব পাৰে],\nবা [{{fullurl:{{FULLPAGENAME}}|action=edit}} এই পৃষ্ঠা সম্পাদনা কৰিব পাৰে]</span>",
"noarticletext-nopermission": "এই পৃষ্ঠাত বৰ্তমান কোনো পাঠ্য নাই।\nআপুনি আন পৃষ্ঠাত [[Special:Search/{{PAGENAME}}|এই শিৰোনামা অনুসন্ধান কৰিব পাৰে]],\nবা <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} সম্পৰ্কীয় অভিলেখ অনুসন্ধান কৰিব পাৰে]</span>, কিন্তু এই পৃষ্ঠা সৃষ্টি কৰিবলৈ আপোনাৰ অনুমতি নাই।",
"missing-revision": "\"{{FULLPAGENAME}}\" নামৰ পৃষ্ঠাৰ #$1 সংশোধনৰ অস্তিত্ব নাই।\n\nসাধাৰণতে বিলোপ কৰা এখন পৃষ্ঠাৰ পুৰণা ইতিহাস লিংক অনুসৰণ কৰিলে এনে হয়।\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} বিলোপন ল'গ]ত অধিক তথ্য পাব।",
"action-edit": "এই পৃষ্ঠা সম্পাদনা কৰক",
"action-createpage": "পৃষ্ঠা সৃষ্টি কৰক",
"action-createtalk": "কথাবতৰা পৃষ্ঠা সৃষ্টি কৰক",
- "action-createaccount": "à¦\8fà¦\87 সদসà§\8dয à¦\8fà¦\95াà¦\89নà§\8dà¦\9f সৃষ্টি কৰক",
+ "action-createaccount": "à¦\8fà¦\87 সদসà§\8dয à¦\8fà¦\95াà¦\89ণà§\8dà¦\9f সৃষ্টি কৰক",
"action-minoredit": "সম্পাদনা অগুৰুত্বপূৰ্ণ বুলি চিহ্নিত কৰক",
"action-move": "এই পৃষ্ঠা স্থানান্তৰ কৰক",
"action-move-subpages": "এই পৃষ্ঠা আৰু ইয়াৰ উপপৃষ্ঠাসমূহ আঁতৰাওক",
"blocklogtext": "এই অভিলেখ অৱৰোধ কৰা আৰু অৱৰোধ আঁতৰ কৰা সদস্য সম্পৰ্কীয়।\nস্বয়ংক্ৰিয়ভাৱে প্ৰতিবন্ধক পোৱা আই.পি. ঠিকনাবোৰ ইয়াত তালিকাভুক্ত কৰা হোৱা নাই।\nসাম্প্ৰতিক কাৰ্যৰত নিষেধ আৰু প্ৰতিবন্ধকৰ বাবে [[Special:BlockList|প্ৰতিবন্ধক তালিকা]] চাওক।",
"unblocklogentry": "$1 বাৰণ উঠাই লোৱা হ’ল",
"block-log-flags-anononly": "কেৱল বেনামী সদস্য",
- "block-log-flags-nocreate": "à¦\8fà¦\95াà¦\89ন্ট সৃষ্টি নিষ্ক্ৰিয় কৰা হৈছে",
+ "block-log-flags-nocreate": "à¦\8fà¦\95াà¦\89ণ্ট সৃষ্টি নিষ্ক্ৰিয় কৰা হৈছে",
"block-log-flags-noautoblock": "স্বয়ংক্ৰিয়-প্ৰতিবন্ধক নিষ্ক্ৰিয় কৰা হৈছে",
"block-log-flags-noemail": "ই-মেইল অৱৰোধ কৰা হৈছে",
"block-log-flags-nousertalk": "নিজৰ কথা-বতৰা পৃষ্ঠা সম্পাদনা কৰিব নোৱাৰি",
"block-log-flags-angry-autoblock": "বৰ্ধিত স্বয়ংক্ৰিয়-প্ৰতিবন্ধক সক্ৰিয় কৰা হৈছে",
"block-log-flags-hiddenname": "সদস্যনাম গোপন কৰা হ’ল",
- "range_block_disabled": "প্ৰশাসকৰ পৰিসীমা প্ৰতিবন্ধক সৃষ্টি কৰিব পৰা ক্ষমতা নিষ্ক্ৰিয় কৰা হৈছে ।",
+ "range_block_disabled": "প্ৰশাসকৰ পৰিসীমা প্ৰতিবন্ধক সৃষ্টি কৰিব পৰা ক্ষমতা নিষ্ক্ৰিয় কৰা হৈছে।",
"ipb_expiry_invalid": "অবৈধ ম্যাদ উকলা সময়",
"ipb_expiry_temp": "গুপ্ত সদস্যনাম অৱৰোধ স্থায়ী হ’ব লাগিব ।",
"ipb_hide_invalid": "এই বিষয়বস্তু নিবাৰণ কৰিব পৰা নগ’ল; ইয়াত {{PLURAL:$1|এটা সম্পাদনা|$1টা সম্পাদনা}} আছে ।",
"post-expand-template-argument-category-desc": "Пасьля раскрыцьця аргумэнту шаблёну (нешта ў трайных дужках, напрыклад, <code>{{{Foo}}}</code>), старонка перавышае памер <code>$wgMaxArticleSize</code>.",
"expensive-parserfunction-category-desc": "На старонцы ўжываецца зашмат рэсурсаёмістых функцыяў парсэру (такіх, як <code>#ifexist</code>). Глядзіце [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
"broken-file-category-desc": "Катэгорыя дадаецца, калі старонка ўтрымлівае няслушную спасылку на файл (спасылку на файл, які не існуе).",
+ "hidden-category-category-desc": "Гэта катэгорыя з дададзенай меткай <code><nowiki>__HIDDENCAT__</nowiki></code> у ёй, што па змоўчаньні не адлюстроўвае яе на старонках у сьпісе катэгорыяў.",
"mailnologin": "Няма адрасу атрымальніка",
"mailnologintext": "Вам неабходна [[Special:UserLogin|ўвайсьці ў сыстэму]] і мець пацьверджаны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах]], каб дасылаць лісты іншым удзельнікам.",
"emailuser": "Даслаць ліст",
"sp-contributions-blocklog": "Registre de bloquejos",
"sp-contributions-suppresslog": "contribucions suprimides de l'usuari",
"sp-contributions-deleted": "contribucions d'usuari esborrades",
- "sp-contributions-uploads": "pujades",
+ "sp-contributions-uploads": "càrregues",
"sp-contributions-logs": "registres",
"sp-contributions-talk": "discussió",
"sp-contributions-userrights": "gestió de drets d'usuari",
"listingcontinuesabbrev": "(кхин дlа)",
"index-category": "Меттигтерахьйо агlонаш",
"noindex-category": "ДӀахьушйоцу агӀонаш",
- "broken-file-category": "{{#switch:{{NAMESPACE}}\n |{{ns:0}}=Ð\91олÑ\85 Ñ\86абеÑ\88 Ñ\84айлийн Ñ\85Ñ\8cажоÑ\80агаÑ\88 йолÑ\83 агÓ\80онаÑ\88}}",
+ "broken-file-category": "{{#switch:{{NAMESPACE}}\n |{{ns:0}}=Болх цабеш файлийн хьажоргаш йолу агӀонаш}}",
"about": "Цуьнах лаьцна",
"article": "Яззам",
"newwindow": "(керлачу корехь)",
"rows": "МогӀанаш:",
"columns": "БӀогӀамаш:",
"searchresultshead": "Лаха",
- "stub-threshold": "Ð\9aеÑ\87 Ñ\8fÑ\80ан доза <a href=\"#\" class=\"stub\">коÑ\8cÑ\80Ñ\82амогÓ\80амна Ñ\85Ñ\8cажоÑ\80агаÑ\88</a> (байÑ\82аÑ\88каÑ\85):",
+ "stub-threshold": "Кеч яран доза <a href=\"#\" class=\"stub\">коьртамогӀамна хьажоргаш</a> (байташках):",
"stub-threshold-disabled": "ДӀадайина",
"recentchangesdays": "Керла нисдар гайта динахь:",
"recentchangesdays-max": "Къезиг $1 {{PLURAL:$1|дена}}",
"brokenredirectstext": "Лахара дӀасахьажийнарш ю йоцучу агӀонийн тӀе хьажийна:",
"brokenredirects-edit": "нисъе",
"brokenredirects-delete": "дӀаяккха",
- "withoutinterwiki": "ЮкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80агаÑ\88 йоÑ\86Ñ\83 агÓ\80онаÑ\88",
+ "withoutinterwiki": "Юкъарвики-хьажоргаш йоцу агӀонаш",
"withoutinterwiki-summary": "Лахара агӀонийн юкъарвики-хьажоргаш яц:",
"withoutinterwiki-submit": "Гайта",
"fewestrevisions": "ЧIогIа кIезиг башхонаш йолу агIонаш",
"whatlinkshere-hideredirs": "$1 дӀасахьажорш",
"whatlinkshere-hidetrans": "$1 латораш",
"whatlinkshere-hidelinks": "$1 хьажоргаш",
- "whatlinkshere-hideimages": "$1 Ñ\84айлийн Ñ\85Ñ\8cажоÑ\80агаÑ\88",
+ "whatlinkshere-hideimages": "$1 файлийн хьажоргаш",
"whatlinkshere-filters": "Литтарш",
"autoblockid": "Ша блоккхетар #$1",
"block": "Декъашхочун блоктохар",
"protectedpages": "پەڕە پارێزراوەکان",
"protectedpages-indef": "تەنیا پاراستنە بێسنوورەکان",
"protectedpages-cascade": "تەنیا پاراستنە زنجیرییەکان",
+ "protectedpages-noredirect": "ڕەوانەکەرەکان بشارەوە",
"protectedpagesempty": "هیچ لاپەڕەیک ئێستا بەم دیاریکراوانە نەپارێزراوە.",
"protectedpages-page": "پەڕە",
+ "protectedpages-params": "پارامەترەکانی پاراستن",
+ "protectedpages-reason": "ھۆکار",
"protectedtitles": "سەرناوە پارێزراوەکان",
"protectedtitlesempty": "ھیچ سەرناوێک بەم سنوورانەوە ئێستا نەپارێزراوە.",
"listusers": "پێرستی بەکارھێنەران",
"whatlinkshere-links": "$1 ligami",
"whatlinkshere-hidetrans": "inclusione",
"whatlinkshere-hidelinks": "$1 ligami",
- "ipadressorusername": "Adrizzu IP o nome di cuntributore",
+ "ipaddressorusername": "Adrizzu IP o nome di cuntributore",
"ipbreason": "Mutivu:",
"ipboptions": "2 ore:2 hours,1 ghjornu:1 day,3 ghjorni:3 days,1 sittimana:1 week,2 sittimane:2 weeks,1 mese:1 month,3 mesi:3 months,6 mesi:6 months,1 annu:1 year,infinitu:infinite",
"ipblocklist": "Cuntributori bluccati",
"file-nohires": "Una diversione incù una risoluzione più alta ùn hè micca dispunibile.",
"show-big-image": "Schedariu originale",
"show-big-image-other": "{{PLURAL:$2|Altra risuluzione|Altre risuluzioni}}: $1.",
- "showhidebots": "($1 boti)",
"noimages": "Nulla da vede.",
"ilsubmit": "Ricerca",
"bydate": "per data",
"table_pager_limit_label": "Risultati per pagina:",
"table_pager_limit_submit": "Invià",
"table_pager_empty": "Micca risultati",
+ "autosumm-replace": "Pagina sustituita incù '$1'",
"autoredircomment": "Reindirizzamentu à [[$1]]",
"autosumm-new": "Pagina nova: $1",
"watchlistedit-raw-titles": "Pagine:",
"tags-edit": "mudificà",
"logentry-delete-delete": "$1 ha cancellatu a pagina $3",
"logentry-move-move": "$1 {{GENDER:$2|hà spustatu}} a pagina $3 à $4",
+ "logentry-newusers-create": "U participante $3 hè statu creatu da $1",
"rightsnone": "(nessunu)",
"expand_templates_output": "Risultatu"
}
"withoutinterwiki-submit": "Bımocne",
"fewestrevisions": "Pelê be senık çımraviyarnayışi",
"nbytes": "$1 {{PLURAL:$1|bayt|bayti}}",
- "ncategories": "$1 {{PLURAL:$1|Kategori|Kategoriy}}",
+ "ncategories": "$1 {{PLURAL:$1|Kategoriye|Kategoriy}}",
"ninterwikis": "$1 {{PLURAL:$1|interwiki|interwikiy}}",
"nlinks": "$1 {{PLURAL:$1|link|linkî}}",
"nmembers": "$1 {{PLURAL:$1|eza|ezayan}}",
"move": "Bere",
"movethispage": "Ena pele bere",
"unusedimagestext": "Enê dosyey estê, feqet zerrey yew pele de wedardey niyê.\nXo vira mekerê ke, sıteyê webiê bini şenê direkt ebe URLi yew dosya ra gırê bê, u wına şenê verba gurênayışo feal de tiya hewna lista bê.",
- "unusedcategoriestext": "kategoriyê ke cêrdeyê estê lakin qet ju wesiqa yana kategori de nexebtênê.",
+ "unusedcategoriestext": "Kategoriyê ke cêr derê, nê bıbê zi, terefê qet madeyan ya zi kategoriyan ra nêgureniyenê.",
"notargettitle": "Hedef çini yo",
"notargettext": "qey xebıtnayişê ney fonksiyoni şıma yew hedef nişane nêkerd.",
"nopagetitle": "wina yew pelê hedefi çin o.",
"listgrouprights-addgroup-self-all": "şıma eşkeni hesabê xo re heme gruban têare bıkerî",
"listgrouprights-removegroup-self-all": "şıma hesabê xo ra eşkeni heme gruban bıveci",
"listgrouprights-namespaceprotection-namespace": "Caynami",
- "trackingcategories": "Kategoriye taqiban",
- "trackingcategories-msg": "Kategoriya taqibi",
+ "trackingcategories": "Kategoriyê teqibi",
+ "trackingcategories-msg": "Kategoriya teqibi",
"trackingcategories-name": "Namey mesaci",
"trackingcategories-desc": "Kriterê definayışê kategoriye",
"trackingcategories-disabled": "Kategoriya feal niya",
"nowatchlist": "listeya temaşa kerdıişê şıma de yew madde zi çina.",
"watchlistanontext": "qey vurnayişê maddeya listeya temaşakerdişi $1.",
"watchnologin": "Şıma cıkewtış nêvıraşto",
- "addwatch": "Listeyê seyri deke",
+ "addwatch": "Lista seyrkerdışi ke",
"addedwatchtext": "Ma pele \"[[:$1]]\" zerri [[Special:Watchlist|watchlist]]ê tı kerd de.\nEna deme ra, ma qe vurnayışan ser ena pele tı haberdar keni.",
- "removewatch": "Listedê mınê seyr kerdışi ra hewad",
+ "removewatch": "Lista seyrkerdışi ra wedare",
"removedwatchtext": "Ena pela \"[[:$1]]\" biya wedariya [[Special:Watchlist|listeyê seyr-kerdışi şıma]].",
"watch": "Seyr ke",
"watchthispage": "Ena pele seyr ke",
"tooltip-compareselectedversions": "Ena per de ferqê rewziyonan de dı weçinaya bıvinê",
"tooltip-watch": "Ena pele lista xoya seyrkerdışi ke",
"tooltip-watchlistedit-normal-submit": "Sernuşteyan wedare",
- "tooltip-watchlistedit-raw-submit": "Listeyê seyri newen ke",
+ "tooltip-watchlistedit-raw-submit": "Lista seyrkerdışi newe ke",
"tooltip-recreate": "pel hewn a bışiyo zi tepiya biya",
"tooltip-upload": "Sergen de bari be",
"tooltip-rollback": "\"Peyser bia\" be yew tık pela iştıraq(an)ê peyên|i(an) peyser ano.",
"pageinfo-recent-edits": "Amariya vurnayışan ($1 ra nata)",
"pageinfo-recent-authors": "Amarina nuştekaran pêro",
"pageinfo-magic-words": "{{PLURAL:$1|Çekuya|Çekuyê}} ($1) sihırini",
- "pageinfo-hidden-categories": "($1) {{PLURAL:$1|Kategoriyer|Kategoriyan}} bınımne",
+ "pageinfo-hidden-categories": "{{PLURAL:$1|Kategoriya nımıtiye|Kategoriyê nımıtey}} ($1)",
"pageinfo-templates": "{{PLURAL:$1|Şablono|Şablonê}} ke mocniyenê ($1)",
"pageinfo-transclusions": "{{PLURAL:$1|1 Pele|$1 Pelan}} de bestiya pıra",
"pageinfo-toolboxlink": "Melumatê pele",
"exif-languagecode": "Zıwan",
"exif-iimversion": "Verqaydê IIM",
"exif-iimcategory": "Kategoriye",
- "exif-iimsupplementalcategory": "Kategoriyê temam kerdışi",
+ "exif-iimsupplementalcategory": "Kategoriyê temamkerdışi",
"exif-datetimeexpires": "No peyra mekarênê",
"exif-datetimereleased": "Bıroşe",
"exif-originaltransmissionref": "Oricinal pusula da kodê açarnayışi",
"bitrate-yottabits": "$1Ybps",
"lag-warn-normal": "Vurnayîşî ke {{PLURAL:$1|seniye|seniyeyî}} ra newiyerî belki inan nimucneno.",
"lag-warn-high": "Eka serverê databaseyî zaf hebitiyeno, ayra vurnayîşî ke {{PLURAL:$1|seniye|seniyeyî}} ra newiyerî belki inan nimucneno.",
- "watchlistedit-normal-title": "Listeyê seyirkerdişi bivurne",
- "watchlistedit-normal-legend": "Listeya seyri ra sername wedarne.",
+ "watchlistedit-normal-title": "Lista seyrkerdışi bıvurne",
+ "watchlistedit-normal-legend": "Lista seyrkerdışi ra sernameyan wedare",
"watchlistedit-normal-explain": "Listeyê seyr kerdîşî ti de serogî cor de mucnayiyo.\nEka ti wazeno seroğ biwedarne, kuti ke kistê de, ay işaret bike u \"{{int:Watchlistedit-normal-submit}}\" klik bike.\nTi hem zi eşkeno [[Special:EditWatchlist/raw|edit the raw list]].",
"watchlistedit-normal-submit": "Sernuşteyan wedare",
"watchlistedit-normal-done": "{{PLURAL:$1|1 seroğ|$1 seroğî}} seyr kerdişê tu ra wedarno.",
- "watchlistedit-raw-title": "Listeyê seyirkerdişi ye hami bivurne",
- "watchlistedit-raw-legend": "Listeyê seyirkerdişi ye hami bivurne",
+ "watchlistedit-raw-title": "Lista seyrkerdışia xame bıvurne",
+ "watchlistedit-raw-legend": "Lista seyrkerdışia xame bıvurne",
"watchlistedit-raw-explain": "Listeyê seyr kerdîşî ti de serogî cor de mucnayiyo u ti eşkeno pê dekerdiş u wedarnayîş liste bivurne.\nEka vurnayîşê ti qediyo, Listeyê Seyr Kerdişî Rocaniye Bike \"{{int:Watchlistedit-raw-submit}}\" klik bike.\nTi hem zi eşkeno [[Special:EditWatchlist|use the standard editor]].",
"watchlistedit-raw-titles": "Seroğî:",
- "watchlistedit-raw-submit": "Listeyê seyri newen ke",
+ "watchlistedit-raw-submit": "Lista seyrkerdışi newe ke",
"watchlistedit-raw-done": "Listeyê tuyê seyrkerdişi rocaniye biyo",
"watchlistedit-raw-added": "{{PLURAL:$1|1 seroğ|$1 seroğî}} de kerd:",
"watchlistedit-raw-removed": "{{PLURAL:$1|1 seroğ|$1 seroği}} besteriyaye:",
- "watchlisttools-view": "vurnayışanê eleqadari bıvin",
- "watchlisttools-edit": "Lista seyrkerdışi bıvênên u bıvurnên",
- "watchlisttools-raw": "Listeyê seyr-kerdışi bıvin",
+ "watchlisttools-view": "Vurnayışanê elaqedaran bıvêne",
+ "watchlisttools-edit": "Lista seyrkerdışi bıvêne û bıvurne",
+ "watchlisttools-raw": "Lista seyrkerdışia xame bıvurne",
"iranian-calendar-m1": "Farvardin",
"iranian-calendar-m2": "Ordibeheşt",
"iranian-calendar-m3": "Xordad",
"right-move": "Move pages",
"right-move-subpages": "Move pages with their subpages",
"right-move-rootuserpages": "Move root user pages",
+ "right-move-categorypages": "Move category pages",
"right-movefile": "Move files",
"right-suppressredirect": "Not create redirects from source pages when moving pages",
"right-upload": "Upload files",
"action-move": "move this page",
"action-move-subpages": "move this page, and its subpages",
"action-move-rootuserpages": "move root user pages",
+ "action-move-categorypages": "move category pages",
"action-movefile": "move this file",
"action-upload": "upload this file",
"action-reupload": "overwrite this existing file",
"movepagetalktext": "The associated talk page will be automatically moved along with it <strong>unless:</strong>\n*A non-empty talk page already exists under the new name, or\n*You uncheck the box below.\n\nIn those cases, you will have to move or merge the page manually if desired.",
"movearticle": "Move page:",
"moveuserpage-warning": "<strong>Warning:</strong> You are about to move a user page. Please note that only the page will be moved and the user will <em>not</em> be renamed.",
+ "movecategorypage-warning": "<strong>Warning:</strong> You are about to move a category page. Please note that only the page will be moved and any pages in the old category will <em>not</em> be recategorized into the new one.",
"movenologintext": "You must be a registered user and [[Special:UserLogin|logged in]] to move a page.",
"movenotallowed": "You do not have permission to move pages.",
"movenotallowedfile": "You do not have permission to move files.",
"cant-move-user-page": "You do not have permission to move user pages (apart from subpages).",
"cant-move-to-user-page": "You do not have permission to move a page to a user page (except to a user subpage).",
+ "cant-move-category-page": "You do not have permission to move category pages.",
+ "cant-move-to-category-page": "You do not have permission to move a page to a category page.",
"newtitle": "To new title:",
"move-watch": "Watch source page and target page",
"movepagebtn": "Move page",
"movenosubpage": "This page has no subpages.",
"movereason": "Reason:",
"move-redirect-text": "",
+ "category-move-redirect-override": "-",
"revertmove": "revert",
"delete_and_move": "Delete and move",
"delete_and_move_text": "== Deletion required ==\nThe destination page \"[[:$1]]\" already exists.\nDo you want to delete it to make way for the move?",
"variantname-shi-tfng": "shi-Tfng",
"variantname-shi-latn": "shi-Latn",
"variantname-shi": "shi",
+ "variantname-uz": "uz",
+ "variantname-uz-latn": "uz-Latn",
+ "variantname-uz-cyrl": "uz-Cyrl",
"metadata": "Metadata",
"metadata-help": "This file contains additional information, probably added from the digital camera or scanner used to create or digitize it.\nIf the file has been modified from its original state, some details may not fully reflect the modified file.",
"metadata-expand": "Show extended details",
"watchlistedit-normal-submit": "Remove titles",
"watchlistedit-normal-done": "{{PLURAL:$1|1 title was|$1 titles were}} removed from your watchlist:",
"watchlistedit-raw-title": "Edit raw watchlist",
- "watchlistedit-raw-legend": "Edit raw watchlist",
+ "watchlistedit-raw-legend": "Edit raw watchlist",
"watchlistedit-raw-explain": "Titles on your watchlist are shown below, and can be edited by adding to and removing from the list;\none title per line.\nWhen finished, click \"{{int:Watchlistedit-raw-submit}}\".\nYou can also [[Special:EditWatchlist|use the standard editor]].",
- "watchlistedit-raw-titles": "Titles:",
- "watchlistedit-raw-submit": "Update watchlist",
- "watchlistedit-raw-done": "Your watchlist has been updated.",
- "watchlistedit-raw-added": "{{PLURAL:$1|1 title was|$1 titles were}} added:",
- "watchlistedit-raw-removed": "{{PLURAL:$1|1 title was|$1 titles were}} removed:",
+ "watchlistedit-raw-titles": "Titles:",
+ "watchlistedit-raw-submit": "Update watchlist",
+ "watchlistedit-raw-done": "Your watchlist has been updated.",
+ "watchlistedit-raw-added": "{{PLURAL:$1|1 title was|$1 titles were}} added:",
+ "watchlistedit-raw-removed": "{{PLURAL:$1|1 title was|$1 titles were}} removed:",
+ "watchlistedit-clear-title": "Cleared watchlist",
+ "watchlistedit-clear-legend": "Clear watchlist",
+ "watchlistedit-clear-explain": "All of the titles will be removed from your watchlist",
+ "watchlistedit-clear-titles": "Titles:",
+ "watchlistedit-clear-submit": "Clear the watchlist (This is permanent!)",
+ "watchlistedit-clear-done": "Your watchlist has been cleared.",
+ "watchlistedit-clear-removed": "{{PLURAL:$1|1 title was|$1 titles were}} removed:",
+ "watchlistedit-too-many": "There are too many pages to display here.",
+ "watchlisttools-clear": "Clear the watchlist",
"watchlisttools-view": "View relevant changes",
"watchlisttools-edit": "View and edit watchlist",
"watchlisttools-raw": "Edit raw watchlist",
"tog-watchlisthideliu": "Ocultar las ediciones de los usuarios registrados en la lista de seguimiento",
"tog-watchlisthideanons": "Ocultar las ediciones de los usuarios anónimos en la lista de seguimiento",
"tog-watchlisthidepatrolled": "Ocultar las ediciones patrulladas en la lista de seguimiento",
- "tog-ccmeonemails": "Recibir copias de los correos que envío a otros usuarios",
+ "tog-ccmeonemails": "Recibir copias de los mensajes que envíe a otros usuarios",
"tog-diffonly": "No mostrar bajo las ''diferencias'' el contenido de la página",
"tog-showhiddencats": "Mostrar las categorías escondidas",
"tog-norollbackdiff": "Omitir la diferencia después de revertir",
"nospecialpagetext": "<strong>Ha solicitado una página especial inexistente.</strong>\n\nPuedes ver una lista de las páginas especiales en [[Special:SpecialPages|{{int:specialpages}}]].",
"error": "Error",
"databaseerror": "Error de la base de datos",
- "databaseerror-text": "Se ha producido un error en la base de datos.\nEsto puede indicar un bug en el software.",
+ "databaseerror-text": "Ocurrió un error de consulta de la base de datos.\nEsto puede indicar un fallo en el software.",
"databaseerror-textcl": "Se ha producido un error en la base de datos.",
"databaseerror-query": "Consulta: $1",
"databaseerror-function": "Función: $1",
"viewsourcetext": "Puedes ver y copiar el código fuente de esta página:",
"viewyourtext": "Puedes ver y copiar el código de '''tus ediciones''' a esta página:",
"protectedinterface": "Esta página proporciona el texto de la interfaz del software en este wiki, y está protegida para prevenir el abuso.\nPara agregar o cambiar las traducciones para todos los wikis, por favor, usa [//translatewiki.net/ translatewiki.net], el proyecto de localización de MediaWiki.",
- "editinginterface": "'''Aviso:''' Estás editando una página usada para proporcionar el texto de la interfaz para el software. \nLos cambios en esta página afectarán a la apariencia de la interfaz para los demás usuarios de este wiki. \nPara añadir o cambiar las traducciones, por favor considera usar [//translatewiki.net/ translatewiki.net], el proyecto de localización de MediaWiki.",
+ "editinginterface": "<strong>Aviso:</strong> Estás editando una página usada para proporcionar el texto de la interfaz para el software. \nLos cambios en esta página afectarán la apariencia de la interfaz para los demás usuarios de este wiki. \nPara añadir o cambiar las traducciones utiliza [//translatewiki.net/ translatewiki.net], el proyecto de localización de MediaWiki.",
"cascadeprotected": "Esta página ha sido protegida para su edición, porque está incluida en {{PLURAL:$1|la siguiente página|las siguientes páginas}}, que están protegidas con la opción de «cascada»:\n$2",
"namespaceprotected": "No tienes permiso para editar las páginas del espacio de nombres '''$1'''.",
"customcssprotected": "No tienes permiso para editar esta página CSS, porque contiene configuraciones personales de otro usuario.",
"mycustomjsprotected": "No tienes permiso para editar esta página JavaScript.",
"myprivateinfoprotected": "No tienes permiso para editar tu información privada.",
"mypreferencesprotected": "No tienes permiso para editar tus preferencias.",
- "ns-specialprotected": "Las páginas especiales no se pueden editar",
+ "ns-specialprotected": "No se pueden editar las páginas especiales.",
"titleprotected": "Esta página ha sido protegida contra creación por [[User:$1|$1]].\nEl motivo dado fue: \"''$2''\".",
"filereadonlyerror": "No se puede modificar el archivo \"$1\" porque el repositorio de archivos \"$2\" está en modo de sólo lectura.\nEl administrador que lo ha bloqueado ofrece esta explicación: \"$3\".",
"invalidtitle-knownnamespace": "Título no válido con el espacio de nombres \"$2\" y el texto \"$3\"",
"exception-nologin": "No has iniciado sesión",
"exception-nologin-text": "[[Special:Userlogin|Inicia sesión]] para acceder a esta página o acción.",
"exception-nologin-text-manual": "Necesitas $1 para acceder a esta página o acción.",
- "virus-badscanner": "Error de configuración: Antivirus desconocido: ''$1''",
+ "virus-badscanner": "Configuración incorrecta: antivirus desconocido: <em>$1</em>",
"virus-scanfailed": "falló el análisis (código $1)",
"virus-unknownscanner": "antivirus desconocido:",
- "logouttext": "\"'Usted está ahora desconectado.\"'\nTenga en cuenta que algunas páginas pueden continuar mostrándose como si todavía estuviera conectado, hasta que borres la caché de tu navegador.",
+ "logouttext": "<strong>Ha finalizado tu sesión.</strong>\n\nPuede que algunas páginas continúen mostrándose como si la sesión estuviera iniciada hasta que vacíes la memoria caché del navegador.",
"welcomeuser": "¡Te damos la bienvenida, $1!",
"welcomecreation-msg": "Se ha creado tu cuenta.\nNo olvides personalizar tus [[Special:Preferences|preferencias de {{SITENAME}}]].",
"yourname": "Nombre de usuario:",
"remembermypassword": "Mantenerme conectado en este navegador (hasta $1 {{PLURAL:$1|día|días}})",
"userlogin-remembermypassword": "Mantener mi sesión iniciada",
"userlogin-signwithsecure": "Usar conexión segura",
- "yourdomainname": "Dominio",
+ "yourdomainname": "Tu dominio:",
"password-change-forbidden": "No puedes cambiar las contraseñas de este wiki.",
"externaldberror": "Hubo un error de autenticación externa de la base de datos o bien no tienes autorización para actualizar tu cuenta externa.",
"login": "Acceder",
"pt-login": "Iniciar sesión",
"pt-login-button": "Iniciar sesión",
"pt-createaccount": "Crear una cuenta",
- "pt-userlogout": "Cerrar sesión",
+ "pt-userlogout": "Salir",
"php-mail-error-unknown": "Error desconocido en la función mail() de PHP.",
"user-mail-no-addy": "Se ha intentado enviar correo electrónico sin una dirección de correo electrónico.",
"user-mail-no-body": "Trató de enviar un correo electrónico con un cuerpo vacío o excesivamente corto.",
"trackingcategories-disabled": "La categoría está desactivada",
"mailnologin": "Ninguna dirección de envio",
"mailnologintext": "Debes [[Special:UserLogin|iniciar sesión]] y tener una dirección electrónica válida en tus [[Special:Preferences|preferencias]] para enviar un correo electrónico a otros usuarios.",
- "emailuser": "Enviar un correo electrónico a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}",
- "emailuser-title-target": "Enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}",
+ "emailuser": "Enviar un mensaje de correo a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}",
+ "emailuser-title-target": "Enviar un mensaje a {{GENDER:$1|este usuario|esta usuaria}}",
"emailuser-title-notarget": "Enviar un correo electrónico al usuario",
- "emailpage": "Enviar un correo electrónico a un usuario",
+ "emailpage": "Enviar mensaje al usuario",
"emailpagetext": "Puedes usar el formulario de abajo para enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}.\nLa dirección de correo electrónico que indicaste en [[Special:Preferences|tus preferencias de usuario]] aparecerá en el campo \"Remitente\" o \"De\" para que el destinatario pueda responderte.",
"defemailsubject": "Correo electrónico enviado por el usuario «$1» desde {{SITENAME}}",
"usermaildisabled": "Correo electrónico del usuario deshabilitado",
"specialpages-note": "* Páginas especiales normales\n* <span class=\"mw-specialpagerestricted\">Páginas especiales restringidas.</span>\n* <span class=\"mw-specialpagecached\">Páginas especiales en caché (podrían ser obsoletas).</span>",
"specialpages-group-maintenance": "Reportes de mantenimiento",
"specialpages-group-other": "Otras páginas especiales",
- "specialpages-group-login": "Iniciar sesión / Crear cuenta",
+ "specialpages-group-login": "Acceder/crear cuenta",
"specialpages-group-changes": "Cambios recientes y registros",
"specialpages-group-media": "Páginas sobre archivos",
"specialpages-group-users": "Usuarios y permisos",
"searchbutton": "Bilatu",
"go": "Joan",
"searcharticle": "Joan",
- "history": "Orrialdearen historia",
+ "history": "Orriaren historia",
"history_short": "Historia",
"updatedmarker": "nire azkeneko bisitaz geroztik eguneratuta",
"printableversion": "Inprimatzeko bertsioa",
"pagemerge-logentry": "[[$1]] [[$2]](r)ekin batu da ($3(e)raino berrikuspenak)",
"revertmerge": "Bereiztu",
"mergelogpagetext": "Jarraian dagoen zerrendak orrialde baten historiatik beste batera egindako azken bateratzeak erakusten ditu.",
- "history-title": "«$1» orrialdearen historia berrikuspena",
+ "history-title": "«$1» orriaren historia berrikuspena",
"difference-title": "«$1»: berrikuspenen arteko aldeak",
"difference-title-multipage": "«$1» eta «$2» orrien arteko aldeak",
"difference-multipage": "(Orrien arteko aldeak)",
"edit": "Muokkaa",
"edit-local": "Muokkaa paikallista kuvausta",
"create": "Luo sivu",
- "create-local": "Lisää paikallinen kuvaus",
+ "create-local": "Luo paikallinen kuvaus",
"editthispage": "Muokkaa tätä sivua",
"create-this-page": "Luo tämä sivu",
"delete": "Poista",
"newimages": "Uudet tiedostot",
"imagelisttext": "Alla on {{PLURAL:$1|1 tiedosto|$1 tiedostoa}} lajiteltuna <strong>$2</strong>.",
"newimages-summary": "Tällä toimintosivulla on viimeisimmät tallennetut tiedostot.",
- "newimages-legend": "Suodin",
+ "newimages-legend": "Suodatin",
"newimages-label": "Tiedostonimi (tai osa siitä)",
"newimages-showbots": "Näytä bottien tekemät tallennukset",
"noimages": "Ei uusia tiedostoja.",
"newimages-summary": "Cette page spéciale affiche les derniers fichiers importés.",
"newimages-legend": "Nom du fichier",
"newimages-label": "Nom du fichier (ou une partie de celui-ci) :",
+ "newimages-showbots": "Afficher les imports par des robots",
"noimages": "Aucune image à afficher.",
"ilsubmit": "Rechercher",
"bydate": "par date",
"newimages-summary": "Questa pagina speciale mostra i file caricati più di recente.",
"newimages-legend": "Filtra",
"newimages-label": "Nome file (o una parte di esso):",
+ "newimages-showbots": "Mostra caricamenti di bot",
"noimages": "Non c'è nulla da vedere.",
"ilsubmit": "Ricerca",
"bydate": "per data",
"compare-submit": "Confronta",
"compare-invalid-title": "Il titolo che hai specificato non è valido.",
"compare-title-not-exists": "Il titolo che hai specificato non esiste.",
- "compare-revision-not-exists": "La revisione che hai specificato non esiste.",
+ "compare-revision-not-exists": "La versione che hai specificato non esiste.",
"dberr-problems": "Questo sito sta avendo dei problemi tecnici.",
"dberr-again": "Prova ad attendere qualche minuto e ricaricare.",
"dberr-info": "(Impossibile contattare il server del database: $1)",
"pageinfo-length": "Бет ұзындығы (байтпен)",
"pageinfo-article-id": "Бет ID-і",
"pageinfo-language": "Бет мәлімет тілі",
- "pageinfo-content-model": "Бет мағұлымат қалпы",
+ "pageinfo-content-model": "Бет мағлұмат қалпы",
"pageinfo-robot-policy": "Индекстеуді робот жүргізеді",
"pageinfo-robot-index": "Рұқсат берілген",
"pageinfo-robot-noindex": "Рұқсат етілмеген",
"logentry-delete-event": "$1 $3 бетіндегі {{PLURAL:$5|журнал оқиғасы|$5 журнал оқиғасы}} көрінісін {{GENDER:$2|өзгертті}}: $4",
"logentry-delete-revision": "$1 $3 бетіндегі {{PLURAL:$5|нұсқа|$5 нұсқа}} көрінісін {{GENDER:$2|өзгертті}}: $4",
"logentry-suppress-event": "$1 $3 бетіндегі {{PLURAL:$5|журнал оқиғасы|$5 журнал оқиғасы}} көрінісін құпия түрде {{GENDER:$2|өзгертті}}: $4",
- "revdelete-content-hid": "мағұлымат жасырылған",
+ "revdelete-content-hid": "мағлұмат жасырылған",
"revdelete-summary-hid": "өңдеу түйіндемесі жасырылған",
"revdelete-uname-hid": "қатысушы есімі жасырылған",
"revdelete-content-unhid": "мағлұматы жасырылмаған",
"username": "{{GENDER:$1|사용자 이름}}:",
"uid": "{{GENDER:$1|사용자}} ID:",
"prefs-memberingroups": "{{GENDER:$2|소속}} {{PLURAL:$1|그룹}}:",
- "prefs-registration": "ë\93±ë¡\9d ì\9d¼ì\8b\9c:",
+ "prefs-registration": "ë\93±ë¡\9d ì\8b\9cê°\84:",
"yourrealname": "실명:",
"yourlanguage": "언어:",
"yourvariant": "언어 변종:",
"newimages-summary": "이 특수 문서는 최근에 올라온 파일을 나열하고 있습니다.",
"newimages-legend": "필터",
"newimages-label": "파일 이름 (또는 그 일부분):",
+ "newimages-showbots": "봇이 올린 것 보기",
"noimages": "그림이 없습니다.",
"ilsubmit": "검색",
"bydate": "날짜",
"exif-subsectime": "Дел од секундата во кој е сликано",
"exif-subsectimeoriginal": "Дел од секундата во кој е фотографирано",
"exif-subsectimedigitized": "Дел од секундата во кој е дигитализирано",
- "exif-exposuretime": "Ð\95кÑ\81позиÑ\86иÑ\98а",
+ "exif-exposuretime": "Ð\92Ñ\80еме на изложеноÑ\81Ñ\82",
"exif-exposuretime-format": "$1 сек ($2)",
"exif-fnumber": "F-бр.",
"exif-fnumber-format": "f/$1",
- "exif-exposureprogram": "Режим на екÑ\81позиÑ\86иÑ\98а",
+ "exif-exposureprogram": "Ð\9fÑ\80огÑ\80ам на изложÑ\83ваÑ\9aе",
"exif-spectralsensitivity": "Спектрална осетливост",
"exif-isospeedratings": "Светлоосетливост по ISO",
"exif-shutterspeedvalue": "APEX-брзина на затворачот",
"exif-aperturevalue": "APEX-oтвор",
"exif-brightnessvalue": "APEX-светлост",
- "exif-exposurebiasvalue": "Ð\9dадомеÑ\81Ñ\82ок на екÑ\81позиÑ\86иÑ\98аÑ\82а",
+ "exif-exposurebiasvalue": "Ð\9dадомеÑ\81Ñ\82ок на изложÑ\83ваÑ\9aеÑ\82о",
"exif-maxaperturevalue": "Макс. отвореност на блендата",
"exif-subjectdistance": "Оддалеченост до објектот",
"exif-meteringmode": "Режим на мерачот",
"exif-focalplaneyresolution": "Разложеност на жаришната рамнина Y",
"exif-focalplaneresolutionunit": "Единица за разложеност на жаришната рамнина",
"exif-subjectlocation": "Положба на субјектот",
- "exif-exposureindex": "Ð\98ндекÑ\81 на екÑ\81позиÑ\86иÑ\98аÑ\82а",
+ "exif-exposureindex": "Ð\9fоказаÑ\82ел на изложÑ\83ваÑ\9aеÑ\82о",
"exif-sensingmethod": "Метод на сензорот",
"exif-filesource": "Извор на податотеката",
"exif-scenetype": "Тип на сцена",
"exif-customrendered": "Дополнитела обработка на сликата",
- "exif-exposuremode": "Режим на екÑ\81позиÑ\86иÑ\98а",
+ "exif-exposuremode": "Режим на изложÑ\83ваÑ\9aе",
"exif-whitebalance": "Рамнотежа на бело",
"exif-digitalzoomratio": "Сооднос на дигиталното приближување (зум)",
"exif-focallengthin35mmfilm": "Жаришно растојание кај 35 мм филм",
"exif-scenetype-1": "Директно фотографирана слика",
"exif-customrendered-0": "Нормален процес",
"exif-customrendered-1": "Нестандарден процес",
- "exif-exposuremode-0": "Ð\90вÑ\82омаÑ\82Ñ\81ка екÑ\81позиÑ\86иÑ\98а",
- "exif-exposuremode-1": "РаÑ\87на екÑ\81позиÑ\86иÑ\98а",
+ "exif-exposuremode-0": "Ð\90вÑ\82омаÑ\82Ñ\81ко изложÑ\83ваÑ\9aе",
+ "exif-exposuremode-1": "РаÑ\87но изложÑ\83ваÑ\9aе",
"exif-exposuremode-2": "Автоматски со зададен распон",
"exif-whitebalance-0": "Автоматска рамнотежа на бело",
"exif-whitebalance-1": "Рачна рамнотежа на бело",
"jumptonavigation": "വഴികാട്ടി",
"jumptosearch": "തിരയൂ",
"view-pool-error": "ക്ഷമിക്കണം, ഈ നിമിഷം സെർവറുകൾ അമിതഭാരം കൈകാര്യം ചെയ്യുകയാണ്.\nധാരാളം ഉപയോക്താക്കൾ ഈ താൾ കാണുവാൻ ശ്രമിച്ചുകൊണ്ടിരിക്കുകയാണ്.\nഇനിയും താൾ ലഭ്യമാക്കുവാൻ താങ്കൾ ശ്രമിക്കുന്നതിന് മുൻപ് ദയവായി അല്പസമയം കാത്തിരിക്കുക.\n\n$1",
+ "generic-pool-error": "ക്ഷമിക്കണം, ഈ നിമിഷം സെർവറുകൾ അമിതഭാരം കൈകാര്യം ചെയ്യുകയാണ്.\nധാരാളം ഉപയോക്താക്കൾ ഈ സ്രോതസ്സുകൾ കാണുവാൻ ശ്രമിച്ചുകൊണ്ടിരിക്കുകയാണ്.\nഇനിയും ഇത് ലഭ്യമാക്കുവാൻ താങ്കൾ ശ്രമിക്കുന്നതിന് മുൻപ് ദയവായി അല്പസമയം കാത്തിരിക്കുക.",
"pool-timeout": "പൂട്ട് മാറാനുള്ള കാത്തിരിപ്പ് സമയം",
"pool-queuefull": "പൂൾ ക്യൂ നിറഞ്ഞിരിക്കുന്നു",
"pool-errorunknown": "അപരിചിതമായ പിഴവ്",
"emailuser": "Enviar-lhe um e-mail",
"emailuser-title-target": "Enviar e-mail para {{GENDER:$1|este usuário|esta usuária}}",
"emailuser-title-notarget": "Enviar e-mail",
- "emailpage": "Contactar usuário",
+ "emailpage": "Enviar e-mail ao usuário",
"emailpagetext": "Você pode usar o formulário a seguir para enviar um e-mail para {{GENDER:$1|este usuário|esta usuária}}.\nO endereço de e-mail que você inseriu em [[Special:Preferences|suas preferências de usuário]] irá aparecer como o endereço do remetente da mensagem, com o destinatário podendo responder diretamente para você.",
"defemailsubject": "E-mail do usuário \"$1\" da {{SITENAME}}",
"usermaildisabled": "O e-mail do usuário foi desativado",
"emailccsubject": "Cópia de sua mensagem para $1: $2",
"emailsent": "E-mail enviado",
"emailsenttext": "Sua mensagem foi enviada.",
- "emailuserfooter": "Este e-mail foi enviado por $1 para $2 através da opção de \"contactar usuário\" da {{SITENAME}}.",
+ "emailuserfooter": "Este e-mail foi enviado por $1 para $2 através da opção de \"enviar e-mail ao usuário\" da {{SITENAME}}.",
"usermessage-summary": "Deixar mensagem de sistema.",
"usermessage-editor": "Mensagens de sistema",
"watchlist": "Páginas vigiadas",
"compare-revision-not-exists": "A revisão que você especificou não existe.",
"dberr-problems": "Desculpe! Este sítio está passando por dificuldades técnicas.",
"dberr-again": "Experimente esperar alguns minutos e atualizar.",
- "dberr-info": "(Não foi possível contactar o servidor de base de dados: $1)",
+ "dberr-info": "(Não foi possível contatar o servidor de base de dados: $1)",
"dberr-info-hidden": "(Não foi possível contatar o banco de dados do servidor)",
"dberr-usegoogle": "Você pode tentar pesquisar no Google entretanto.",
"dberr-outofdate": "Note que os seus índices relativos ao nosso conteúdo podem estar desatualizados.",
"right-move": "{{doc-right|move}}\nThe right to move any page that is not protected from moving.\n{{Identical|Move page}}",
"right-move-subpages": "{{doc-right|move-subpages}}",
"right-move-rootuserpages": "{{doc-right|move-rootuserpages}}",
+ "right-move-categorypages": "{{doc-right|move-categorypages}}",
"right-movefile": "{{doc-right|movefile}}",
"right-suppressredirect": "{{doc-right|suppressredirect}}",
"right-upload": "{{doc-right|upload}}\nThe right to [[Special:Upload|upload]] a file (this includes images, media, audio, ...).\n{{Identical|Upload file}}",
"action-move": "{{Doc-action|move}}",
"action-move-subpages": "{{Doc-action|move-subpages}}",
"action-move-rootuserpages": "{{Doc-action|move-rootuserpages}}",
+ "action-move-categorypages": "{{Doc-action|move-categorypages}}",
"action-movefile": "{{doc-action|movefile}}",
"action-upload": "{{Doc-action|upload}}",
"action-reupload": "{{Doc-action|reupload}}",
"movepagetalktext": "Text on the special 'Move page'. This text only appears if the talk page is not empty.",
"movearticle": "The text before the name of the page that you are moving. Can be translated as \"Page that is going to be moved\". Used in [[Special:MovePage]].\n\nSee also:\n* {{msg-mw|move-page-legend|legend for the form}}\n* {{msg-mw|newtitle|label for new title}}\n* {{msg-mw|movereason|label for textarea}}\n* {{msg-mw|movetalk|label for checkbox}}\n* {{msg-mw|move-leave-redirect|label for checkbox}}\n* {{msg-mw|fix-double-redirects|label for checkbox}}\n* {{msg-mw|move-subpages|label for checkbox}}\n* {{msg-mw|move-talk-subpages|label for checkbox}}\n* {{msg-mw|move-watch|label for checkbox}}\n{{Identical|Move page}}",
"moveuserpage-warning": "Used as warning in [[Special:MovePage]], when moving a user page.",
- "movenologintext": "Text of message on special page 'Permissions Errors', which appears when somebody tries to move a page without being logged in.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}",
- "movenotallowed": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenologintext}}",
- "movenotallowedfile": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
- "cant-move-user-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
- "cant-move-to-user-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+ "movecategorypage-warning": "Used as warning in [[Special:MovePage]], when moving a category page.",
+ "movenologintext": "Text of message on special page 'Permissions Errors', which appears when somebody tries to move a page without being logged in.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}",
+ "movenotallowed": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenologintext}}",
+ "movenotallowedfile": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+ "cant-move-user-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+ "cant-move-to-user-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+ "cant-move-category-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+ "cant-move-to-category-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
"newtitle": "Used in the special page \"[[Special:MovePage]]\". The text for the inputbox to give the new page title.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|Movearticle|label for old title}}\n* {{msg-mw|Movereason|label for textarea}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}\n* {{msg-mw|Move-watch|label for checkbox}}",
"move-watch": "The text of the checkbox to watch the pages you are moving from and to. If checked, both the destination page and the original page will be added to the watchlist, even if you decide not to leave a redirect behind.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|Movearticle|label for old title}}\n* {{msg-mw|Newtitle|label for new title}}\n* {{msg-mw|Movereason|label for textarea}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}",
"movepagebtn": "Button label on the special 'Move page'.\n\n{{Identical|Move page}}",
"movenosubpage": "See also:\n* {{msg-mw|movesubpage|section header}}\n* {{msg-mw|movenosubpage|without subpage}}\n* {{msg-mw|movesubpagetext|with subpages}}",
"movereason": "Used in [[Special:MovePage]]. The text for the inputbox to give a reason for the page move.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|Movearticle|label for old title}}\n* {{msg-mw|Newtitle|label for new title}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}\n* {{msg-mw|Move-watch|label for checkbox}}\n{{Identical|Reason}}",
"move-redirect-text": "{{ignored}}The text that's added to a redirected page when that redirect is created.",
+ "category-move-redirect-override": "{{ignored}}The text that's added to a redirected category page when that redirect is created.",
"revertmove": "{{Identical|Revert}}",
"delete_and_move": "Button text on the move page when the target page already exists.",
"delete_and_move_text": "Used when moving a page, but the destination page already exists and needs deletion.\n\nThis message is to confirm that you really want to delete the page.\n\nParameters:\n* $1 - the destination page title\n\nSee also:\n* {{msg-mw|Delete and move confirm}}",
"variantname-shi-tfng": "{{optional}}",
"variantname-shi-latn": "{{optional}}",
"variantname-shi": "{{optional}}",
+ "variantname-uz": "{{optional}}",
+ "variantname-uz-latn": "{{optional}}",
+ "variantname-uz-cyrl": "{{optional}}",
"metadata": "The title of a section on an image description page, with information and data about the image. For example of message in use see [[commons:File:Titan-crystal_bar.JPG|Commons]].\n{{Identical|Metadata}}",
"metadata-help": "This message is followed by a table with metadata.",
"metadata-expand": "On an image description page, there is mostly a table containing data (metadata) about the image. The most important data are shown, but if you click on this link, you can see more data and information. For the link to hide back the less important data, see {{msg-mw|Metadata-collapse}}.",
"exif-gpsdifferential": "Label for EXIF information. Indicates whether differential correction is applied to the GPS receiver.",
"exif-coordinate-format": "{{optional}}\nFor formatting GPS latitude coordinates. Parameters:\n* $1 - degrees\n* $2 - minutes\n* $3 - seconds (up to two decimal places)\n* $4 - direction (N, S, W, or E)\n* $5 - (Unused) coordinate as a single positive or negative real number",
"exif-jpegfilecomment": "This is not a true exif tag, but the contents of the JPEG COM segment. This often contains a file source, but can potentially contain any comment about the file. This is similar to {{msg-mw|exif-usercomment}}, {{msg-mw|exif-pngfilecomment}}, and {{msg-mw|exif-giffilecomment}}.",
- "exif-keywords": "List of keywords for the photograph (or other media).\n\nThis can come from IPTC-iim 2:25 keyword field, or XMP's dc:subject field.",
+ "exif-keywords": "List of keywords for the photograph (or other media).\n\nThis can come from IPTC-iim 2:25 keyword field, or XMP's dc:subject field.\n{{Identical|Keyword}}",
"exif-worldregioncreated": "The world region (generally that means continent, but could also include 'World' as a whole) where the media was created.",
"exif-countrycreated": "Country that the picture was taken in. Note this is where it was taken, not what country is depicted in the picture.",
"exif-countrycodecreated": "ISO Code for the country that the picture was taken in. Note this is where it was taken, not what country is depicted in the picture.",
"descending_abbrev": "Abbreviation of descending order.\nSee also:\n* {{msg-mw|Ascending abbrev}}\n* {{msg-mw|Descending abbrev}}",
"table_pager_next": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).\n{{Identical|Next page}}",
"table_pager_prev": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).\n{{Identical|Previous page}}",
- "table_pager_first": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).",
- "table_pager_last": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).",
+ "table_pager_first": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).\n{{Identical|First page}}",
+ "table_pager_last": "Used as image button text of pager. See [[Support|example]] (the bottom of the page).\n{{Identical|Last page}}",
"table_pager_limit": "Do not use PLURAL in this message, because ''$1'' is not the actual number. ''$1'' is a limit selector drop-down list.",
"table_pager_limit_label": "Used as label for input field.",
"table_pager_limit_submit": "{{Identical|Go}}",
"watchlistedit-raw-done": "A message which appears after the raw watchlist has been updated using [[Special:Watchlist/raw]].",
"watchlistedit-raw-added": "Message on [[Special:EditWatchlist/raw]].\n\nThe message appears after at least 1 message is added to the raw watchlist.\n\nFollowed by list of page titles which are added.\n\nParameters:\n* $1 - number of page titles which are added\nSee also:\n* {{msg-mw|Watchlistedit-normal-done}}\n* {{msg-mw|Watchlistedit-raw-removed}}",
"watchlistedit-raw-removed": "Message on [[Special:EditWatchlist/raw]].\n\nThe message appears after at least 1 message is deleted from the raw watchlist.\n\nFollowed by list of page titles which are removed.\n\nParameters:\n* $1 - number of page titles which are removed\nSee also:\n* {{msg-mw|Watchlistedit-normal-done}}\n* {{msg-mw|Watchlistedit-raw-added}}",
+ "watchlistedit-clear-title": "Title of [[Special:Watchlist/clear|Special page]].\n\n{{Identical|Clear watchlist}}",
+ "watchlistedit-clear-legend": "Heading of dialogue box on [[Special:Watchlist/clear]].\n\n{{Identical|Edit clear watchlist}}",
+ "watchlistedit-clear-explain": "All of the titles will be removed from your watchlist",
+ "watchlistedit-clear-titles": "Text above edit box containing items being watched on [[Special:Watchlist/clear]].\n{{Identical|Title}}",
+ "watchlistedit-clear-submit": "Text of submit button on [[Special:Watchlist/clear]].\n\nSee also:\n* {{msg-mw|Watchlistedit-clear-submit}}\n* {{msg-mw|Tooltip-watchlistedit-clear-submit}}",
+ "watchlistedit-clear-done": "A message which appears after the watchlist has been cleared using [[Special:Watchlist/clear]].",
+ "watchlistedit-clear-removed": "Message on [[Special:EditWatchlist/clear]].\n\nThe message appears once the watchlist has been cleared.",
+ "watchlistedit-too-many": "Message on [[Special:EditWatchlist]] that is used when there are too many titles to display.",
+ "watchlisttools-clear": "[[Special:Watchlist]]: Navigation link under the title.\n\nSee also:\n* {{msg-mw|watchlisttools-clear}}\n* {{msg-mw|watchlisttools-clear}}",
"watchlisttools-view": "[[Special:Watchlist]]: Navigation link under the title.\n\nSee also:\n* {{msg-mw|watchlisttools-edit}}\n* {{msg-mw|watchlisttools-raw}}",
"watchlisttools-edit": "[[Special:Watchlist]]: Navigation link under the title.\n\nSee also:\n* {{msg-mw|Watchlisttools-view}}\n* {{msg-mw|Watchlisttools-raw}}",
"watchlisttools-raw": "[[Special:Watchlist]]: Navigation link under the title.\n\nSee also:\n* {{msg-mw|watchlisttools-view}}\n* {{msg-mw|watchlisttools-edit}}\n{{Identical|Edit raw watchlist}}",
"Reedy",
"The Evil IP address",
"לערי ריינהארט",
- "아라"
+ "아라",
+ "Fitoschido"
]
},
"tog-underline": "T'inkikunata uranpi sikwiy",
"pagemerge-logentry": "[[$1]]-ta [[$2]]-man huñusqa (llamk'apusqakuna $3-kama)",
"revertmerge": "Huñusqata kutichiy",
"mergelogpagetext": "Kay qatiqpiqa aswan ñaqha huk p'anqa wiñay kawsaymanta huk p'anqa wiñay kawsayman huñusqakunatam rikunki.",
- "history-title": "\"$1\" p'anqata hukchasqakunap wiñay kawsaynin",
+ "history-title": "«$1» p’anqata hukchasqakunap wiñay kawsaynin",
"difference-title": "$1 nisqapaq musuqchasqapura wakin kaynin",
"difference-title-multipage": "$1, $2 sutiyuq willañiqipura wakin kaynin",
"difference-multipage": "(P'anqakunaqa manam kaqllachu)",
"protectedpagetext": "Šėts poslapis īr ožrakints, saugont anū nū redagavėma.",
"viewsourcetext": "Tomsta galėt veizietė ėr kopėjoutė poslapė kuoda:",
"protectedinterface": "Šėtom poslapi īr pruogramėnės ironguos sasajuos teksts katros īr apsauguots, kū neprietelē anū nasogadėntu.",
- "editinginterface": "'''Diemesė:''' Tamsta keitat poslapi, katros īr nauduojams programėnės irongas sōsajės tekstė. Pakeitėmā tamė poslapū tēpuogi pakeis nauduotuojė sōsajės ėšruoda ė kėtėims nauduotujams. Jēgo nuorėt pargoldītė, siūluom pasėnauduotė [//translatewiki.net/wiki/Main_Page?setlang=bat-smg „translatewiki.net“], „MediaWiki“ lokalėzacėjės pruojėktu.",
+ "editinginterface": "<strong>Diemesė:</strong> Tamsta keitat poslapi, katros īr nauduojams programėnės irongas sōsajės tekstė. Pakeitėmā tamė poslapū tēpuogi pakeis nauduotuojė sōsajės ėšruoda ė kėtėims nauduotujams. Jēgo nuorėt pargoldītė, siūluom pasėnauduotė [//translatewiki.net „translatewiki.net“], „MediaWiki“ lokalėzacėjės pruojėktu.",
"namespaceprotected": "Tamsta netorėt teisiu keistė poslapiu '''$1''' srėtī.",
"ns-specialprotected": "Specēlė̅ jė poslapē negal būtė keitamė.",
"logouttext": "'''Daba Tamsta esat atsėjongės.'''\n\nGalat ė tuoliau nauduotė {{SITENAME}} anuonimėškā aba <span class='plainlinks'>[$1 prisėjonkat]</span> ėš naujė šėtuo patiu a kėto nauduotuojė vardu.\nPastebiejims: katruos nekatruos poslapiuos ė tuoliau gal ruodītė būktā būtomiet prisėjongės lėgė tuol, kumet ėšvalīsėt sava naršīklės dietovė (''cache'').",
"recreate-moveddeleted-warn": "'''Parspiejėms: Tamsta ikeliat faila, katros onkstiau bova ėštrėnts.'''\n\nTamsta torietomiet nusprēstė, a īr naudėnga tuoliau ikeldinietė ta faila.\nTuo faila pašalinėma istuorėjė īr pateikta dielē patuogoma:",
"moveddeleted-notice": "Tas poslapis bova ėštrėnts.\nĖštrėnta poslapė versėju sārašos īr pateikts paveiziejėmō žemiau.",
"edit-conflict": "Redagavėma kuonflėktos",
- "postedit-confirmation": "Tamstas padėrbts pakeitėms ėšsauguots īr.",
+ "postedit-confirmation-saved": "Tamstas padėrbts pakeitėms ėšsauguots īr.",
"post-expand-template-inclusion-warning": "Perspiejėms: Šabluonu īterpėma dėdoms īr par dėdelis.\nKāp katrėi šabluonā nebus ītrauktė.",
"post-expand-template-inclusion-category": "Poslapē, kur šabluonu īterpėma dėdoms viršėjams",
"post-expand-template-argument-warning": "Perspiejėms: Tas poslapis tor nuors vėina šabluona argomenta, katros tor per dėdli ėšplietėma dėdoma.\nTė argomentā bova praleistė.",
"blockip": "Ožblokoutė nauduotuoja",
"blockip-legend": "Blokoutė nauduotuoja",
"blockiptext": "Nauduokėt šėta fuorma noriedamė oždraustė redagavėma teises nuruodīto IP adreso a nauduotuojo. Tas torietu būt atlėikama tam, kū sostabdītomiet vandalėzma, ė vagol [[{{ns:project}}:Puolitėka|puolitėka]].\nŽemiau nuruodīkėt tėkslē prižastė.",
- "ipadressorusername": "IP adresos a nauduotuojė vards",
+ "ipaddressorusername": "IP adresos a nauduotuojė vards",
"ipbexpiry": "Galiuojėma čiesos",
"ipbreason": "Prīžastis:",
"ipbreason-dropdown": "*Dažniausės bluokavėma prižastīs\n** Melagėngas infuormacėjės rašīms\n** Torėnė trīnims ėš poslapiu\n** Spaminims\n** Zaunu/bikuo rašīms i poslapios\n** Gondinėmā/Pėktžuodiavėmā\n** Pėktnaudžiavėms paskėruomis\n** Netėnkams nauduotuojė vards",
"newimages": "Naujausiu abruozdieliu galerėjė",
"imagelisttext": "Žemiau īr '''$1''' failu sārašos, sorūšiouts $2.",
"newimages-label": "Faila vards (ar anuo dalis):",
- "showhidebots": "($1 robotos)",
"ilsubmit": "Ėiškoutė",
"bydate": "palē data",
"sp-newimages-showfrom": "Ruodītė naujus abruozdielius pradedant nū $2, $1",
"grouppage-sysop": "{{ns:project}}:Maamulada",
"right-read": "Akhri maqaalada",
"right-edit": "Wax ka bedel bogyaalo",
+ "right-createpage": "Samaynta bogag (taasoo aan lahayn bogag wadahadal)",
+ "right-createtalk": "Samaynta bogagga wadahadalka",
+ "right-createaccount": "Samaynta akoon isticmaale cusub",
"right-move": "Wareeji maqaalada",
"right-upload": "Soo geli fayl",
+ "right-writeapi": "Adeegsiga API ee qorista",
"right-delete": "Tirtir maqaalada",
"right-bigdelete": "Tirtir maqaalada taariikhda dheer leh",
"right-browsearchive": "Raadi maqaalada la tirtiray",
"right-undelete": "Ha tirtirin bog",
+ "right-editmyusercss": "Bedel galalka CSS ee isticmaalaha laftiisa",
+ "right-editmyuserjs": "Bedel galalka JavaScript ee isticmaalaha laftiisa",
+ "right-editmywatchlist": "Bedel liiska waardiyaha. Eeg qaybo ka mid ah dhaqdhaqaaqa in aan weli lagu kordhin haddi uusan jirin xitaa xaqaan.",
+ "right-editmyprivateinfo": "Bedel macluumaadka gaarka ah (sida. ciwaanka e-mail-ka , iyo magaca saxda ah)",
+ "right-editmyoptions": "Bedelka dooqyada",
"newuserlogpage": "Gudagalaha Isticmaale sameeyay",
"action-read": "akhri boggaan",
"action-edit": "wax ka bedel boggaan",
"action-createpage": "sameey bogyaalo",
+ "action-createtalk": "Samaynta bogagga wadahadalka",
"action-upload": "soo geli file'kaan",
"action-delete": "tirtir boggaan",
"action-browsearchive": "Raadi maqaalada la tirtiray",
"listusers-submit": "I'tus",
"listusers-noresult": "Lama helin isticmaale.",
"listusers-blocked": "(waa la mamnuucay)",
+ "listgrouprights": "Xuquuqaha koox isticmaalada",
+ "listgrouprights-summary": "Kani waa liiska koox isticmaale yaal ah ee la aqoonsaday wikigaan, in ay leeyihiin xuquuqdaan.\nWaxaa laga yaabaa in ay halkaan ku jiraan [[{{MediaWiki:Listgrouprights-helppage}}|macluumaad dheeraad ah]] ee ku saabsan xuquuqaha kala gadisan.",
+ "listgrouprights-key": "Ciwaanka:\n* <span class=\"listgrouprights-granted\">Xuquuq la siiyey</span>\n* <span class=\"listgrouprights-revoked\">Xuquuq laga qaaday</span>",
+ "listgrouprights-group": "Kooxda",
+ "listgrouprights-rights": "Xuquuqaha",
"listgrouprights-members": "(Inta ka mid ah liiskooda)",
"mailnologin": "Ma'jiro cinwaan wax lagu diro",
"mailnologintext": "Waa in aad [[Special:UserLogin|gudaha ku jirtaa]]\nkuna haysatid E-boosto sax ah [[Special:Preferences|dooqyadaada]],\nsi aad ugu dirto E-boosto isticmaalayaasha kale.",
"metadata-help": "Faylkaan wuxuu leeyahay faah faahin dheeraad ah,waxaa laga yaabaa in lagu isticmaalay digital kaamiro ama skanner oo lagu sameeyo sawir ama lagu digitilays gareeyay.\nHadii faylka wax laga badalay sida oo markiisa hore ahaa, waxaa laga yaabaa in ee faah faahinta faylkaan eesan dhameestirneen.",
"metadata-fields": "Sawirka qeybihiisa metadata oo ku tixan fariintaan waxaa lagu dari doonaa bogga sawirka meesha laga arko markii miiska metadata la qariyo.Kuwa kale waxaa loo qarinaa sida default.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
"exif-iimcategory": "Qeybta",
+ "exif-dc-rights": "Xuquuqaha",
"watchlistall2": "dhamaan",
"namespacesall": "dhamaan",
"monthsall": "Dhamaan",
"fileduplicatesearch-legend": "Raadi mid tusaale ah",
"fileduplicatesearch-submit": "Raadi",
"specialpages": "bogagga khaaska ah",
+ "specialpages-note-top": "Furaha",
"specialpages-group-pages": "liiska maqaalada",
"blankpage": "Bog masaxan",
"tag-filter": "[[Special:Tags|Filtaraha]] tag:",
"watchlistanontext": "Морате бити $1 да бисте гледали и уређивали ставке на вашем списку надгледања.",
"watchnologin": "Нисте пријављени",
"addwatch": "Додај на списак надгледања",
- "addedwatchtext": "Страница „[[:$1]]“ је додата на ваш [[Special:Watchlist|списак надгледања]].\nБудуће измене ове странице и њене странице за разговор биће наведене овде.",
+ "addedwatchtext": "Страница „[[:$1]]“ је додата на ваш [[Special:Watchlist|списак надгледања]].\nБудуће измене ове странице и њене странице за разговор биће наведене тамо.",
"removewatch": "Уклони са списка надгледања",
"removedwatchtext": "Страница „[[:$1]]“ је уклоњена с вашег [[Special:Watchlist|списка надгледања]].",
"watch": "Надгледај",
"watchlistanontext": "Morate biti $1 da biste gledali i uređivali stavke na vašem spisku nadgledanja.",
"watchnologin": "Niste prijavljeni",
"addwatch": "Dodaj na spisak nadgledanja",
- "addedwatchtext": "Stranica „[[:$1]]“ je dodata na vaš [[Special:Watchlist|spisak nadgledanja]].\nBuduće izmene ove stranice i njene stranice za razgovor biće navedene ovde.",
+ "addedwatchtext": "Stranica „[[:$1]]“ je dodata na vaš [[Special:Watchlist|spisak nadgledanja]].\nBuduće izmene ove stranice i njene stranice za razgovor biće navedene tamo.",
"removewatch": "Ukloni sa spiska nadgledanja",
"removedwatchtext": "Stranica „[[:$1]]“ je uklonjena s vašeg [[Special:Watchlist|spiska nadgledanja]].",
"watch": "Nadgledaj",
"action-createpage": "สร้างหน้า",
"action-createtalk": "สร้างหน้าอภิปราย",
"action-createaccount": "สร้างบัญชีผู้ใช้นี้",
+ "action-history": "ดูประวัติของหน้านี้",
"action-minoredit": "ทำเครื่องหมายการแก้ไขนี้เป็นการแก้ไขเล็กน้อย",
"action-move": "ย้ายหน้านี้",
"action-move-subpages": "ย้ายหน้านี้ รวมทั้งหน้าย่อย",
"spam_reverting": "ย้อนกลับไปรุ่นก่อนหน้าที่ไม่มีลิงก์ไปยังเว็บ $1",
"spam_blanking": "รุ่นการปรับปรุงทุกรุ่นประกอบไปด้วยลิงก์ไปยังเว็บ $1 (ทำหน้าว่าง)",
"spam_deleting": "ทุกรุ่นที่มีลิงก์ไปยัง $1 กำลังลบ",
+ "simpleantispam-label": "การตรวจสอบสแปม\n<strong>อย่า</strong>กรอกช่องนี้!",
"pageinfo-title": "ข้อมูลสำหรับ \"$1\"",
"pageinfo-not-current": "ขออภัย ไม่สามารถให้ข้อมูลนี้สำหรับรุ่นเก่าได้",
"pageinfo-header-basic": "ข้อมูลเบื้องต้น",
"newimages-summary": "หน้าพิเศษนี้แสดงไฟล์ที่ถูกอัปโหลดล่าสุด",
"newimages-legend": "ตัวกรอง",
"newimages-label": "ชื่อไฟล์ (หรือส่วนหนึ่งของชื่อ):",
+ "newimages-showbots": "แสดงไฟล์ที่บอตอัปโหลด",
"noimages": "ไม่มีให้ดู",
"ilsubmit": "สืบค้น",
"bydate": "ตามวันที่",
"show-big-image": "Toʻliq hajmdagi tasvir",
"noimages": "Tasvir mavjud emas.",
"ilsubmit": "Qidirish",
+ "variantname-uz-latn": "lotincha",
+ "variantname-uz-cyrl": "кириллча",
"metadata": "Metama’lumot",
"metadata-expand": "Batafsil axborotni koʻrsatish",
"metadata-collapse": "Batafsil axborotni yashirish",
"newimages-summary": "本特殊页面展示最后上传的文件。",
"newimages-legend": "过滤",
"newimages-label": "文件名(或它的一部份):",
+ "newimages-showbots": "显示机器人上传",
"noimages": "无可查看文件。",
"ilsubmit": "搜索",
"bydate": "按日期",
"parser-unstrip-loop-warning": "檢測到迴圈",
"parser-unstrip-recursion-limit": "遞歸超過限制 ($1)",
"converter-manual-rule-error": "手動語言轉換規則中檢測到錯誤",
- "undo-success": "該編輯可以被撤銷。請檢查以下對比以核實這正是您想做的,然後儲存以下更改以完成撤銷編輯。",
- "undo-failure": "由於中途的編輯不一致,此編輯不能撤銷。",
+ "undo-success": "此編輯可以被還原。\n請檢查以下比較表,確認您是否要還原,然後儲存以下變更以完成編輯還原。",
+ "undo-failure": "由於編輯的修訂間有衝突,此編輯不能還原。",
"undo-norev": "由於其修訂版本不存在或已刪除,此編輯不能撤銷。",
- "undo-nochange": "æ\98¯æ¬¡ç·¨è¼¯ä¼¼ä¹\8eå·²ç¶\93被æ\92¤é\8a·。",
+ "undo-nochange": "æ¤ç·¨è¼¯å\8f¯è\83½å·²è¢«é\82\84å\8e\9f。",
"undo-summary": "取消由 [[Special:Contributions/$2|$2]] ([[User talk:$2|對話]]) 所作出的修訂 $1",
"undo-summary-username-hidden": "還原隱藏使用者的修訂 $1",
"cantcreateaccounttitle": "無法建立帳號",
"lineno": "行 $1:",
"compareselectedversions": "比較已選擇的修訂",
"showhideselectedversions": "顯示/隱藏已選擇的修訂",
- "editundo": "復原",
+ "editundo": "還原",
"diff-empty": "(無差異)",
"diff-multi-sameuser": "(未顯示相同使用者於中間所作的 $1 次修訂)",
"diff-multi-otherusers": "(未顯示由 $2 位使用者於中間所作的 $1 次修訂)",
"prefs-rc": "最近變更",
"prefs-watchlist": "監視列表",
"prefs-watchlist-days": "監視列表中顯示的天數:",
- "prefs-watchlist-days-max": "最多$1{{PLURAL:$1|天}}",
- "prefs-watchlist-edits": "擴充監視列表中顯示變更次數的上限:",
+ "prefs-watchlist-days-max": "最多 $1 {{PLURAL:$1|天}}",
+ "prefs-watchlist-edits": "展開的監視列表中顯示變更次數上限:",
"prefs-watchlist-edits-max": "最大數量:1000",
"prefs-watchlist-token": "監視列表密鑰:",
"prefs-misc": "雜項",
"editinguser": "變更使用者 '''[[User:$1|$1]]''' 的使用者權限 $2",
"userrights-editusergroup": "編輯使用者群組",
"saveusergroups": "儲存使用者群組",
- "userrights-groupsmember": "屬於:",
- "userrights-groupsmember-auto": "固有屬於:",
- "userrights-groups-help": "您可以更改此使用者所屬的群組:\n* 已勾選的核選方塊代表該使用者屬於該群組。\n* 已勾選的核選方塊代表該使用者不屬於該群組。\n* 有 * 號標示代表一旦加入該群組後便不能移除,反之亦然。",
+ "userrights-groupsmember": "所屬群組:",
+ "userrights-groupsmember-auto": "所屬隱含群組:",
+ "userrights-groups-help": "您可以更改此使用者所屬的群組:\n* 已勾選的核選方塊代表該使用者屬於該群組。\n* 未勾選的核選方塊代表該使用者不屬於該群組。\n* 有 * 號標示代表一旦加入該群組後便不能移除,反之亦然。",
"userrights-reason": "原因:",
"userrights-no-interwiki": "您沒有權限去編輯其它使用者在 Wiki 上的權限。",
"userrights-nodatabase": "資料庫$1不存在或並非為本地的。",
"userrights-nologin": "您必須 [[Special:UserLogin|登入]] 管理員帳號以指定使用者權限。",
"userrights-notallowed": "你無權加入或刪除使用者權限。",
- "userrights-changeable-col": "您可以更改的群組",
- "userrights-unchangeable-col": "您不可以更改的群組",
+ "userrights-changeable-col": "您可變更的群組",
+ "userrights-unchangeable-col": "您不可變更的群組",
"userrights-conflict": "使用者權限更改發生衝突!請重新檢視並確認你的更改。",
"userrights-removed-self": "您已成功移除自己的權限,故此您沒法再次訪問此頁。",
"group": "群組:",
"right-createpage": "建立頁面 (不含討論頁面)",
"right-createtalk": "建立討論頁面",
"right-createaccount": "建立新的使用者帳號",
- "right-minoredit": "標示此編輯為小修訂",
+ "right-minoredit": "標示編輯為小修訂",
"right-move": "移動頁面",
"right-move-subpages": "移動頁面與其子頁面",
"right-move-rootuserpages": "移動根使用者頁面",
"right-reupload-own": "覆蓋由同一位上載的檔案",
"right-reupload-shared": "於本地無視共用媒體檔案庫上的檔案",
"right-upload_by_url": "由一個URL上載檔案",
- "right-purge": "不需要確認之下清除網站快取",
- "right-autoconfirmed": "不受基於IP的頻率限制",
+ "right-purge": "不確認清除網站快取",
+ "right-autoconfirmed": "不受以 IP 為基礎的註冊頻率限制",
"right-bot": "視為一個自動程序",
"right-nominornewtalk": "若討論頁面為小修訂,則不顯示新訊息提示",
- "right-apihighlimits": "在API查詢中使用更高的上限",
- "right-writeapi": "使用API編寫",
+ "right-apihighlimits": "API 查詢中可使用較高上限值",
+ "right-writeapi": "使用寫入 API",
"right-delete": "刪除頁面",
"right-bigdelete": "刪除大量歷史之頁面",
"right-deletelogentry": "刪除及恢復特定的日誌項目",
"right-protect": "更改保護等級以及編輯被連鎖保護的頁面",
"right-editprotected": "編輯保護層級為「{{int:protect-level-sysop}}」的頁面",
"right-editsemiprotected": "編輯保護層級為「{{int:protect-level-autoconfirmed}}」的頁面",
- "right-editinterface": "編輯使用者界面",
+ "right-editinterface": "編輯使用者介面",
"right-editusercssjs": "編輯其他使用者的 CSS 和 JavaScript 檔案",
"right-editusercss": "編輯其他使用者的 CSS 檔案",
"right-edituserjs": "編輯其他使用者的 JavaScript 檔案",
"listduplicatedfiles-summary": "以下列表中某檔案之最新版本與其他檔案之最新版本重複。進包含本地檔案",
"listduplicatedfiles-entry": "檔案[[:File:$1|$1]]與[[$3|其他$2個重複]]。",
"unusedtemplates": "未使用的樣版",
- "unusedtemplatestext": "此頁列出所有於 {{ns:template}} 命名空間下未被其他頁面引用的頁面。\n請在刪除這些樣版前檢查其他使用該樣版的頁面。",
+ "unusedtemplatestext": "此頁面列出所有於 {{ns:template}} 命名空間下未被其他頁面引用的樣版。\n在刪除前,仍需檢查是否有連結這些樣版的其他頁面。",
"unusedtemplateswlh": "其他連結",
"randompage": "隨機頁面",
"randompage-nopages": "在{{PLURAL:$2|命名空間}}中沒有任何頁面:$1。",
"statistics-views-total-desc": "不存在頁面和特殊頁面的查看數未計入",
"statistics-views-peredit": "每次編輯檢視數",
"statistics-users": "已註冊的 [[Special:ListUsers|使用者]]",
- "statistics-users-active": "活躍使用者",
+ "statistics-users-active": "活動使用者",
"statistics-users-active-desc": "在最近 $1 天操作過的使用者",
"statistics-mostpopular": "被查閱次數最多的頁面",
"pageswithprop": "擁有屬性的頁面",
"brokenredirects-edit": "編輯",
"brokenredirects-delete": "刪除",
"withoutinterwiki": "未有語言連結的頁面",
- "withoutinterwiki-summary": "以ä¸\8bç\9a\84é \81é\9d¢æ\98¯æ\9cªæ\9c\89èª\9eè¨\80é\80£çµ\90å\88°å\85¶å®\83èª\9eè¨\80ç\89\88æ\9c¬。",
+ "withoutinterwiki-summary": "ä¸\8bå\88\97æ\98¯æ²\92æ\9c\89é\80£çµ\90å\88°å\85¶å®\83èª\9eè¨\80ç\89\88æ\9c¬ç\9a\84é \81é\9d¢。",
"withoutinterwiki-legend": "字首",
"withoutinterwiki-submit": "顯示",
"fewestrevisions": "最少修訂的頁面",
"protectedtitlesempty": "在這些參數之下並無標題正在保護。",
"listusers": "使用者清單",
"listusers-editsonly": "只顯示有編輯的使用者",
- "listusers-creationsort": "按建立日期排序",
+ "listusers-creationsort": "依建立日期排序",
"listusers-desc": "使用降冪排序",
"usereditcount": "$1 次{{PLURAL:$1|編輯}}",
"usercreated": "於 $1 $2 {{GENDER:$3|建立}}",
"ancientpages": "最舊頁面",
"move": "移動",
"movethispage": "移動本頁",
- "unusedimagestext": "下列檔案未有嵌入任何頁面但它仍然存在。\n請注意其它網站可能直接透過 URL 連結此檔案,所以這裡列出的圖片有可能依然被使用。",
- "unusedcategoriestext": "é\9b\96ç\84¶æ²\92æ\9c\89被å\85¶å®\83é \81é\9d¢æ\88\96è\80\85å\88\86é¡\9eæ\89\80æ\8e¡ç\94¨ï¼\8cä½\86å\88\97表ä¸ç\9a\84å\88\86é¡\9eé \81ä¾\9dç\84¶å\98å\9c¨ã\80\82",
+ "unusedimagestext": "下列為未被任何頁面使用的檔案。\n請注意,其它網站可能直接透過 URL 連結至檔案,所以這裡列出的檔案仍有可能被使用。",
+ "unusedcategoriestext": "ä¸\8bå\88\97å\88\86é¡\9eæ²\92æ\9c\89被å\85¶å®\83é \81é\9d¢æ\88\96è\80\85å\88\86é¡\9eæ\89\80使ç\94¨ã\80\82",
"notargettitle": "無目標",
"notargettext": "您尚未指定目標頁面或使用者以進行此項操作。",
"nopagetitle": "無目標頁面",
"pager-older-n": "較舊 $1 筆",
"suppress": "監督",
"querypage-disabled": "此特殊頁面基於效能的原因已經被停用。",
- "booksources": "網路書源",
- "booksources-search-legend": "尋找網路書源",
+ "booksources": "圖書資源",
+ "booksources-search-legend": "尋找圖書資源",
"booksources-isbn": "國際標準書號:",
"booksources-go": "送出",
"booksources-text": "以下是一份銷售新書或二手書的列表,並可能有{{GENDER:|你|妳|你}}正尋找的書的進一步訊息:",
"cachedspecial-viewing-cached-ts": "您正在閱讀此頁的緩存版本,這可能不是完整的版本。",
"cachedspecial-refresh-now": "查看最新。",
"categories": "頁面分類",
- "categoriespagetext": "以ä¸\8bç\9a\84{{PLURAL:$1|å\88\86é¡\9e}}ä¸å\8c\85å\90«äº\86é \81é\9d¢æ\88\96åª\92é«\94ã\80\82\n[[Special:UnusedCategories|æ\9cªç\94¨å\88\86é¡\9e]]ä¸\8dæ\9c\83å\9c¨é\80\99è£\8få\88\97示ã\80\82\nè«\8bå\90\8cæ\99\82å\8f\83é\96±[[Special:WantedCategories|需要的分類]]。",
+ "categoriespagetext": "ä¸\8bå\88\97ç\82ºå\8c\85å\90«é \81é\9d¢æ\88\96åª\92é«\94ç\9a\84{{PLURAL:$1|å\88\86é¡\9e}}ã\80\82\n[[Special:UnusedCategories|æ\9cªä½¿ç\94¨ç\9a\84å\88\86é¡\9e]] ä¸\8dæ\9c\83å\9c¨æ¤é¡¯ç¤ºã\80\82\nè«\8bå\8f\83è\80\83 [[Special:WantedCategories|需要的分類]]。",
"categoriesfrom": "顯示由此項起之分類:",
"special-categories-sort-count": "按數量排列",
"special-categories-sort-abc": "按字母排列",
"listusers-submit": "顯示",
"listusers-noresult": "查無使用者。",
"listusers-blocked": "(已封鎖)",
- "activeusers": "æ\9c\89æ´»å\8b\95ç\9a\84使ç\94¨è\80\85æ¸\85å\96®",
+ "activeusers": "活動的使用者清單",
"activeusers-intro": "此清單為最近 $1 天有活動的使用者。",
- "activeusers-count": "最近$3天內有$1次編輯",
+ "activeusers-count": "最近 $3 天內有 $1 次動作",
"activeusers-from": "顯示使用者開始自:",
"activeusers-hidebots": "隱藏機器人",
"activeusers-hidesysops": "隱藏管理員",
"activeusers-noresult": "查無使用者。",
"listgrouprights": "使用者群組權限",
"listgrouprights-summary": "以下為此 Wiki 的使用者群組清單,以及相關的存取權限。\n您可以在 [[{{MediaWiki:Listgrouprights-helppage}}|詳細資訊]] 找到有關個別權限的資訊。",
- "listgrouprights-key": "* <span class=\"listgrouprights-granted\">已授予的權限</span>\n* <span class=\"listgrouprights-revoked\">被吊銷的權限</span>",
+ "listgrouprights-key": "說明:\n* <span class=\"listgrouprights-granted\">已授予的權限</span>\n* <span class=\"listgrouprights-revoked\">已撤銷的權限</span>",
"listgrouprights-group": "群組",
"listgrouprights-rights": "權限",
"listgrouprights-helppage": "Help:群組權限",
"unblocklink": "解除封鎖",
"change-blocklink": "變更封鎖",
"contribslink": "貢獻",
- "emaillink": "傳送電郵",
+ "emaillink": "發送電子郵件",
"autoblocker": "您的 IP 位址因最近被 [[User:$1|$1]] 使用過而被自動封鎖。\n封鎖 $1 的原因為 \"$2\"",
"blocklogpage": "查封日誌",
"blocklog-showlog": "此使用者先前被封鎖過。\n以下為封鎖紀錄以供參考:",
"tooltip-recreate": "重建該頁面,無論是否被刪除。",
"tooltip-upload": "開始上傳",
"tooltip-rollback": "點選 \"還原\" 還原至上位貢獻者對此頁面的編輯",
- "tooltip-undo": "「復原」可以在編輯模式上開啟編輯表格以便恢復。它容許在摘要中加入原因。",
+ "tooltip-undo": "\"還原\" 可還原此編輯並以預覽模式開啟編輯表單,讓您可在摘要中加入原因。",
"tooltip-preferences-save": "儲存偏好設定",
"tooltip-summary": "輸入一個簡短的摘要",
"interlanguage-link-title": "$1 – $2",
"filedelete-old-unregistered": "所指定的檔案修訂「$1」在資料庫中不存在。",
"filedelete-current-unregistered": "所指定的檔案「$1」在資料庫中不存在。",
"filedelete-archive-read-only": "存檔目錄「$1」在網頁伺服器中不可寫。",
- "previousdiff": "←上一版本",
- "nextdiff": "下一版本→",
+ "previousdiff": "← 較舊編輯",
+ "nextdiff": "較新編輯 →",
"mediawarning": "<strong>警告</strong>:此檔案類型可能包含惡意代碼。\n若執行可能對您的系統造成損害。",
"imagemaxsize": "圖片大小限制:<br /><em>(用於檔案描述頁面)</em>",
"thumbsize": "縮圖大小:",
"newimages-summary": "此特殊頁面中顯示最新上傳的檔案。",
"newimages-legend": "搜尋",
"newimages-label": "檔案名稱 (或部份):",
+ "newimages-showbots": "顯示機械人上載",
"noimages": "無可檢視圖片。",
"ilsubmit": "搜尋",
"bydate": "按日期",
"comma-separator": "、",
"colon-separator": ":",
"word-separator": "",
- "parentheses": "($1)",
+ "parentheses": " ($1)",
"quotation-marks": "「$1」",
"imgmultipageprev": "← 上一頁",
"imgmultipagenext": "下一頁 →",
"table_pager_first": "第一頁",
"table_pager_last": "最末頁",
"table_pager_limit": "每頁顯示 $1 筆記錄",
- "table_pager_limit_label": "每頁項目數︰",
+ "table_pager_limit_label": "每頁筆數︰",
"table_pager_limit_submit": "送出",
"table_pager_empty": "沒有結果",
"autosumm-blank": "清空頁面",
"unknown_extension_tag": "不明的擴展標籤「$1」",
"duplicate-defaultsort": "警告: 預設的排序鍵「$2」覆蓋先前的預設排序鍵「$1」。",
"version": "版本",
- "version-extensions": "已經安裝的擴展",
+ "version-extensions": "已安裝的擴充套件",
"version-specialpages": "特殊頁面",
- "version-parserhooks": "èª\9eæ³\95é\88\8e",
+ "version-parserhooks": "èª\9eæ³\95é\80£çµ\90(Hook)",
"version-variables": "變數",
- "version-antispam": "垃圾防止",
+ "version-antispam": "垃圾訊息防止",
"version-skins": "外觀",
"version-other": "其他",
"version-mediahandlers": "媒體處理器",
- "version-hooks": "é\88\8e",
- "version-parser-extensiontags": "èª\9eæ³\95æ\93´å±\95標籤",
- "version-parser-function-hooks": "èª\9eæ³\95å\87½æ\95¸é\88\8e",
- "version-hook-name": "é\88\8eå\90\8d",
- "version-hook-subscribedby": "利用於",
+ "version-hooks": "é\80£çµ\90(Hooks)",
+ "version-parser-extensiontags": "èª\9eæ³\95æ\93´å\85\85標籤",
+ "version-parser-function-hooks": "èª\9eæ³\95å\87½æ\95¸é\80£çµ\90",
+ "version-hook-name": "é\80£çµ\90å\90\8d稱",
+ "version-hook-subscribedby": "署名",
"version-version": "(版本 $1)",
- "version-license": "MediaWiki許可證",
- "version-ext-license": "授權",
- "version-ext-colheader-name": "æ\93´å±\95",
+ "version-license": "MediaWiki 授權條款",
+ "version-ext-license": "授權條款",
+ "version-ext-colheader-name": "æ\93´å\85\85å¥\97件",
"version-ext-colheader-version": "版本",
- "version-ext-colheader-license": "許可證",
+ "version-ext-colheader-license": "授權條款",
"version-ext-colheader-description": "說明",
"version-ext-colheader-credits": "作者",
- "version-license-title": "用於$1之許可證",
- "version-license-not-found": "並無與此拓展相關之許可證資訊。",
- "version-credits-title": "用於$1之信用",
- "version-credits-not-found": "並無與此拓展相關之信用資訊。",
- "version-poweredby-credits": "此維基由'''[https://www.mediawiki.org/ MediaWiki]'''驅動,版權所有 © 2001-$1 $2。",
+ "version-license-title": "$1 的授權條款",
+ "version-license-not-found": "查無此擴充套件的詳細授權條款資訊。",
+ "version-credits-title": "$1 的製作群",
+ "version-credits-not-found": "查無此擴充套件的詳細製作群資訊。",
+ "version-poweredby-credits": "此 Wiki 由 <strong>[https://www.mediawiki.org/ MediaWiki]</strong> 開發,版權所有 © 2001-$1 $2。",
"version-poweredby-others": "其他",
- "version-poweredby-translators": "translatewiki.net 上的翻譯者",
- "version-credits-summary": "我們感謝以下人士為[[Special:Version|MediaWiki]]作出的貢獻。",
- "version-license-info": "MediaWiki為自由軟件;您可依據自由軟件基金會所發表的GNU通用公共授權條款規定,就本程式再為發佈與/或修改;無論您依據的是本授權的第二版或(您自行選擇的)任一日後發行的版本。\n\nMediaWiki是基於使用目的而加以發佈,然而不負任何擔保責任;亦無對適售性或特定目的適用性所為的默示性擔保。詳情請參照GNU通用公共授權。\n\n您應已收到附隨於本程式的[{{SERVER}}{{SCRIPTPATH}}/COPYING GNU通用公共授權的副本];如果沒有,請寫信至自由軟件基金會:51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或[//www.gnu.org/licenses/old-licenses/gpl-2.0.html 線上閱讀]。",
- "version-software": "已經安裝的軟件",
+ "version-poweredby-translators": " translatewiki.net 翻譯人員",
+ "version-credits-summary": "我們感謝以下人士為 [[Special:Version|MediaWiki]] 作出的貢獻。",
+ "version-license-info": "MediaWiki 為自由軟體;您可依據自由軟體基金會所發表的 GNU 通用公共授權條款規定,將本程式重新發佈與/或修改;無論您依據的是本授權條款的第二版或 (您可自行選擇) 之後的任何版本。\n\n本程式發佈的目的是希望可以提供幫助,但不負任何擔保責任;亦無隱含對適售性或 特定用途的適用性的情形擔保。詳情請參照 GNU 通用公共授權。\n\n您應已隨本程式收到 [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU 通用公共授權條款的副本];如果沒有,請信件通知自由軟體基金會,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA,或 [//www.gnu.org/licenses/old-licenses/gpl-2.0.html 線上閱讀]。",
+ "version-software": "已經安裝的軟體",
"version-software-product": "產品",
"version-software-version": "版本",
- "version-entrypoints": "入口點URL",
- "version-entrypoints-header-entrypoint": "入口點",
+ "version-entrypoints": "入口 URL",
+ "version-entrypoints-header-entrypoint": "入口",
"version-entrypoints-header-url": "URL",
"version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 條目路徑]",
"redirect": "依檔案、使用者、頁面或修訂 ID 重新導向",
"redirect-lookup": "尋找:",
"redirect-value": "值:",
"redirect-user": "使用者 ID",
- "redirect-page": "頁面ID",
- "redirect-revision": "頁面修訂ID",
+ "redirect-page": "頁面 ID",
+ "redirect-revision": "頁面修訂 ID",
"redirect-file": "檔案名稱",
"redirect-not-exists": "找不到",
- "fileduplicatesearch": "選擇重覆檔案",
- "fileduplicatesearch-summary": "用重覆檔案的切細值去找出檔案是否重覆。",
- "fileduplicatesearch-legend": "æ\89¾重覆",
+ "fileduplicatesearch": "搜尋重覆檔案",
+ "fileduplicatesearch-summary": "依據雜湊值(Hash)來搜尋重複的檔案。",
+ "fileduplicatesearch-legend": "æ\90\9cå°\8b重覆",
"fileduplicatesearch-filename": "檔案名稱:",
"fileduplicatesearch-submit": "搜尋",
"fileduplicatesearch-info": "$1 × $2 像素<br />檔案大小:$3<br />MIME 類型:$4",
- "fileduplicatesearch-result-1": "檔案「$1」無完全相同的重覆。",
- "fileduplicatesearch-result-n": "檔案「$1」有$2項完全相同的重覆。",
- "fileduplicatesearch-noresults": "æ²\92æ\9c\89ç\99¼ç\8f¾å\90\8dç\82ºã\80\8c$1ã\80\8dç\9a\84æ\96\87件。",
+ "fileduplicatesearch-result-1": "檔案 $1 無重覆的檔案。",
+ "fileduplicatesearch-result-n": "檔案 $1 有 $2 筆重覆的檔案。",
+ "fileduplicatesearch-noresults": "æ\9f¥ç\84¡å\90\8d稱ç\82º \"$1\" ç\9a\84æª\94æ¡\88。",
"specialpages": "特殊頁面",
- "specialpages-note-top": "圖例",
- "specialpages-note": "* 標準特殊頁面。\n* <span class=\"mw-specialpagerestricted\">用於重新整理的特殊頁面(可能過時)。</span>",
- "specialpages-group-maintenance": "維護報告",
+ "specialpages-note-top": "說明",
+ "specialpages-note": "* 一般特殊頁面。\n* <span class=\"mw-specialpagerestricted\">受限制的特殊頁面。</span>",
+ "specialpages-group-maintenance": "維護報表",
"specialpages-group-other": "其它特殊頁面",
"specialpages-group-login": "登入/建立新帳號",
"specialpages-group-changes": "最近變更與日誌",
- "specialpages-group-media": "媒體報告和上傳",
+ "specialpages-group-media": "媒體上傳與報表",
"specialpages-group-users": "使用者與權限",
"specialpages-group-highuse": "常用頁面",
"specialpages-group-pages": "頁面清單",
"specialpages-group-pagetools": "頁面工具",
"specialpages-group-wiki": "資料和工具",
- "specialpages-group-redirects": "重新導向至特殊頁面",
- "specialpages-group-spam": "反垃圾工具",
+ "specialpages-group-redirects": "重新導向相關特殊頁面",
+ "specialpages-group-spam": "反垃圾訊息工具",
"blankpage": "空白頁面",
- "intentionallyblankpage": "這個頁面是為空白",
+ "intentionallyblankpage": "此頁面被故意設為空白。",
"external_image_whitelist": " #留下這行一樣的文字<pre>\n#在下面(//之中間部份)輸入正規表達式\n#這些將會跟外部(已超連結的)圖片配合\n#那些配合到出來的會顯示成圖片,否則就只會顯示成連結\n#有 # 開頭的行會當成註解\n#大小寫並無區分\n\n#在這行上面輸入所有的regex。留下這行一樣的文字</pre>",
- "tags": "有效標籤",
- "tag-filter": "[[Special:Tags|標籤]]過濾器:",
+ "tags": "有效變更標籤",
+ "tag-filter": "[[Special:Tags|標籤]]搜尋:",
"tag-filter-submit": "搜尋",
"tag-list-wrapper": "([[Special:Tags|標籤]]:$2)",
"tags-title": "標籤",
"tags-intro": "這個頁面列示出在軟件中已標示的編輯,以及它們的解釋。",
"tags-tag": "標籤名稱",
"tags-display-header": "在更改清單中的出現方式",
- "tags-description-header": "解釋完整描述",
+ "tags-description-header": "完整含意說明",
"tags-active-header": "存檔?",
"tags-hitcount-header": "已加上標籤的更改",
"tags-active-yes": "是",
"tags-active-no": "否",
"tags-edit": "編輯",
- "tags-hitcount": "$1次更改",
+ "tags-hitcount": "$1 次變更",
"comparepages": "比較頁面",
- "compare-page1": "第1頁",
- "compare-page2": "第2頁",
- "compare-rev1": "修訂版本1",
- "compare-rev2": "修訂版本2",
+ "compare-page1": "第 1 頁",
+ "compare-page2": "第 2 頁",
+ "compare-rev1": "修訂 1",
+ "compare-rev2": "修訂 2",
"compare-submit": "比較",
"compare-invalid-title": "所指定標題無效。",
"compare-title-not-exists": "所指定的話題不存在。",
"htmlform-int-toohigh": "您所指定的值高於最大值$1",
"htmlform-required": "此值是必填項",
"htmlform-submit": "提交",
- "htmlform-reset": "撤銷更改",
+ "htmlform-reset": "還原更改",
"htmlform-selectorother-other": "其他",
"htmlform-no": "否",
"htmlform-yes": "是",
"duration-millennia": "$1 千年",
"rotate-comment": "順時針旋轉圖像$1{{PLURAL:$1|度}}",
"limitreport-title": "分析器分析資料:",
- "limitreport-cputime": "CPU使用時間",
- "limitreport-cputime-value": "$1秒",
+ "limitreport-cputime": "CPU 使用時間",
+ "limitreport-cputime-value": "$1 秒",
"limitreport-walltime": "實際使用時間",
- "limitreport-walltime-value": "$1秒",
- "limitreport-ppvisitednodes": "預處理器訪問節點計數",
- "limitreport-ppgeneratednodes": "é \90è\99\95ç\90\86å\99¨ç\94\9fæ\88\90ç¯\80é»\9eè¨\88數",
- "limitreport-postexpandincludesize": "展開後大小",
+ "limitreport-walltime-value": "$1 秒",
+ "limitreport-ppvisitednodes": "預處理器訪問節點次數",
+ "limitreport-ppgeneratednodes": "é \90è\99\95ç\90\86å\99¨ç\94¢ç\94\9fç¯\80é»\9e次數",
+ "limitreport-postexpandincludesize": "展開後的引用大小",
"limitreport-postexpandincludesize-value": "$1/$2 個{{PLURAL:$2|位元組}}",
"limitreport-templateargumentsize": "樣版參數大小",
"limitreport-templateargumentsize-value": "$1/$2 個{{PLURAL:$2|位元組}}",
"limitreport-expansiondepth": "最高展開深度",
- "limitreport-expensivefunctioncount": "高開銷分析函數數位",
+ "limitreport-expensivefunctioncount": "高分析函數次數",
"expandtemplates": "展開樣版",
"expand_templates_intro": "本特殊頁面會將文字中的樣版展開,可以包含支援的分析程式語法,如 <code><nowiki>{{</nowiki>#language:…}}</code> 與變數如 <code><nowiki>{{</nowiki>CURRENTDAY}}</code>。\n實際上,絕大部分在雙括號中的內容都會被展開。",
"expand_templates_title": "上下文標題,用於 {{FULLPAGENAME}} 等:",
"expand_templates_input": "輸入文字:",
"expand_templates_output": "結果:",
- "expand_templates_xml_output": "XML輸出",
- "expand_templates_html_output": "原始HTML輸出",
+ "expand_templates_xml_output": "XML 輸出",
+ "expand_templates_html_output": "原始 HTML 輸出",
"expand_templates_ok": "確定",
"expand_templates_remove_comments": "移除評論",
"expand_templates_remove_nowiki": "在結果中禁止顯示 <nowiki> 標籤",
- "expand_templates_generate_xml": "顯示XML語法樹",
- "expand_templates_generate_rawhtml": "顯示原始HTML",
+ "expand_templates_generate_xml": "顯示 XML 解析樹",
+ "expand_templates_generate_rawhtml": "顯示原始 HTML",
"expand_templates_preview": "預覽"
}
return;
}
- $screenWidth = 80; // TODO: Caculate this!
+ $screenWidth = 80; // TODO: Calculate this!
$tab = " ";
$descWidth = $screenWidth - ( 2 * strlen( $tab ) );
public function __construct() {
parent::__construct();
$this->mDescription = "Build JSON messages files from a PHP messages file";
- $this->addArg( 'phpfile', 'PHP file defining a $messages array', true );
- $this->addArg( 'jsondir', 'Directory to write JSON files to. ' .
- 'Required unless <phpfile> exists and --shim-only is specified', false );
+
+ $this->addArg( 'phpfile', 'PHP file defining a $messages array', false );
+ $this->addArg( 'jsondir', 'Directory to write JSON files to', false );
$this->addOption( 'langcode', 'Language code; only needed for converting core i18n files',
false, true );
+ $this->addOption( 'extension', 'Perform default conversion on an extension',
+ false, true );
$this->addOption( 'shim-only', 'Only create or update the backward-compatibility shim' );
+ $this->addOption( 'supplementary', 'Find supplementary i18n files in subdirs and convert those',
+ false, false );
}
public function execute() {
+ global $IP;
+
$phpfile = $this->getArg( 0 );
$jsondir = $this->getArg( 1 );
+ $extension = $this->getOption( 'extension' );
+ $convertSupplementaryI18nFiles = $this->hasOption( 'supplementary' );
+
+ if ( $extension ) {
+ if ( $phpfile ) {
+ $this->error( "The phpfile is already specified, conflicts with --extension.\n", 1 );
+ }
+ $phpfile = "$IP/extensions/$extension/$extension.i18n.php";
+ }
+
+ if ( !$phpfile ) {
+ $this->error( "I'm here for an argument!\n" );
+ $this->maybeHelp( true );
+ // dies.
+ }
+
+ if ( $convertSupplementaryI18nFiles ) {
+ if ( is_readable( $phpfile ) ) {
+ $this->transformI18nFile( $phpfile, $jsondir );
+ } else {
+ // This is non-fatal because we might want to continue searching for
+ // i18n files in subdirs even if the extension does not include a
+ // primary i18n.php.
+ $this->error( "Warning: no primary i18n file was found." );
+ }
+ $this->output( "Searching for supplementary i18n files...\n" );
+ $dir_iterator = new RecursiveDirectoryIterator( dirname( $phpfile ) );
+ $iterator = new RecursiveIteratorIterator( $dir_iterator, RecursiveIteratorIterator::LEAVES_ONLY );
+ foreach ( $iterator as $path => $fileObject ) {
+ if ( fnmatch( "*.i18n.php", $fileObject->getFilename() ) ) {
+ $this->output( "Converting $path.\n" );
+ $this->transformI18nFile( $path );
+ }
+ }
+ } else {
+ // Just convert the primary i18n file.
+ $this->transformI18nFile( $phpfile, $jsondir );
+ }
+ }
+
+ public function transformI18nFile( $phpfile, $jsondir = null ) {
+ if ( !$jsondir ) {
+ // Assume the json directory should be in the same directory as the
+ // .i18n.php file.
+ $jsondir = dirname( $phpfile ) . "/i18n";
+ }
+ if ( !is_dir( $jsondir ) ) {
+ $this->output( "Creating directory $jsondir.\n" );
+ $success = mkdir( $jsondir );
+ if ( !$success ) {
+ $this->error( "Could not create directory $jsondir\n", 1 );
+ }
+ }
if ( $this->hasOption( 'shim-only' ) ) {
$this->shimOnly( $phpfile, $jsondir );
define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
define( 'MEDIAWIKI_INSTALL', true );
-require_once dirname( __DIR__ ) . "/maintenance/Maintenance.php";
+require_once dirname( __DIR__ ) . '/maintenance/Maintenance.php';
/**
* Maintenance script to install and configure MediaWiki
*
+ * Default values for the options are defined in DefaultSettings.php (see the mapping in CliInstaller.php)
+ * Default for --dbpath (SQLite-specific) is defined in SqliteInstaller::getGlobalDefaults
+ *
* @ingroup Maintenance
*/
class CommandLineInstaller extends Maintenance {
parent::__construct();
global $IP;
- $this->addArg( 'name', 'The name of the wiki', true );
+ $this->addDescription( "CLI-based MediaWiki installation and configuration.\n" .
+ "Defaut options are indicated in parenthesis." );
+
+ $this->addArg( 'name', 'The name of the wiki (MediaWiki)', false );
- $this->addArg( 'admin', 'The username of the wiki administrator (WikiSysop)', true );
+ $this->addArg( 'admin', 'The username of the wiki administrator.' );
$this->addOption( 'pass', 'The password for the wiki administrator.', false, true );
$this->addOption(
'passfile',
$this->addOption( 'dbserver', 'The database host (localhost)', false, true );
$this->addOption( 'dbport', 'The database port; only for PostgreSQL (5432)', false, true );
$this->addOption( 'dbname', 'The database name (my_wiki)', false, true );
- $this->addOption( 'dbpath', 'The path for the SQLite DB (/var/data)', false, true );
+ $this->addOption( 'dbpath', 'The path for the SQLite DB ($IP/data)', false, true );
$this->addOption( 'dbprefix', 'Optional database table name prefix', false, true );
$this->addOption( 'installdbuser', 'The user to use for installing (root)', false, true );
- $this->addOption( 'installdbpass', 'The pasword for the DB user to install as.', false, true );
+ $this->addOption( 'installdbpass', 'The password for the DB user to install as.', false, true );
$this->addOption( 'dbuser', 'The user to use for normal operations (wikiuser)', false, true );
- $this->addOption( 'dbpass', 'The pasword for the DB user for normal operations', false, true );
+ $this->addOption( 'dbpass', 'The password for the DB user for normal operations', false, true );
$this->addOption(
'dbpassfile',
'An alternative way to provide dbpass option, as the contents of this file',
false,
true
);
- $this->addOption( 'confpath', "Path to write LocalSettings.php to, default $IP", false, true );
+ $this->addOption( 'confpath', "Path to write LocalSettings.php to ($IP)", false, true );
/*
$this->addOption( 'dbschema', 'The schema for the MediaWiki DB in pg (mediawiki)', false, true );
- $this->addOption( 'namespace', 'The project namespace (same as the name)', false, true );
+ $this->addOption( 'namespace', 'The project namespace (same as the "name" argument)', false, true );
*/
$this->addOption( 'env-checks', "Run environment checks only, don't change anything" );
}
function execute() {
global $IP;
- // Will not be set if used with --env-checks
- $siteName = isset( $this->mArgs[0] ) ? $this->mArgs[0] : "Don't care";
- $adminName = isset( $this->mArgs[1] ) ? $this->mArgs[1] : null;
+ $siteName = $this->getArg( 0, 'MediaWiki' ); // Will not be set if used with --env-checks
+ $adminName = $this->getArg( 1 );
- $dbpassfile = $this->getOption( 'dbpassfile', false );
- if ( $dbpassfile !== false ) {
- if ( $this->getOption( 'dbpass', false ) !== false ) {
- $this->error( 'WARNING: You provide the options "dbpass" and "dbpassfile". '
- . 'The content of "dbpassfile" overwrites "dbpass".' );
+ $dbpassfile = $this->getOption( 'dbpassfile' );
+ if ( $dbpassfile !== null ) {
+ if ( $this->getOption( 'dbpass' ) !== null ) {
+ $this->error( 'WARNING: You have provided the options "dbpass" and "dbpassfile". '
+ . 'The content of "dbpassfile" overrides "dbpass".' );
}
wfSuppressWarnings();
- $dbpass = file_get_contents( $dbpassfile );
+ $dbpass = file_get_contents( $dbpassfile ); // returns false on failure
wfRestoreWarnings();
if ( $dbpass === false ) {
$this->error( "Couldn't open $dbpassfile", true );
$this->mOptions['dbpass'] = trim( $dbpass, "\r\n" );
}
- $passfile = $this->getOption( 'passfile', false );
- if ( $passfile !== false ) {
- if ( $this->getOption( 'pass', false ) !== false ) {
- $this->error( 'WARNING: You provide the options "pass" and "passfile". '
- . 'The content of "passfile" overwrites "pass".' );
+ $passfile = $this->getOption( 'passfile' );
+ if ( $passfile !== null ) {
+ if ( $this->getOption( 'pass' ) !== null ) {
+ $this->error( 'WARNING: You have provided the options "pass" and "passfile". '
+ . 'The content of "passfile" overrides "pass".' );
}
wfSuppressWarnings();
- $pass = file_get_contents( $passfile );
+ $pass = file_get_contents( $passfile ); // returns false on failure
wfRestoreWarnings();
if ( $pass === false ) {
$this->error( "Couldn't open $passfile", true );
}
- $this->mOptions['pass'] = str_replace( array( "\n", "\r" ), "", $pass );
- } elseif ( $this->getOption( 'pass', false ) === false ) {
+ $this->mOptions['pass'] = trim( $pass, "\r\n" );
+ } elseif ( $this->getOption( 'pass' ) === null ) {
$this->error( 'You need to provide the option "pass" or "passfile"', true );
}
- $installer =
- InstallerOverrides::getCliInstaller( $siteName, $adminName, $this->mOptions );
+ $installer = InstallerOverrides::getCliInstaller( $siteName, $adminName, $this->mOptions );
$status = $installer->doEnvironmentChecks();
if ( $status->isGood() ) {
}
}
-$maintClass = "CommandLineInstaller";
+$maintClass = 'CommandLineInstaller';
require_once RUN_MAINTENANCE_IF_MAIN;
'helplogin-url',
'autocomment-prefix',
'move-redirect-text',
+ 'category-move-redirect-override',
'interlanguage-link-title-langonly',
'createaccount-hook-abort',
);
'right-move',
'right-move-subpages',
'right-move-rootuserpages',
+ 'right-move-categorypages',
'right-movefile',
'right-suppressredirect',
'right-upload',
'action-move',
'action-move-subpages',
'action-move-rootuserpages',
+ 'action-move-categorypages',
'action-movefile',
'action-upload',
'action-reupload',
'movepagetalktext',
'movearticle',
'moveuserpage-warning',
+ 'movecategorypage-warning',
'movenologintext',
'movenotallowed',
'movenotallowedfile',
'cant-move-user-page',
'cant-move-to-user-page',
+ 'cant-move-category-page',
+ 'cant-move-to-category-page',
'newtitle',
'move-watch',
'movepagebtn',
'movenosubpage',
'movereason',
'move-redirect-text',
+ 'category-move-redirect-override',
'revertmove',
'delete_and_move',
'delete_and_move_text',
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.page ADD page_links_updated TIMESTAMP(6) WITH TIME ZONE;
+
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.recentchanges ADD rc_source VARCHAR2(16);
define mw_prefix='{$wgDBprefix}';
-ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE NULL DEFAULT NULL;
+ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE;
user_touched TIMESTAMP(6) WITH TIME ZONE,
user_registration TIMESTAMP(6) WITH TIME ZONE,
user_editcount NUMBER,
- user_password_expires TIMESTAMP(6) WITH TIME ZONE NULL DEFAULT NULL
+ user_password_expires TIMESTAMP(6) WITH TIME ZONE
);
ALTER TABLE &mw_prefix.mwuser ADD CONSTRAINT &mw_prefix.mwuser_pk PRIMARY KEY (user_id);
CREATE UNIQUE INDEX &mw_prefix.mwuser_u01 ON &mw_prefix.mwuser (user_name);
-- Create a dummy user to satisfy fk contraints especially with revisions
INSERT INTO &mw_prefix.mwuser
- VALUES (0,'Anonymous',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, '', current_timestamp, current_timestamp, 0);
+ (user_id, user_name, user_options, user_touched, user_registration, user_editcount)
+ VALUES (0,'Anonymous','', current_timestamp, current_timestamp,0);
CREATE TABLE &mw_prefix.user_groups (
ug_user NUMBER DEFAULT 0 NOT NULL,
page_is_new CHAR(1) DEFAULT '0' NOT NULL,
page_random NUMBER(15,14) NOT NULL,
page_touched TIMESTAMP(6) WITH TIME ZONE,
+ page_links_updated TIMESTAMP(6) WITH TIME ZONE,
page_latest NUMBER DEFAULT 0 NOT NULL, -- FK?
page_len NUMBER DEFAULT 0 NOT NULL,
page_content_model VARCHAR2(32)
-- Create a dummy page to satisfy fk contraints especially with revisions
INSERT INTO &mw_prefix.page
- VALUES (0, 0, ' ', NULL, 0, 0, 0, 0, current_timestamp, 0, 0, NULL);
+ VALUES (0, 0, ' ', NULL, 0, 0, 0, 0, current_timestamp, NULL, 0, 0, NULL);
/*$mw$*/
CREATE TRIGGER &mw_prefix.page_set_random BEFORE INSERT ON &mw_prefix.page
CREATE TABLE &mw_prefix.recentchanges (
rc_id NUMBER NOT NULL,
rc_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
- rc_cur_time TIMESTAMP(6) WITH TIME ZONE NOT NULL,
+ rc_cur_time TIMESTAMP(6) WITH TIME ZONE,
rc_user NUMBER DEFAULT 0 NOT NULL,
rc_user_text VARCHAR2(255) NOT NULL,
rc_namespace NUMBER DEFAULT 0 NOT NULL,
rc_this_oldid NUMBER DEFAULT 0 NOT NULL,
rc_last_oldid NUMBER DEFAULT 0 NOT NULL,
rc_type CHAR(1) DEFAULT '0' NOT NULL,
+ rc_source VARCHAR2(16),
rc_patrolled CHAR(1) DEFAULT '0' NOT NULL,
rc_ip VARCHAR2(15),
rc_old_len NUMBER,
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * @ingroup Maintenance
+ */
+class PageExists extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Report whether a specific page exists";
+ $this->addArg( 'title', 'Page title to check whether it exists' );
+ }
+
+ public function execute() {
+ $titleArg = $this->getArg();
+ $title = Title::newFromText( $titleArg );
+ $pageExists = $title && $title->exists();
+
+ $text = '';
+ $code = 0;
+ if ( $pageExists ) {
+ $text = "{$title} exists.";
+ } else {
+ $text = "{$title} doesn't exist.";
+ $code = 1;
+ }
+ $this->output( $text );
+ $this->error( '', $code );
+ }
+}
+
+$maintClass = "PageExists";
+require_once RUN_MAINTENANCE_IF_MAIN;
+
'jquery' => array(
'scripts' => 'resources/lib/jquery/jquery.js',
+ 'debugScripts' => 'resources/lib/jquery/jquery.migrate.js',
'debugRaw' => false,
'targets' => array( 'desktop', 'mobile' ),
),
--- /dev/null
+/*!
+ * jQuery Migrate - v1.2.1 - 2013-05-08
+ * https://github.com/jquery/jquery-migrate
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
+ */
+(function( jQuery, window, undefined ) {
+// See http://bugs.jquery.com/ticket/13335
+// "use strict";
+
+
+var warnedAbout = {};
+
+// List of warnings already given; public read only
+jQuery.migrateWarnings = [];
+
+// Set to true to prevent console output; migrateWarnings still maintained
+// jQuery.migrateMute = false;
+
+// Show a message on the console so devs know we're active
+if ( !jQuery.migrateMute && window.console && window.console.log ) {
+ window.console.log("JQMIGRATE: Logging is active");
+}
+
+// Set to false to disable traces that appear with warnings
+if ( jQuery.migrateTrace === undefined ) {
+ jQuery.migrateTrace = true;
+}
+
+// Forget any warnings we've already given; public
+jQuery.migrateReset = function() {
+ warnedAbout = {};
+ jQuery.migrateWarnings.length = 0;
+};
+
+function migrateWarn( msg) {
+ var console = window.console;
+ if ( !warnedAbout[ msg ] ) {
+ warnedAbout[ msg ] = true;
+ jQuery.migrateWarnings.push( msg );
+ if ( console && console.warn && !jQuery.migrateMute ) {
+ console.warn( "JQMIGRATE: " + msg );
+ if ( jQuery.migrateTrace && console.trace ) {
+ console.trace();
+ }
+ }
+ }
+}
+
+function migrateWarnProp( obj, prop, value, msg ) {
+ if ( Object.defineProperty ) {
+ // On ES5 browsers (non-oldIE), warn if the code tries to get prop;
+ // allow property to be overwritten in case some other plugin wants it
+ try {
+ Object.defineProperty( obj, prop, {
+ configurable: true,
+ enumerable: true,
+ get: function() {
+ migrateWarn( msg );
+ return value;
+ },
+ set: function( newValue ) {
+ migrateWarn( msg );
+ value = newValue;
+ }
+ });
+ return;
+ } catch( err ) {
+ // IE8 is a dope about Object.defineProperty, can't warn there
+ }
+ }
+
+ // Non-ES5 (or broken) browser; just set the property
+ jQuery._definePropertyBroken = true;
+ obj[ prop ] = value;
+}
+
+if ( document.compatMode === "BackCompat" ) {
+ // jQuery has never supported or tested Quirks Mode
+ migrateWarn( "jQuery is not compatible with Quirks Mode" );
+}
+
+
+var attrFn = jQuery( "<input/>", { size: 1 } ).attr("size") && jQuery.attrFn,
+ oldAttr = jQuery.attr,
+ valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
+ function() { return null; },
+ valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
+ function() { return undefined; },
+ rnoType = /^(?:input|button)$/i,
+ rnoAttrNodeType = /^[238]$/,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ ruseDefault = /^(?:checked|selected)$/i;
+
+// jQuery.attrFn
+migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );
+
+jQuery.attr = function( elem, name, value, pass ) {
+ var lowerName = name.toLowerCase(),
+ nType = elem && elem.nodeType;
+
+ if ( pass ) {
+ // Since pass is used internally, we only warn for new jQuery
+ // versions where there isn't a pass arg in the formal params
+ if ( oldAttr.length < 4 ) {
+ migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
+ }
+ if ( elem && !rnoAttrNodeType.test( nType ) &&
+ (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
+ return jQuery( elem )[ name ]( value );
+ }
+ }
+
+ // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
+ // for disconnected elements we don't warn on $( "<button>", { type: "button" } ).
+ if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {
+ migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
+ }
+
+ // Restore boolHook for boolean property/attribute synchronization
+ if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
+ jQuery.attrHooks[ lowerName ] = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" &&
+ ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+ };
+
+ // Warn only for attributes that can remain distinct from their properties post-1.9
+ if ( ruseDefault.test( lowerName ) ) {
+ migrateWarn( "jQuery.fn.attr('" + lowerName + "') may use property instead of attribute" );
+ }
+ }
+
+ return oldAttr.call( jQuery, elem, name, value );
+};
+
+// attrHooks: value
+jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "button" ) {
+ return valueAttrGet.apply( this, arguments );
+ }
+ if ( nodeName !== "input" && nodeName !== "option" ) {
+ migrateWarn("jQuery.fn.attr('value') no longer gets properties");
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "button" ) {
+ return valueAttrSet.apply( this, arguments );
+ }
+ if ( nodeName !== "input" && nodeName !== "option" ) {
+ migrateWarn("jQuery.fn.attr('value', val) no longer sets properties");
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+};
+
+
+var matched, browser,
+ oldInit = jQuery.fn.init,
+ oldParseJSON = jQuery.parseJSON,
+ // Note: XSS check is done below after string is trimmed
+ rquickExpr = /^([^<]*)(<[\w\W]+>)([^>]*)$/;
+
+// $(html) "looks like html" rule change
+jQuery.fn.init = function( selector, context, rootjQuery ) {
+ var match;
+
+ if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
+ (match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {
+ // This is an HTML string according to the "old" rules; is it still?
+ if ( selector.charAt( 0 ) !== "<" ) {
+ migrateWarn("$(html) HTML strings must start with '<' character");
+ }
+ if ( match[ 3 ] ) {
+ migrateWarn("$(html) HTML text after last tag is ignored");
+ }
+ // Consistently reject any HTML-like string starting with a hash (#9521)
+ // Note that this may break jQuery 1.6.x code that otherwise would work.
+ if ( match[ 0 ].charAt( 0 ) === "#" ) {
+ migrateWarn("HTML string cannot start with a '#' character");
+ jQuery.error("JQMIGRATE: Invalid selector string (XSS)");
+ }
+ // Now process using loose rules; let pre-1.8 play too
+ if ( context && context.context ) {
+ // jQuery object as context; parseHTML expects a DOM object
+ context = context.context;
+ }
+ if ( jQuery.parseHTML ) {
+ return oldInit.call( this, jQuery.parseHTML( match[ 2 ], context, true ),
+ context, rootjQuery );
+ }
+ }
+ return oldInit.apply( this, arguments );
+};
+jQuery.fn.init.prototype = jQuery.fn;
+
+// Let $.parseJSON(falsy_value) return null
+jQuery.parseJSON = function( json ) {
+ if ( !json && json !== null ) {
+ migrateWarn("jQuery.parseJSON requires a valid JSON string");
+ return null;
+ }
+ return oldParseJSON.apply( this, arguments );
+};
+
+jQuery.uaMatch = function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+};
+
+// Don't clobber any existing jQuery.browser in case it's different
+if ( !jQuery.browser ) {
+ matched = jQuery.uaMatch( navigator.userAgent );
+ browser = {};
+
+ if ( matched.browser ) {
+ browser[ matched.browser ] = true;
+ browser.version = matched.version;
+ }
+
+ // Chrome is Webkit, but Webkit is also Safari.
+ if ( browser.chrome ) {
+ browser.webkit = true;
+ } else if ( browser.webkit ) {
+ browser.safari = true;
+ }
+
+ jQuery.browser = browser;
+}
+
+// Warn if the code tries to get jQuery.browser
+migrateWarnProp( jQuery, "browser", jQuery.browser, "jQuery.browser is deprecated" );
+
+jQuery.sub = function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ migrateWarn( "jQuery.sub() is deprecated" );
+ return jQuerySub;
+};
+
+
+// Ensure that $.ajax gets the new parseJSON defined in core.js
+jQuery.ajaxSetup({
+ converters: {
+ "text json": jQuery.parseJSON
+ }
+});
+
+
+var oldFnData = jQuery.fn.data;
+
+jQuery.fn.data = function( name ) {
+ var ret, evt,
+ elem = this[0];
+
+ // Handles 1.7 which has this behavior and 1.8 which doesn't
+ if ( elem && name === "events" && arguments.length === 1 ) {
+ ret = jQuery.data( elem, name );
+ evt = jQuery._data( elem, name );
+ if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
+ migrateWarn("Use of jQuery.fn.data('events') is deprecated");
+ return evt;
+ }
+ }
+ return oldFnData.apply( this, arguments );
+};
+
+
+var rscriptType = /\/(java|ecma)script/i,
+ oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
+
+jQuery.fn.andSelf = function() {
+ migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
+ return oldSelf.apply( this, arguments );
+};
+
+// Since jQuery.clean is used internally on older versions, we only shim if it's missing
+if ( !jQuery.clean ) {
+ jQuery.clean = function( elems, context, fragment, scripts ) {
+ // Set context per 1.8 logic
+ context = context || document;
+ context = !context.nodeType && context[0] || context;
+ context = context.ownerDocument || context;
+
+ migrateWarn("jQuery.clean() is deprecated");
+
+ var i, elem, handleScript, jsTags,
+ ret = [];
+
+ jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );
+
+ // Complex logic lifted directly from jQuery 1.8
+ if ( fragment ) {
+ // Special handling of each script element
+ handleScript = function( elem ) {
+ // Check if we consider it executable
+ if ( !elem.type || rscriptType.test( elem.type ) ) {
+ // Detach the script and store it in the scripts array (if provided) or the fragment
+ // Return truthy to indicate that it has been handled
+ return scripts ?
+ scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
+ fragment.appendChild( elem );
+ }
+ };
+
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
+ // Check if we're done after handling an executable script
+ if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
+ // Append to fragment and handle embedded scripts
+ fragment.appendChild( elem );
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
+ jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
+
+ // Splice the scripts into ret after their former ancestor and advance our index beyond them
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ i += jsTags.length;
+ }
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var eventAdd = jQuery.event.add,
+ eventRemove = jQuery.event.remove,
+ eventTrigger = jQuery.event.trigger,
+ oldToggle = jQuery.fn.toggle,
+ oldLive = jQuery.fn.live,
+ oldDie = jQuery.fn.die,
+ ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
+ rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
+ rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
+ hoverHack = function( events ) {
+ if ( typeof( events ) !== "string" || jQuery.event.special.hover ) {
+ return events;
+ }
+ if ( rhoverHack.test( events ) ) {
+ migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
+ }
+ return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+// Event props removed in 1.9, put them back if needed; no practical way to warn them
+if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
+ jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
+}
+
+// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
+if ( jQuery.event.dispatch ) {
+ migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
+}
+
+// Support for 'hover' pseudo-event and ajax event warnings
+jQuery.event.add = function( elem, types, handler, data, selector ){
+ if ( elem !== document && rajaxEvent.test( types ) ) {
+ migrateWarn( "AJAX events should be attached to document: " + types );
+ }
+ eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
+};
+jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
+ eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
+};
+
+jQuery.fn.error = function() {
+ var args = Array.prototype.slice.call( arguments, 0);
+ migrateWarn("jQuery.fn.error() is deprecated");
+ args.splice( 0, 0, "error" );
+ if ( arguments.length ) {
+ return this.bind.apply( this, args );
+ }
+ // error event should not bubble to window, although it does pre-1.7
+ this.triggerHandler.apply( this, args );
+ return this;
+};
+
+jQuery.fn.toggle = function( fn, fn2 ) {
+
+ // Don't mess with animation or css toggles
+ if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
+ return oldToggle.apply( this, arguments );
+ }
+ migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
+
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+};
+
+jQuery.fn.live = function( types, data, fn ) {
+ migrateWarn("jQuery.fn.live() is deprecated");
+ if ( oldLive ) {
+ return oldLive.apply( this, arguments );
+ }
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+};
+
+jQuery.fn.die = function( types, fn ) {
+ migrateWarn("jQuery.fn.die() is deprecated");
+ if ( oldDie ) {
+ return oldDie.apply( this, arguments );
+ }
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+};
+
+// Turn global events into document-triggered events
+jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
+ if ( !elem && !rajaxEvent.test( event ) ) {
+ migrateWarn( "Global events are undocumented and deprecated" );
+ }
+ return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
+};
+jQuery.each( ajaxEvents.split("|"),
+ function( _, name ) {
+ jQuery.event.special[ name ] = {
+ setup: function() {
+ var elem = this;
+
+ // The document needs no shimming; must be !== for oldIE
+ if ( elem !== document ) {
+ jQuery.event.add( document, name + "." + jQuery.guid, function() {
+ jQuery.event.trigger( name, null, elem, true );
+ });
+ jQuery._data( this, name, jQuery.guid++ );
+ }
+ return false;
+ },
+ teardown: function() {
+ if ( this !== document ) {
+ jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
+ }
+ return false;
+ }
+ };
+ }
+);
+
+
+})( jQuery, window );
},
"ooui-dialog-action-close": "Джаб",
"ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
- "ooui-outline-control-move-up": "Элементни башына кёчюр"
+ "ooui-outline-control-move-up": "Элементни башына кёчюр",
+ "ooui-outline-control-remove": "Пунктну кетер",
+ "ooui-toolbar-more": "Энтда"
}
/*!
- * OOjs UI v0.1.0-pre (7d2507b267)
+ * OOjs UI v0.1.0-pre (7b3672591f)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: Mon May 05 2014 14:13:13 GMT-0700 (PDT)
+ * Date: Fri May 09 2014 13:27:04 GMT+0200 (CEST)
*/
( function ( OO ) {
/*!
- * OOjs UI v0.1.0-pre (7d2507b267)
+ * OOjs UI v0.1.0-pre (7b3672591f)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: Mon May 05 2014 14:13:12 GMT-0700 (PDT)
+ * Date: Fri May 09 2014 13:27:04 GMT+0200 (CEST)
*/
/* Textures */
// Return the Promise
return apiDeferred.promise( { abort: xhr.abort } ).fail( function ( code, details ) {
- mw.log( 'mw.Api error: ', code, details );
+ if ( code !== 'abort' ) {
+ mw.log( 'mw.Api error: ', code, details );
+ }
} );
},
function doWatchInternal( pages, ok, err, addParams ) {
// XXX: Parameter addParams is undocumented because we inherit this
// documentation in the public method...
- var apiPromise = this.post(
+ var apiPromise = this.postWithToken( 'watch',
$.extend(
{
action: 'watch',
titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
- token: mw.user.tokens.get( 'watchToken' ),
uselang: mw.config.get( 'wgUserLanguage' )
},
addParams
border: 1px solid #dddddd;
}
-/* table standards */
-table.rimage {
- float: right;
- width: 1pt;
- position: relative;
- margin-left: 1em;
- margin-bottom: 1em;
- text-align: center;
-}
-
body {
background: white;
color: black;
/* Galleries (see shared.css for more info) */
li.gallerybox {
vertical-align: top;
- display: -moz-inline-box;
display: inline-block;
}
* @deprecated since 1.17 Use mediawiki.util instead
*/
msg = 'Use mediawiki.util instead.';
-mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
-mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
mw.log.deprecate( win, 'addPortletLink', mw.util.addPortletLink, msg );
mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
+msg = 'Use jquery.accessKeyLabel instead.';
+mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
+mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
/**
* Wikipage import methods
$settings = array(
'wgServer' => 'http://example.org',
+ 'wgServerName' => 'example.org',
'wgScript' => '/index.php',
'wgScriptPath' => '/',
'wgArticlePath' => '/wiki/$1',
* @covers MWNamespace::isMovable
*/
public function testIsMovable() {
- $this->assertFalse( MWNamespace::isMovable( NS_CATEGORY ) );
+ $this->assertFalse( MWNamespace::isMovable( NS_SPECIAL ) );
# @todo FIXME: Write more tests!!
}
) {
return new ParserOutput( $this->getNativeData() );
}
+
+ /**
+ * @see AbstractContent::fillParserOutput()
+ *
+ * @param Title $title Context title for parsing
+ * @param int|null $revId Revision ID (for {{REVISIONID}})
+ * @param ParserOptions|null $options Parser options
+ * @param bool $generateHtml Whether or not to generate HTML
+ * @param ParserOutput &$output The output object to fill (reference).
+ */
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output ) {
+ $output = new ParserOutput( $this->getNativeData() );
+ }
}
* @group Database
* ^--- needed, because we do need the database to test link updates
*/
-class CssContentTest extends MediaWikiTestCase {
+class CssContentTest extends JavaScriptContentTest {
protected function setUp() {
parent::setUp();
*/
class TextContentTest extends MediaWikiLangTestCase {
protected $context;
+ protected $savedContentGetParserOutput;
protected function setUp() {
+ global $wgHooks;
+
parent::setUp();
// Anon user
$user = new User();
$user->setName( '127.0.0.1' );
+ $this->context = new RequestContext( new FauxRequest() );
+ $this->context->setTitle( Title::newFromText( 'Test' ) );
+ $this->context->setUser( $user );
+
$this->setMwGlobals( array(
'wgUser' => $user,
'wgTextModelsToParse' => array(
'wgAlwaysUseTidy' => false,
) );
- $this->context = new RequestContext( new FauxRequest() );
- $this->context->setTitle( Title::newFromText( 'Test' ) );
- $this->context->setUser( $user );
+ // bypass hooks that force custom rendering
+ if ( isset( $wgHooks['ContentGetParserOutput'] ) ) {
+ $this->savedContentGetParserOutput = $wgHooks['ContentGetParserOutput'];
+ unset( $wgHooks['ContentGetParserOutput'] );
+ }
+ }
+
+ public function teardown() {
+ global $wgHooks;
+
+ // restore hooks that force custom rendering
+ if ( $this->savedContentGetParserOutput !== null ) {
+ $wgHooks['ContentGetParserOutput'] = $this->savedContentGetParserOutput;
+ }
+
+ parent::teardown();
}
public function newContent( $text ) {
$tmpGlobals['wgContLang'] = Language::factory( 'en' );
$tmpGlobals['wgSitename'] = 'MediaWiki';
$tmpGlobals['wgServer'] = 'http://example.org';
+ $tmpGlobals['wgServerName'] = 'example.org';
$tmpGlobals['wgScript'] = '/index.php';
$tmpGlobals['wgScriptPath'] = '/';
$tmpGlobals['wgArticlePath'] = '/wiki/$1';
$this->assertEquals( $expected, $text );
}
+ /**
+ * @expectedException MWException
+ * @expectedExceptionMessage Parser state cleared while parsing. Did you call Parser::parse recursively?
+ * @covers Parser::lock
+ */
+ public function testRecursiveParse() {
+ global $wgParser;
+ $title = Title::newFromText( 'foo' );
+ $po = new ParserOptions;
+ $wgParser->setHook( 'recursivecallparser', array( $this, 'helperParserFunc' ) );
+ $wgParser->parse( '<recursivecallparser>baz</recursivecallparser>', $title, $po );
+ }
+
+ public function helperParserFunc( $input, $args, $parser) {
+ $title = Title::newFromText( 'foo' );
+ $po = new ParserOptions;
+ $parser->parse( $input, $title, $po );
+ return 'bar';
+ }
+
/**
* @covers Parser::callParserFunction
*/
pear channel-discover components.ez.no
pear channel-discover pear.symfony.com
pear update-channels
- pear install --alldeps phpunit/PHPUnit
+ #Temporary fix for 64597
+ pear install --alldeps phpunit/PHPUnit-3.7.35
else if ( has_binary apt-get ); then
echo Installing phpunit with apt-get
apt-get install phpunit