merged master
Change-Id: Iad12ee382d6aeb1fab6fefb611d290b74865ea4b
This commit is contained in:
commit
d87135d706
544 changed files with 16373 additions and 7901 deletions
23
.jshintignore
Normal file
23
.jshintignore
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# upstream libs
|
||||
resources/jquery/jquery.appear.js
|
||||
resources/jquery/jquery.async.js
|
||||
resources/jquery/jquery.cycle.all.js
|
||||
resources/jquery/jquery.cookie.js
|
||||
resources/jquery/jquery.farbtastic.js
|
||||
resources/jquery/jquery.form.js
|
||||
resources/jquery/jquery.hoverIntent.js
|
||||
resources/jquery/jquery.js
|
||||
resources/jquery/jquery.json.js
|
||||
resources/jquery/jquery.mockjax.js
|
||||
resources/jquery/jquery.qunit.js
|
||||
resources/jquery/jquery.validate.js
|
||||
resources/jquery/jquery.xmldom.js
|
||||
resources/jquery.effects
|
||||
resources/jquery.tipsy
|
||||
resources/jquery.ui
|
||||
resources/mediawiki.libs/mediawiki.libs.jpegmeta.js
|
||||
tests/jasmine/lib/jasmine-1.0.1/jasmine-html.js
|
||||
tests/jasmine/lib/jasmine-1.0.1/jasmine.js
|
||||
|
||||
# legacy stuff
|
||||
skins/common
|
||||
22
.jshintrc
Normal file
22
.jshintrc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"predef": [
|
||||
"mediaWiki",
|
||||
"jQuery",
|
||||
"QUnit"
|
||||
],
|
||||
|
||||
"bitwise": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noempty": true,
|
||||
"undef": true,
|
||||
"trailing": true,
|
||||
|
||||
"laxbreak": true,
|
||||
"smarttabs": true,
|
||||
|
||||
"browser": true
|
||||
}
|
||||
3
README
3
README
|
|
@ -46,8 +46,7 @@ The MediaWiki software was written by:
|
|||
* Victor Vasiliev
|
||||
* Rotem Liss
|
||||
* Platonides
|
||||
* Antoine Musso
|
||||
* Several others (view CREDITS for a more complete list)
|
||||
* Many others (view CREDITS for a more complete list)
|
||||
|
||||
The contributors hold the copyright to this work, and it is licensed under the
|
||||
terms of the GNU General Public License, version 2 or later (see
|
||||
|
|
|
|||
|
|
@ -20,11 +20,18 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
* `$wgUsePathInfo = true;` is no longer needed to make $wgArticlePath work on servers
|
||||
using like nginx, lighttpd, and apache over fastcgi. MediaWiki now always extracts
|
||||
path info from REQUEST_URI if it's available.
|
||||
* The user right 'upload_by_url' is no longer given to sysops by default.
|
||||
This only affects installations which have $wgAllowCopyUploads set to true.
|
||||
* Removed f-prot support from $wgAntivirusSetup.
|
||||
* $wgDBerrorLogInUTC to log error in $wgDBerrorLog using an UTC date instead
|
||||
of the wiki timezone set by $wgLocalTimezone.
|
||||
|
||||
=== New features in 1.20 ===
|
||||
* Added TitleIsAlwaysKnown hook which gets called when determining if a page exists.
|
||||
* Added NamespaceIsMovable hook which gets called when determining if pages in a
|
||||
certain namespace can be moved.
|
||||
* Added SpecialPageBeforeExecute hook which gets called before SpecialPage::execute.
|
||||
* Added SpecialPageAfterExecute hook which gets called after SpecialPage::execute.
|
||||
* (bug 32341) Add upload by URL domain limitation.
|
||||
* &useskin=default will now always display the default skin. Useful for users with a
|
||||
preference for the non-default skin to look at something using the default skin.
|
||||
|
|
@ -55,6 +62,8 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
* Edit notices can now be translated.
|
||||
* (bug 35680) jQuery upgraded to 1.7.2.
|
||||
* jQuery UI upgraded to 1.8.21.
|
||||
* (bug 35705) QUnit upgraded from v1.2.0 to v1.8.0.
|
||||
* (bug 37604) jquery.cookie upgraded to 2011 version.
|
||||
* (bug 22887) Add warning and tracking category for preprocessor errors
|
||||
* (bug 31704) Allow selection of associated namespace on the watchlist
|
||||
* (bug 5445) Now remove autoblocks when a user is unblocked.
|
||||
|
|
@ -67,7 +76,6 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
* New getCreator and getOldestRevision methods added to WikiPage class
|
||||
* (bug 4220) the XML dump format schema now have unique identity constraints
|
||||
for page and revision identifiers. Patch by Elvis Stansvik.
|
||||
* (bug 35705) QUnit upgraded from v1.2.0 to v1.8.0.
|
||||
* cleanupSpam.php now can delete spam pages if --delete was specified instead of blanking
|
||||
them.
|
||||
* Added new hook ChangePasswordForm to allow adding of additional fields in Special:ChangePassword
|
||||
|
|
@ -76,6 +84,23 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
Will be null on previewing a page being created.
|
||||
* Added new hook AfterFinalPageOutput to allow modifications to buffered page output before sent
|
||||
to the client.
|
||||
* (bug 37627) UserNotLoggedIn() exception to show a generic error page whenever
|
||||
a user is not logged in.
|
||||
* Watched status in changes lists are no longer indicated by <strong></strong>
|
||||
tags with class "mw-watched". Instead, each line now has a class
|
||||
"mw-changeslist-line-watched" or "mw-changeslist-line-not-watched", and the
|
||||
title itself is surrounded by <span></span> tags with class "mw-title".
|
||||
* Added ContribsPager::reallyDoQuery hook allowing extensions to data to MyContribs
|
||||
* Added new hook ParserAfterParse to allow extensions to affect parsed output
|
||||
after the parse is complete but before block level processing, link holder
|
||||
replacement, and so on.
|
||||
* (bug 34678) Added InternalParseBeforeSanitize hook which gets called during Parser's
|
||||
internalParse method just before the parser removes unwanted/dangerous HTML tags.
|
||||
* (bug 36783) Implement jQuery Promise interface in mediawiki.api module.
|
||||
* Make dates in sortable tables sort according to the page content language
|
||||
instead of the site content language
|
||||
* (bug 37926) Deleterevision will no longer allow users to delete log entries,
|
||||
the new deletelogentry permission is required for this.
|
||||
|
||||
=== Bug fixes in 1.20 ===
|
||||
* (bug 30245) Use the correct way to construct a log page title.
|
||||
|
|
@ -118,16 +143,34 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
* (bug 35572) Blocks appear to succeed even if query fails due to wrong DB structure
|
||||
* (bug 31757) Add a word-separator between help-messages in HTMLForm
|
||||
* (bug 30410) Removed deprecated $wgFilterCallback and the 'filtered' API error.
|
||||
* (bug 32604) Some messages needs escaping of wikitext inside username
|
||||
* (bug 32604) Some messages needs escaping of wikitext inside username.
|
||||
* (bug 36537) Rename wfArrayToCGI to wfArrayToCgi for consistency with wfCgiToArray.
|
||||
* (bug 25946) The message on the top of Special:RecentChanges is now displayed
|
||||
* (bug 25946) The message on the top of Special:RecentChanges is now displayed.
|
||||
in user language instead of content language.
|
||||
* (bug 35264) Wrong type used for <ns> in export.xsd
|
||||
* (bug 24985) Use $wgTmpDirectory as the default temp directory so that people
|
||||
who don't have access to /tmp can specify an alternative.
|
||||
* (bug 27283) SqlBagOStuff breaks PostgreSQL transactions.
|
||||
* (bug 35727) mw.Api ajax() should put token parameter last.
|
||||
* (bug 260) Handle <pre> overflow automatically with a scroll bar.
|
||||
* (bug 37708) mw.Uri.clone() should make a deep copy.
|
||||
* (bug 38024) ResourceLoader should not create empty stylesheets for modules
|
||||
that don't have stylesheets.
|
||||
* (bug 36812) Special:ActiveUsers "Hide bots" should hide users from any group
|
||||
having the "bot" user right, instead of just the default "bot" user group.
|
||||
* (bug 35082) mw.util.addPortletLink incorrectly adds link to mutiple <ul> tags.
|
||||
* (bug 36495) Sanitizer::fixDeprecatedAttributes should convert "align"
|
||||
attribute to margin or float instead of text-align (for non-table-cells).
|
||||
* (bug 36991) jquery.tablesorter should extract date sort format from date
|
||||
string instead of global config. Dates like "April 1 2012" and "1 April 2012"
|
||||
now sort correctly regardless of the content language's DefaultDateFormat.
|
||||
* (bug 31895) mw.loader mode now correct when triggered from a $.fn.ready
|
||||
handler that is bound before mediawiki.js's handler (e.g. browser-userscripts
|
||||
like greasemonkey).
|
||||
* (bug 38152) jquery.tablesorter: Use .data() instead of .attr(), so that live
|
||||
values are used instead of just the fixed values from when the tablesorter
|
||||
was initialized.
|
||||
* (bug 38093) Gender of changed user groups missing in Special:Log/rights
|
||||
|
||||
=== API changes in 1.20 ===
|
||||
* (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
|
||||
|
|
@ -139,13 +182,24 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
|
|||
* (bug 32497) API now allows changing of protection level using pageid.
|
||||
* (bug 32498) API now allows comparing pages using pageids.
|
||||
* (bug 30975) API import of pages with invalid characters in this wiki leads to Fatal Error.
|
||||
* (bug 30488) API now allows listing of backlinks/embeddedin/imageusage per pageid
|
||||
* (bug 34927) Output media_type for list=filearchive
|
||||
* (bug 28814) add properties to output of action=parse
|
||||
* (bug 33224) add variants of content language to meta=siteinfo
|
||||
* (bug 36761) "Mark pages as visited" now submits previously established filter options
|
||||
* (bug 32643) action=purge with forcelinkupdate no longer crashes when ratelimit is reached
|
||||
* The paraminfo module now also contains result properties for most modules
|
||||
* (bug 30488) API now allows listing of backlinks/embeddedin/imageusage per pageid.
|
||||
* (bug 34927) Output media_type for list=filearchive.
|
||||
* (bug 28814) add properties to output of action=parse.
|
||||
* (bug 33224) add variants of content language to meta=siteinfo.
|
||||
* (bug 36761) "Mark pages as visited" now submits previously established filter options.
|
||||
* (bug 32643) action=purge with forcelinkupdate no longer crashes when ratelimit is reached.
|
||||
* The paraminfo module now also contains result properties for most modules.
|
||||
* (bug 32348) Allow descending order for list=alllinks.
|
||||
* (bug 31777) Upload unknown error ``fileexists-forbidden''.
|
||||
* (bug 32382) Allow descending order for list=iwbacklinks.
|
||||
* (bug 32381) Allow descending order for list=backlinks, list=embeddedin and list=imageusage.
|
||||
* (bug 32383) Allow descending order for list=langbacklinks.
|
||||
* API meta=siteinfo can now return the list of known variable IDs.
|
||||
* (bug 35980) list=deletedrevs now honors drdir correctly in "all" mode (mode #3).
|
||||
* (bug 29290) API avoids mangling fields in continuation parameters
|
||||
* (bug 36987) API avoids mangling fields in continuation parameters
|
||||
* (bug 30836) siteinfo prop=specialpagealiases will no longer return nonexistent special pages
|
||||
* (bug 38190) Add "required" flag to some token params for hint in api docs.
|
||||
|
||||
=== Languages updated in 1.20 ===
|
||||
|
||||
|
|
@ -153,6 +207,7 @@ MediaWiki supports over 350 languages. Many localisations are updated
|
|||
regularly. Below only new and removed languages are listed, as well as
|
||||
changes to languages because of Bugzilla reports.
|
||||
|
||||
* Emilian (egl) added.
|
||||
* Tornedalen Finnish (fit) added.
|
||||
* Mizo (lus) added.
|
||||
* Santali (sat) added.
|
||||
|
|
|
|||
2
UPGRADE
2
UPGRADE
|
|
@ -76,7 +76,7 @@ behaviour of MediaWiki.
|
|||
|
||||
Extensions usually need to be upgraded at the same time as the MediaWiki core.
|
||||
|
||||
In MediaWiki 1.14 some extensions are migrated into the core. Please see the
|
||||
In MediaWiki 1.14 some extensions were migrated into the core. Please see the
|
||||
HISTORY section "Migrated extensions" and disable these extensions in your
|
||||
LocalSettings.php
|
||||
|
||||
|
|
|
|||
39
api.php
39
api.php
|
|
@ -62,43 +62,6 @@ if ( !$wgEnableAPI ) {
|
|||
die(1);
|
||||
}
|
||||
|
||||
// Selectively allow cross-site AJAX
|
||||
|
||||
/**
|
||||
* Helper function to convert wildcard string into a regex
|
||||
* '*' => '.*?'
|
||||
* '?' => '.'
|
||||
*
|
||||
* @param $search string
|
||||
* @return string
|
||||
*/
|
||||
function convertWildcard( $search ) {
|
||||
$search = preg_quote( $search, '/' );
|
||||
$search = str_replace(
|
||||
array( '\*', '\?' ),
|
||||
array( '.*?', '.' ),
|
||||
$search
|
||||
);
|
||||
return "/$search/";
|
||||
}
|
||||
|
||||
if ( $wgCrossSiteAJAXdomains && isset( $_SERVER['HTTP_ORIGIN'] ) ) {
|
||||
$exceptions = array_map( 'convertWildcard', $wgCrossSiteAJAXdomainExceptions );
|
||||
$regexes = array_map( 'convertWildcard', $wgCrossSiteAJAXdomains );
|
||||
foreach ( $regexes as $regex ) {
|
||||
if ( preg_match( $regex, $_SERVER['HTTP_ORIGIN'] ) ) {
|
||||
foreach ( $exceptions as $exc ) { // Check against exceptions
|
||||
if ( preg_match( $exc, $_SERVER['HTTP_ORIGIN'] ) ) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
header( "Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}" );
|
||||
header( 'Access-Control-Allow-Credentials: true' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set a dummy $wgTitle, because $wgTitle == null breaks various things
|
||||
// In a perfect world this wouldn't be necessary
|
||||
$wgTitle = Title::makeTitle( NS_MAIN, 'API' );
|
||||
|
|
@ -107,7 +70,7 @@ $wgTitle = Title::makeTitle( NS_MAIN, 'API' );
|
|||
* is some form of an ApiMain, possibly even one that produces an error message,
|
||||
* but we don't care here, as that is handled by the ctor.
|
||||
*/
|
||||
$processor = new ApiMain( $wgRequest, $wgEnableWriteAPI );
|
||||
$processor = new ApiMain( RequestContext::getMain(), $wgEnableWriteAPI );
|
||||
|
||||
// Process data & print results
|
||||
$processor->execute();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.7.xsd
|
||||
|
|
@ -227,7 +228,7 @@
|
|||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
|
|
|
|||
|
|
@ -245,6 +245,10 @@ $block: The block from which the autoblock is coming.
|
|||
'AbortDiffCache': Can be used to cancel the caching of a diff
|
||||
&$diffEngine: DifferenceEngine object
|
||||
|
||||
'AbortEmailNotification': Can be used to cancel email notifications for an edit.
|
||||
$editor: The User who made the change.
|
||||
$title: The Title of the page that was edited.
|
||||
|
||||
'AbortLogin': Return false to cancel account login.
|
||||
$user: the User object being authenticated against
|
||||
$password: the password being submitted, not yet checked for validity
|
||||
|
|
@ -437,6 +441,8 @@ $user: the user (object) deleting the article
|
|||
$reason: the reason (string) the article is being deleted
|
||||
$error: if the deletion was prohibited, the (raw HTML) error message to display
|
||||
(added in 1.13)
|
||||
$status: Status object, modify this to throw an error. Overridden by $error
|
||||
(added in 1.20)
|
||||
|
||||
'ArticleDeleteComplete': after an article is deleted
|
||||
$article: the WikiPage that was deleted
|
||||
|
|
@ -762,10 +768,18 @@ $modeName: the requested content model name
|
|||
&$pager: Pager object for contributions
|
||||
&$queryInfo: The query for the contribs Pager
|
||||
|
||||
'ContribsPager::reallyDoQuery': Called before really executing the query for My Contributions
|
||||
&$data: an array of results of all contribs queries
|
||||
$pager: The ContribsPager object hooked into
|
||||
$offset: Index offset, inclusive
|
||||
$limit: Exact query limit
|
||||
$descending: Query direction, false for ascending, true for descending
|
||||
|
||||
'ContributionsLineEnding': Called before a contributions HTML line is finished
|
||||
$page: SpecialPage object for contributions
|
||||
$ret: the HTML line
|
||||
&$ret: the HTML line
|
||||
$row: the DB row for this line
|
||||
&$classes: the classes to add to the surrounding <li>
|
||||
|
||||
'ContributionsToolLinks': Change tool links above Special:Contributions
|
||||
$id: User identifier
|
||||
|
|
@ -1201,8 +1215,16 @@ $prefix: interwiki prefix we are looking for.
|
|||
&$iwData: output array describing the interwiki with keys iw_url, iw_local,
|
||||
iw_trans and optionally iw_api and iw_wikiid.
|
||||
|
||||
'InternalParseBeforeSanitize': during Parser's internalParse method just before the
|
||||
parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/
|
||||
onlyinclude and other processings. Ideal for syntax-extensions after template/parser
|
||||
function execution which respect nowiki and HTML-comments.
|
||||
&$parser: Parser object
|
||||
&$text: string containing partially parsed text
|
||||
&$stripState: Parser's internal StripState object
|
||||
|
||||
'InternalParseBeforeLinks': during Parser's internalParse method before links
|
||||
but after noinclude/includeonly/onlyinclude and other processing.
|
||||
but after nowiki/noinclude/includeonly/onlyinclude and other processings.
|
||||
&$parser: Parser object
|
||||
&$text: string containing partially parsed text
|
||||
&$stripState: Parser's internal StripState object
|
||||
|
|
@ -1542,6 +1564,12 @@ A parser extension which depends on user options should install
|
|||
this hook and append its values to the key.
|
||||
$hash: reference to a hash key string which can be modified
|
||||
|
||||
'ParserAfterParse': Called from Parser::parse() just after the call to
|
||||
Parser::internalParse() returns
|
||||
$parser: parser object
|
||||
$text: text being parsed
|
||||
$stripState: stripState used (object)
|
||||
|
||||
'ParserAfterStrip': Same as ParserBeforeStrip
|
||||
|
||||
'ParserAfterTidy': Called after Parser::tidy() in Parser::parse()
|
||||
|
|
@ -1680,6 +1708,11 @@ $out: OutputPage object
|
|||
'RecentChange_save': called at the end of RecentChange::save()
|
||||
$recentChange: RecentChange object
|
||||
|
||||
'RedirectSpecialArticleRedirectParams': lets you alter the set of
|
||||
parameter names such as "oldid" that are preserved when using
|
||||
redirecting special pages such as Special:MyPage and Special:MyTalk.
|
||||
&$redirectParams: An array of parameters preserved by redirecting special pages.
|
||||
|
||||
'RequestContextCreateSkin': Called when RequestContext::getSkin creates a skin instance.
|
||||
Can be used by an extension override what skin is used in certain contexts.
|
||||
IContextSource $context: The RequestContext the skin is being created for.
|
||||
|
|
@ -1911,6 +1944,14 @@ Each key maps to an associative array with a 'msg' (message key) and a 'default'
|
|||
hook to remove a core special page
|
||||
$list: list (array) of core special pages
|
||||
|
||||
'SpecialPageAfterExecute': called after SpecialPage::execute
|
||||
$special: the SpecialPage object
|
||||
$subPage: the subpage string or null if no subpage was specified
|
||||
|
||||
'SpecialPageBeforeExecute': called before SpecialPage::execute
|
||||
$special: the SpecialPage object
|
||||
$subPage: the subpage string or null if no subpage was specified
|
||||
|
||||
'SpecialPasswordResetOnSubmit': when executing a form submission on Special:PasswordReset
|
||||
$users: array of User objects
|
||||
$data: array of data submitted by the user
|
||||
|
|
|
|||
|
|
@ -1448,10 +1448,12 @@ class Article extends Page {
|
|||
|
||||
$this->doDelete( $reason, $suppress );
|
||||
|
||||
if ( $request->getCheck( 'wpWatch' ) && $user->isLoggedIn() ) {
|
||||
WatchAction::doWatch( $title, $user );
|
||||
} elseif ( $title->userIsWatching() ) {
|
||||
WatchAction::doUnwatch( $title, $user );
|
||||
if ( $user->isLoggedIn() && $request->getCheck( 'wpWatch' ) != $user->isWatched( $title ) ) {
|
||||
if ( $request->getCheck( 'wpWatch' ) ) {
|
||||
WatchAction::doWatch( $title, $user );
|
||||
} else {
|
||||
WatchAction::doUnwatch( $title, $user );
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -1521,7 +1523,7 @@ class Article extends Page {
|
|||
} else {
|
||||
$suppress = '';
|
||||
}
|
||||
$checkWatch = $user->getBoolOption( 'watchdeletion' ) || $this->getTitle()->userIsWatching();
|
||||
$checkWatch = $user->getBoolOption( 'watchdeletion' ) || $user->isWatched( $this->getTitle() );
|
||||
|
||||
$form = Xml::openElement( 'form', array( 'method' => 'post',
|
||||
'action' => $this->getTitle()->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
|
||||
|
|
@ -1605,7 +1607,8 @@ class Article extends Page {
|
|||
public function doDelete( $reason, $suppress = false ) {
|
||||
$error = '';
|
||||
$outputPage = $this->getContext()->getOutput();
|
||||
if ( $this->mPage->doDeleteArticle( $reason, $suppress, 0, true, $error ) ) {
|
||||
$status = $this->mPage->doDeleteArticleReal( $reason, $suppress, 0, true, $error );
|
||||
if ( $status->isGood() ) {
|
||||
$deleted = $this->getTitle()->getPrefixedText();
|
||||
|
||||
$outputPage->setPageTitle( wfMessage( 'actioncomplete' ) );
|
||||
|
|
@ -1618,8 +1621,9 @@ class Article extends Page {
|
|||
} else {
|
||||
$outputPage->setPageTitle( wfMessage( 'cannotdelete-title', $this->getTitle()->getPrefixedText() ) );
|
||||
if ( $error == '' ) {
|
||||
$errors = $status->getErrorsArray();
|
||||
$outputPage->wrapWikiMsg( "<div class=\"error mw-error-cannotdelete\">\n$1\n</div>",
|
||||
array( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) )
|
||||
$errors[0]
|
||||
);
|
||||
$outputPage->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
|
||||
|
||||
|
|
|
|||
|
|
@ -433,6 +433,7 @@ $wgAutoloadLocalClasses = array(
|
|||
'LinkCache' => 'includes/cache/LinkCache.php',
|
||||
'MessageCache' => 'includes/cache/MessageCache.php',
|
||||
'ObjectFileCache' => 'includes/cache/ObjectFileCache.php',
|
||||
'ProcessCacheLRU' => 'includes/cache/ProcessCacheLRU.php',
|
||||
'ResourceFileCache' => 'includes/cache/ResourceFileCache.php',
|
||||
'SquidUpdate' => 'includes/cache/SquidUpdate.php',
|
||||
'TitleDependency' => 'includes/cache/CacheDependency.php',
|
||||
|
|
@ -449,6 +450,9 @@ $wgAutoloadLocalClasses = array(
|
|||
'IContextSource' => 'includes/context/IContextSource.php',
|
||||
'RequestContext' => 'includes/context/RequestContext.php',
|
||||
|
||||
# includes/dao
|
||||
'IDBAccessObject' => 'includes/dao/IDBAccessObject.php',
|
||||
|
||||
# includes/db
|
||||
'Blob' => 'includes/db/DatabaseUtility.php',
|
||||
'ChronologyProtector' => 'includes/db/LBFactory.php',
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ interface ICacheHelper {
|
|||
function saveCache();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
|
@ -319,7 +320,8 @@ class CacheHelper implements ICacheHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class ChangeTags {
|
|||
*
|
||||
*/
|
||||
static function formatSummaryRow( $tags, $page ) {
|
||||
global $wgLang;
|
||||
|
||||
if( !$tags )
|
||||
return array( '', array() );
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ class ChangeTags {
|
|||
);
|
||||
$classes[] = Sanitizer::escapeClass( "mw-tag-$tag" );
|
||||
}
|
||||
$markers = '(' . implode( ', ', $displayTags ) . ')';
|
||||
$markers = wfMessage( 'parentheses' )->rawParams( $wgLang->commaList( $displayTags ) )->text();
|
||||
$markers = Xml::tags( 'span', array( 'class' => 'mw-tag-markers' ), $markers );
|
||||
|
||||
return array( $markers, $classes );
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class ChangesList extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the list to use a <li class="watchlist-(namespace)-(page)"> tag
|
||||
* Sets the list to use a "<li class='watchlist-(namespace)-(page)'>" tag
|
||||
* @param $value Boolean
|
||||
*/
|
||||
public function setWatchlistDivs( $value = true ) {
|
||||
|
|
@ -123,7 +123,7 @@ class ChangesList extends ContextSource {
|
|||
if( !isset( $this->message ) ) {
|
||||
foreach ( explode( ' ', 'cur diff hist last blocklink history ' .
|
||||
'semicolon-separator pipe-separator' ) as $msg ) {
|
||||
$this->message[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) );
|
||||
$this->message[$msg] = $this->msg( $msg )->escaped();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ class ChangesList extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Provide the <abbr> element appropriate to a given abbreviated flag,
|
||||
* Provide the "<abbr>" element appropriate to a given abbreviated flag,
|
||||
* namely the flag indicating a new page, a minor edit, a bot edit, or an
|
||||
* unpatrolled edit. By default in English it will contain "N", "m", "b",
|
||||
* "!" respectively, plus it will have an appropriate title and class.
|
||||
|
|
@ -192,6 +192,7 @@ class ChangesList extends ContextSource {
|
|||
$this->rcCacheIndex = 0;
|
||||
$this->lastdate = '';
|
||||
$this->rclistOpen = false;
|
||||
$this->getOutput()->addModuleStyles( 'mediawiki.special.changeslist' );
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -199,22 +200,31 @@ class ChangesList extends ContextSource {
|
|||
* Show formatted char difference
|
||||
* @param $old Integer: bytes
|
||||
* @param $new Integer: bytes
|
||||
* @param $context IContextSource context to use
|
||||
* @return String
|
||||
*/
|
||||
public static function showCharacterDifference( $old, $new ) {
|
||||
global $wgRCChangedSizeThreshold, $wgLang, $wgMiserMode;
|
||||
$szdiff = $new - $old;
|
||||
public static function showCharacterDifference( $old, $new, IContextSource $context = null ) {
|
||||
global $wgRCChangedSizeThreshold, $wgMiserMode;
|
||||
|
||||
$code = $wgLang->getCode();
|
||||
static $fastCharDiff = array();
|
||||
if ( !isset($fastCharDiff[$code]) ) {
|
||||
$fastCharDiff[$code] = $wgMiserMode || wfMsgNoTrans( 'rc-change-size' ) === '$1';
|
||||
if ( !$context ) {
|
||||
$context = RequestContext::getMain();
|
||||
}
|
||||
|
||||
$formattedSize = $wgLang->formatNum($szdiff);
|
||||
$new = (int)$new;
|
||||
$old = (int)$old;
|
||||
$szdiff = $new - $old;
|
||||
|
||||
$lang = $context->getLanguage();
|
||||
$code = $lang->getCode();
|
||||
static $fastCharDiff = array();
|
||||
if ( !isset($fastCharDiff[$code]) ) {
|
||||
$fastCharDiff[$code] = $wgMiserMode || $context->msg( 'rc-change-size' )->plain() === '$1';
|
||||
}
|
||||
|
||||
$formattedSize = $lang->formatNum( $szdiff );
|
||||
|
||||
if ( !$fastCharDiff[$code] ) {
|
||||
$formattedSize = wfMsgExt( 'rc-change-size', array( 'parsemag' ), $formattedSize );
|
||||
$formattedSize = $context->msg( 'rc-change-size', $formattedSize )->text();
|
||||
}
|
||||
|
||||
if( abs( $szdiff ) > abs( $wgRCChangedSizeThreshold ) ) {
|
||||
|
|
@ -234,11 +244,34 @@ class ChangesList extends ContextSource {
|
|||
$formattedSizeClass = 'mw-plusminus-neg';
|
||||
}
|
||||
|
||||
$formattedTotalSize = wfMsgExt( 'rc-change-size-new', 'parsemag', $wgLang->formatNum( $new ) );
|
||||
$formattedTotalSize = $context->msg( 'rc-change-size-new' )->numParams( $new )->text();
|
||||
|
||||
return Html::element( $tag,
|
||||
array( 'dir' => 'ltr', 'class' => $formattedSizeClass, 'title' => $formattedTotalSize ),
|
||||
wfMessage( 'parentheses', $formattedSize )->plain() ) . $wgLang->getDirMark();
|
||||
$context->msg( 'parentheses', $formattedSize )->plain() ) . $lang->getDirMark();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the character difference of one or several changes.
|
||||
*
|
||||
* @param $old RecentChange
|
||||
* @param $new RecentChange last change to use, if not provided, $old will be used
|
||||
* @return string HTML fragment
|
||||
*/
|
||||
public function formatCharacterDifference( RecentChange $old, RecentChange $new = null ) {
|
||||
$oldlen = $old->mAttribs['rc_old_len'];
|
||||
|
||||
if ( $new ) {
|
||||
$newlen = $new->mAttribs['rc_new_len'];
|
||||
} else {
|
||||
$newlen = $old->mAttribs['rc_new_len'];
|
||||
}
|
||||
|
||||
if( $oldlen === null || $newlen === null ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return self::showCharacterDifference( $oldlen, $newlen, $this->getContext() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -255,7 +288,7 @@ class ChangesList extends ContextSource {
|
|||
|
||||
public function insertDateHeader( &$s, $rc_timestamp ) {
|
||||
# Make date header if necessary
|
||||
$date = $this->getLanguage()->date( $rc_timestamp, true, true );
|
||||
$date = $this->getLanguage()->userDate( $rc_timestamp, $this->getUser() );
|
||||
if( $date != $this->lastdate ) {
|
||||
if( $this->lastdate != '' ) {
|
||||
$s .= "</ul>\n";
|
||||
|
|
@ -339,10 +372,8 @@ class ChangesList extends ContextSource {
|
|||
if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
|
||||
$articlelink = '<span class="history-deleted">' . $articlelink . '</span>';
|
||||
}
|
||||
# Bolden pages watched by this user
|
||||
if( $watched ) {
|
||||
$articlelink = "<strong class=\"mw-watched\">{$articlelink}</strong>";
|
||||
}
|
||||
# To allow for boldening pages watched by this user
|
||||
$articlelink = "<span class=\"mw-title\">{$articlelink}</span>";
|
||||
# RTL/LTR marker
|
||||
$articlelink .= $this->getLanguage()->getDirMark();
|
||||
|
||||
|
|
@ -358,7 +389,7 @@ class ChangesList extends ContextSource {
|
|||
*/
|
||||
public function insertTimestamp( &$s, $rc ) {
|
||||
$s .= $this->message['semicolon-separator'] .
|
||||
$this->getLanguage()->time( $rc->mAttribs['rc_timestamp'], true, true ) . ' . . ';
|
||||
$this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() ) . ' . . ';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -369,7 +400,7 @@ class ChangesList extends ContextSource {
|
|||
*/
|
||||
public function insertUserRelatedLinks( &$s, &$rc ) {
|
||||
if( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
|
||||
$s .= ' <span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
|
||||
$s .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
|
||||
} else {
|
||||
$s .= $this->getLanguage()->getDirMark() . Linker::userLink( $rc->mAttribs['rc_user'],
|
||||
$rc->mAttribs['rc_user_text'] );
|
||||
|
|
@ -385,12 +416,13 @@ class ChangesList extends ContextSource {
|
|||
*/
|
||||
public function insertLogEntry( $rc ) {
|
||||
$formatter = LogFormatter::newFromRow( $rc->mAttribs );
|
||||
$formatter->setContext( $this->getContext() );
|
||||
$formatter->setShowUserToolLinks( true );
|
||||
$mark = $this->getLanguage()->getDirMark();
|
||||
return $formatter->getActionText() . " $mark" . $formatter->getComment();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Insert a formatted comment
|
||||
* @param $rc RecentChange
|
||||
* @return string
|
||||
|
|
@ -398,7 +430,7 @@ class ChangesList extends ContextSource {
|
|||
public function insertComment( $rc ) {
|
||||
if( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) {
|
||||
if( $this->isDeleted( $rc, Revision::DELETED_COMMENT ) ) {
|
||||
return ' <span class="history-deleted">' . wfMsgHtml( 'rev-deleted-comment' ) . '</span>';
|
||||
return ' <span class="history-deleted">' . $this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
|
||||
} else {
|
||||
return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
|
||||
}
|
||||
|
|
@ -422,8 +454,7 @@ class ChangesList extends ContextSource {
|
|||
static $cache = array();
|
||||
if( $count > 0 ) {
|
||||
if( !isset( $cache[$count] ) ) {
|
||||
$cache[$count] = wfMsgExt( 'number_of_watching_users_RCview',
|
||||
array('parsemag', 'escape' ), $this->getLanguage()->formatNum( $count ) );
|
||||
$cache[$count] = $this->msg( 'number_of_watching_users_RCview' )->numParams( $count )->escaped();
|
||||
}
|
||||
return $cache[$count];
|
||||
} else {
|
||||
|
|
@ -533,7 +564,9 @@ class OldChangesList extends ChangesList {
|
|||
/**
|
||||
* Format a line using the old system (aka without any javascript).
|
||||
*
|
||||
* @param $rc RecentChange
|
||||
* @param $rc RecentChange, passed by reference
|
||||
* @param $watched Bool (default false)
|
||||
* @param $linenumber Int (default null)
|
||||
* @return string
|
||||
*/
|
||||
public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
|
||||
|
|
@ -558,6 +591,10 @@ class OldChangesList extends ChangesList {
|
|||
}
|
||||
}
|
||||
|
||||
// Indicate watched status on the line to allow for more
|
||||
// comprehensive styling.
|
||||
$classes[] = $watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
|
||||
|
||||
// Moved pages (very very old, not supported anymore)
|
||||
if( $rc->mAttribs['rc_type'] == RC_MOVE || $rc->mAttribs['rc_type'] == RC_MOVE_OVER_REDIRECT ) {
|
||||
// Log entries
|
||||
|
|
@ -588,9 +625,9 @@ class OldChangesList extends ChangesList {
|
|||
# Edit/log timestamp
|
||||
$this->insertTimestamp( $s, $rc );
|
||||
# Bytes added or removed
|
||||
if( $wgRCShowChangedSize ) {
|
||||
$cd = $rc->getCharacterDifference();
|
||||
if( $cd != '' ) {
|
||||
if ( $wgRCShowChangedSize ) {
|
||||
$cd = $this->formatCharacterDifference( $rc );
|
||||
if ( $cd !== '' ) {
|
||||
$s .= "$cd . . ";
|
||||
}
|
||||
}
|
||||
|
|
@ -614,8 +651,7 @@ class OldChangesList extends ChangesList {
|
|||
|
||||
# How many users watch this page
|
||||
if( $rc->numberofWatchingusers > 0 ) {
|
||||
$s .= ' ' . wfMsgExt( 'number_of_watching_users_RCview',
|
||||
array( 'parsemag', 'escape' ), $this->getLanguage()->formatNum( $rc->numberofWatchingusers ) );
|
||||
$s .= ' ' . $this->numberofWatchingusers( $rc->numberofWatchingusers );
|
||||
}
|
||||
|
||||
if( $this->watchlist ) {
|
||||
|
|
@ -667,7 +703,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
$curIdEq = array( 'curid' => $rc->mAttribs['rc_cur_id'] );
|
||||
|
||||
# If it's a new day, add the headline and flush the cache
|
||||
$date = $this->getLanguage()->date( $rc->mAttribs['rc_timestamp'], true );
|
||||
$date = $this->getLanguage()->userDate( $rc->mAttribs['rc_timestamp'], $this->getUser() );
|
||||
$ret = '';
|
||||
if( $date != $this->lastdate ) {
|
||||
# Process current cache
|
||||
|
|
@ -715,7 +751,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
$showdifflinks = false;
|
||||
}
|
||||
|
||||
$time = $this->getLanguage()->time( $rc->mAttribs['rc_timestamp'], true, true );
|
||||
$time = $this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() );
|
||||
$rc->watched = $watched;
|
||||
$rc->link = $clink;
|
||||
$rc->timestamp = $time;
|
||||
|
|
@ -764,7 +800,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
|
||||
# Make user links
|
||||
if( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
|
||||
$rc->userlink = ' <span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
|
||||
$rc->userlink = ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
|
||||
} else {
|
||||
$rc->userlink = Linker::userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
|
||||
$rc->usertalklink = Linker::userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
|
||||
|
|
@ -808,14 +844,16 @@ class EnhancedChangesList extends ChangesList {
|
|||
wfProfileIn( __METHOD__ );
|
||||
|
||||
# Add the namespace and title of the block as part of the class
|
||||
$classes = array( 'mw-collapsible', 'mw-collapsed', 'mw-enhanced-rc' );
|
||||
if ( $block[0]->mAttribs['rc_log_type'] ) {
|
||||
# Log entry
|
||||
$classes = 'mw-collapsible mw-collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-'
|
||||
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-'
|
||||
. $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
|
||||
} else {
|
||||
$classes = 'mw-collapsible mw-collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns'
|
||||
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns'
|
||||
. $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
|
||||
}
|
||||
$classes[] = $block[0]->watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
|
||||
$r = Html::openElement( 'table', array( 'class' => $classes ) ) .
|
||||
Html::openElement( 'tr' );
|
||||
|
||||
|
|
@ -875,9 +913,9 @@ class EnhancedChangesList extends ChangesList {
|
|||
}
|
||||
|
||||
$users = ' <span class="changedby">'
|
||||
. $this->getContext()->msg( 'brackets' )->rawParams(
|
||||
. $this->msg( 'brackets' )->rawParams(
|
||||
implode( $this->message['semicolon-separator'], $users )
|
||||
)->plain() . '</span>';
|
||||
)->escaped() . '</span>';
|
||||
|
||||
$tl = '<span class="mw-collapsible-toggle mw-enhancedchanges-arrow"></span>';
|
||||
$r .= "<td>$tl</td>";
|
||||
|
|
@ -895,7 +933,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
|
||||
# Article link
|
||||
if( $namehidden ) {
|
||||
$r .= ' <span class="history-deleted">' . wfMsgHtml( 'rev-deleted-event' ) . '</span>';
|
||||
$r .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-event' )->escaped() . '</span>';
|
||||
} elseif( $allLogs ) {
|
||||
$r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
|
||||
} else {
|
||||
|
|
@ -909,7 +947,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
$n = count($block);
|
||||
static $nchanges = array();
|
||||
if ( !isset( $nchanges[$n] ) ) {
|
||||
$nchanges[$n] = wfMsgExt( 'nchanges', array( 'parsemag', 'escape' ), $this->getLanguage()->formatNum( $n ) );
|
||||
$nchanges[$n] = $this->msg( 'nchanges' )->numParams( $n )->escaped();
|
||||
}
|
||||
# Total change link
|
||||
$r .= ' ';
|
||||
|
|
@ -970,8 +1008,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
$first--;
|
||||
}
|
||||
# Get net change
|
||||
$chardiff = $rcObj->getCharacterDifference( $block[$first]->mAttribs['rc_old_len'],
|
||||
$block[$last]->mAttribs['rc_new_len'] );
|
||||
$chardiff = $this->formatCharacterDifference( $block[$first], $block[$last] );
|
||||
|
||||
if( $chardiff == '' ) {
|
||||
$r .= ' ';
|
||||
|
|
@ -1032,8 +1069,11 @@ class EnhancedChangesList extends ChangesList {
|
|||
$r .= ' . . ';
|
||||
|
||||
# Character diff
|
||||
if( $wgRCShowChangedSize && $rcObj->getCharacterDifference() ) {
|
||||
$r .= $rcObj->getCharacterDifference() . ' . . ' ;
|
||||
if ( $wgRCShowChangedSize ) {
|
||||
$cd = $this->formatCharacterDifference( $rcObj );
|
||||
if ( $cd !== '' ) {
|
||||
$r .= "$cd . . ";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $rcObj->mAttribs['rc_type'] == RC_LOG ) {
|
||||
|
|
@ -1066,7 +1106,7 @@ class EnhancedChangesList extends ChangesList {
|
|||
* @param $dir String: one of '', 'd', 'l', 'r'
|
||||
* @param $alt String: text
|
||||
* @param $title String: text
|
||||
* @return String: HTML <img> tag
|
||||
* @return String: HTML "<img>" tag
|
||||
*/
|
||||
protected function arrow( $dir, $alt='', $title='' ) {
|
||||
global $wgStylePath;
|
||||
|
|
@ -1079,26 +1119,25 @@ class EnhancedChangesList extends ChangesList {
|
|||
/**
|
||||
* Generate HTML for a right- or left-facing arrow,
|
||||
* depending on language direction.
|
||||
* @return String: HTML <img> tag
|
||||
* @return String: HTML "<img>" tag
|
||||
*/
|
||||
protected function sideArrow() {
|
||||
global $wgLang;
|
||||
$dir = $wgLang->isRTL() ? 'l' : 'r';
|
||||
return $this->arrow( $dir, '+', wfMsg( 'rc-enhanced-expand' ) );
|
||||
$dir = $this->getLanguage()->isRTL() ? 'l' : 'r';
|
||||
return $this->arrow( $dir, '+', $this->msg( 'rc-enhanced-expand' )->text() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML for a down-facing arrow
|
||||
* depending on language direction.
|
||||
* @return String: HTML <img> tag
|
||||
* @return String: HTML "<img>" tag
|
||||
*/
|
||||
protected function downArrow() {
|
||||
return $this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) );
|
||||
return $this->arrow( 'd', '-', $this->msg( 'rc-enhanced-hide' )->text() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML for a spacer image
|
||||
* @return String: HTML <img> tag
|
||||
* @return String: HTML "<img>" tag
|
||||
*/
|
||||
protected function spacerArrow() {
|
||||
return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
|
||||
|
|
@ -1118,14 +1157,16 @@ class EnhancedChangesList extends ChangesList {
|
|||
|
||||
$type = $rcObj->mAttribs['rc_type'];
|
||||
$logType = $rcObj->mAttribs['rc_log_type'];
|
||||
$classes = array( 'mw-enhanced-rc' );
|
||||
if( $logType ) {
|
||||
# Log entry
|
||||
$classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-'
|
||||
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-'
|
||||
. $logType . '-' . $rcObj->mAttribs['rc_title'] );
|
||||
} else {
|
||||
$classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' .
|
||||
$classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' .
|
||||
$rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
|
||||
}
|
||||
$classes[] = $rcObj->watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
|
||||
$r = Html::openElement( 'table', array( 'class' => $classes ) ) .
|
||||
Html::openElement( 'tr' );
|
||||
|
||||
|
|
@ -1162,20 +1203,22 @@ class EnhancedChangesList extends ChangesList {
|
|||
}
|
||||
$r .= ' . . ';
|
||||
# Character diff
|
||||
if( $wgRCShowChangedSize && ($cd = $rcObj->getCharacterDifference()) ) {
|
||||
$r .= "$cd . . ";
|
||||
if ( $wgRCShowChangedSize ) {
|
||||
$cd = $this->formatCharacterDifference( $rcObj );
|
||||
if ( $cd !== '' ) {
|
||||
$r .= "$cd . . ";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $type == RC_LOG ) {
|
||||
$r .= $this->insertLogEntry( $rcObj );
|
||||
} else {
|
||||
} else {
|
||||
$r .= ' '.$rcObj->userlink . $rcObj->usertalklink;
|
||||
$r .= $this->insertComment( $rcObj );
|
||||
$this->insertRollback( $r, $rcObj );
|
||||
}
|
||||
|
||||
# Tags
|
||||
$classes = explode( ' ', $classes );
|
||||
$this->insertTags( $r, $rcObj, $classes );
|
||||
# Show how many people are watching this if enabled
|
||||
$r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers);
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ class Cookie {
|
|||
* A better method might be to use a blacklist like
|
||||
* http://publicsuffix.org/
|
||||
*
|
||||
* @fixme fails to detect 3-letter top-level domains
|
||||
* @fixme fails to detect 2-letter top-level domains for single-domain use (probably not a big problem in practice, but there are test cases)
|
||||
* @todo fixme fails to detect 3-letter top-level domains
|
||||
* @todo fixme fails to detect 2-letter top-level domains for single-domain use (probably not a big problem in practice, but there are test cases)
|
||||
*
|
||||
* @param $domain String: the domain to validate
|
||||
* @param $originDomain String: (optional) the domain the cookie originates from
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@
|
|||
/**
|
||||
* Abstract base class for update jobs that do something with some secondary
|
||||
* data extracted from article.
|
||||
*
|
||||
* @note: subclasses should NOT start or commit transactions in their doUpdate() method,
|
||||
* a transaction will automatically be wrapped around the update. If need be,
|
||||
* subclasses can override the beginTransaction() and commitTransaction() methods.
|
||||
*/
|
||||
abstract class DataUpdate implements DeferrableUpdate {
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -88,10 +88,19 @@ class DeferredUpdates {
|
|||
}
|
||||
|
||||
foreach ( $updates as $update ) {
|
||||
$update->doUpdate();
|
||||
try {
|
||||
$update->doUpdate();
|
||||
|
||||
if ( $doCommit && $dbw->trxLevel() ) {
|
||||
$dbw->commit( __METHOD__ );
|
||||
if ( $doCommit && $dbw->trxLevel() ) {
|
||||
$dbw->commit( __METHOD__ );
|
||||
}
|
||||
} catch ( MWException $e ) {
|
||||
// We don't want exceptions thrown during deferred updates to
|
||||
// be reported to the user since the output is already sent.
|
||||
// Instead we just log them.
|
||||
if ( !$e instanceof ErrorPageError ) {
|
||||
wfDebugLog( 'exception', $e->getLogMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Constants
|
||||
* @defgroup Constants MediaWiki constants
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -603,8 +603,8 @@ class EditPage {
|
|||
wfProfileOut( get_class( $this ) . "::importContentFormData" );
|
||||
}
|
||||
|
||||
# Truncate for whole multibyte characters. +5 bytes for ellipsis
|
||||
$this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 250 );
|
||||
# Truncate for whole multibyte characters
|
||||
$this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 255 );
|
||||
|
||||
# If the summary consists of a heading, e.g. '==Foobar==', extract the title from the
|
||||
# header syntax, e.g. 'Foobar'. This is mainly an issue when we are using wpSummary for
|
||||
|
|
@ -616,7 +616,7 @@ class EditPage {
|
|||
# currently doing double duty as both edit summary and section title. Right now this
|
||||
# is just to allow API edits to work around this limitation, but this should be
|
||||
# incorporated into the actual edit form when EditPage is rewritten (Bugs 18654, 26312).
|
||||
$this->sectiontitle = $wgLang->truncate( $request->getText( 'wpSectionTitle' ), 250 );
|
||||
$this->sectiontitle = $wgLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
|
||||
$this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
|
||||
|
||||
$this->edittime = $request->getVal( 'wpEdittime' );
|
||||
|
|
@ -778,7 +778,7 @@ class EditPage {
|
|||
} elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
|
||||
# Watch creations
|
||||
$this->watchthis = true;
|
||||
} elseif ( $this->mTitle->userIsWatching() ) {
|
||||
} elseif ( $wgUser->isWatched( $this->mTitle ) ) {
|
||||
# Already watched
|
||||
$this->watchthis = true;
|
||||
}
|
||||
|
|
@ -1306,9 +1306,9 @@ class EditPage {
|
|||
|
||||
wfProfileOut( __METHOD__ . '-checks' );
|
||||
|
||||
// Use SELECT FOR UPDATE here to avoid transaction collision in
|
||||
// WikiPage::updateRevisionOn() and ending in the self::AS_END case.
|
||||
$this->mArticle->loadPageData( 'forupdate' );
|
||||
# Load the page data from the master. If anything changes in the meantime,
|
||||
# we detect it by using page_latest like a token in a 1 try compare-and-swap.
|
||||
$this->mArticle->loadPageData( 'fromdbmaster' );
|
||||
$new = !$this->mArticle->exists();
|
||||
|
||||
try {
|
||||
|
|
@ -1594,7 +1594,7 @@ class EditPage {
|
|||
*/
|
||||
protected function commitWatch() {
|
||||
global $wgUser;
|
||||
if ( $this->watchthis xor $this->mTitle->userIsWatching() ) {
|
||||
if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin( __METHOD__ );
|
||||
if ( $this->watchthis ) {
|
||||
|
|
@ -1639,7 +1639,7 @@ class EditPage {
|
|||
* @private
|
||||
* @todo document
|
||||
*
|
||||
* @parma $editText string
|
||||
* @param $editText string
|
||||
*
|
||||
* @return bool
|
||||
* @deprecated since 1.WD, use mergeChangesIntoContent() instead
|
||||
|
|
@ -1734,7 +1734,7 @@ class EditPage {
|
|||
/**
|
||||
* Check given input text against $wgSpamRegex, and return the text of the first match.
|
||||
*
|
||||
* @parma $text string
|
||||
* @param $text string
|
||||
*
|
||||
* @return string|bool matching string or false
|
||||
*/
|
||||
|
|
@ -1990,6 +1990,10 @@ class EditPage {
|
|||
$wgOut->addHTML( Html::hidden( 'wpIgnoreBlankSummary', true ) );
|
||||
}
|
||||
|
||||
if ( $this->undidRev ) {
|
||||
$wgOut->addHTML( Html::hidden( 'wpUndidRevision', $this->undidRev ) );
|
||||
}
|
||||
|
||||
if ( $this->hasPresetSummary ) {
|
||||
// If a summary has been preset using &summary= we dont want to prompt for
|
||||
// a different summary. Only prompt for a summary if the summary is blanked.
|
||||
|
|
@ -2267,7 +2271,7 @@ class EditPage {
|
|||
* @return array An array in the format array( $label, $input )
|
||||
*/
|
||||
function getSummaryInput( $summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null ) {
|
||||
// Note: the maxlength is overriden in JS to 250 and to make it use UTF-8 bytes, not characters.
|
||||
// Note: the maxlength is overriden in JS to 255 and to make it use UTF-8 bytes, not characters.
|
||||
$inputAttrs = ( is_array( $inputAttrs ) ? $inputAttrs : array() ) + array(
|
||||
'id' => 'wpSummary',
|
||||
'maxlength' => '200',
|
||||
|
|
@ -2591,7 +2595,16 @@ HTML
|
|||
'</div>' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the copyright warning
|
||||
*
|
||||
* Renamed to getCopyrightWarning(), old name kept around for backwards compatibility
|
||||
*/
|
||||
protected function getCopywarn() {
|
||||
return self::getCopyrightWarning( $this->mTitle );
|
||||
}
|
||||
|
||||
public static function getCopyrightWarning( $title ) {
|
||||
global $wgRightsText;
|
||||
if ( $wgRightsText ) {
|
||||
$copywarnMsg = array( 'copyrightwarning',
|
||||
|
|
@ -2602,7 +2615,7 @@ HTML
|
|||
'[[' . wfMsgForContent( 'copyrightpage' ) . ']]' );
|
||||
}
|
||||
// Allow for site and per-namespace customization of contribution/copyright notice.
|
||||
wfRunHooks( 'EditPageCopyrightWarning', array( $this->mTitle, &$copywarnMsg ) );
|
||||
wfRunHooks( 'EditPageCopyrightWarning', array( $title, &$copywarnMsg ) );
|
||||
|
||||
return "<div id=\"editpage-copywarn\">\n" .
|
||||
call_user_func_array( "wfMsgNoTrans", $copywarnMsg ) . "\n</div>";
|
||||
|
|
@ -3181,8 +3194,8 @@ HTML
|
|||
* failure, etc).
|
||||
*
|
||||
* @todo This doesn't include category or interlanguage links.
|
||||
* Would need to enhance it a bit, <s>maybe wrap them in XML
|
||||
* or something...</s> that might also require more skin
|
||||
* Would need to enhance it a bit, "<s>maybe wrap them in XML
|
||||
* or something...</s>" that might also require more skin
|
||||
* initialization, so check whether that's a problem.
|
||||
*/
|
||||
function livePreview() {
|
||||
|
|
@ -3325,12 +3338,14 @@ HTML
|
|||
* @private
|
||||
*/
|
||||
function checkUnicodeCompliantBrowser() {
|
||||
global $wgBrowserBlackList;
|
||||
if ( empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
|
||||
global $wgBrowserBlackList, $wgRequest;
|
||||
|
||||
$currentbrowser = $wgRequest->getHeader( 'User-Agent' );
|
||||
if ( $currentbrowser === false ) {
|
||||
// No User-Agent header sent? Trust it by default...
|
||||
return true;
|
||||
}
|
||||
$currentbrowser = $_SERVER["HTTP_USER_AGENT"];
|
||||
|
||||
foreach ( $wgBrowserBlackList as $browser ) {
|
||||
if ( preg_match( $browser, $currentbrowser ) ) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ class MWException extends Exception {
|
|||
var $logId;
|
||||
|
||||
/**
|
||||
* Should the exception use $wgOut to output the error ?
|
||||
* Should the exception use $wgOut to output the error?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function useOutputPage() {
|
||||
|
|
@ -44,7 +45,8 @@ class MWException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* Can the extension use wfMsg() to get i18n messages ?
|
||||
* Can the extension use wfMsg() to get i18n messages?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function useMessageCache() {
|
||||
|
|
@ -62,9 +64,9 @@ class MWException extends Exception {
|
|||
/**
|
||||
* Run hook to allow extensions to modify the text of the exception
|
||||
*
|
||||
* @param $name String: class name of the exception
|
||||
* @param $args Array: arguments to pass to the callback functions
|
||||
* @return Mixed: string to output or null if any hook has been called
|
||||
* @param $name string: class name of the exception
|
||||
* @param $args array: arguments to pass to the callback functions
|
||||
* @return string|null string to output or null if any hook has been called
|
||||
*/
|
||||
function runHooks( $name, $args = array() ) {
|
||||
global $wgExceptionHooks;
|
||||
|
|
@ -97,11 +99,11 @@ class MWException extends Exception {
|
|||
/**
|
||||
* Get a message from i18n
|
||||
*
|
||||
* @param $key String: message name
|
||||
* @param $fallback String: default message if the message cache can't be
|
||||
* @param $key string: message name
|
||||
* @param $fallback string: default message if the message cache can't be
|
||||
* called by the exception
|
||||
* The function also has other parameters that are arguments for the message
|
||||
* @return String message with arguments replaced
|
||||
* @return string message with arguments replaced
|
||||
*/
|
||||
function msg( $key, $fallback /*[, params...] */ ) {
|
||||
$args = array_slice( func_get_args(), 2 );
|
||||
|
|
@ -118,7 +120,7 @@ class MWException extends Exception {
|
|||
* backtrace to the error, otherwise show a message to ask to set it to true
|
||||
* to show that information.
|
||||
*
|
||||
* @return String html to output
|
||||
* @return string html to output
|
||||
*/
|
||||
function getHTML() {
|
||||
global $wgShowExceptionDetails;
|
||||
|
|
@ -128,10 +130,10 @@ class MWException extends Exception {
|
|||
'</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) .
|
||||
"</p>\n";
|
||||
} else {
|
||||
return
|
||||
return
|
||||
"<div class=\"errorbox\">" .
|
||||
'[' . $this->getLogId() . '] ' .
|
||||
gmdate( 'Y-m-d H:i:s' ) .
|
||||
gmdate( 'Y-m-d H:i:s' ) .
|
||||
": Fatal exception of type " . get_class( $this ) . "</div>\n" .
|
||||
"<!-- Set \$wgShowExceptionDetails = true; " .
|
||||
"at the bottom of LocalSettings.php to show detailed " .
|
||||
|
|
@ -140,8 +142,10 @@ class MWException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the text to display when reporting the error on the command line.
|
||||
* If $wgShowExceptionDetails is true, return a text message with a
|
||||
* backtrace to the error.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getText() {
|
||||
|
|
@ -157,13 +161,21 @@ class MWException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return titles of this error page
|
||||
* @return String
|
||||
* Return the title of the page when reporting this error in a HTTP response.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getPageTitle() {
|
||||
return $this->msg( 'internalerror', "Internal error" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random ID for this error.
|
||||
* This allows to link the exception to its correspoding log entry when
|
||||
* $wgShowExceptionDetails is set to false.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getLogId() {
|
||||
if ( $this->logId === null ) {
|
||||
$this->logId = wfRandomString( 8 );
|
||||
|
|
@ -175,7 +187,7 @@ class MWException extends Exception {
|
|||
* Return the requested URL and point to file and line number from which the
|
||||
* exception occured
|
||||
*
|
||||
* @return String
|
||||
* @return string
|
||||
*/
|
||||
function getLogMessage() {
|
||||
global $wgRequest;
|
||||
|
|
@ -197,7 +209,9 @@ class MWException extends Exception {
|
|||
return "[$id] $url Exception from line $line of $file: $message";
|
||||
}
|
||||
|
||||
/** Output the exception report using HTML */
|
||||
/**
|
||||
* Output the exception report using HTML.
|
||||
*/
|
||||
function reportHTML() {
|
||||
global $wgOut;
|
||||
if ( $this->useOutputPage() ) {
|
||||
|
|
@ -213,13 +227,20 @@ class MWException extends Exception {
|
|||
$wgOut->output();
|
||||
} else {
|
||||
header( "Content-Type: text/html; charset=utf-8" );
|
||||
echo "<!doctype html>\n" .
|
||||
'<html><head>' .
|
||||
'<title>' . htmlspecialchars( $this->getPageTitle() ) . '</title>' .
|
||||
"</head><body>\n";
|
||||
|
||||
$hookResult = $this->runHooks( get_class( $this ) . "Raw" );
|
||||
if ( $hookResult ) {
|
||||
die( $hookResult );
|
||||
echo $hookResult;
|
||||
} else {
|
||||
echo $this->getHTML();
|
||||
}
|
||||
|
||||
echo $this->getHTML();
|
||||
die(1);
|
||||
echo "</body></html>\n";
|
||||
die( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +275,9 @@ class MWException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* Check whether we are in command line mode or not to report the exception
|
||||
* in the correct format.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isCommandLine() {
|
||||
|
|
@ -265,6 +288,7 @@ class MWException extends Exception {
|
|||
/**
|
||||
* Exception class which takes an HTML error message, and does not
|
||||
* produce a backtrace. Replacement for OutputPage::fatalError().
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class FatalError extends MWException {
|
||||
|
|
@ -285,14 +309,21 @@ class FatalError extends MWException {
|
|||
}
|
||||
|
||||
/**
|
||||
* An error page which can definitely be safely rendered using the OutputPage
|
||||
* An error page which can definitely be safely rendered using the OutputPage.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class ErrorPageError extends MWException {
|
||||
public $title, $msg, $params;
|
||||
|
||||
/**
|
||||
* @todo document
|
||||
*
|
||||
* Note: these arguments are keys into wfMsg(), not text!
|
||||
*
|
||||
* @param $title A title
|
||||
* @param $msg String|Message . In string form, should be a message key
|
||||
* @param $params Array Array to wfMsg()
|
||||
*/
|
||||
function __construct( $title, $msg, $params = null ) {
|
||||
$this->title = $title;
|
||||
|
|
@ -318,6 +349,8 @@ class ErrorPageError extends MWException {
|
|||
* Show an error page on a badtitle.
|
||||
* Similar to ErrorPage, but emit a 400 HTTP error code to let mobile
|
||||
* browser it is not really a valid content.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class BadTitleError extends ErrorPageError {
|
||||
|
||||
|
|
@ -347,6 +380,7 @@ class BadTitleError extends ErrorPageError {
|
|||
/**
|
||||
* Show an error when a user tries to do something they do not have the necessary
|
||||
* permissions for.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class PermissionsError extends ErrorPageError {
|
||||
|
|
@ -383,7 +417,8 @@ class PermissionsError extends ErrorPageError {
|
|||
|
||||
/**
|
||||
* Show an error when the wiki is locked/read-only and the user tries to do
|
||||
* something that requires write access
|
||||
* something that requires write access.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class ReadOnlyError extends ErrorPageError {
|
||||
|
|
@ -397,7 +432,8 @@ class ReadOnlyError extends ErrorPageError {
|
|||
}
|
||||
|
||||
/**
|
||||
* Show an error when the user hits a rate limit
|
||||
* Show an error when the user hits a rate limit.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class ThrottledError extends ErrorPageError {
|
||||
|
|
@ -416,7 +452,8 @@ class ThrottledError extends ErrorPageError {
|
|||
}
|
||||
|
||||
/**
|
||||
* Show an error when the user tries to do something whilst blocked
|
||||
* Show an error when the user tries to do something whilst blocked.
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class UserBlockedError extends ErrorPageError {
|
||||
|
|
@ -457,6 +494,52 @@ class UserBlockedError extends ErrorPageError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a generic "user is not logged in" error page.
|
||||
*
|
||||
* This is essentially an ErrorPageError exception which by default use the
|
||||
* 'exception-nologin' as a title and 'exception-nologin-text' for the message.
|
||||
* @see bug 37627
|
||||
*
|
||||
* @par Example:
|
||||
* @code
|
||||
* if( $user->isAnon ) {
|
||||
* throw new UserNotLoggedIn();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Please note the parameters are mixed up compared to ErrorPageError, this
|
||||
* is done to be able to simply specify a reason whitout overriding the default
|
||||
* title.
|
||||
*
|
||||
* @par Example:
|
||||
* @code
|
||||
* if( $user->isAnon ) {
|
||||
* throw new UserNotLoggedIn( 'action-require-loggedin' );
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @ingroup Exception
|
||||
*/
|
||||
class UserNotLoggedIn extends ErrorPageError {
|
||||
|
||||
/**
|
||||
* @param $reasonMsg A message key containing the reason for the error.
|
||||
* Optional, default: 'exception-nologin-text'
|
||||
* @param $titleMsg A message key to set the page title.
|
||||
* Optional, default: 'exception-nologin'
|
||||
* @param $params Parameters to wfMsg().
|
||||
* Optiona, default: null
|
||||
*/
|
||||
public function __construct(
|
||||
$reasonMsg = 'exception-nologin-text',
|
||||
$titleMsg = 'exception-nologin',
|
||||
$params = null
|
||||
) {
|
||||
parent::__construct( $titleMsg, $reasonMsg, $params );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an error that looks like an HTTP server error.
|
||||
* Replacement for wfHttpError().
|
||||
|
|
@ -572,7 +655,8 @@ class MWExceptionHandler {
|
|||
/**
|
||||
* Print a message, if possible to STDERR.
|
||||
* Use this in command line mode only (see isCommandLine)
|
||||
* @param $message String Failure text
|
||||
*
|
||||
* @param $message string Failure text
|
||||
*/
|
||||
public static function printError( $message ) {
|
||||
# NOTE: STDERR may not be available, especially if php-cgi is used from the command line (bug #15602).
|
||||
|
|
@ -586,8 +670,9 @@ class MWExceptionHandler {
|
|||
|
||||
/**
|
||||
* Print a message after escaping it and converting newlines to <br>
|
||||
* Use this for non-command line failures
|
||||
* @param $message String Failure text
|
||||
* Use this for non-command line failures.
|
||||
*
|
||||
* @param $message string Failure text
|
||||
*/
|
||||
private static function escapeEchoAndDie( $message ) {
|
||||
echo nl2br( htmlspecialchars( $message ) ) . "\n";
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ class WikiExporter {
|
|||
*/
|
||||
var $sink;
|
||||
|
||||
/**
|
||||
* Returns the export schema version.
|
||||
* @return string
|
||||
*/
|
||||
public static function schemaVersion() {
|
||||
return "0.7"; #FIXME: bump this when pushing ContentHandler additions.
|
||||
}
|
||||
|
||||
/**
|
||||
* If using WikiExporter::STREAM to stream a large amount of data,
|
||||
* provide a database connection which is not managed by
|
||||
|
|
@ -465,14 +473,16 @@ class WikiExporter {
|
|||
class XmlDumpWriter {
|
||||
/**
|
||||
* Returns the export schema version.
|
||||
* @deprecated in 1.20; use WikiExporter::schemaVersion() instead
|
||||
* @return string
|
||||
*/
|
||||
function schemaVersion() {
|
||||
return "0.8"; #FIXME: Make sure to bump this to > 0.7 when merging Wikidata branch!
|
||||
wfDeprecated( __METHOD__, '1.20' );
|
||||
return WikiExporter::schemaVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the XML output stream's root <mediawiki> element.
|
||||
* Opens the XML output stream's root "<mediawiki>" element.
|
||||
* This does not include an xml directive, so is safe to include
|
||||
* as a subelement in a larger XML stream. Namespace and XML Schema
|
||||
* references are included.
|
||||
|
|
@ -483,7 +493,7 @@ class XmlDumpWriter {
|
|||
*/
|
||||
function openStream() {
|
||||
global $wgLanguageCode;
|
||||
$ver = $this->schemaVersion();
|
||||
$ver = WikiExporter::schemaVersion();
|
||||
return Xml::element( 'mediawiki', array(
|
||||
'xmlns' => "http://www.mediawiki.org/xml/export-$ver/",
|
||||
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
||||
|
|
@ -572,7 +582,7 @@ class XmlDumpWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Opens a <page> section on the output stream, with data
|
||||
* Opens a "<page>" section on the output stream, with data
|
||||
* from the given database row.
|
||||
*
|
||||
* @param $row object
|
||||
|
|
@ -604,7 +614,7 @@ class XmlDumpWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Closes a <page> section on the output stream.
|
||||
* Closes a "<page>" section on the output stream.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
|
|
@ -614,7 +624,7 @@ class XmlDumpWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dumps a <revision> section on the output stream, with
|
||||
* Dumps a "<revision>" section on the output stream, with
|
||||
* data filled in from the given database row.
|
||||
*
|
||||
* @param $row object
|
||||
|
|
@ -700,7 +710,7 @@ class XmlDumpWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dumps a <logitem> section on the output stream, with
|
||||
* Dumps a "<logitem>" section on the output stream, with
|
||||
* data filled in from the given database row.
|
||||
*
|
||||
* @param $row object
|
||||
|
|
@ -748,6 +758,7 @@ class XmlDumpWriter {
|
|||
|
||||
/**
|
||||
* @param $timestamp string
|
||||
* @param $indent string Default to six spaces
|
||||
* @return string
|
||||
*/
|
||||
function writeTimestamp( $timestamp, $indent = " " ) {
|
||||
|
|
@ -758,6 +769,7 @@ class XmlDumpWriter {
|
|||
/**
|
||||
* @param $id
|
||||
* @param $text string
|
||||
* @param $indent string Default to six spaces
|
||||
* @return string
|
||||
*/
|
||||
function writeContributor( $id, $text, $indent = " " ) {
|
||||
|
|
@ -779,7 +791,7 @@ class XmlDumpWriter {
|
|||
* @return string
|
||||
*/
|
||||
function writeUploads( $row, $dumpContents = false ) {
|
||||
if ( $row->page_namespace == NS_IMAGE ) {
|
||||
if ( $row->page_namespace == NS_FILE ) {
|
||||
$img = wfLocalFile( $row->page_title );
|
||||
if ( $img && $img->exists() ) {
|
||||
$out = '';
|
||||
|
|
@ -837,7 +849,7 @@ class XmlDumpWriter {
|
|||
* Return prefixed text form of title, but using the content language's
|
||||
* canonical namespace. This skips any special-casing such as gendered
|
||||
* user namespaces -- which while useful, are not yet listed in the
|
||||
* XML <siteinfo> data so are unsafe in export.
|
||||
* XML "<siteinfo>" data so are unsafe in export.
|
||||
*
|
||||
* @param Title $title
|
||||
* @return string
|
||||
|
|
|
|||
|
|
@ -183,34 +183,35 @@ class FeedItem {
|
|||
* @todo document (needs one-sentence top-level class description).
|
||||
* @ingroup Feed
|
||||
*/
|
||||
class ChannelFeed extends FeedItem {
|
||||
/**#@+
|
||||
* Abstract function, override!
|
||||
* @abstract
|
||||
*/
|
||||
|
||||
abstract class ChannelFeed extends FeedItem {
|
||||
/**
|
||||
* Generate Header of the feed
|
||||
* @par Example:
|
||||
* @code
|
||||
* print "<feed>";
|
||||
* @endcode
|
||||
* @param $item
|
||||
*/
|
||||
function outHeader() {
|
||||
# print "<feed>";
|
||||
}
|
||||
abstract public function outHeader();
|
||||
|
||||
/**
|
||||
* Generate an item
|
||||
* @par Example:
|
||||
* @code
|
||||
* print "<item>...</item>";
|
||||
* @endcode
|
||||
* @param $item
|
||||
*/
|
||||
function outItem( $item ) {
|
||||
# print "<item>...</item>";
|
||||
}
|
||||
abstract public function outItem( $item );
|
||||
|
||||
/**
|
||||
* Generate Footer of the feed
|
||||
* @par Example:
|
||||
* @code
|
||||
* print "</feed>";
|
||||
* @endcode
|
||||
*/
|
||||
function outFooter() {
|
||||
# print "</feed>";
|
||||
}
|
||||
/**#@-*/
|
||||
abstract public function outFooter();
|
||||
|
||||
/**
|
||||
* Setup and send HTTP headers. Don't send any content;
|
||||
|
|
|
|||
|
|
@ -119,10 +119,12 @@ class FileDeleteForm {
|
|||
// file, otherwise go back to the description page
|
||||
$wgOut->addReturnTo( $this->oldimage ? $this->title : Title::newMainPage() );
|
||||
|
||||
if ( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) {
|
||||
WatchAction::doWatch( $this->title, $wgUser );
|
||||
} elseif ( $this->title->userIsWatching() ) {
|
||||
WatchAction::doUnwatch( $this->title, $wgUser );
|
||||
if ( $wgUser->isLoggedIn() && $wgRequest->getCheck( 'wpWatch' ) != $wgUser->isWatched( $this->title ) ) {
|
||||
if ( $wgRequest->getCheck( 'wpWatch' ) ) {
|
||||
WatchAction::doWatch( $this->title, $wgUser );
|
||||
} else {
|
||||
WatchAction::doUnwatch( $this->title, $wgUser );
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -154,12 +156,19 @@ class FileDeleteForm {
|
|||
$status = $file->deleteOld( $oldimage, $reason, $suppress );
|
||||
if( $status->ok ) {
|
||||
// Need to do a log item
|
||||
$log = new LogPage( 'delete' );
|
||||
$logComment = wfMsgForContent( 'deletedrevision', $oldimage );
|
||||
if( trim( $reason ) != '' ) {
|
||||
$logComment .= wfMsgForContent( 'colon-separator' ) . $reason;
|
||||
}
|
||||
$log->addEntry( 'delete', $title, $logComment );
|
||||
|
||||
$logtype = $suppress ? 'suppress' : 'delete';
|
||||
|
||||
$logEntry = new ManualLogEntry( $logtype, 'delete' );
|
||||
$logEntry->setPerformer( $user );
|
||||
$logEntry->setTarget( $title );
|
||||
$logEntry->setComment( $logComment );
|
||||
$logid = $logEntry->insert();
|
||||
$logEntry->publish( $logid );
|
||||
}
|
||||
} else {
|
||||
$status = Status::newFatal( 'cannotdelete',
|
||||
|
|
@ -170,7 +179,10 @@ class FileDeleteForm {
|
|||
try {
|
||||
// delete the associated article first
|
||||
$error = '';
|
||||
if ( $page->doDeleteArticleReal( $reason, $suppress, 0, false, $error, $user ) >= WikiPage::DELETE_SUCCESS ) {
|
||||
$deleteStatus = $page->doDeleteArticleReal( $reason, $suppress, 0, false, $error, $user );
|
||||
// doDeleteArticleReal() returns a non-fatal error status if the page
|
||||
// or revision is missing, so check for isOK() rather than isGood()
|
||||
if ( $deleteStatus->isOK() ) {
|
||||
$status = $file->delete( $reason, $suppress );
|
||||
if( $status->isOK() ) {
|
||||
$dbw->commit( __METHOD__ );
|
||||
|
|
@ -210,7 +222,7 @@ class FileDeleteForm {
|
|||
$suppress = '';
|
||||
}
|
||||
|
||||
$checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $this->title->userIsWatching();
|
||||
$checkWatch = $wgUser->getBoolOption( 'watchdeletion' ) || $wgUser->isWatched( $this->title );
|
||||
$form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getAction(),
|
||||
'id' => 'mw-img-deleteconfirm' ) ) .
|
||||
Xml::openElement( 'fieldset' ) .
|
||||
|
|
|
|||
|
|
@ -1053,11 +1053,22 @@ function wfDebugLog( $logGroup, $text, $public = true ) {
|
|||
* @param $text String: database error message.
|
||||
*/
|
||||
function wfLogDBError( $text ) {
|
||||
global $wgDBerrorLog;
|
||||
global $wgDBerrorLog, $wgDBerrorLogInUTC;
|
||||
if ( $wgDBerrorLog ) {
|
||||
$host = wfHostname();
|
||||
$wiki = wfWikiID();
|
||||
$text = date( 'D M j G:i:s T Y' ) . "\t$host\t$wiki\t$text";
|
||||
|
||||
if( $wgDBerrorLogInUTC ) {
|
||||
$wikiTimezone = date_default_timezone_get();
|
||||
date_default_timezone_set( 'UTC' );
|
||||
}
|
||||
$date = date( 'D M j G:i:s T Y' );
|
||||
if( $wgDBerrorLogInUTC ) {
|
||||
// Restore timezone
|
||||
date_default_timezone_set( $wikiTimezone );
|
||||
}
|
||||
|
||||
$text = "$date\t$host\t$wiki\t$text";
|
||||
wfErrorLog( $text, $wgDBerrorLog );
|
||||
}
|
||||
}
|
||||
|
|
@ -1758,6 +1769,15 @@ function wfDebugDieBacktrace( $msg = '' ) {
|
|||
function wfHostname() {
|
||||
static $host;
|
||||
if ( is_null( $host ) ) {
|
||||
|
||||
# Hostname overriding
|
||||
global $wgOverrideHostname;
|
||||
if( $wgOverrideHostname !== false ) {
|
||||
# Set static and skip any detection
|
||||
$host = $wgOverrideHostname;
|
||||
return $host;
|
||||
}
|
||||
|
||||
if ( function_exists( 'posix_uname' ) ) {
|
||||
// This function not present on Windows
|
||||
$uname = posix_uname();
|
||||
|
|
@ -2054,7 +2074,7 @@ function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
|
|||
* Escapes the given text so that it may be output using addWikiText()
|
||||
* without any linking, formatting, etc. making its way through. This
|
||||
* is achieved by substituting certain characters with HTML entities.
|
||||
* As required by the callers, <nowiki> is not used.
|
||||
* As required by the callers, "<nowiki>" is not used.
|
||||
*
|
||||
* @param $text String: text to be escaped
|
||||
* @return String
|
||||
|
|
@ -2865,9 +2885,11 @@ function wfEscapeShellArg( ) {
|
|||
* (non-zero is usually failure)
|
||||
* @param $environ Array optional environment variables which should be
|
||||
* added to the executed command environment.
|
||||
* @param $limits Array optional array with limits(filesize, memory, time)
|
||||
* this overwrites the global wgShellMax* limits.
|
||||
* @return string collected stdout as a string (trailing newlines stripped)
|
||||
*/
|
||||
function wfShellExec( $cmd, &$retval = null, $environ = array() ) {
|
||||
function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
|
||||
global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime;
|
||||
|
||||
static $disabled;
|
||||
|
|
@ -2915,9 +2937,9 @@ function wfShellExec( $cmd, &$retval = null, $environ = array() ) {
|
|||
$cmd = $envcmd . $cmd;
|
||||
|
||||
if ( php_uname( 's' ) == 'Linux' ) {
|
||||
$time = intval( $wgMaxShellTime );
|
||||
$mem = intval( $wgMaxShellMemory );
|
||||
$filesize = intval( $wgMaxShellFileSize );
|
||||
$time = intval ( isset($limits['time']) ? $limits['time'] : $wgMaxShellTime );
|
||||
$mem = intval ( isset($limits['memory']) ? $limits['memory'] : $wgMaxShellMemory );
|
||||
$filesize = intval ( isset($limits['filesize']) ? $limits['filesize'] : $wgMaxShellFileSize );
|
||||
|
||||
if ( $time > 0 && $mem > 0 ) {
|
||||
$script = "$IP/bin/ulimit4.sh";
|
||||
|
|
@ -3183,11 +3205,11 @@ function wfUseMW( $req_ver ) {
|
|||
|
||||
/**
|
||||
* Return the final portion of a pathname.
|
||||
* Reimplemented because PHP5's basename() is buggy with multibyte text.
|
||||
* Reimplemented because PHP5's "basename()" is buggy with multibyte text.
|
||||
* http://bugs.php.net/bug.php?id=33898
|
||||
*
|
||||
* PHP's basename() only considers '\' a pathchar on Windows and Netware.
|
||||
* We'll consider it so always, as we don't want \s in our Unix paths either.
|
||||
* We'll consider it so always, as we don't want '\s' in our Unix paths either.
|
||||
*
|
||||
* @param $path String
|
||||
* @param $suffix String: to remove if present
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ class HTMLForm extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Wrap the form innards in an actual <form> element
|
||||
* Wrap the form innards in an actual "<form>" element
|
||||
* @param $html String HTML contents to wrap.
|
||||
* @return String wrapped HTML.
|
||||
*/
|
||||
|
|
@ -688,7 +688,7 @@ class HTMLForm extends ContextSource {
|
|||
/**
|
||||
* Format a stack of error messages into a single HTML string
|
||||
* @param $errors Array of message keys/values
|
||||
* @return String HTML, a <ul> list of errors
|
||||
* @return String HTML, a "<ul>" list of errors
|
||||
*/
|
||||
public static function formatErrors( $errors ) {
|
||||
$errorstr = '';
|
||||
|
|
@ -761,16 +761,16 @@ class HTMLForm extends ContextSource {
|
|||
$this->mId = $id;
|
||||
}
|
||||
/**
|
||||
* Prompt the whole form to be wrapped in a <fieldset>, with
|
||||
* this text as its <legend> element.
|
||||
* @param $legend String HTML to go inside the <legend> element.
|
||||
* Prompt the whole form to be wrapped in a "<fieldset>", with
|
||||
* this text as its "<legend>" element.
|
||||
* @param $legend String HTML to go inside the "<legend>" element.
|
||||
* Will be escaped
|
||||
*/
|
||||
public function setWrapperLegend( $legend ) { $this->mWrapperLegend = $legend; }
|
||||
|
||||
/**
|
||||
* Prompt the whole form to be wrapped in a <fieldset>, with
|
||||
* this message as its <legend> element.
|
||||
* Prompt the whole form to be wrapped in a "<fieldset>", with
|
||||
* this message as its "<legend>" element.
|
||||
* @since 1.19
|
||||
* @param $msg String message key
|
||||
*/
|
||||
|
|
@ -780,7 +780,7 @@ class HTMLForm extends ContextSource {
|
|||
|
||||
/**
|
||||
* Set the prefix for various default messages
|
||||
* TODO: currently only used for the <fieldset> legend on forms
|
||||
* @todo currently only used for the "<fieldset>" legend on forms
|
||||
* with multiple sections; should be used elsewhre?
|
||||
* @param $p String
|
||||
*/
|
||||
|
|
@ -819,10 +819,10 @@ class HTMLForm extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* TODO: Document
|
||||
* @todo Document
|
||||
* @param $fields array[]|HTMLFormField[] array of fields (either arrays or objects)
|
||||
* @param $sectionName string ID attribute of the <table> tag for this section, ignored if empty
|
||||
* @param $fieldsetIDPrefix string ID prefix for the <fieldset> tag of each subsection, ignored if empty
|
||||
* @param $sectionName string ID attribute of the "<table>" tag for this section, ignored if empty
|
||||
* @param $fieldsetIDPrefix string ID prefix for the "<fieldset>" tag of each subsection, ignored if empty
|
||||
* @return String
|
||||
*/
|
||||
public function displaySection( $fields, $sectionName = '', $fieldsetIDPrefix = '' ) {
|
||||
|
|
@ -938,8 +938,8 @@ class HTMLForm extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a string to go in the <legend> of a section fieldset. Override this if you
|
||||
* want something more complicated
|
||||
* Get a string to go in the "<legend>" of a section fieldset.
|
||||
* Override this if you want something more complicated.
|
||||
* @param $key String
|
||||
* @return String
|
||||
*/
|
||||
|
|
@ -1350,7 +1350,7 @@ abstract class HTMLFormField {
|
|||
|
||||
/**
|
||||
* flatten an array of options to a single array, for instance,
|
||||
* a set of <options> inside <optgroups>.
|
||||
* a set of "<options>" inside "<optgroups>".
|
||||
* @param $options array Associative Array with values either Strings
|
||||
* or Arrays
|
||||
* @return Array flattened input
|
||||
|
|
@ -1889,7 +1889,7 @@ class HTMLMultiSelectField extends HTMLFormField {
|
|||
* ** <option value>
|
||||
* * New Optgroup header
|
||||
* Plus a text field underneath for an additional reason. The 'value' of the field is
|
||||
* ""<select>: <extra reason>"", or "<extra reason>" if nothing has been selected in the
|
||||
* "<select>: <extra reason>", or "<extra reason>" if nothing has been selected in the
|
||||
* select dropdown.
|
||||
* @todo FIXME: If made 'required', only the text field should be compulsory.
|
||||
*/
|
||||
|
|
@ -1991,7 +1991,7 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
|
|||
|
||||
/**
|
||||
* @param $request WebRequest
|
||||
* @return Array( <overall message>, <select value>, <text field value> )
|
||||
* @return Array("<overall message>","<select value>","<text field value>")
|
||||
*/
|
||||
function loadDataFromRequest( $request ) {
|
||||
if ( $request->getCheck( $this->mName ) ) {
|
||||
|
|
|
|||
|
|
@ -548,9 +548,10 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Output a <script> tag with the given contents. TODO: do some useful
|
||||
* escaping as well, like if $contents contains literal '</script>' or (for
|
||||
* XML) literal "]]>".
|
||||
* Output a "<script>" tag with the given contents.
|
||||
*
|
||||
* @todo do some useful escaping as well, like if $contents contains
|
||||
* literal "</script>" or (for XML) literal "]]>".
|
||||
*
|
||||
* @param $contents string JavaScript
|
||||
* @return string Raw HTML
|
||||
|
|
@ -572,8 +573,8 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Output a <script> tag linking to the given URL, e.g.,
|
||||
* <script src=foo.js></script>.
|
||||
* Output a "<script>" tag linking to the given URL, e.g.,
|
||||
* "<script src=foo.js></script>".
|
||||
*
|
||||
* @param $url string
|
||||
* @return string Raw HTML
|
||||
|
|
@ -591,9 +592,9 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Output a <style> tag with the given contents for the given media type
|
||||
* Output a "<style>" tag with the given contents for the given media type
|
||||
* (if any). TODO: do some useful escaping as well, like if $contents
|
||||
* contains literal '</style>' (admittedly unlikely).
|
||||
* contains literal "</style>" (admittedly unlikely).
|
||||
*
|
||||
* @param $contents string CSS
|
||||
* @param $media mixed A media type string, like 'screen'
|
||||
|
|
@ -613,7 +614,7 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Output a <link rel=stylesheet> linking to the given URL for the given
|
||||
* Output a "<link rel=stylesheet>" linking to the given URL for the given
|
||||
* media type (if any).
|
||||
*
|
||||
* @param $url string
|
||||
|
|
@ -630,7 +631,7 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience function to produce an <input> element. This supports the
|
||||
* Convenience function to produce an "<input>" element. This supports the
|
||||
* new HTML5 input types and attributes, and will silently strip them if
|
||||
* $wgHtml5 is false.
|
||||
*
|
||||
|
|
@ -663,11 +664,12 @@ class Html {
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience function to produce an <input> element. This supports leaving
|
||||
* out the cols= and rows= which Xml requires and are required by HTML4/XHTML
|
||||
* but not required by HTML5 and will silently set cols="" and rows="" if
|
||||
* $wgHtml5 is false and cols and rows are omitted (HTML4 validates present
|
||||
* but empty cols="" and rows="" as valid).
|
||||
* Convenience function to produce an "<input>" element.
|
||||
*
|
||||
* This supports leaving out the cols= and rows= which Xml requires and are
|
||||
* required by HTML4/XHTML but not required by HTML5 and will silently set
|
||||
* cols="" and rows="" if $wgHtml5 is false and cols and rows are omitted
|
||||
* (HTML4 validates present but empty cols="" and rows="" as valid).
|
||||
*
|
||||
* @param $name string name attribute
|
||||
* @param $value string value attribute
|
||||
|
|
@ -706,7 +708,7 @@ class Html {
|
|||
*
|
||||
* @param $params array:
|
||||
* - selected: [optional] Id of namespace which should be pre-selected
|
||||
* - all: [optional] Value of item for "all namespaces". If null or unset, no <option> is generated to select all namespaces
|
||||
* - all: [optional] Value of item for "all namespaces". If null or unset, no "<option>" is generated to select all namespaces
|
||||
* - label: text for label to add before the field
|
||||
* - exclude: [optional] Array of namespace ids to exclude
|
||||
* - disable: [optional] Array of namespace ids for which the option should be disabled in the selector
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ class Http {
|
|||
*
|
||||
* file:// should not be allowed here for security purpose (r67684)
|
||||
*
|
||||
* @fixme this is wildly inaccurate and fails to actually check most stuff
|
||||
* @todo FIXME this is wildly inaccurate and fails to actually check most stuff
|
||||
*
|
||||
* @param $uri Mixed: URI to check for validity
|
||||
* @return Boolean
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class ImagePage extends Article {
|
|||
# should be in page content language
|
||||
$pageLang = $this->getTitle()->getPageLanguage();
|
||||
$out->addHTML( Xml::openElement( 'div', array( 'id' => 'mw-imagepage-content',
|
||||
'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(),
|
||||
'lang' => $pageLang->getHtmlCode(), 'dir' => $pageLang->getDir(),
|
||||
'class' => 'mw-content-'.$pageLang->getDir() ) ) );
|
||||
|
||||
parent::view();
|
||||
|
|
@ -414,12 +414,11 @@ class ImagePage extends Article {
|
|||
|
||||
if ( $page > 1 ) {
|
||||
$label = $out->parse( wfMsg( 'imgmultipageprev' ), false );
|
||||
$link = Linker::link(
|
||||
$link = Linker::linkKnown(
|
||||
$this->getTitle(),
|
||||
$label,
|
||||
array(),
|
||||
array( 'page' => $page - 1 ),
|
||||
array( 'known', 'noclasses' )
|
||||
array( 'page' => $page - 1 )
|
||||
);
|
||||
$thumb1 = Linker::makeThumbLinkObj( $this->getTitle(), $this->displayImg, $link, $label, 'none',
|
||||
array( 'page' => $page - 1 ) );
|
||||
|
|
@ -429,12 +428,11 @@ class ImagePage extends Article {
|
|||
|
||||
if ( $page < $count ) {
|
||||
$label = wfMsg( 'imgmultipagenext' );
|
||||
$link = Linker::link(
|
||||
$link = Linker::linkKnown(
|
||||
$this->getTitle(),
|
||||
$label,
|
||||
array(),
|
||||
array( 'page' => $page + 1 ),
|
||||
array( 'known', 'noclasses' )
|
||||
array( 'page' => $page + 1 )
|
||||
);
|
||||
$thumb2 = Linker::makeThumbLinkObj( $this->getTitle(), $this->displayImg, $link, $label, 'none',
|
||||
array( 'page' => $page + 1 ) );
|
||||
|
|
@ -646,7 +644,7 @@ EOT
|
|||
|
||||
# External editing link
|
||||
if ( $wgUseExternalEditor ) {
|
||||
$elink = Linker::link(
|
||||
$elink = Linker::linkKnown(
|
||||
$this->getTitle(),
|
||||
wfMsgHtml( 'edit-externally' ),
|
||||
array(),
|
||||
|
|
@ -654,8 +652,7 @@ EOT
|
|||
'action' => 'edit',
|
||||
'externaledit' => 'true',
|
||||
'mode' => 'file'
|
||||
),
|
||||
array( 'known', 'noclasses' )
|
||||
)
|
||||
);
|
||||
$out->addHTML(
|
||||
'<li id="mw-imagepage-edit-external">' . $elink . ' <small>' .
|
||||
|
|
@ -830,13 +827,7 @@ EOT
|
|||
foreach ( $dupes as $file ) {
|
||||
$fromSrc = '';
|
||||
if ( $file->isLocal() ) {
|
||||
$link = Linker::link(
|
||||
$file->getTitle(),
|
||||
null,
|
||||
array(),
|
||||
array(),
|
||||
array( 'known', 'noclasses' )
|
||||
);
|
||||
$link = Linker::linkKnown( $file->getTitle() );
|
||||
} else {
|
||||
$link = Linker::makeExternalLink( $file->getDescriptionUrl(),
|
||||
$file->getTitle()->getPrefixedText() );
|
||||
|
|
@ -1006,10 +997,10 @@ class ImageHistoryList extends ContextSource {
|
|||
if ( !$iscur ) {
|
||||
$q['oldimage'] = $img;
|
||||
}
|
||||
$row .= Linker::link(
|
||||
$row .= Linker::linkKnown(
|
||||
$this->title,
|
||||
wfMsgHtml( $iscur ? 'filehist-deleteall' : 'filehist-deleteone' ),
|
||||
array(), $q, array( 'known' )
|
||||
array(), $q
|
||||
);
|
||||
}
|
||||
# Link to hide content. Don't show useless link to people who cannot hide revisions.
|
||||
|
|
@ -1046,7 +1037,7 @@ class ImageHistoryList extends ContextSource {
|
|||
if ( $file->isDeleted( File::DELETED_FILE ) ) {
|
||||
$row .= wfMsgHtml( 'filehist-revert' );
|
||||
} else {
|
||||
$row .= Linker::link(
|
||||
$row .= Linker::linkKnown(
|
||||
$this->title,
|
||||
wfMsgHtml( 'filehist-revert' ),
|
||||
array(),
|
||||
|
|
@ -1054,8 +1045,7 @@ class ImageHistoryList extends ContextSource {
|
|||
'action' => 'revert',
|
||||
'oldimage' => $img,
|
||||
'wpEditToken' => $user->getEditToken( $img )
|
||||
),
|
||||
array( 'known', 'noclasses' )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1074,7 +1064,7 @@ class ImageHistoryList extends ContextSource {
|
|||
$this->preventClickjacking();
|
||||
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
|
||||
# Make a link to review the image
|
||||
$url = Linker::link(
|
||||
$url = Linker::linkKnown(
|
||||
$revdel,
|
||||
$lang->timeanddate( $timestamp, true ),
|
||||
array(),
|
||||
|
|
@ -1082,8 +1072,7 @@ class ImageHistoryList extends ContextSource {
|
|||
'target' => $this->title->getPrefixedText(),
|
||||
'file' => $img,
|
||||
'token' => $user->getEditToken( $img )
|
||||
),
|
||||
array( 'known', 'noclasses' )
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$url = $lang->timeanddate( $timestamp, true );
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* MediaWiki page data importer
|
||||
* MediaWiki page data importer.
|
||||
*
|
||||
* Copyright © 2003,2005 Brion Vibber <brion@pobox.com>
|
||||
* http://www.mediawiki.org/
|
||||
|
|
@ -275,7 +275,7 @@ class WikiImporter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Notify the callback function when a new <page> is reached.
|
||||
* Notify the callback function when a new "<page>" is reached.
|
||||
* @param $title Title
|
||||
*/
|
||||
function pageCallback( $title ) {
|
||||
|
|
@ -285,7 +285,7 @@ class WikiImporter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Notify the callback function when a </page> is closed.
|
||||
* Notify the callback function when a "</page>" is closed.
|
||||
* @param $title Title
|
||||
* @param $origTitle Title
|
||||
* @param $revCount Integer
|
||||
|
|
|
|||
|
|
@ -407,6 +407,11 @@ class Linker {
|
|||
* despite $query not being used.
|
||||
*
|
||||
* @param $nt Title
|
||||
* @param $html String [optional]
|
||||
* @param $query String [optional]
|
||||
* @param $trail String [optional]
|
||||
* @param $prefix String [optional]
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -978,7 +983,7 @@ class Linker {
|
|||
* @param $userName String: user name in database.
|
||||
* @param $altUserName String: text to display instead of the user name (optional)
|
||||
* @return String: HTML fragment
|
||||
* @since 1.19 Method exists for a long time. $displayText was added in 1.19.
|
||||
* @since 1.19 Method exists for a long time. $altUserName was added in 1.19.
|
||||
*/
|
||||
public static function userLink( $userId, $userName, $altUserName = false ) {
|
||||
if ( $userId == 0 ) {
|
||||
|
|
@ -1646,11 +1651,17 @@ class Linker {
|
|||
* other users.
|
||||
*
|
||||
* @param $rev Revision object
|
||||
* @param $context IContextSource context to use or null for the main context.
|
||||
* @return string
|
||||
*/
|
||||
public static function generateRollback( $rev ) {
|
||||
public static function generateRollback( $rev, IContextSource $context = null ) {
|
||||
if ( $context === null ) {
|
||||
$context = RequestContext::getMain();
|
||||
}
|
||||
|
||||
return '<span class="mw-rollback-link">'
|
||||
. wfMessage( 'brackets' )->rawParams( self::buildRollbackLink( $rev ) )->plain()
|
||||
. $context->msg( 'brackets' )->rawParams(
|
||||
self::buildRollbackLink( $rev, $context ) )->plain()
|
||||
. '</span>';
|
||||
}
|
||||
|
||||
|
|
@ -1658,24 +1669,28 @@ class Linker {
|
|||
* Build a raw rollback link, useful for collections of "tool" links
|
||||
*
|
||||
* @param $rev Revision object
|
||||
* @param $context IContextSource context to use or null for the main context.
|
||||
* @return String: HTML fragment
|
||||
*/
|
||||
public static function buildRollbackLink( $rev ) {
|
||||
global $wgRequest, $wgUser;
|
||||
public static function buildRollbackLink( $rev, IContextSource $context = null ) {
|
||||
if ( $context === null ) {
|
||||
$context = RequestContext::getMain();
|
||||
}
|
||||
|
||||
$title = $rev->getTitle();
|
||||
$query = array(
|
||||
'action' => 'rollback',
|
||||
'from' => $rev->getUserText(),
|
||||
'token' => $wgUser->getEditToken( array( $title->getPrefixedText(), $rev->getUserText() ) ),
|
||||
'token' => $context->getUser()->getEditToken( array( $title->getPrefixedText(), $rev->getUserText() ) ),
|
||||
);
|
||||
if ( $wgRequest->getBool( 'bot' ) ) {
|
||||
if ( $context->getRequest()->getBool( 'bot' ) ) {
|
||||
$query['bot'] = '1';
|
||||
$query['hidediff'] = '1'; // bug 15999
|
||||
}
|
||||
return self::link(
|
||||
$title,
|
||||
wfMsgHtml( 'rollbacklink' ),
|
||||
array( 'title' => wfMsg( 'tooltip-rollback' ) ),
|
||||
$context->msg( 'rollbacklink' )->escaped(),
|
||||
array( 'title' => $context->msg( 'tooltip-rollback' )->text() ),
|
||||
$query,
|
||||
array( 'known', 'noclasses' )
|
||||
);
|
||||
|
|
@ -1713,7 +1728,7 @@ class Linker {
|
|||
}
|
||||
$outText .= "</div><ul>\n";
|
||||
|
||||
usort( $templates, array( 'Title', 'compare' ) );
|
||||
usort( $templates, 'Title::compare' );
|
||||
foreach ( $templates as $titleObj ) {
|
||||
$r = $titleObj->getRestrictions( 'edit' );
|
||||
if ( in_array( 'sysop', $r ) ) {
|
||||
|
|
@ -1913,10 +1928,10 @@ class Linker {
|
|||
* Creates a (show/hide) link for deleting revisions/log entries
|
||||
*
|
||||
* @param $query Array: query parameters to be passed to link()
|
||||
* @param $restricted Boolean: set to true to use a <strong> instead of a <span>
|
||||
* @param $restricted Boolean: set to true to use a "<strong>" instead of a "<span>"
|
||||
* @param $delete Boolean: set to true to use (show/hide) rather than (show)
|
||||
*
|
||||
* @return String: HTML <a> link to Special:Revisiondelete, wrapped in a
|
||||
* @return String: HTML "<a>" link to Special:Revisiondelete, wrapped in a
|
||||
* span to allow for customization of appearance with CSS
|
||||
*/
|
||||
public static function revDeleteLink( $query = array(), $restricted = false, $delete = true ) {
|
||||
|
|
|
|||
|
|
@ -821,9 +821,7 @@ class LinksDeletionUpdate extends SqlDataUpdate {
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param $title Title of the page we're updating
|
||||
* @param $parserOutput ParserOutput: output from a full parse of this page
|
||||
* @param $recursive Boolean: queue jobs for recursive updates?
|
||||
* @param $page WikiPage Page we are updating
|
||||
*/
|
||||
function __construct( Title $title ) {
|
||||
parent::__construct( );
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* This class encapsulates "magic words" such as #redirect, __NOTOC__, etc.
|
||||
* This class encapsulates "magic words" such as "#redirect", __NOTOC__, etc.
|
||||
*
|
||||
* @par Usage:
|
||||
* @code
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
*
|
||||
* To add magic words in an extension, use $magicWords in a file listed in
|
||||
* $wgExtensionMessagesFiles[].
|
||||
*
|
||||
*
|
||||
* @par Example:
|
||||
* @code
|
||||
* $magicWords = array();
|
||||
|
|
|
|||
|
|
@ -341,6 +341,33 @@ class MWNamespace {
|
|||
return $wgContentNamespaces;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all namespace indices which are considered subject, aka not a talk
|
||||
* or special namespace. See also MWNamespace::isSubject
|
||||
*
|
||||
* @return array of namespace indices
|
||||
*/
|
||||
public static function getSubjectNamespaces() {
|
||||
return array_filter(
|
||||
MWNamespace::getValidNamespaces(),
|
||||
'MWNamespace::isSubject'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all namespace indices which are considered talks, aka not a subject
|
||||
* or special namespace. See also MWNamespace::isTalk
|
||||
*
|
||||
* @return array of namespace indices
|
||||
*/
|
||||
public static function getTalkNamespaces() {
|
||||
return array_filter(
|
||||
MWNamespace::getValidNamespaces(),
|
||||
'MWNamespace::isTalk'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the namespace first-letter capitalized?
|
||||
*
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@
|
|||
* @todo document
|
||||
*/
|
||||
class OutputPage extends ContextSource {
|
||||
/// Should be private. Used with addMeta() which adds <meta>
|
||||
/// Should be private. Used with addMeta() which adds "<meta>"
|
||||
var $mMetatags = array();
|
||||
|
||||
/// <meta keywords="stuff"> most of the time the first 10 links to an article
|
||||
/// "<meta keywords='stuff'>" most of the time the first 10 links to an article
|
||||
var $mKeywords = array();
|
||||
|
||||
var $mLinktags = array();
|
||||
|
|
@ -50,7 +50,7 @@ class OutputPage extends ContextSource {
|
|||
/// Should be private - has getter and setter. Contains the HTML title
|
||||
var $mPagetitle = '';
|
||||
|
||||
/// Contains all of the <body> content. Should be private we got set/get accessors and the append() method.
|
||||
/// Contains all of the "<body>" content. Should be private we got set/get accessors and the append() method.
|
||||
var $mBodytext = '';
|
||||
|
||||
/**
|
||||
|
|
@ -60,7 +60,7 @@ class OutputPage extends ContextSource {
|
|||
*/
|
||||
public $mDebugtext = ''; // TODO: we might want to replace it by wfDebug() wfDebugLog()
|
||||
|
||||
/// Should be private. Stores contents of <title> tag
|
||||
/// Should be private. Stores contents of "<title>" tag
|
||||
var $mHTMLtitle = '';
|
||||
|
||||
/// Should be private. Is the displayed content related to the source of the corresponding wiki article.
|
||||
|
|
@ -116,8 +116,8 @@ class OutputPage extends ContextSource {
|
|||
/**
|
||||
* Should be private. Used for JavaScript (pre resource loader)
|
||||
* We should split js / css.
|
||||
* mScripts content is inserted as is in <head> by Skin. This might contains
|
||||
* either a link to a stylesheet or inline css.
|
||||
* mScripts content is inserted as is in "<head>" by Skin. This might
|
||||
* contains either a link to a stylesheet or inline css.
|
||||
*/
|
||||
var $mScripts = '';
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ class OutputPage extends ContextSource {
|
|||
*/
|
||||
var $mPageLinkTitle = '';
|
||||
|
||||
/// Array of elements in <head>. Parser might add its own headers!
|
||||
/// Array of elements in "<head>". Parser might add its own headers!
|
||||
var $mHeadItems = array();
|
||||
|
||||
// @todo FIXME: Next variables probably comes from the resource loader
|
||||
|
|
@ -197,7 +197,7 @@ class OutputPage extends ContextSource {
|
|||
|
||||
/**
|
||||
* Comes from the parser. This was probably made to load CSS/JS only
|
||||
* if we had <gallery>. Used directly in CategoryPage.php
|
||||
* if we had "<gallery>". Used directly in CategoryPage.php
|
||||
* Looks like resource loader can replace this.
|
||||
*/
|
||||
var $mNoGallery = false;
|
||||
|
|
@ -237,7 +237,6 @@ class OutputPage extends ContextSource {
|
|||
private $mFollowPolicy = 'follow';
|
||||
private $mVaryHeader = array(
|
||||
'Accept-Encoding' => array( 'list-contains=gzip' ),
|
||||
'Cookie' => null
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
@ -293,7 +292,7 @@ class OutputPage extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a new <meta> tag
|
||||
* Add a new "<meta>" tag
|
||||
* To add an http-equiv meta tag, precede the name with "http:"
|
||||
*
|
||||
* @param $name String tag name
|
||||
|
|
@ -406,7 +405,7 @@ class OutputPage extends ContextSource {
|
|||
/**
|
||||
* Add a self-contained script tag with the given contents
|
||||
*
|
||||
* @param $script String: JavaScript text, no <script> tags
|
||||
* @param $script String: JavaScript text, no "<script>" tags
|
||||
*/
|
||||
public function addInlineScript( $script ) {
|
||||
$this->mScripts .= Html::inlineScript( "\n$script\n" ) . "\n";
|
||||
|
|
@ -780,7 +779,7 @@ class OutputPage extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* "HTML title" means the contents of <title>.
|
||||
* "HTML title" means the contents of "<title>".
|
||||
* It is stored as plain, unescaped text and will be run through htmlspecialchars in the skin file.
|
||||
*
|
||||
* @param $name string
|
||||
|
|
@ -794,7 +793,7 @@ class OutputPage extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the "HTML title", i.e. the content of the <title> tag.
|
||||
* Return the "HTML title", i.e. the content of the "<title>" tag.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
|
|
@ -805,7 +804,7 @@ class OutputPage extends ContextSource {
|
|||
/**
|
||||
* Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
|
||||
*
|
||||
* param @t Title
|
||||
* @param $t Title
|
||||
*/
|
||||
public function setRedirectedFrom( $t ) {
|
||||
$this->mRedirectedFrom = $t;
|
||||
|
|
@ -1363,11 +1362,11 @@ class OutputPage extends ContextSource {
|
|||
* Set the timestamp of the revision which will be displayed. This is used
|
||||
* to avoid a extra DB call in Skin::lastModified().
|
||||
*
|
||||
* @param $revid Mixed: string, or null
|
||||
* @param $timestamp Mixed: string, or null
|
||||
* @return Mixed: previous value
|
||||
*/
|
||||
public function setRevisionTimestamp( $timestmap ) {
|
||||
return wfSetVar( $this->mRevisionTimestamp, $timestmap );
|
||||
public function setRevisionTimestamp( $timestamp) {
|
||||
return wfSetVar( $this->mRevisionTimestamp, $timestamp );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1722,6 +1721,16 @@ class OutputPage extends ContextSource {
|
|||
$this->mVaryHeader[$header] = array_unique( (array)$this->mVaryHeader[$header] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Vary: header on which to vary caches. Based on the keys of $mVaryHeader,
|
||||
* such as Accept-Encoding or Cookie
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public function getVaryHeader() {
|
||||
return 'Vary: ' . join( ', ', array_keys( $this->mVaryHeader ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a complete X-Vary-Options header
|
||||
*
|
||||
|
|
@ -1834,11 +1843,12 @@ class OutputPage extends ContextSource {
|
|||
$response->header( "ETag: $this->mETag" );
|
||||
}
|
||||
|
||||
$this->addVaryHeader( 'Cookie' );
|
||||
$this->addAcceptLanguage();
|
||||
|
||||
# don't serve compressed data to clients who can't handle it
|
||||
# maintain different caches for logged-in users and non-logged in ones
|
||||
$response->header( 'Vary: ' . join( ', ', array_keys( $this->mVaryHeader ) ) );
|
||||
$response->header( $this->getVaryHeader() );
|
||||
|
||||
if ( $wgUseXVO ) {
|
||||
# Add an X-Vary-Options header for Squid with Wikimedia patches
|
||||
|
|
@ -2017,11 +2027,11 @@ class OutputPage extends ContextSource {
|
|||
/**
|
||||
* Prepare this object to display an error page; disable caching and
|
||||
* indexing, clear the current text and redirect, set the page's title
|
||||
* and optionally an custom HTML title (content of the <title> tag).
|
||||
* and optionally an custom HTML title (content of the "<title>" tag).
|
||||
*
|
||||
* @param $pageTitle String|Message will be passed directly to setPageTitle()
|
||||
* @param $htmlTitle String|Message will be passed directly to setHTMLTitle();
|
||||
* optional, if not passed the <title> attribute will be
|
||||
* optional, if not passed the "<title>" attribute will be
|
||||
* based on $pageTitle
|
||||
*/
|
||||
public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
|
||||
|
|
@ -2385,7 +2395,7 @@ $templates
|
|||
/**
|
||||
* @param $sk Skin The given Skin
|
||||
* @param $includeStyle Boolean: unused
|
||||
* @return String: The doctype, opening <html>, and head element.
|
||||
* @return String: The doctype, opening "<html>", and head element.
|
||||
*/
|
||||
public function headElement( Skin $sk, $includeStyle = true ) {
|
||||
global $wgContLang;
|
||||
|
|
@ -2510,19 +2520,21 @@ $templates
|
|||
* @param $only String ResourceLoaderModule TYPE_ class constant
|
||||
* @param $useESI boolean
|
||||
* @param $extraQuery Array with extra query parameters to add to each request. array( param => value )
|
||||
* @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a <script src="..."> tag
|
||||
* @return string html <script> and <style> tags
|
||||
* @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a "<script src='...'>" tag
|
||||
* @return string html "<script>" and "<style>" tags
|
||||
*/
|
||||
protected function makeResourceLoaderLink( $modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false ) {
|
||||
global $wgResourceLoaderUseESI;
|
||||
|
||||
$modules = (array) $modules;
|
||||
|
||||
if ( !count( $modules ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( count( $modules ) > 1 ) {
|
||||
// Remove duplicate module requests
|
||||
$modules = array_unique( (array) $modules );
|
||||
$modules = array_unique( $modules );
|
||||
// Sort module names so requests are more uniform
|
||||
sort( $modules );
|
||||
|
||||
|
|
@ -2539,7 +2551,7 @@ $templates
|
|||
// Create keyed-by-group list of module objects from modules list
|
||||
$groups = array();
|
||||
$resourceLoader = $this->getResourceLoader();
|
||||
foreach ( (array) $modules as $name ) {
|
||||
foreach ( $modules as $name ) {
|
||||
$module = $resourceLoader->getModule( $name );
|
||||
# Check that we're allowed to include this module on this page
|
||||
if ( !$module
|
||||
|
|
@ -2560,7 +2572,7 @@ $templates
|
|||
}
|
||||
|
||||
$links = '';
|
||||
foreach ( $groups as $group => $modules ) {
|
||||
foreach ( $groups as $group => $grpModules ) {
|
||||
// Special handling for user-specific groups
|
||||
$user = null;
|
||||
if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
|
||||
|
|
@ -2584,10 +2596,10 @@ $templates
|
|||
$context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
|
||||
// Extract modules that know they're empty
|
||||
$emptyModules = array ();
|
||||
foreach ( $modules as $key => $module ) {
|
||||
foreach ( $grpModules as $key => $module ) {
|
||||
if ( $module->isKnownEmpty( $context ) ) {
|
||||
$emptyModules[$key] = 'ready';
|
||||
unset( $modules[$key] );
|
||||
unset( $grpModules[$key] );
|
||||
}
|
||||
}
|
||||
// Inline empty modules: since they're empty, just mark them as 'ready'
|
||||
|
|
@ -2605,7 +2617,7 @@ $templates
|
|||
}
|
||||
|
||||
// If there are no modules left, skip this group
|
||||
if ( $modules === array() ) {
|
||||
if ( count( $grpModules ) === 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -2616,12 +2628,12 @@ $templates
|
|||
if ( $group === 'private' ) {
|
||||
if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
|
||||
$links .= Html::inlineStyle(
|
||||
$resourceLoader->makeModuleResponse( $context, $modules )
|
||||
$resourceLoader->makeModuleResponse( $context, $grpModules )
|
||||
);
|
||||
} else {
|
||||
$links .= Html::inlineScript(
|
||||
ResourceLoader::makeLoaderConditionalScript(
|
||||
$resourceLoader->makeModuleResponse( $context, $modules )
|
||||
$resourceLoader->makeModuleResponse( $context, $grpModules )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -2637,7 +2649,7 @@ $templates
|
|||
if ( $group === 'user' ) {
|
||||
// Get the maximum timestamp
|
||||
$timestamp = 1;
|
||||
foreach ( $modules as $module ) {
|
||||
foreach ( $grpModules as $module ) {
|
||||
$timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
|
||||
}
|
||||
// Add a version parameter so cache will break when things change
|
||||
|
|
@ -2645,7 +2657,7 @@ $templates
|
|||
}
|
||||
|
||||
$url = ResourceLoader::makeLoaderURL(
|
||||
array_keys( $modules ),
|
||||
array_keys( $grpModules ),
|
||||
$this->getLanguage()->getCode(),
|
||||
$this->getSkin()->getSkinName(),
|
||||
$user,
|
||||
|
|
@ -2688,7 +2700,7 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* JS stuff to put in the <head>. This is the startup module, config
|
||||
* JS stuff to put in the "<head>". This is the startup module, config
|
||||
* vars and modules marked with position 'top'
|
||||
*
|
||||
* @return String: HTML fragment
|
||||
|
|
@ -2736,12 +2748,12 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* JS stuff to put at the 'bottom', which can either be the bottom of the <body>
|
||||
* or the bottom of the <head> depending on $wgResourceLoaderExperimentalAsyncLoading:
|
||||
* JS stuff to put at the 'bottom', which can either be the bottom of the "<body>"
|
||||
* or the bottom of the "<head>" depending on $wgResourceLoaderExperimentalAsyncLoading:
|
||||
* modules marked with position 'bottom', legacy scripts ($this->mScripts),
|
||||
* user preferences, site JS and user JS
|
||||
*
|
||||
* @param $inHead boolean If true, this HTML goes into the <head>, if false it goes into the <body>
|
||||
* @param $inHead boolean If true, this HTML goes into the "<head>", if false it goes into the "<body>"
|
||||
* @return string
|
||||
*/
|
||||
function getScriptsForBottomQueue( $inHead ) {
|
||||
|
|
@ -2857,7 +2869,7 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* JS stuff to put at the bottom of the <body>
|
||||
* JS stuff to put at the bottom of the "<body>"
|
||||
* @return string
|
||||
*/
|
||||
function getBottomScripts() {
|
||||
|
|
@ -2872,7 +2884,7 @@ $templates
|
|||
/**
|
||||
* Add one or more variables to be set in mw.config in JavaScript.
|
||||
*
|
||||
* @param $key {String|Array} Key or array of key/value pars.
|
||||
* @param $keys {String|Array} Key or array of key/value pairs.
|
||||
* @param $value {Mixed} [optional] Value of the configuration variable.
|
||||
*/
|
||||
public function addJsConfigVars( $keys, $value = null ) {
|
||||
|
|
@ -2955,6 +2967,9 @@ $templates
|
|||
'wgPageContentLanguage' => $lang->getCode(),
|
||||
'wgSeparatorTransformTable' => $compactSeparatorTransTable,
|
||||
'wgDigitTransformTable' => $compactDigitTransTable,
|
||||
'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
|
||||
'wgMonthNames' => $lang->getMonthNamesArray(),
|
||||
'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
|
||||
'wgRelevantPageName' => $relevantTitle->getPrefixedDBKey(),
|
||||
);
|
||||
if ( $wgContLang->hasVariants() ) {
|
||||
|
|
@ -3008,7 +3023,7 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* @param $addContentType bool: Whether <meta> specifying content type should be returned
|
||||
* @param $addContentType bool: Whether "<meta>" specifying content type should be returned
|
||||
*
|
||||
* @return array in format "link name or number => 'link html'".
|
||||
*/
|
||||
|
|
@ -3242,7 +3257,7 @@ $templates
|
|||
|
||||
/**
|
||||
* @param $unused
|
||||
* @param $addContentType bool: Whether <meta> specifying content type should be returned
|
||||
* @param $addContentType bool: Whether "<meta>" specifying content type should be returned
|
||||
*
|
||||
* @return string HTML tag links to be put in the header.
|
||||
*/
|
||||
|
|
@ -3251,7 +3266,7 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* Generate a <link rel/> for a feed.
|
||||
* Generate a "<link rel/>" for a feed.
|
||||
*
|
||||
* @param $type String: feed type
|
||||
* @param $url String: URL to the feed
|
||||
|
|
@ -3306,7 +3321,7 @@ $templates
|
|||
}
|
||||
|
||||
/**
|
||||
* Build a set of <link>s for the stylesheets specified in the $this->styles array.
|
||||
* Build a set of "<link>" elements for the stylesheets specified in the $this->styles array.
|
||||
* These will be applied to various media & IE conditionals.
|
||||
*
|
||||
* @return string
|
||||
|
|
|
|||
|
|
@ -175,6 +175,15 @@ abstract class IndexPager extends ContextSource implements Pager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Database object in use
|
||||
*
|
||||
* @return DatabaseBase
|
||||
*/
|
||||
public function getDatabase() {
|
||||
return $this->mDb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the query, using information from the object context. This function
|
||||
* has been kept minimal to make it overridable if necessary, to allow for
|
||||
|
|
@ -194,6 +203,7 @@ abstract class IndexPager extends ContextSource implements Pager {
|
|||
$queryLimit,
|
||||
$descending
|
||||
);
|
||||
|
||||
$this->extractResultInfo( $this->mOffset, $queryLimit, $this->mResult );
|
||||
$this->mQueryDone = true;
|
||||
|
||||
|
|
@ -303,7 +313,20 @@ abstract class IndexPager extends ContextSource implements Pager {
|
|||
* @param $descending Boolean: query direction, false for ascending, true for descending
|
||||
* @return ResultWrapper
|
||||
*/
|
||||
function reallyDoQuery( $offset, $limit, $descending ) {
|
||||
public function reallyDoQuery( $offset, $limit, $descending ) {
|
||||
list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo( $offset, $limit, $descending );
|
||||
return $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build variables to use by the database wrapper.
|
||||
*
|
||||
* @param $offset String: index offset, inclusive
|
||||
* @param $limit Integer: exact query limit
|
||||
* @param $descending Boolean: query direction, false for ascending, true for descending
|
||||
* @return array
|
||||
*/
|
||||
protected function buildQueryInfo( $offset, $limit, $descending ) {
|
||||
$fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
|
||||
$info = $this->getQueryInfo();
|
||||
$tables = $info['tables'];
|
||||
|
|
@ -327,8 +350,7 @@ abstract class IndexPager extends ContextSource implements Pager {
|
|||
$conds[] = $this->mIndexField . $operator . $this->mDb->addQuotes( $offset );
|
||||
}
|
||||
$options['LIMIT'] = intval( $limit );
|
||||
$res = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
|
||||
return new ResultWrapper( $this->mDb, $res );
|
||||
return array( $tables, $fields, $conds, $fname, $options, $join_conds );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -980,7 +1002,7 @@ abstract class TablePager extends IndexPager {
|
|||
* @protected
|
||||
*
|
||||
* @param $row Object: the database result row
|
||||
* @return Array of <attr> => <value>
|
||||
* @return Array of attribute => value
|
||||
*/
|
||||
function getRowAttrs( $row ) {
|
||||
$class = $this->getRowClass( $row );
|
||||
|
|
@ -1095,7 +1117,7 @@ abstract class TablePager extends IndexPager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a <select> element which has options for each of the allowed limits
|
||||
* Get a "<select>" element which has options for each of the allowed limits
|
||||
*
|
||||
* @return String: HTML fragment
|
||||
*/
|
||||
|
|
@ -1125,7 +1147,7 @@ abstract class TablePager extends IndexPager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get <input type="hidden"> elements for use in a method="get" form.
|
||||
* Get \<input type="hidden"\> elements for use in a method="get" form.
|
||||
* Resubmits all defined elements of the query string, except for a
|
||||
* blacklist, passed in the $blacklist parameter.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@ class Preferences {
|
|||
|
||||
if ( $wgEnableAPI ) {
|
||||
# Some random gibberish as a proposed default
|
||||
// @fixme This should use CryptRand but we may not want to read urandom on every view
|
||||
// @todo Fixme: this should use CryptRand but we may not want to read urandom on every view
|
||||
$hash = sha1( mt_rand() . microtime( true ) );
|
||||
|
||||
$defaultPreferences['watchlisttoken'] = array(
|
||||
|
|
@ -1587,7 +1587,7 @@ class PreferencesForm extends HTMLForm {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the <legend> for a given section key. Normally this is the
|
||||
* Get the "<legend>" for a given section key. Normally this is the
|
||||
* prefs-$key message but we'll allow extensions to override it.
|
||||
* @param $key string
|
||||
* @return string
|
||||
|
|
|
|||
|
|
@ -318,10 +318,12 @@ class ProtectionForm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) {
|
||||
WatchAction::doWatch( $this->mTitle, $wgUser );
|
||||
} elseif ( $this->mTitle->userIsWatching() ) {
|
||||
WatchAction::doUnwatch( $this->mTitle, $wgUser );
|
||||
if ( $wgUser->isLoggedIn() && $wgRequest->getCheck( 'mwProtectWatch' ) != $wgUser->isWatched( $this->mTitle ) ) {
|
||||
if ( $wgRequest->getCheck( 'mwProtectWatch' ) ) {
|
||||
WatchAction::doWatch( $this->mTitle, $wgUser );
|
||||
} else {
|
||||
WatchAction::doUnwatch( $this->mTitle, $wgUser );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Utility class for creating new RC entries
|
||||
*
|
||||
|
|
@ -108,13 +108,7 @@ class RecentChange {
|
|||
* @return RecentChange
|
||||
*/
|
||||
public static function newFromId( $rcid ) {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$row = $dbr->selectRow( 'recentchanges', '*', array( 'rc_id' => $rcid ), __METHOD__ );
|
||||
if( $row !== false ) {
|
||||
return self::newFromRow( $row );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return self::newFromConds( array( 'rc_id' => $rcid ), __METHOD__ );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -126,18 +120,12 @@ class RecentChange {
|
|||
*/
|
||||
public static function newFromConds( $conds, $fname = __METHOD__ ) {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select(
|
||||
'recentchanges',
|
||||
'*',
|
||||
$conds,
|
||||
$fname
|
||||
);
|
||||
if( $res instanceof ResultWrapper && $res->numRows() > 0 ) {
|
||||
$row = $res->fetchObject();
|
||||
$res->free();
|
||||
$row = $dbr->selectRow( 'recentchanges', '*', $conds, $fname );
|
||||
if ( $row !== false ) {
|
||||
return self::newFromRow( $row );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
# Accessors
|
||||
|
|
@ -170,7 +158,7 @@ class RecentChange {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return bool|\Title
|
||||
* @return bool|Title
|
||||
*/
|
||||
public function getMovedToTitle() {
|
||||
if( $this->mMovedToTitle === false ) {
|
||||
|
|
@ -243,13 +231,15 @@ class RecentChange {
|
|||
}
|
||||
$title = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
|
||||
|
||||
# @todo FIXME: This would be better as an extension hook
|
||||
$enotif = new EmailNotification();
|
||||
$status = $enotif->notifyOnPageChange( $editor, $title,
|
||||
$this->mAttribs['rc_timestamp'],
|
||||
$this->mAttribs['rc_comment'],
|
||||
$this->mAttribs['rc_minor'],
|
||||
$this->mAttribs['rc_last_oldid'] );
|
||||
if ( wfRunHooks( 'AbortEmailNotification', array($editor, $title) ) ) {
|
||||
# @todo FIXME: This would be better as an extension hook
|
||||
$enotif = new EmailNotification();
|
||||
$status = $enotif->notifyOnPageChange( $editor, $title,
|
||||
$this->mAttribs['rc_timestamp'],
|
||||
$this->mAttribs['rc_comment'],
|
||||
$this->mAttribs['rc_minor'],
|
||||
$this->mAttribs['rc_last_oldid'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -781,7 +771,7 @@ class RecentChange {
|
|||
}
|
||||
} else {
|
||||
$ip = $wgRequest->getIP();
|
||||
if( !$ip )
|
||||
if( !$ip )
|
||||
$ip = '';
|
||||
}
|
||||
return $ip;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
/**
|
||||
* @todo document
|
||||
*/
|
||||
class Revision {
|
||||
class Revision implements IDBAccessObject {
|
||||
protected $mId;
|
||||
protected $mPage;
|
||||
protected $mUserText;
|
||||
|
|
@ -51,7 +51,7 @@ class Revision {
|
|||
const DELETED_RESTRICTED = 8;
|
||||
// Convenience field
|
||||
const SUPPRESSED_USER = 12;
|
||||
// Audience options for Revision::getText()
|
||||
// Audience options for accessors
|
||||
const FOR_PUBLIC = 1;
|
||||
const FOR_THIS_USER = 2;
|
||||
const RAW = 3;
|
||||
|
|
@ -60,11 +60,17 @@ class Revision {
|
|||
* Load a page revision from a given revision ID number.
|
||||
* Returns null if no such revision can be found.
|
||||
*
|
||||
* $flags include:
|
||||
* IDBAccessObject::LATEST_READ : Select the data from the master
|
||||
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
|
||||
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
|
||||
*
|
||||
* @param $id Integer
|
||||
* @param $flags Integer (optional)
|
||||
* @return Revision or null
|
||||
*/
|
||||
public static function newFromId( $id ) {
|
||||
return Revision::newFromConds( array( 'rev_id' => intval( $id ) ) );
|
||||
public static function newFromId( $id, $flags = 0 ) {
|
||||
return self::newFromConds( array( 'rev_id' => intval( $id ) ), $flags );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,11 +78,17 @@ class Revision {
|
|||
* that's attached to a given title. If not attached
|
||||
* to that title, will return null.
|
||||
*
|
||||
* $flags include:
|
||||
* IDBAccessObject::LATEST_READ : Select the data from the master
|
||||
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
|
||||
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
|
||||
*
|
||||
* @param $title Title
|
||||
* @param $id Integer (optional)
|
||||
* @param $flags Integer Bitfield (optional)
|
||||
* @return Revision or null
|
||||
*/
|
||||
public static function newFromTitle( $title, $id = 0 ) {
|
||||
public static function newFromTitle( $title, $id = 0, $flags = 0 ) {
|
||||
$conds = array(
|
||||
'page_namespace' => $title->getNamespace(),
|
||||
'page_title' => $title->getDBkey()
|
||||
|
|
@ -84,7 +96,7 @@ class Revision {
|
|||
if ( $id ) {
|
||||
// Use the specified ID
|
||||
$conds['rev_id'] = $id;
|
||||
} elseif ( wfGetLB()->getServerCount() > 1 ) {
|
||||
} elseif ( !( $flags & self::AVOID_MASTER ) && wfGetLB()->getServerCount() > 1 ) {
|
||||
// Get the latest revision ID from the master
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
|
||||
|
|
@ -96,7 +108,7 @@ class Revision {
|
|||
// Use a join to get the latest revision
|
||||
$conds[] = 'rev_id=page_latest';
|
||||
}
|
||||
return Revision::newFromConds( $conds );
|
||||
return self::newFromConds( $conds, $flags );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,15 +116,21 @@ class Revision {
|
|||
* that's attached to a given page ID.
|
||||
* Returns null if no such revision can be found.
|
||||
*
|
||||
* $flags include:
|
||||
* IDBAccessObject::LATEST_READ : Select the data from the master
|
||||
* IDBAccessObject::LOCKING_READ : Select & lock the data from the master
|
||||
* IDBAccessObject::AVOID_MASTER : Avoid master queries; data may be stale
|
||||
*
|
||||
* @param $revId Integer
|
||||
* @param $pageId Integer (optional)
|
||||
* @param $flags Integer Bitfield (optional)
|
||||
* @return Revision or null
|
||||
*/
|
||||
public static function newFromPageId( $pageId, $revId = 0 ) {
|
||||
public static function newFromPageId( $pageId, $revId = 0, $flags = 0 ) {
|
||||
$conds = array( 'page_id' => $pageId );
|
||||
if ( $revId ) {
|
||||
$conds['rev_id'] = $revId;
|
||||
} elseif ( wfGetLB()->getServerCount() > 1 ) {
|
||||
} elseif ( !( $flags & self::AVOID_MASTER ) && wfGetLB()->getServerCount() > 1 ) {
|
||||
// Get the latest revision ID from the master
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
|
||||
|
|
@ -123,7 +141,7 @@ class Revision {
|
|||
} else {
|
||||
$conds[] = 'rev_id = page_latest';
|
||||
}
|
||||
return Revision::newFromConds( $conds );
|
||||
return self::newFromConds( $conds, $flags );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -189,7 +207,7 @@ class Revision {
|
|||
* @return Revision or null
|
||||
*/
|
||||
public static function loadFromId( $db, $id ) {
|
||||
return Revision::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) );
|
||||
return self::loadFromConds( $db, array( 'rev_id' => intval( $id ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,7 +227,7 @@ class Revision {
|
|||
} else {
|
||||
$conds[] = 'rev_id=page_latest';
|
||||
}
|
||||
return Revision::loadFromConds( $db, $conds );
|
||||
return self::loadFromConds( $db, $conds );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -228,7 +246,7 @@ class Revision {
|
|||
} else {
|
||||
$matchId = 'page_latest';
|
||||
}
|
||||
return Revision::loadFromConds( $db,
|
||||
return self::loadFromConds( $db,
|
||||
array( "rev_id=$matchId",
|
||||
'page_namespace' => $title->getNamespace(),
|
||||
'page_title' => $title->getDBkey() )
|
||||
|
|
@ -246,7 +264,7 @@ class Revision {
|
|||
* @return Revision or null
|
||||
*/
|
||||
public static function loadFromTimestamp( $db, $title, $timestamp ) {
|
||||
return Revision::loadFromConds( $db,
|
||||
return self::loadFromConds( $db,
|
||||
array( 'rev_timestamp' => $db->timestamp( $timestamp ),
|
||||
'page_namespace' => $title->getNamespace(),
|
||||
'page_title' => $title->getDBkey() )
|
||||
|
|
@ -257,14 +275,17 @@ class Revision {
|
|||
* Given a set of conditions, fetch a revision.
|
||||
*
|
||||
* @param $conditions Array
|
||||
* @param $flags integer (optional)
|
||||
* @return Revision or null
|
||||
*/
|
||||
public static function newFromConds( $conditions ) {
|
||||
$db = wfGetDB( DB_SLAVE );
|
||||
$rev = Revision::loadFromConds( $db, $conditions );
|
||||
if( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$rev = Revision::loadFromConds( $dbw, $conditions );
|
||||
private static function newFromConds( $conditions, $flags = 0 ) {
|
||||
$db = wfGetDB( ( $flags & self::LATEST_READ ) ? DB_MASTER : DB_SLAVE );
|
||||
$rev = self::loadFromConds( $db, $conditions, $flags );
|
||||
if ( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) {
|
||||
if ( !( $flags & self::LATEST_READ ) && !( $flags & self::AVOID_MASTER ) ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$rev = self::loadFromConds( $dbw, $conditions, $flags );
|
||||
}
|
||||
}
|
||||
return $rev;
|
||||
}
|
||||
|
|
@ -275,10 +296,11 @@ class Revision {
|
|||
*
|
||||
* @param $db DatabaseBase
|
||||
* @param $conditions Array
|
||||
* @param $flags integer (optional)
|
||||
* @return Revision or null
|
||||
*/
|
||||
private static function loadFromConds( $db, $conditions ) {
|
||||
$res = Revision::fetchFromConds( $db, $conditions );
|
||||
private static function loadFromConds( $db, $conditions, $flags = 0 ) {
|
||||
$res = self::fetchFromConds( $db, $conditions, $flags );
|
||||
if( $res ) {
|
||||
$row = $res->fetchObject();
|
||||
if( $row ) {
|
||||
|
|
@ -299,7 +321,7 @@ class Revision {
|
|||
* @return ResultWrapper
|
||||
*/
|
||||
public static function fetchRevision( $title ) {
|
||||
return Revision::fetchFromConds(
|
||||
return self::fetchFromConds(
|
||||
wfGetDB( DB_SLAVE ),
|
||||
array( 'rev_id=page_latest',
|
||||
'page_namespace' => $title->getNamespace(),
|
||||
|
|
@ -314,20 +336,25 @@ class Revision {
|
|||
*
|
||||
* @param $db DatabaseBase
|
||||
* @param $conditions Array
|
||||
* @param $flags integer (optional)
|
||||
* @return ResultWrapper
|
||||
*/
|
||||
private static function fetchFromConds( $db, $conditions ) {
|
||||
private static function fetchFromConds( $db, $conditions, $flags = 0 ) {
|
||||
$fields = array_merge(
|
||||
self::selectFields(),
|
||||
self::selectPageFields(),
|
||||
self::selectUserFields()
|
||||
);
|
||||
$options = array( 'LIMIT' => 1 );
|
||||
if ( $flags & self::FOR_UPDATE ) {
|
||||
$options[] = 'FOR UPDATE';
|
||||
}
|
||||
return $db->select(
|
||||
array( 'revision', 'page', 'user' ),
|
||||
$fields,
|
||||
$conditions,
|
||||
__METHOD__,
|
||||
array( 'LIMIT' => 1 ),
|
||||
$options,
|
||||
array( 'page' => self::pageJoinCond(), 'user' => self::userJoinCond() )
|
||||
);
|
||||
}
|
||||
|
|
@ -1037,7 +1064,7 @@ class Revision {
|
|||
if( $this->getTitle() ) {
|
||||
$prev = $this->getTitle()->getPreviousRevisionID( $this->getId() );
|
||||
if( $prev ) {
|
||||
return Revision::newFromTitle( $this->getTitle(), $prev );
|
||||
return self::newFromTitle( $this->getTitle(), $prev );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -1052,7 +1079,7 @@ class Revision {
|
|||
if( $this->getTitle() ) {
|
||||
$next = $this->getTitle()->getNextRevisionID( $this->getId() );
|
||||
if ( $next ) {
|
||||
return Revision::newFromTitle( $this->getTitle(), $next );
|
||||
return self::newFromTitle( $this->getTitle(), $next );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -1182,7 +1209,7 @@ class Revision {
|
|||
$text = gzdeflate( $text );
|
||||
$flags[] = 'gzip';
|
||||
} else {
|
||||
wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" );
|
||||
wfDebug( __METHOD__ . " -- no zlib support, not compressing\n" );
|
||||
}
|
||||
}
|
||||
return implode( ',', $flags );
|
||||
|
|
@ -1203,7 +1230,7 @@ class Revision {
|
|||
$this->checkContentModel();
|
||||
|
||||
$data = $this->mText;
|
||||
$flags = Revision::compressRevisionText( $data );
|
||||
$flags = self::compressRevisionText( $data );
|
||||
|
||||
# Write to external storage if required
|
||||
if( $wgDefaultExternalStore ) {
|
||||
|
|
@ -1237,7 +1264,6 @@ class Revision {
|
|||
$rev_id = isset( $this->mId )
|
||||
? $this->mId
|
||||
: $dbw->nextSequenceValue( 'revision_rev_id_seq' );
|
||||
|
||||
$row = array(
|
||||
'rev_id' => $rev_id,
|
||||
'rev_page' => $this->mPage,
|
||||
|
|
@ -1552,7 +1578,7 @@ class Revision {
|
|||
static function countByTitle( $db, $title ) {
|
||||
$id = $title->getArticleID();
|
||||
if( $id ) {
|
||||
return Revision::countByPageId( $db, $id );
|
||||
return self::countByPageId( $db, $id );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ abstract class RevisionItemBase {
|
|||
abstract public function canViewContent();
|
||||
|
||||
/**
|
||||
* Get the HTML of the list item. Should be include <li></li> tags.
|
||||
* Get the HTML of the list item. Should be include "<li></li>" tags.
|
||||
* This is used to show the list in HTML form, by the special page.
|
||||
*/
|
||||
abstract public function getHTML();
|
||||
|
|
|
|||
|
|
@ -692,6 +692,16 @@ class Sanitizer {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $attribute === 'align' && !in_array( $element, $cells ) ) {
|
||||
if ( $value === 'center' ) {
|
||||
$style .= ' margin-left: auto;';
|
||||
$property = 'margin-right';
|
||||
$value = 'auto';
|
||||
} else {
|
||||
$property = 'float';
|
||||
}
|
||||
}
|
||||
|
||||
$style .= " $property: $value;";
|
||||
|
||||
unset( $attribs[$attribute] );
|
||||
|
|
@ -1243,7 +1253,7 @@ class Sanitizer {
|
|||
* a. named char refs can only be < > & ", others are
|
||||
* numericized (this way we're well-formed even without a DTD)
|
||||
* b. any numeric char refs must be legal chars, not invalid or forbidden
|
||||
* c. use &#x, not &#X
|
||||
* c. use lower cased "&#x", not "&#X"
|
||||
* d. fix or reject non-valid attributes
|
||||
*
|
||||
* @param $text String
|
||||
|
|
@ -1411,7 +1421,7 @@ class Sanitizer {
|
|||
/**
|
||||
* If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
|
||||
* return the UTF-8 encoding of that character. Otherwise, returns
|
||||
* pseudo-entity source (eg &foo;)
|
||||
* pseudo-entity source (eg "&foo;")
|
||||
*
|
||||
* @param $name String
|
||||
* @return String
|
||||
|
|
|
|||
|
|
@ -22,13 +22,17 @@
|
|||
|
||||
/**
|
||||
* Class to expand PHP execution time for a function call.
|
||||
* Use this when performing changes that should not be interrupted.
|
||||
*
|
||||
* On construction, set_time_limit() is called and set to $seconds.
|
||||
* If the client aborts the connection, PHP will continue to run.
|
||||
* When the object goes out of scope, the timer is restarted, with
|
||||
* the original time limit minus the time the object existed.
|
||||
*/
|
||||
class ScopedPHPTimeout {
|
||||
protected $startTime; // float; seconds
|
||||
protected $oldTimeout; // integer; seconds
|
||||
protected $oldIgnoreAbort; // boolean
|
||||
|
||||
protected static $stackDepth = 0; // integer
|
||||
protected static $totalCalls = 0; // integer
|
||||
|
|
@ -50,6 +54,7 @@ class ScopedPHPTimeout {
|
|||
} elseif ( self::$stackDepth > 0 ) { // recursion guard
|
||||
trigger_error( "Resursive invocation of " . __CLASS__ . " attempted." );
|
||||
} else {
|
||||
$this->oldIgnoreAbort = ignore_user_abort( true );
|
||||
$this->oldTimeout = ini_set( 'max_execution_time', $seconds );
|
||||
$this->startTime = microtime( true );
|
||||
++self::$stackDepth;
|
||||
|
|
@ -73,6 +78,7 @@ class ScopedPHPTimeout {
|
|||
// take some measures to prevent this. Track total time and calls.
|
||||
self::$totalElapsed += $elapsed;
|
||||
--self::$stackDepth;
|
||||
ignore_user_abort( $this->oldIgnoreAbort );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ class SiteConfiguration {
|
|||
|
||||
/**
|
||||
* Optional callback to load full configuration data.
|
||||
* @var string|array
|
||||
*/
|
||||
public $fullLoadCallback = null;
|
||||
|
||||
|
|
@ -155,6 +156,8 @@ class SiteConfiguration {
|
|||
* argument and the wiki in the second one.
|
||||
* if suffix and lang are passed they will be used for the return value of
|
||||
* self::siteFromDB() and self::$suffixes will be ignored
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
public $siteParamsCallback = null;
|
||||
|
||||
|
|
@ -189,7 +192,7 @@ class SiteConfiguration {
|
|||
if( array_key_exists( $wiki, $thisSetting ) ) {
|
||||
$retval = $thisSetting[$wiki];
|
||||
break;
|
||||
} elseif( array_key_exists( "+$wiki", $thisSetting ) && is_array( $thisSetting["+$wiki"] ) ) {
|
||||
} elseif ( array_key_exists( "+$wiki", $thisSetting ) && is_array( $thisSetting["+$wiki"] ) ) {
|
||||
$retval = $thisSetting["+$wiki"];
|
||||
}
|
||||
|
||||
|
|
@ -203,8 +206,9 @@ class SiteConfiguration {
|
|||
}
|
||||
break 2;
|
||||
} elseif( array_key_exists( "+$tag", $thisSetting ) && is_array($thisSetting["+$tag"]) ) {
|
||||
if( !isset( $retval ) )
|
||||
if( !isset( $retval ) ) {
|
||||
$retval = array();
|
||||
}
|
||||
$retval = self::arrayMerge( $retval, $thisSetting["+$tag"] );
|
||||
}
|
||||
}
|
||||
|
|
@ -218,9 +222,10 @@ class SiteConfiguration {
|
|||
$retval = $thisSetting[$suffix];
|
||||
}
|
||||
break;
|
||||
} elseif( array_key_exists( "+$suffix", $thisSetting ) && is_array($thisSetting["+$suffix"]) ) {
|
||||
if (!isset($retval))
|
||||
} elseif ( array_key_exists( "+$suffix", $thisSetting ) && is_array($thisSetting["+$suffix"]) ) {
|
||||
if ( !isset( $retval ) ) {
|
||||
$retval = array();
|
||||
}
|
||||
$retval = self::arrayMerge( $retval, $thisSetting["+$suffix"] );
|
||||
}
|
||||
}
|
||||
|
|
@ -287,8 +292,9 @@ class SiteConfiguration {
|
|||
}
|
||||
|
||||
$value = $this->getSetting( $varname, $wiki, $params );
|
||||
if ( $append && is_array( $value ) && is_array( $GLOBALS[$var] ) )
|
||||
if ( $append && is_array( $value ) && is_array( $GLOBALS[$var] ) ) {
|
||||
$value = self::arrayMerge( $value, $GLOBALS[$var] );
|
||||
}
|
||||
if ( !is_null( $value ) ) {
|
||||
$localSettings[$var] = $value;
|
||||
}
|
||||
|
|
@ -408,8 +414,9 @@ class SiteConfiguration {
|
|||
}
|
||||
|
||||
foreach( $default as $name => $def ){
|
||||
if( !isset( $ret[$name] ) || ( is_array( $default[$name] ) && !is_array( $ret[$name] ) ) )
|
||||
if( !isset( $ret[$name] ) || ( is_array( $default[$name] ) && !is_array( $ret[$name] ) ) ) {
|
||||
$ret[$name] = $default[$name];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
|
@ -430,18 +437,21 @@ class SiteConfiguration {
|
|||
protected function mergeParams( $wiki, $suffix, /*array*/ $params, /*array*/ $wikiTags ){
|
||||
$ret = $this->getWikiParams( $wiki );
|
||||
|
||||
if( is_null( $ret['suffix'] ) )
|
||||
if( is_null( $ret['suffix'] ) ) {
|
||||
$ret['suffix'] = $suffix;
|
||||
}
|
||||
|
||||
$ret['tags'] = array_unique( array_merge( $ret['tags'], $wikiTags ) );
|
||||
|
||||
$ret['params'] += $params;
|
||||
|
||||
// Automatically fill that ones if needed
|
||||
if( !isset( $ret['params']['lang'] ) && !is_null( $ret['lang'] ) )
|
||||
if( !isset( $ret['params']['lang'] ) && !is_null( $ret['lang'] ) ){
|
||||
$ret['params']['lang'] = $ret['lang'];
|
||||
if( !isset( $ret['params']['site'] ) && !is_null( $ret['suffix'] ) )
|
||||
}
|
||||
if( !isset( $ret['params']['site'] ) && !is_null( $ret['suffix'] ) ) {
|
||||
$ret['params']['site'] = $ret['suffix'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
|
@ -455,8 +465,9 @@ class SiteConfiguration {
|
|||
public function siteFromDB( $db ) {
|
||||
// Allow override
|
||||
$def = $this->getWikiParams( $db );
|
||||
if( !is_null( $def['suffix'] ) && !is_null( $def['lang'] ) )
|
||||
if( !is_null( $def['suffix'] ) && !is_null( $def['lang'] ) ) {
|
||||
return array( $def['suffix'], $def['lang'] );
|
||||
}
|
||||
|
||||
$site = null;
|
||||
$lang = null;
|
||||
|
|
@ -513,7 +524,7 @@ class SiteConfiguration {
|
|||
}
|
||||
|
||||
public function loadFullData() {
|
||||
if ($this->fullLoadCallback && !$this->fullLoadDone) {
|
||||
if ( $this->fullLoadCallback && !$this->fullLoadDone ) {
|
||||
call_user_func( $this->fullLoadCallback, $this );
|
||||
$this->fullLoadDone = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ abstract class Skin extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Make a <script> tag containing global variables
|
||||
* Make a "<script>" tag containing global variables
|
||||
*
|
||||
* @deprecated in 1.19
|
||||
* @param $unused
|
||||
|
|
@ -363,7 +363,7 @@ abstract class Skin extends ContextSource {
|
|||
* inside ->getOutput() is deprecated. The $out arg is kept
|
||||
* for compatibility purposes with skins.
|
||||
* @param $out OutputPage
|
||||
* @delete
|
||||
* @todo delete
|
||||
*/
|
||||
abstract function setupSkinUserCss( OutputPage $out );
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ abstract class Skin extends ContextSource {
|
|||
|
||||
/**
|
||||
* This will be called by OutputPage::headElement when it is creating the
|
||||
* <body> tag, skins can override it if they have a need to add in any
|
||||
* "<body>" tag, skins can override it if they have a need to add in any
|
||||
* body attributes or classes of their own.
|
||||
* @param $out OutputPage
|
||||
* @param $bodyAttrs Array
|
||||
|
|
@ -636,9 +636,9 @@ abstract class Skin extends ContextSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* This gets called shortly before the </body> tag.
|
||||
* This gets called shortly before the "</body>" tag.
|
||||
*
|
||||
* @return String HTML-wrapped JS code to be put before </body>
|
||||
* @return String HTML-wrapped JS code to be put before "</body>"
|
||||
*/
|
||||
function bottomScripts() {
|
||||
// TODO and the suckage continues. This function is really just a wrapper around
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class LegacyTemplate extends BaseTemplate {
|
|||
}
|
||||
|
||||
/**
|
||||
* This will be called immediately after the <body> tag. Split into
|
||||
* This will be called immediately after the "<body>" tag. Split into
|
||||
* two functions to make it easier to subclass.
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -159,8 +159,8 @@ class LegacyTemplate extends BaseTemplate {
|
|||
}
|
||||
|
||||
/**
|
||||
* This gets called shortly before the </body> tag.
|
||||
* @return String HTML to be put before </body>
|
||||
* This gets called shortly before the "</body>" tag.
|
||||
* @return String HTML to be put before "</body>"
|
||||
*/
|
||||
function afterContent() {
|
||||
return $this->doAfterContent();
|
||||
|
|
@ -638,7 +638,7 @@ class LegacyTemplate extends BaseTemplate {
|
|||
$title = $this->getSkin()->getTitle();
|
||||
|
||||
if ( $wgOut->isArticleRelated() ) {
|
||||
if ( $title->userIsWatching() ) {
|
||||
if ( $wgUser->isWatched( $title ) ) {
|
||||
$text = wfMsg( 'unwatchthispage' );
|
||||
$query = array(
|
||||
'action' => 'unwatch',
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class SkinTemplate extends Skin {
|
|||
var $template = 'QuickTemplate';
|
||||
|
||||
/**
|
||||
* Whether this skin use OutputPage::headElement() to generate the <head>
|
||||
* Whether this skin use OutputPage::headElement() to generate the "<head>"
|
||||
* tag
|
||||
*/
|
||||
var $useHeadElement = false;
|
||||
|
|
@ -258,7 +258,7 @@ class SkinTemplate extends Skin {
|
|||
/* XXX currently unused, might get useful later
|
||||
$tpl->set( 'editable', ( !$title->isSpecialPage() ) );
|
||||
$tpl->set( 'exists', $title->getArticleID() != 0 );
|
||||
$tpl->set( 'watch', $title->userIsWatching() ? 'unwatch' : 'watch' );
|
||||
$tpl->set( 'watch', $user->isWatched( $title ) ? 'unwatch' : 'watch' );
|
||||
$tpl->set( 'protect', count( $title->isProtected() ) ? 'unprotect' : 'protect' );
|
||||
$tpl->set( 'helppage', $this->msg( 'helppage' )->text() );
|
||||
*/
|
||||
|
|
@ -974,7 +974,7 @@ class SkinTemplate extends Skin {
|
|||
* a change to that procedure these messages will have to remain as
|
||||
* the global versions.
|
||||
*/
|
||||
$mode = $title->userIsWatching() ? 'unwatch' : 'watch';
|
||||
$mode = $user->isWatched( $title ) ? 'unwatch' : 'watch';
|
||||
$token = WatchAction::getWatchToken( $title, $user, $mode );
|
||||
$content_navigation['actions'][$mode] = array(
|
||||
'class' => $onPage && ( $action == 'watch' || $action == 'unwatch' ) ? 'selected' : false,
|
||||
|
|
@ -1605,26 +1605,39 @@ abstract class BaseTemplate extends QuickTemplate {
|
|||
* Makes a link, usually used by makeListItem to generate a link for an item
|
||||
* in a list used in navigation lists, portlets, portals, sidebars, etc...
|
||||
*
|
||||
* $key is a string, usually a key from the list you are generating this link from
|
||||
* $item is an array containing some of a specific set of keys.
|
||||
* The text of the link will be generated either from the contents of the "text"
|
||||
* key in the $item array, if a "msg" key is present a message by that name will
|
||||
* be used, and if neither of those are set the $key will be used as a message name.
|
||||
* @param $key string usually a key from the list you are generating this
|
||||
* link from.
|
||||
* @param $item array contains some of a specific set of keys.
|
||||
*
|
||||
* The text of the link will be generated either from the contents of the
|
||||
* "text" key in the $item array, if a "msg" key is present a message by
|
||||
* that name will be used, and if neither of those are set the $key will be
|
||||
* used as a message name.
|
||||
*
|
||||
* If a "href" key is not present makeLink will just output htmlescaped text.
|
||||
* The href, id, class, rel, and type keys are used as attributes for the link if present.
|
||||
* If an "id" or "single-id" (if you don't want the actual id to be output on the link)
|
||||
* is present it will be used to generate a tooltip and accesskey for the link.
|
||||
* The "href", "id", "class", "rel", and "type" keys are used as attributes
|
||||
* for the link if present.
|
||||
*
|
||||
* If an "id" or "single-id" (if you don't want the actual id to be output
|
||||
* on the link) is present it will be used to generate a tooltip and
|
||||
* accesskey for the link.
|
||||
*
|
||||
* If you don't want an accesskey, set $item['tooltiponly'] = true;
|
||||
* $options can be used to affect the output of a link:
|
||||
* You can use a text-wrapper key to specify a list of elements to wrap the
|
||||
* text of a link in. This should be an array of arrays containing a 'tag' and
|
||||
* optionally an 'attributes' key. If you only have one element you don't need
|
||||
* to wrap it in another array. eg: To use <a><span>...</span></a> in all links
|
||||
* use array( 'text-wrapper' => array( 'tag' => 'span' ) ) for your options.
|
||||
* A link-class key can be used to specify additional classes to apply to all links.
|
||||
* A link-fallback can be used to specify a tag to use instead of <a> if there is
|
||||
* no link. eg: If you specify 'link-fallback' => 'span' than any non-link will
|
||||
* output a <span> instead of just text.
|
||||
*
|
||||
* @param $options array can be used to affect the output of a link.
|
||||
* Possible options are:
|
||||
* - 'text-wrapper' key to specify a list of elements to wrap the text of
|
||||
* a link in. This should be an array of arrays containing a 'tag' and
|
||||
* optionally an 'attributes' key. If you only have one element you don't
|
||||
* need to wrap it in another array. eg: To use <a><span>...</span></a>
|
||||
* in all links use array( 'text-wrapper' => array( 'tag' => 'span' ) )
|
||||
* for your options.
|
||||
* - 'link-class' key can be used to specify additional classes to apply
|
||||
* to all links.
|
||||
* - 'link-fallback' can be used to specify a tag to use instead of "<a>"
|
||||
* if there is no link. eg: If you specify 'link-fallback' => 'span' than
|
||||
* any non-link will output a "<span>" instead of just text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function makeLink( $key, $item, $options = array() ) {
|
||||
|
|
@ -1686,17 +1699,22 @@ abstract class BaseTemplate extends QuickTemplate {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates a list item for a navigation, portlet, portal, sidebar... etc list
|
||||
* $key is a string, usually a key from the list you are generating this link from
|
||||
* $item is an array of list item data containing some of a specific set of keys.
|
||||
* Generates a list item for a navigation, portlet, portal, sidebar... list
|
||||
*
|
||||
* @param $key string, usually a key from the list you are generating this link from.
|
||||
* @param $item array, of list item data containing some of a specific set of keys.
|
||||
* The "id" and "class" keys will be used as attributes for the list item,
|
||||
* if "active" contains a value of true a "active" class will also be appended to class.
|
||||
* If you want something other than a <li> you can pass a tag name such as
|
||||
*
|
||||
* @param $options array
|
||||
*
|
||||
* If you want something other than a "<li>" you can pass a tag name such as
|
||||
* "tag" => "span" in the $options array to change the tag used.
|
||||
* link/content data for the list item may come in one of two forms
|
||||
* A "links" key may be used, in which case it should contain an array with
|
||||
* a list of links to include inside the list item, see makeLink for the format
|
||||
* of individual links array items.
|
||||
* a list of links to include inside the list item, see makeLink for the
|
||||
* format of individual links array items.
|
||||
*
|
||||
* Otherwise the relevant keys from the list item $item array will be passed
|
||||
* to makeLink instead. Note however that "id" and "class" are used by the
|
||||
* list item directly so they will not be passed to makeLink
|
||||
|
|
@ -1704,6 +1722,7 @@ abstract class BaseTemplate extends QuickTemplate {
|
|||
* If you need an id or class on a single link you should include a "links"
|
||||
* array with just one link item inside of it.
|
||||
* $options is also passed on to makeLink calls
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function makeListItem( $key, $item, $options = array() ) {
|
||||
|
|
|
|||
|
|
@ -589,15 +589,70 @@ class SpecialPage {
|
|||
$out->setPageTitle( $this->getDescription() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point.
|
||||
*
|
||||
* @since 1.20
|
||||
*
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
public final function run( $subPage ) {
|
||||
/**
|
||||
* Gets called before @see SpecialPage::execute.
|
||||
*
|
||||
* @since 1.20
|
||||
*
|
||||
* @param $special SpecialPage
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
wfRunHooks( 'SpecialPageBeforeExecute', array( &$this, $subPage ) );
|
||||
|
||||
$this->beforeExecute( $subPage );
|
||||
$this->execute( $subPage );
|
||||
$this->afterExecute( $subPage );
|
||||
|
||||
/**
|
||||
* Gets called after @see SpecialPage::execute.
|
||||
*
|
||||
* @since 1.20
|
||||
*
|
||||
* @param $special SpecialPage
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
wfRunHooks( 'SpecialPageAfterExecute', array( &$this, $subPage ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called before @see SpecialPage::execute.
|
||||
*
|
||||
* @since 1.20
|
||||
*
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
protected function beforeExecute( $subPage ) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called after @see SpecialPage::execute.
|
||||
*
|
||||
* @since 1.20
|
||||
*
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
protected function afterExecute( $subPage ) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Default execute method
|
||||
* Checks user permissions, calls the function given in mFunction
|
||||
*
|
||||
* This must be overridden by subclasses; it will be made abstract in a future version
|
||||
*
|
||||
* @param $par String subpage string, if one was specified
|
||||
* @param $subPage string|null
|
||||
*/
|
||||
function execute( $par ) {
|
||||
public function execute( $subPage ) {
|
||||
$this->setHeaders();
|
||||
$this->checkPermissions();
|
||||
|
||||
|
|
@ -607,7 +662,7 @@ class SpecialPage {
|
|||
require_once( $this->mFile );
|
||||
}
|
||||
$this->outputHeader();
|
||||
call_user_func( $func, $par, $this );
|
||||
call_user_func( $func, $subPage, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1081,17 +1136,103 @@ class SpecialCreateAccount extends SpecialRedirectToSpecial {
|
|||
* users.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Superclass for any RedirectSpecialPage which redirects the user
|
||||
* to a particular article (as opposed to user contributions, logs, etc.).
|
||||
*
|
||||
* For security reasons these special pages are restricted to pass on
|
||||
* the following subset of GET parameters to the target page while
|
||||
* removing all others:
|
||||
*
|
||||
* - useskin, uselang, printable: to alter the appearance of the resulting page
|
||||
*
|
||||
* - redirect: allows viewing one's user page or talk page even if it is a
|
||||
* redirect.
|
||||
*
|
||||
* - rdfrom: allows redirecting to one's user page or talk page from an
|
||||
* external wiki with the "Redirect from..." notice.
|
||||
*
|
||||
* - limit, offset: Useful for linking to history of one's own user page or
|
||||
* user talk page. For example, this would be a link to "the last edit to your
|
||||
* user talk page in the year 2010":
|
||||
* http://en.wikipedia.org/w/index.php?title=Special:MyPage&offset=20110000000000&limit=1&action=history
|
||||
*
|
||||
* - feed: would allow linking to the current user's RSS feed for their user
|
||||
* talk page:
|
||||
* http://en.wikipedia.org/w/index.php?title=Special:MyTalk&action=history&feed=rss
|
||||
*
|
||||
* - preloadtitle: Can be used to provide a default section title for a
|
||||
* preloaded new comment on one's own talk page.
|
||||
*
|
||||
* - summary : Can be used to provide a default edit summary for a preloaded
|
||||
* edit to one's own user page or talk page.
|
||||
*
|
||||
* - preview: Allows showing/hiding preview on first edit regardless of user
|
||||
* preference, useful for preloaded edits where you know preview wouldn't be
|
||||
* useful.
|
||||
*
|
||||
* - internaledit, externaledit, mode: Allows forcing the use of the
|
||||
* internal/external editor, e.g. to force the internal editor for
|
||||
* short/simple preloaded edits.
|
||||
*
|
||||
* - redlink: Affects the message the user sees if their talk page/user talk
|
||||
* page does not currently exist. Avoids confusion for newbies with no user
|
||||
* pages over why they got a "permission error" following this link:
|
||||
* http://en.wikipedia.org/w/index.php?title=Special:MyPage&redlink=1
|
||||
*
|
||||
* - debug: determines whether the debug parameter is passed to load.php,
|
||||
* which disables reformatting and allows scripts to be debugged. Useful
|
||||
* when debugging scripts that manipulate one's own user page or talk page.
|
||||
*
|
||||
* @par Hook extension:
|
||||
* Extensions can add to the redirect parameters list by using the hook
|
||||
* RedirectSpecialArticleRedirectParams
|
||||
*
|
||||
* This hook allows extensions which add GET parameters like FlaggedRevs to
|
||||
* retain those parameters when redirecting using special pages.
|
||||
*
|
||||
* @par Hook extension example:
|
||||
* @code
|
||||
* $wgHooks['RedirectSpecialArticleRedirectParams'][] =
|
||||
* 'MyExtensionHooks::onRedirectSpecialArticleRedirectParams';
|
||||
* public static function onRedirectSpecialArticleRedirectParams( &$redirectParams ) {
|
||||
* $redirectParams[] = 'stable';
|
||||
* return true;
|
||||
* }
|
||||
* @endcode
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
abstract class RedirectSpecialArticle extends RedirectSpecialPage {
|
||||
function __construct( $name ) {
|
||||
parent::__construct( $name );
|
||||
$redirectParams = array(
|
||||
'action',
|
||||
'redirect', 'rdfrom',
|
||||
# Options for preloaded edits
|
||||
'preload', 'editintro', 'preloadtitle', 'summary',
|
||||
# Options for overriding user settings
|
||||
'preview', 'internaledit', 'externaledit', 'mode',
|
||||
# Options for history/diffs
|
||||
'section', 'oldid', 'diff', 'dir',
|
||||
'limit', 'offset', 'feed',
|
||||
# Misc options
|
||||
'redlink', 'debug',
|
||||
# Options for action=raw; missing ctype can break JS or CSS in some browsers
|
||||
'ctype', 'maxage', 'smaxage',
|
||||
);
|
||||
|
||||
wfRunHooks( "RedirectSpecialArticleRedirectParams", array(&$redirectParams) );
|
||||
$this->mAllowedRedirectParams = $redirectParams;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to construct a special page pointing to current user user's page.
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialMypage extends RedirectSpecialPage {
|
||||
class SpecialMypage extends RedirectSpecialArticle {
|
||||
function __construct() {
|
||||
parent::__construct( 'Mypage' );
|
||||
$this->mAllowedRedirectParams = array( 'action', 'preload', 'preloadtitle', 'editintro',
|
||||
'section', 'oldid', 'diff', 'dir',
|
||||
// Options for action=raw; missing ctype can break JS or CSS in some browsers
|
||||
'ctype', 'maxage', 'smaxage' );
|
||||
}
|
||||
|
||||
function getRedirect( $subpage ) {
|
||||
|
|
@ -1107,11 +1248,9 @@ class SpecialMypage extends RedirectSpecialPage {
|
|||
* Shortcut to construct a special page pointing to current user talk page.
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialMytalk extends RedirectSpecialPage {
|
||||
class SpecialMytalk extends RedirectSpecialArticle {
|
||||
function __construct() {
|
||||
parent::__construct( 'Mytalk' );
|
||||
$this->mAllowedRedirectParams = array( 'action', 'preload', 'preloadtitle', 'editintro',
|
||||
'section', 'oldid', 'diff', 'dir' );
|
||||
}
|
||||
|
||||
function getRedirect( $subpage ) {
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ class SpecialPageFactory {
|
|||
// Execute special page
|
||||
$profName = 'Special:' . $page->getName();
|
||||
wfProfileIn( $profName );
|
||||
$page->execute( $par );
|
||||
$page->run( $par );
|
||||
wfProfileOut( $profName );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@
|
|||
/**
|
||||
* Abstract base class for update jobs that put some secondary data extracted
|
||||
* from article content into the database.
|
||||
*
|
||||
* @note: subclasses should NOT start or commit transactions in their doUpdate() method,
|
||||
* a transaction will automatically be wrapped around the update. Starting another
|
||||
* one would break the outer transaction bracket. If need be, subclasses can override
|
||||
* the beginTransaction() and commitTransaction() methods.
|
||||
*/
|
||||
abstract class SqlDataUpdate extends DataUpdate {
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,15 @@ class SquidPurgeClient {
|
|||
* The socket resource, or null for unconnected, or false for disabled due to error
|
||||
*/
|
||||
var $socket;
|
||||
|
||||
|
||||
var $readBuffer;
|
||||
|
||||
var $bodyRemaining;
|
||||
|
||||
/**
|
||||
* @param $server string
|
||||
* @param $options array
|
||||
*/
|
||||
public function __construct( $server, $options = array() ) {
|
||||
$parts = explode( ':', $server, 2 );
|
||||
$this->host = $parts[0];
|
||||
|
|
@ -340,6 +348,9 @@ class SquidPurgeClient {
|
|||
$this->bodyRemaining = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $msg string
|
||||
*/
|
||||
protected function log( $msg ) {
|
||||
wfDebugLog( 'squid', __CLASS__." ($this->host): $msg\n" );
|
||||
}
|
||||
|
|
@ -353,6 +364,9 @@ class SquidPurgeClientPool {
|
|||
var $clients = array();
|
||||
var $timeout = 5;
|
||||
|
||||
/**
|
||||
* @param $options array
|
||||
*/
|
||||
function __construct( $options = array() ) {
|
||||
if ( isset( $options['timeout'] ) ) {
|
||||
$this->timeout = $options['timeout'];
|
||||
|
|
@ -372,6 +386,9 @@ class SquidPurgeClientPool {
|
|||
$startTime = microtime( true );
|
||||
while ( !$done ) {
|
||||
$readSockets = $writeSockets = array();
|
||||
/**
|
||||
* @var $client SquidPurgeClient
|
||||
*/
|
||||
foreach ( $this->clients as $clientIndex => $client ) {
|
||||
$sockets = $client->getReadSocketsForSelect();
|
||||
foreach ( $sockets as $i => $socket ) {
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class StringUtils {
|
|||
* Returns an Iterator
|
||||
* @param $separator
|
||||
* @param $subject
|
||||
* @return ArrayIterator|\ExplodeIterator
|
||||
* @return ArrayIterator|ExplodeIterator
|
||||
*/
|
||||
static function explode( $separator, $subject ) {
|
||||
if ( substr_count( $subject, $separator ) > 1000 ) {
|
||||
|
|
|
|||
|
|
@ -1526,6 +1526,7 @@ class Title {
|
|||
/**
|
||||
* Is $wgUser watching this page?
|
||||
*
|
||||
* @deprecated in 1.20; use User::isWatched() instead.
|
||||
* @return Bool
|
||||
*/
|
||||
public function userIsWatching() {
|
||||
|
|
@ -2883,7 +2884,7 @@ class Title {
|
|||
* @return Int or 0 if the page doesn't exist
|
||||
*/
|
||||
public function getLatestRevID( $flags = 0 ) {
|
||||
if ( $this->mLatestID !== false ) {
|
||||
if ( !( $flags & Title::GAID_FOR_UPDATE ) && $this->mLatestID !== false ) {
|
||||
return intval( $this->mLatestID );
|
||||
}
|
||||
# Calling getArticleID() loads the field from cache as needed
|
||||
|
|
@ -2909,7 +2910,7 @@ class Title {
|
|||
*
|
||||
* - This is called from WikiPage::doEdit() and WikiPage::insertOn() to allow
|
||||
* loading of the new page_id. It's also called from
|
||||
* WikiPage::doDeleteArticle()
|
||||
* WikiPage::doDeleteArticleReal()
|
||||
*
|
||||
* @param $newid Int the new Article ID
|
||||
*/
|
||||
|
|
@ -3322,16 +3323,14 @@ class Title {
|
|||
* @return Array of String the URLs
|
||||
*/
|
||||
public function getSquidURLs() {
|
||||
global $wgContLang;
|
||||
|
||||
$urls = array(
|
||||
$this->getInternalURL(),
|
||||
$this->getInternalURL( 'action=history' )
|
||||
);
|
||||
|
||||
// purge variant urls as well
|
||||
if ( $wgContLang->hasVariants() ) {
|
||||
$variants = $wgContLang->getVariants();
|
||||
$pageLang = $this->getPageLanguage();
|
||||
if ( $pageLang->hasVariants() ) {
|
||||
$variants = $pageLang->getVariants();
|
||||
foreach ( $variants as $vCode ) {
|
||||
$urls[] = $this->getInternalURL( '', $vCode );
|
||||
}
|
||||
|
|
@ -3513,6 +3512,10 @@ class Title {
|
|||
$wgUser->spreadAnyEditBlock();
|
||||
return $err;
|
||||
}
|
||||
// Check suppressredirect permission
|
||||
if ( $auth && !$wgUser->isAllowed( 'suppressredirect' ) ) {
|
||||
$createRedirect = true;
|
||||
}
|
||||
|
||||
// If it is a file, move it first.
|
||||
// It is done before all other moving stuff is done because it's hard to revert.
|
||||
|
|
@ -3609,8 +3612,8 @@ class Title {
|
|||
*
|
||||
* @param $nt Title the page to move to, which should be a redirect or nonexistent
|
||||
* @param $reason String The reason for the move
|
||||
* @param $createRedirect Bool Whether to leave a redirect at the old title. Ignored
|
||||
* if the user doesn't have the suppressredirect right
|
||||
* @param $createRedirect Bool Whether to leave a redirect at the old title. Does not check
|
||||
* if the user has the suppressredirect right
|
||||
* @throws MWException
|
||||
*/
|
||||
private function moveToInternal( &$nt, $reason = '', $createRedirect = true ) {
|
||||
|
|
@ -3624,7 +3627,7 @@ class Title {
|
|||
$logType = 'move';
|
||||
}
|
||||
|
||||
$redirectSuppressed = !$createRedirect && $wgUser->isAllowed( 'suppressredirect' );
|
||||
$redirectSuppressed = !$createRedirect;
|
||||
|
||||
$logEntry = new ManualLogEntry( 'move', $logType );
|
||||
$logEntry->setPerformer( $wgUser );
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ class User {
|
|||
const MW_USER_VERSION = MW_USER_VERSION;
|
||||
const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
|
||||
|
||||
/**
|
||||
* Maximum items in $mWatchedItems
|
||||
*/
|
||||
const MAX_WATCHED_ITEMS_CACHE = 100;
|
||||
|
||||
/**
|
||||
* Array of Strings List of member variables which are saved to the
|
||||
* shared cache (memcached). Any operation which changes the
|
||||
|
|
@ -114,6 +119,7 @@ class User {
|
|||
'delete',
|
||||
'deletedhistory',
|
||||
'deletedtext',
|
||||
'deletelogentry',
|
||||
'deleterevision',
|
||||
'edit',
|
||||
'editinterface',
|
||||
|
|
@ -219,6 +225,11 @@ class User {
|
|||
*/
|
||||
private $mBlockedFromCreateAccount = false;
|
||||
|
||||
/**
|
||||
* @var Array
|
||||
*/
|
||||
private $mWatchedItems = array();
|
||||
|
||||
static $idCacheByName = array();
|
||||
|
||||
/**
|
||||
|
|
@ -517,7 +528,7 @@ class User {
|
|||
* as 300.300.300.300 will return true because it looks like an IP
|
||||
* address, despite not being strictly valid.
|
||||
*
|
||||
* We match \d{1,3}\.\d{1,3}\.\d{1,3}\.xxx as an anonymous IP
|
||||
* We match "\d{1,3}\.\d{1,3}\.\d{1,3}\.xxx" as an anonymous IP
|
||||
* address because the usemod software would "cloak" anonymous IP
|
||||
* addresses like this, if we allowed accounts like this to be created
|
||||
* new users could get the old edits of these anonymous users.
|
||||
|
|
@ -2278,9 +2289,11 @@ class User {
|
|||
$this->loadOptions();
|
||||
|
||||
// Explicitly NULL values should refer to defaults
|
||||
global $wgDefaultUserOptions;
|
||||
if( is_null( $val ) && isset( $wgDefaultUserOptions[$oname] ) ) {
|
||||
$val = $wgDefaultUserOptions[$oname];
|
||||
if( is_null( $val ) ) {
|
||||
$defaultOption = self::getDefaultOption( $oname );
|
||||
if( !is_null( $defaultOption ) ) {
|
||||
$val = $defaultOption;
|
||||
}
|
||||
}
|
||||
|
||||
$this->mOptions[$oname] = $val;
|
||||
|
|
@ -2613,14 +2626,34 @@ class User {
|
|||
return RequestContext::getMain()->getSkin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a WatchedItem for this user and $title.
|
||||
*
|
||||
* @param $title Title
|
||||
* @return WatchedItem
|
||||
*/
|
||||
public function getWatchedItem( $title ) {
|
||||
$key = $title->getNamespace() . ':' . $title->getDBkey();
|
||||
|
||||
if ( isset( $this->mWatchedItems[$key] ) ) {
|
||||
return $this->mWatchedItems[$key];
|
||||
}
|
||||
|
||||
if ( count( $this->mWatchedItems ) >= self::MAX_WATCHED_ITEMS_CACHE ) {
|
||||
$this->mWatchedItems = array();
|
||||
}
|
||||
|
||||
$this->mWatchedItems[$key] = WatchedItem::fromUserTitle( $this, $title );
|
||||
return $this->mWatchedItems[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the watched status of an article.
|
||||
* @param $title Title of the article to look at
|
||||
* @return Bool
|
||||
*/
|
||||
public function isWatched( $title ) {
|
||||
$wl = WatchedItem::fromUserTitle( $this, $title );
|
||||
return $wl->isWatched();
|
||||
return $this->getWatchedItem( $title )->isWatched();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2628,8 +2661,7 @@ class User {
|
|||
* @param $title Title of the article to look at
|
||||
*/
|
||||
public function addWatch( $title ) {
|
||||
$wl = WatchedItem::fromUserTitle( $this, $title );
|
||||
$wl->addWatch();
|
||||
$this->getWatchedItem( $title )->addWatch();
|
||||
$this->invalidateCache();
|
||||
}
|
||||
|
||||
|
|
@ -2638,8 +2670,7 @@ class User {
|
|||
* @param $title Title of the article to look at
|
||||
*/
|
||||
public function removeWatch( $title ) {
|
||||
$wl = WatchedItem::fromUserTitle( $this, $title );
|
||||
$wl->removeWatch();
|
||||
$this->getWatchedItem( $title )->removeWatch();
|
||||
$this->invalidateCache();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -504,9 +504,9 @@ class WebRequest {
|
|||
* Fetch a text string from the given array or return $default if it's not
|
||||
* set. Carriage returns are stripped from the text, and with some language
|
||||
* modules there is an input transliteration applied. This should generally
|
||||
* be used for form <textarea> and <input> fields. Used for user-supplied
|
||||
* freeform text input (for which input transformations may be required - e.g.
|
||||
* Esperanto x-coding).
|
||||
* be used for form "<textarea>" and "<input>" fields. Used for
|
||||
* user-supplied freeform text input (for which input transformations may
|
||||
* be required - e.g. Esperanto x-coding).
|
||||
*
|
||||
* @param $name String
|
||||
* @param $default String: optional
|
||||
|
|
|
|||
|
|
@ -392,23 +392,6 @@ class MediaWiki {
|
|||
return $article;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleaning up request by doing deferred updates, DB transaction, and the output
|
||||
*/
|
||||
public function finalCleanup() {
|
||||
wfProfileIn( __METHOD__ );
|
||||
// Now commit any transactions, so that unreported errors after
|
||||
// output() don't roll back the whole DB transaction
|
||||
$factory = wfGetLBFactory();
|
||||
$factory->commitMasterChanges();
|
||||
// Output everything!
|
||||
$this->context->getOutput()->output();
|
||||
// Do any deferred jobs
|
||||
DeferredUpdates::doUpdates( 'commit' );
|
||||
$this->doJobs();
|
||||
wfProfileOut( __METHOD__ );
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a job from the job queue
|
||||
*/
|
||||
|
|
@ -447,12 +430,23 @@ class MediaWiki {
|
|||
* Ends this task peacefully
|
||||
*/
|
||||
public function restInPeace() {
|
||||
// Do any deferred jobs
|
||||
DeferredUpdates::doUpdates( 'commit' );
|
||||
|
||||
// Execute a job from the queue
|
||||
$this->doJobs();
|
||||
|
||||
// Log message usage, if $wgAdaptiveMessageCache is set to true
|
||||
MessageCache::logMessages();
|
||||
|
||||
// Log profiling data, e.g. in the database or UDP
|
||||
wfLogProfilingData();
|
||||
|
||||
// Commit and close up!
|
||||
$factory = wfGetLBFactory();
|
||||
$factory->commitMasterChanges();
|
||||
$factory->shutdown();
|
||||
|
||||
wfDebug( "Request ended normally\n" );
|
||||
}
|
||||
|
||||
|
|
@ -599,7 +593,13 @@ class MediaWiki {
|
|||
}
|
||||
|
||||
$this->performRequest();
|
||||
$this->finalCleanup();
|
||||
|
||||
// Now commit any transactions, so that unreported errors after
|
||||
// output() don't roll back the whole DB transaction
|
||||
wfGetLBFactory()->commitMasterChanges();
|
||||
|
||||
// Output everything!
|
||||
$this->context->getOutput()->output();
|
||||
|
||||
wfProfileOut( __METHOD__ );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,13 @@ class WikiReference {
|
|||
private $mServer; ///< server URL, may be protocol-relative, e.g. '//www.mediawiki.org'
|
||||
private $mPath; ///< path, '/wiki/$1'
|
||||
|
||||
/**
|
||||
* @param $major string
|
||||
* @param $minor string
|
||||
* @param $canonicalServer string
|
||||
* @param $path string
|
||||
* @param $server null|string
|
||||
*/
|
||||
public function __construct( $major, $minor, $canonicalServer, $path, $server = null ) {
|
||||
$this->mMajor = $major;
|
||||
$this->mMinor = $minor;
|
||||
|
|
@ -186,8 +193,17 @@ class WikiReference {
|
|||
return $this->mCanonicalServer . $this->getLocalUrl( $page );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a canonical server URL
|
||||
* @return string
|
||||
*/
|
||||
public function getCanonicalServer() {
|
||||
return $this->mCanonicalServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for getCanonicalUrl(), for backwards compatibility.
|
||||
* @param $page string
|
||||
* @return String
|
||||
*/
|
||||
public function getUrl( $page ) {
|
||||
|
|
|
|||
|
|
@ -34,30 +34,6 @@ abstract class Page {}
|
|||
* @internal documentation reviewed 15 Mar 2010
|
||||
*/
|
||||
class WikiPage extends Page {
|
||||
// doDeleteArticleReal() return values. Values less than zero indicate fatal errors,
|
||||
// values greater than zero indicate that there were problems not resulting in page
|
||||
// not being deleted
|
||||
|
||||
/**
|
||||
* Delete operation aborted by hook
|
||||
*/
|
||||
const DELETE_HOOK_ABORTED = -1;
|
||||
|
||||
/**
|
||||
* Deletion successful
|
||||
*/
|
||||
const DELETE_SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* Page not found
|
||||
*/
|
||||
const DELETE_NO_PAGE = 1;
|
||||
|
||||
/**
|
||||
* No revisions found to delete
|
||||
*/
|
||||
const DELETE_NO_REVISIONS = 2;
|
||||
|
||||
// Constants for $mDataLoadedFrom and related
|
||||
|
||||
/**
|
||||
|
|
@ -606,7 +582,14 @@ class WikiPage extends Page {
|
|||
return; // page doesn't exist or is missing page_latest info
|
||||
}
|
||||
|
||||
$revision = Revision::newFromPageId( $this->getId(), $latest );
|
||||
// Bug 37225: if session S1 loads the page row FOR UPDATE, the result always includes the
|
||||
// latest changes committed. This is true even within REPEATABLE-READ transactions, where
|
||||
// S1 normally only sees changes committed before the first S1 SELECT. Thus we need S1 to
|
||||
// also gets the revision row FOR UPDATE; otherwise, it may not find it since a page row
|
||||
// UPDATE and revision row INSERT by S2 may have happened after the first S1 SELECT.
|
||||
// http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read.
|
||||
$flags = ( $this->mDataLoadedFrom == self::DATA_FOR_UPDATE ) ? Revision::LOCKING_READ : 0;
|
||||
$revision = Revision::newFromPageId( $this->getId(), $latest, $flags );
|
||||
if ( $revision ) { // sanity
|
||||
$this->setLastEdit( $revision );
|
||||
}
|
||||
|
|
@ -1288,7 +1271,7 @@ class WikiPage extends Page {
|
|||
$conditions,
|
||||
__METHOD__ );
|
||||
|
||||
$result = $dbw->affectedRows() != 0;
|
||||
$result = $dbw->affectedRows() > 0;
|
||||
if ( $result ) {
|
||||
$this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
|
||||
$this->setLastEdit( $revision );
|
||||
|
|
@ -1724,6 +1707,10 @@ class WikiPage extends Page {
|
|||
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $status;
|
||||
} elseif ( !$old_content ) {
|
||||
# Sanity check for bug 37225
|
||||
wfProfileOut( __METHOD__ );
|
||||
throw new MWException( "Could not find text for current revision {$oldid}." );
|
||||
}
|
||||
|
||||
$revision = new Revision( array(
|
||||
|
|
@ -1740,6 +1727,10 @@ class WikiPage extends Page {
|
|||
'content_format' => $serialisation_format,
|
||||
) ); #XXX: pass content object?!
|
||||
|
||||
# Bug 37225: use accessor to get the text as Revision may trim it.
|
||||
# After trimming, the text may be a duplicate of the current text.
|
||||
$content = $revision->getContent(); // sanity; EditPage should trim already
|
||||
|
||||
$changed = !$content->equals( $old_content );
|
||||
|
||||
if ( $changed ) {
|
||||
|
|
@ -1872,6 +1863,9 @@ class WikiPage extends Page {
|
|||
) );
|
||||
$revisionId = $revision->insertOn( $dbw );
|
||||
|
||||
# Bug 37225: use accessor to get the text as Revision may trim it
|
||||
$text = $revision->getText(); // sanity; EditPage should trim already
|
||||
|
||||
# Update the page record with revision data
|
||||
$this->updateRevisionOn( $dbw, $revision, 0 );
|
||||
|
||||
|
|
@ -2423,7 +2417,10 @@ class WikiPage extends Page {
|
|||
}
|
||||
|
||||
/**
|
||||
* Same as doDeleteArticleReal(), but returns more detailed success/failure status
|
||||
* Same as doDeleteArticleReal(), but returns a simple boolean. This is kept around for
|
||||
* backwards compatibility, if you care about error reporting you should use
|
||||
* doDeleteArticleReal() instead.
|
||||
*
|
||||
* Deletes the article with database consistency, writes logs, purges caches
|
||||
*
|
||||
* @param $reason string delete reason for deletion log
|
||||
|
|
@ -2441,8 +2438,8 @@ class WikiPage extends Page {
|
|||
public function doDeleteArticle(
|
||||
$reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
|
||||
) {
|
||||
return $this->doDeleteArticleReal( $reason, $suppress, $id, $commit, $error, $user )
|
||||
== WikiPage::DELETE_SUCCESS;
|
||||
$status = $this->doDeleteArticleReal( $reason, $suppress, $id, $commit, $error, $user );
|
||||
return $status->isGood();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2459,7 +2456,9 @@ class WikiPage extends Page {
|
|||
* @param $commit boolean defaults to true, triggers transaction end
|
||||
* @param &$error Array of errors to append to
|
||||
* @param $user User The deleting user
|
||||
* @return int: One of WikiPage::DELETE_* constants
|
||||
* @return Status: Status object; if successful, $status->value is the log_id of the
|
||||
* deletion log entry. If the page couldn't be deleted because it wasn't
|
||||
* found, $status is a non-fatal 'cannotdelete' error
|
||||
*/
|
||||
public function doDeleteArticleReal(
|
||||
$reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
|
||||
|
|
@ -2468,20 +2467,28 @@ class WikiPage extends Page {
|
|||
|
||||
wfDebug( __METHOD__ . "\n" );
|
||||
|
||||
$status = Status::newGood();
|
||||
|
||||
if ( $this->mTitle->getDBkey() === '' ) {
|
||||
return WikiPage::DELETE_NO_PAGE;
|
||||
$status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) );
|
||||
return $status;
|
||||
}
|
||||
|
||||
$user = is_null( $user ) ? $wgUser : $user;
|
||||
if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error ) ) ) {
|
||||
return WikiPage::DELETE_HOOK_ABORTED;
|
||||
if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) {
|
||||
if ( $status->isOK() ) {
|
||||
// Hook aborted but didn't set a fatal status
|
||||
$status->fatal( 'delete-hook-aborted' );
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
if ( $id == 0 ) {
|
||||
$this->loadPageData( 'forupdate' );
|
||||
$id = $this->getID();
|
||||
if ( $id == 0 ) {
|
||||
return WikiPage::DELETE_NO_PAGE;
|
||||
$status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) );
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2551,7 +2558,8 @@ class WikiPage extends Page {
|
|||
|
||||
if ( !$ok ) {
|
||||
$dbw->rollback( __METHOD__ );
|
||||
return WikiPage::DELETE_NO_REVISIONS;
|
||||
$status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) );
|
||||
return $status;
|
||||
}
|
||||
|
||||
$this->doDeleteUpdates( $id, $content );
|
||||
|
|
@ -2571,7 +2579,8 @@ class WikiPage extends Page {
|
|||
}
|
||||
|
||||
wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id ) );
|
||||
return WikiPage::DELETE_SUCCESS;
|
||||
$status->value = $logid;
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -210,15 +210,18 @@ class Xml {
|
|||
* @param string $selected The language code of the selected language
|
||||
* @param boolean $customisedOnly If true only languages which have some content are listed
|
||||
* @param string $inLanguage The ISO code of the language to display the select list in (optional)
|
||||
* @param array $overrideAttrs Override the attributes of the select tag (since 1.20)
|
||||
* @param Message|null $msg Label message key (since 1.20)
|
||||
* @return array containing 2 items: label HTML and select list HTML
|
||||
*/
|
||||
public static function languageSelector( $selected, $customisedOnly = true, $inLanguage = null ) {
|
||||
public static function languageSelector( $selected, $customisedOnly = true, $inLanguage = null, $overrideAttrs = array(), Message $msg = null ) {
|
||||
global $wgLanguageCode;
|
||||
|
||||
$languages = Language::fetchLanguageNames( $inLanguage, $customisedOnly ? 'mwfile' : 'mw' );
|
||||
$include = $customisedOnly ? 'mwfile' : 'mw';
|
||||
$languages = Language::fetchLanguageNames( $inLanguage, $include );
|
||||
|
||||
// Make sure the site language is in the list; a custom language code might not have a
|
||||
// defined name...
|
||||
// Make sure the site language is in the list;
|
||||
// a custom language code might not have a defined name...
|
||||
if( !array_key_exists( $wgLanguageCode, $languages ) ) {
|
||||
$languages[$wgLanguageCode] = $wgLanguageCode;
|
||||
}
|
||||
|
|
@ -228,7 +231,7 @@ class Xml {
|
|||
/**
|
||||
* If a bogus value is set, default to the content language.
|
||||
* Otherwise, no default is selected and the user ends up
|
||||
* with an Afrikaans interface since it's first in the list.
|
||||
* with Afrikaans since it's first in the list.
|
||||
*/
|
||||
$selected = isset( $languages[$selected] ) ? $selected : $wgLanguageCode;
|
||||
$options = "\n";
|
||||
|
|
@ -236,12 +239,15 @@ class Xml {
|
|||
$options .= Xml::option( "$code - $name", $code, ($code == $selected) ) . "\n";
|
||||
}
|
||||
|
||||
$attrs = array( 'id' => 'wpUserLanguage', 'name' => 'wpUserLanguage' );
|
||||
$attrs = array_merge( $attrs, $overrideAttrs );
|
||||
|
||||
if( $msg === null ) {
|
||||
$msg = wfMessage( 'yourlanguage' );
|
||||
}
|
||||
return array(
|
||||
Xml::label( wfMsg('yourlanguage'), 'wpUserLanguage' ),
|
||||
Xml::tags( 'select',
|
||||
array( 'id' => 'wpUserLanguage', 'name' => 'wpUserLanguage' ),
|
||||
$options
|
||||
)
|
||||
Xml::label( $msg->text(), $attrs['id'] ),
|
||||
Xml::tags( 'select', $attrs, $options )
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2570,7 +2570,6 @@ $zh2Hant = array(
|
|||
'龚' => '龔',
|
||||
'龛' => '龕',
|
||||
'龟' => '龜',
|
||||
'' => '棡',
|
||||
'𠮶' => '嗰',
|
||||
'𡒄' => '壈',
|
||||
'𦈖' => '䌈',
|
||||
|
|
@ -10389,7 +10388,6 @@ $zh2Hans = array(
|
|||
'棖' => '枨',
|
||||
'棗' => '枣',
|
||||
'棟' => '栋',
|
||||
'棡' => '',
|
||||
'棧' => '栈',
|
||||
'棲' => '栖',
|
||||
'棶' => '梾',
|
||||
|
|
|
|||
|
|
@ -418,34 +418,11 @@ class HistoryPager extends ReverseChronologicalPager {
|
|||
$batch->add( NS_USER_TALK, $row->rev_user_text );
|
||||
}
|
||||
}
|
||||
$this->parentLens = $this->getParentLengths( $revIds );
|
||||
$this->parentLens = Revision::getParentLengths( $this->mDb, $revIds );
|
||||
$batch->execute();
|
||||
$this->mResult->seek( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a batched query to get the parent revision lengths
|
||||
* @param $revIds array
|
||||
* @return array
|
||||
* @TODO: stolen from Contributions, refactor
|
||||
*/
|
||||
private function getParentLengths( array $revIds ) {
|
||||
$revLens = array();
|
||||
if ( !$revIds ) {
|
||||
return $revLens; // empty
|
||||
}
|
||||
wfProfileIn( __METHOD__ );
|
||||
$res = $this->mDb->select( 'revision',
|
||||
array( 'rev_id', 'rev_len' ),
|
||||
array( 'rev_id' => $revIds ),
|
||||
__METHOD__ );
|
||||
foreach ( $res as $row ) {
|
||||
$revLens[$row->rev_id] = $row->rev_len;
|
||||
}
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $revLens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates begin of history list with a submit button
|
||||
*
|
||||
|
|
@ -635,18 +612,17 @@ class HistoryPager extends ReverseChronologicalPager {
|
|||
|
||||
if ( $notificationtimestamp && ( $row->rev_timestamp >= $notificationtimestamp ) ) {
|
||||
$s2 .= ' <span class="updatedmarker">' . $this->msg( 'updatedmarker' )->escaped() . '</span>';
|
||||
$classes[] = 'mw-history-line-updated';
|
||||
}
|
||||
|
||||
$tools = array();
|
||||
|
||||
# Rollback and undo links
|
||||
if ( $prevRev &&
|
||||
!count( $this->getTitle()->getUserPermissionsErrors( 'edit', $this->getUser() ) ) )
|
||||
{
|
||||
if ( $latest && !count( $this->getTitle()->getUserPermissionsErrors( 'rollback', $this->getUser() ) ) ) {
|
||||
if ( $prevRev && $this->getTitle()->quickUserCan( 'edit', $user ) ) {
|
||||
if ( $latest && $this->getTitle()->quickUserCan( 'rollback', $user ) ) {
|
||||
$this->preventClickjacking();
|
||||
$tools[] = '<span class="mw-rollback-link">' .
|
||||
Linker::buildRollbackLink( $rev ) . '</span>';
|
||||
Linker::buildRollbackLink( $rev, $this->getContext() ) . '</span>';
|
||||
}
|
||||
|
||||
if ( !$rev->isDeleted( Revision::DELETED_TEXT )
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class InfoAction extends FormlessAction {
|
|||
* @return mixed array or boolean false
|
||||
*/
|
||||
public static function pageCountInfo( $title ) {
|
||||
wfProfileIn( __METHOD__ );
|
||||
$id = $title->getArticleID();
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
|
|
@ -114,8 +115,8 @@ class InfoAction extends FormlessAction {
|
|||
'watchlist',
|
||||
'COUNT(*)',
|
||||
array(
|
||||
'wl_namespace' => $title->getNamespace(),
|
||||
'wl_title' => $title->getDBkey(),
|
||||
'wl_namespace' => $title->getNamespace()
|
||||
),
|
||||
__METHOD__
|
||||
);
|
||||
|
|
@ -133,15 +134,21 @@ class InfoAction extends FormlessAction {
|
|||
array( 'rev_page' => $id ),
|
||||
__METHOD__
|
||||
);
|
||||
$result = array( 'watchers' => $watchers, 'edits' => $edits,
|
||||
'authors' => $authors );
|
||||
|
||||
$views = (int)$dbr->selectField(
|
||||
'page',
|
||||
'page_counter',
|
||||
array( 'page_id' => $id ),
|
||||
__METHOD__
|
||||
);
|
||||
global $wgDisableCounters;
|
||||
if ( !$wgDisableCounters ) {
|
||||
$views = (int)$dbr->selectField(
|
||||
'page',
|
||||
'page_counter',
|
||||
array( 'page_id' => $id ),
|
||||
__METHOD__
|
||||
);
|
||||
$result['views'] = $views;
|
||||
}
|
||||
|
||||
return array( 'watchers' => $watchers, 'edits' => $edits,
|
||||
'authors' => $authors, 'views' => $views );
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,6 @@ class RevisiondeleteAction extends FormlessAction {
|
|||
public function show() {
|
||||
$special = SpecialPageFactory::getPage( 'Revisiondelete' );
|
||||
$special->setContext( $this->getContext() );
|
||||
$special->execute( '' );
|
||||
$special->run( '' );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 5, 2006
|
||||
*
|
||||
* Copyright © 2006, 2010 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006, 2010 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -134,7 +134,7 @@ abstract class ApiBase extends ContextSource {
|
|||
/**
|
||||
* Get the name of the module as shown in the profiler log
|
||||
*
|
||||
* @param $db DatabaseBase
|
||||
* @param $db DatabaseBase|bool
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -825,7 +825,7 @@ abstract class ApiBase extends ContextSource {
|
|||
*/
|
||||
protected function getWatchlistValue ( $watchlist, $titleObj, $userOption = null ) {
|
||||
|
||||
$userWatching = $titleObj->userIsWatching();
|
||||
$userWatching = $this->getUser()->isWatched( $titleObj );
|
||||
|
||||
switch ( $watchlist ) {
|
||||
case 'watch':
|
||||
|
|
@ -1184,7 +1184,8 @@ abstract class ApiBase extends ContextSource {
|
|||
* @param $errorCode string Brief, arbitrary, stable string to allow easy
|
||||
* automated identification of the error, e.g., 'unknown_action'
|
||||
* @param $httpRespCode int HTTP response code
|
||||
* @param $extradata array Data to add to the <error> element; array in ApiResult format
|
||||
* @param $extradata array Data to add to the "<error>" element; array in ApiResult format
|
||||
* @throws UsageException
|
||||
*/
|
||||
public function dieUsage( $description, $errorCode, $httpRespCode = 0, $extradata = null ) {
|
||||
Profiler::instance()->close();
|
||||
|
|
@ -1307,6 +1308,8 @@ abstract class ApiBase extends ContextSource {
|
|||
'specialpage-cantexecute' => array( 'code' => 'specialpage-cantexecute', 'info' => "You don't have permission to view the results of this special page" ),
|
||||
'invalidoldimage' => array( 'code' => 'invalidoldimage', 'info' => 'The oldimage parameter has invalid format' ),
|
||||
'nodeleteablefile' => array( 'code' => 'nodeleteablefile', 'info' => 'No such old version of the file' ),
|
||||
'fileexists-forbidden' => array( 'code' => 'fileexists-forbidden', 'info' => 'A file with name "$1" already exists, and cannot be overwritten.' ),
|
||||
'fileexists-shared-forbidden' => array( 'code' => 'fileexists-shared-forbidden', 'info' => 'A file with name "$1" already exists in the shared file repository, and cannot be overwritten.' ),
|
||||
|
||||
// ApiEditPage messages
|
||||
'noimageredirect-anon' => array( 'code' => 'noimageredirect-anon', 'info' => "Anonymous users can't create image redirects" ),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 4, 2007
|
||||
*
|
||||
* Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -72,9 +72,9 @@ class ApiBlock extends ApiBase {
|
|||
$data = array(
|
||||
'Target' => $params['user'],
|
||||
'Reason' => array(
|
||||
is_null( $params['reason'] ) ? '' : $params['reason'],
|
||||
$params['reason'],
|
||||
'other',
|
||||
is_null( $params['reason'] ) ? '' : $params['reason']
|
||||
$params['reason']
|
||||
),
|
||||
'Expiry' => $params['expiry'] == 'never' ? 'infinite' : $params['expiry'],
|
||||
'HardBlock' => !$params['anononly'],
|
||||
|
|
@ -156,7 +156,7 @@ class ApiBlock extends ApiBase {
|
|||
ApiBase::PARAM_DEPRECATED => true,
|
||||
),
|
||||
'expiry' => 'never',
|
||||
'reason' => null,
|
||||
'reason' => '',
|
||||
'anononly' => false,
|
||||
'nocreate' => false,
|
||||
'autoblock' => false,
|
||||
|
|
@ -174,7 +174,7 @@ class ApiBlock extends ApiBase {
|
|||
'token' => 'A block token previously obtained through prop=info',
|
||||
'gettoken' => 'If set, a block token will be returned, and no other action will be taken',
|
||||
'expiry' => 'Relative expiry time, e.g. \'5 months\' or \'2 weeks\'. If set to \'infinite\', \'indefinite\' or \'never\', the block will never expire.',
|
||||
'reason' => 'Reason for block (optional)',
|
||||
'reason' => 'Reason for block',
|
||||
'anononly' => 'Block anonymous users only (i.e. disable anonymous edits for this IP)',
|
||||
'nocreate' => 'Prevent account creation',
|
||||
'autoblock' => 'Automatically block the last used IP address, and any subsequent IP addresses they try to login from',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Jun 30, 2007
|
||||
*
|
||||
* Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -52,17 +52,18 @@ class ApiDelete extends ApiBase {
|
|||
}
|
||||
|
||||
$titleObj = $pageObj->getTitle();
|
||||
$reason = ( isset( $params['reason'] ) ? $params['reason'] : null );
|
||||
$reason = $params['reason'];
|
||||
$user = $this->getUser();
|
||||
|
||||
if ( $titleObj->getNamespace() == NS_FILE ) {
|
||||
$retval = self::deleteFile( $pageObj, $user, $params['token'], $params['oldimage'], $reason, false );
|
||||
$status = self::deleteFile( $pageObj, $user, $params['token'], $params['oldimage'], $reason, false );
|
||||
} else {
|
||||
$retval = self::delete( $pageObj, $user, $params['token'], $reason );
|
||||
$status = self::delete( $pageObj, $user, $params['token'], $reason );
|
||||
}
|
||||
|
||||
if ( count( $retval ) ) {
|
||||
$this->dieUsageMsg( reset( $retval ) ); // We don't care about multiple errors, just report one of them
|
||||
if ( !$status->isGood() ) {
|
||||
$errors = $status->getErrorsArray();
|
||||
$this->dieUsageMsg( $errors[0] ); // We don't care about multiple errors, just report one of them
|
||||
}
|
||||
|
||||
// Deprecated parameters
|
||||
|
|
@ -75,7 +76,11 @@ class ApiDelete extends ApiBase {
|
|||
}
|
||||
$this->setWatch( $watch, $titleObj, 'watchdeletion' );
|
||||
|
||||
$r = array( 'title' => $titleObj->getPrefixedText(), 'reason' => $reason );
|
||||
$r = array(
|
||||
'title' => $titleObj->getPrefixedText(),
|
||||
'reason' => $reason,
|
||||
'logid' => $status->value
|
||||
);
|
||||
$this->getResult()->addValue( null, $this->getModuleName(), $r );
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +102,7 @@ class ApiDelete extends ApiBase {
|
|||
* @param $user User doing the action
|
||||
* @param $token String: delete token (same as edit token)
|
||||
* @param $reason String: reason for the deletion. Autogenerated if NULL
|
||||
* @return Title::getUserPermissionsErrors()-like array
|
||||
* @return Status
|
||||
*/
|
||||
public static function delete( Page $page, User $user, $token, &$reason = null ) {
|
||||
$title = $page->getTitle();
|
||||
|
|
@ -119,11 +124,7 @@ class ApiDelete extends ApiBase {
|
|||
|
||||
$error = '';
|
||||
// Luckily, Article.php provides a reusable delete function that does the hard work for us
|
||||
if ( $page->doDeleteArticle( $reason, false, 0, true, $error ) ) {
|
||||
return array();
|
||||
} else {
|
||||
return array( array( 'cannotdelete', $title->getPrefixedText() ) );
|
||||
}
|
||||
return $page->doDeleteArticleReal( $reason, false, 0, true, $error );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,7 +134,7 @@ class ApiDelete extends ApiBase {
|
|||
* @param $oldimage
|
||||
* @param $reason
|
||||
* @param $suppress bool
|
||||
* @return array|Title
|
||||
* @return Status
|
||||
*/
|
||||
public static function deleteFile( Page $page, User $user, $token, $oldimage, &$reason = null, $suppress = false ) {
|
||||
$title = $page->getTitle();
|
||||
|
|
@ -162,12 +163,7 @@ class ApiDelete extends ApiBase {
|
|||
if ( is_null( $reason ) ) { // Log and RC don't like null reasons
|
||||
$reason = '';
|
||||
}
|
||||
$status = FileDeleteForm::doDelete( $title, $file, $oldimage, $reason, $suppress );
|
||||
if ( !$status->isGood() ) {
|
||||
return array( array( 'cannotdelete', $title->getPrefixedText() ) );
|
||||
}
|
||||
|
||||
return array();
|
||||
return FileDeleteForm::doDelete( $title, $file, $oldimage, $reason, $suppress );
|
||||
}
|
||||
|
||||
public function mustBePosted() {
|
||||
|
|
@ -184,7 +180,10 @@ class ApiDelete extends ApiBase {
|
|||
'pageid' => array(
|
||||
ApiBase::PARAM_TYPE => 'integer'
|
||||
),
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'reason' => null,
|
||||
'watch' => array(
|
||||
ApiBase::PARAM_DFLT => false,
|
||||
|
|
@ -225,7 +224,8 @@ class ApiDelete extends ApiBase {
|
|||
return array(
|
||||
'' => array(
|
||||
'title' => 'string',
|
||||
'reason' => 'string'
|
||||
'reason' => 'string',
|
||||
'logid' => 'integer'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 25, 2008
|
||||
*
|
||||
* Copyright © 2008 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2008 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on August 16, 2007
|
||||
*
|
||||
* Copyright © 2007 Iker Labarga <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2007 Iker Labarga "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -464,7 +464,10 @@ class ApiEditPage extends ApiBase {
|
|||
ApiBase::PARAM_REQUIRED => false,
|
||||
),
|
||||
'text' => null,
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'summary' => null,
|
||||
'minor' => false,
|
||||
'notminor' => false,
|
||||
|
|
|
|||
|
|
@ -98,7 +98,10 @@ class ApiEmailUser extends ApiBase {
|
|||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'ccme' => false,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 05, 2007
|
||||
*
|
||||
* Copyright © 2007 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 13, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -126,7 +126,10 @@ class ApiFileRevert extends ApiBase {
|
|||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true,
|
||||
),
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 19, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 22, 2006
|
||||
*
|
||||
* Copyright © 2008 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2008 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 19, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 22, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Feb 2, 2009
|
||||
*
|
||||
* Copyright © 2009 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2009 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 22, 2006
|
||||
*
|
||||
* Copyright © 2008 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2008 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 22, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 19, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -83,16 +83,40 @@ class ApiFormatXml extends ApiFormatBase {
|
|||
|
||||
/**
|
||||
* This method takes an array and converts it to XML.
|
||||
*
|
||||
* There are several noteworthy cases:
|
||||
*
|
||||
* If array contains a key '_element', then the code assumes that ALL other keys are not important and replaces them with the value['_element'].
|
||||
* Example: name='root', value = array( '_element'=>'page', 'x', 'y', 'z') creates <root> <page>x</page> <page>y</page> <page>z</page> </root>
|
||||
* If array contains a key '_element', then the code assumes that ALL
|
||||
* other keys are not important and replaces them with the
|
||||
* value['_element'].
|
||||
*
|
||||
* If any of the array's element key is '*', then the code treats all other key->value pairs as attributes, and the value['*'] as the element's content.
|
||||
* Example: name='root', value = array( '*'=>'text', 'lang'=>'en', 'id'=>10) creates <root lang='en' id='10'>text</root>
|
||||
* @par Example:
|
||||
* @verbatim
|
||||
* name='root', value = array( '_element'=>'page', 'x', 'y', 'z')
|
||||
* @endverbatim
|
||||
* creates:
|
||||
* @verbatim
|
||||
* <root> <page>x</page> <page>y</page> <page>z</page> </root>
|
||||
* @endverbatim
|
||||
*
|
||||
* If neither key is found, all keys become element names, and values become element content.
|
||||
* The method is recursive, so the same rules apply to any sub-arrays.
|
||||
* If any of the array's element key is '*', then the code treats all
|
||||
* other key->value pairs as attributes, and the value['*'] as the
|
||||
* element's content.
|
||||
*
|
||||
* @par Example:
|
||||
* @verbatim
|
||||
* name='root', value = array( '*'=>'text', 'lang'=>'en', 'id'=>10)
|
||||
* @endverbatim
|
||||
* creates:
|
||||
* @verbatim
|
||||
* <root lang='en' id='10'>text</root>
|
||||
* @endverbatim
|
||||
*
|
||||
* Finally neither key is found, all keys become element names, and values
|
||||
* become element content.
|
||||
*
|
||||
* @note The method is recursive, so the same rules apply to any
|
||||
* sub-arrays.
|
||||
*
|
||||
* @param $elemName
|
||||
* @param $elemValue
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 19, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 6, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Feb 4, 2009
|
||||
*
|
||||
* Copyright © 2009 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2009 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -98,7 +98,10 @@ class ApiImport extends ApiBase {
|
|||
public function getAllowedParams() {
|
||||
global $wgImportSources;
|
||||
return array(
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'summary' => null,
|
||||
'xml' => null,
|
||||
'interwikisource' => array(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 19, 2006
|
||||
*
|
||||
* Copyright © 2006-2007 Yuri Astrakhan <Firstname><Lastname>@gmail.com,
|
||||
* Copyright © 2006-2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com",
|
||||
* Daniel Cannon (cannon dot danielc at gmail dot com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Jan 4, 2008
|
||||
*
|
||||
* Copyright © 2008 Yuri Astrakhan <Firstname><Lastname>@gmail.com,
|
||||
* Copyright © 2008 Yuri Astrakhan "<Firstname><Lastname>@gmail.com",
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 4, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -355,6 +355,12 @@ class ApiMain extends ApiBase {
|
|||
* have been accumulated, and replace it with an error message and a help screen.
|
||||
*/
|
||||
protected function executeActionWithErrorHandling() {
|
||||
// Verify the CORS header before executing the action
|
||||
if ( !$this->handleCORS() ) {
|
||||
// handleCORS() has sent a 403, abort
|
||||
return;
|
||||
}
|
||||
|
||||
// In case an error occurs during data output,
|
||||
// clear the output buffer and print just the error information
|
||||
ob_start();
|
||||
|
|
@ -403,9 +409,94 @@ class ApiMain extends ApiBase {
|
|||
ob_end_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the &origin= query parameter against the Origin: HTTP header and respond appropriately.
|
||||
*
|
||||
* If no origin parameter is present, nothing happens.
|
||||
* If an origin parameter is present but doesn't match the Origin header, a 403 status code
|
||||
* is set and false is returned.
|
||||
* If the parameter and the header do match, the header is checked against $wgCrossSiteAJAXdomains
|
||||
* and $wgCrossSiteAJAXdomainExceptions, and if the origin qualifies, the appropriate CORS
|
||||
* headers are set.
|
||||
*
|
||||
* @return bool False if the caller should abort (403 case), true otherwise (all other cases)
|
||||
*/
|
||||
protected function handleCORS() {
|
||||
global $wgCrossSiteAJAXdomains, $wgCrossSiteAJAXdomainExceptions;
|
||||
$response = $this->getRequest()->response();
|
||||
$originParam = $this->getParameter( 'origin' ); // defaults to null
|
||||
if ( $originParam === null ) {
|
||||
// No origin parameter, nothing to do
|
||||
return true;
|
||||
}
|
||||
// Origin: header is a space-separated list of origins, check all of them
|
||||
$originHeader = isset( $_SERVER['HTTP_ORIGIN'] ) ? $_SERVER['HTTP_ORIGIN'] : '';
|
||||
$origins = explode( ' ', $originHeader );
|
||||
if ( !in_array( $originParam, $origins ) ) {
|
||||
// origin parameter set but incorrect
|
||||
// Send a 403 response
|
||||
$message = HttpStatus::getMessage( 403 );
|
||||
$response->header( "HTTP/1.1 403 $message", true, 403 );
|
||||
$response->header( 'Cache-Control: no-cache' );
|
||||
echo "'origin' parameter does not match Origin header\n";
|
||||
return false;
|
||||
}
|
||||
if ( self::matchOrigin( $originParam, $wgCrossSiteAJAXdomains, $wgCrossSiteAJAXdomainExceptions ) ) {
|
||||
$response->header( "Access-Control-Allow-Origin: $originParam" );
|
||||
$response->header( 'Access-Control-Allow-Credentials: true' );
|
||||
$this->getOutput()->addVaryHeader( 'Origin' );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to match an Origin header against a set of rules and a set of exceptions
|
||||
* @param $value string Origin header
|
||||
* @param $rules array Set of wildcard rules
|
||||
* @param $exceptions array Set of wildcard rules
|
||||
* @return bool True if $value matches a rule in $rules and doesn't match any rules in $exceptions, false otherwise
|
||||
*/
|
||||
protected static function matchOrigin( $value, $rules, $exceptions ) {
|
||||
foreach ( $rules as $rule ) {
|
||||
if ( preg_match( self::wildcardToRegex( $rule ), $value ) ) {
|
||||
// Rule matches, check exceptions
|
||||
foreach ( $exceptions as $exc ) {
|
||||
if ( preg_match( self::wildcardToRegex( $exc ), $value ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert wildcard string into a regex
|
||||
* '*' => '.*?'
|
||||
* '?' => '.'
|
||||
*
|
||||
* @param $wildcard string String with wildcards
|
||||
* @return string Regular expression
|
||||
*/
|
||||
protected static function wildcardToRegex( $wildcard ) {
|
||||
$wildcard = preg_quote( $wildcard, '/' );
|
||||
$wildcard = str_replace(
|
||||
array( '\*', '\?' ),
|
||||
array( '.*?', '.' ),
|
||||
$wildcard
|
||||
);
|
||||
return "/https?:\/\/$wildcard/";
|
||||
}
|
||||
|
||||
protected function sendCacheHeaders() {
|
||||
global $wgUseXVO, $wgVaryOnXFP;
|
||||
$response = $this->getRequest()->response();
|
||||
$out = $this->getOutput();
|
||||
|
||||
if ( $wgVaryOnXFP ) {
|
||||
$out->addVaryHeader( 'X-Forwarded-Proto' );
|
||||
}
|
||||
|
||||
if ( $this->mCacheMode == 'private' ) {
|
||||
$response->header( 'Cache-Control: private' );
|
||||
|
|
@ -413,13 +504,9 @@ class ApiMain extends ApiBase {
|
|||
}
|
||||
|
||||
if ( $this->mCacheMode == 'anon-public-user-private' ) {
|
||||
$xfp = $wgVaryOnXFP ? ', X-Forwarded-Proto' : '';
|
||||
$response->header( 'Vary: Accept-Encoding, Cookie' . $xfp );
|
||||
$out->addVaryHeader( 'Cookie' );
|
||||
$response->header( $out->getVaryHeader() );
|
||||
if ( $wgUseXVO ) {
|
||||
$out = $this->getOutput();
|
||||
if ( $wgVaryOnXFP ) {
|
||||
$out->addVaryHeader( 'X-Forwarded-Proto' );
|
||||
}
|
||||
$response->header( $out->getXVO() );
|
||||
if ( $out->haveCacheVaryCookies() ) {
|
||||
// Logged in, mark this request private
|
||||
|
|
@ -436,12 +523,9 @@ class ApiMain extends ApiBase {
|
|||
}
|
||||
|
||||
// Send public headers
|
||||
if ( $wgVaryOnXFP ) {
|
||||
$response->header( 'Vary: Accept-Encoding, X-Forwarded-Proto' );
|
||||
if ( $wgUseXVO ) {
|
||||
// Bleeeeegh. Our header setting system sucks
|
||||
$response->header( 'X-Vary-Options: Accept-Encoding;list-contains=gzip, X-Forwarded-Proto' );
|
||||
}
|
||||
$response->header( $out->getVaryHeader() );
|
||||
if ( $wgUseXVO ) {
|
||||
$response->header( $out->getXVO() );
|
||||
}
|
||||
|
||||
// If nobody called setCacheMaxAge(), use the (s)maxage parameters
|
||||
|
|
@ -785,6 +869,7 @@ class ApiMain extends ApiBase {
|
|||
),
|
||||
'requestid' => null,
|
||||
'servedby' => false,
|
||||
'origin' => null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -810,6 +895,12 @@ class ApiMain extends ApiBase {
|
|||
'maxage' => 'Set the max-age header to this many seconds. Errors are never cached',
|
||||
'requestid' => 'Request ID to distinguish requests. This will just be output back to you',
|
||||
'servedby' => 'Include the hostname that served the request in the results. Unconditionally shown on error',
|
||||
'origin' => array(
|
||||
'When accessing the API using a cross-domain AJAX request (CORS), set this to the originating domain.',
|
||||
'This must match one of the origins in the Origin: header exactly, so it has to be set to something like http://en.wikipedia.org or https://meta.wikimedia.org .',
|
||||
'If this parameter does not match the Origin: header, a 403 response will be returned.',
|
||||
'If this parameter matches the Origin: header and the origin is whitelisted, an Access-Control-Allow-Origin header will be set.',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -877,11 +968,11 @@ class ApiMain extends ApiBase {
|
|||
protected function getCredits() {
|
||||
return array(
|
||||
'API developers:',
|
||||
' Roan Kattouw <Firstname>.<Lastname>@gmail.com (lead developer Sep 2007-present)',
|
||||
' Roan Kattouw "<Firstname>.<Lastname>@gmail.com" (lead developer Sep 2007-present)',
|
||||
' Victor Vasiliev - vasilvv at gee mail dot com',
|
||||
' Bryan Tong Minh - bryan . tongminh @ gmail . com',
|
||||
' Sam Reed - sam @ reedyboy . net',
|
||||
' Yuri Astrakhan <Firstname><Lastname>@gmail.com (creator, lead developer Sep 2006-Sep 2007)',
|
||||
' Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007)',
|
||||
'',
|
||||
'Please send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org',
|
||||
'or file a bug report at https://bugzilla.wikimedia.org/'
|
||||
|
|
@ -1070,8 +1161,18 @@ class ApiMain extends ApiBase {
|
|||
class UsageException extends MWException {
|
||||
|
||||
private $mCodestr;
|
||||
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
private $mExtraData;
|
||||
|
||||
/**
|
||||
* @param $message string
|
||||
* @param $codestr string
|
||||
* @param $code int
|
||||
* @param $extradata array|null
|
||||
*/
|
||||
public function __construct( $message, $codestr, $code = 0, $extradata = null ) {
|
||||
parent::__construct( $message, $code );
|
||||
$this->mCodestr = $codestr;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 31, 2007
|
||||
*
|
||||
* Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -37,9 +37,6 @@ class ApiMove extends ApiBase {
|
|||
public function execute() {
|
||||
$user = $this->getUser();
|
||||
$params = $this->extractRequestParams();
|
||||
if ( is_null( $params['reason'] ) ) {
|
||||
$params['reason'] = '';
|
||||
}
|
||||
|
||||
$this->requireOnlyOneParameter( $params, 'from', 'fromid' );
|
||||
|
||||
|
|
@ -180,8 +177,11 @@ class ApiMove extends ApiBase {
|
|||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'token' => null,
|
||||
'reason' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'reason' => '',
|
||||
'movetalk' => false,
|
||||
'movesubpages' => false,
|
||||
'noredirect' => false,
|
||||
|
|
@ -213,7 +213,7 @@ class ApiMove extends ApiBase {
|
|||
'fromid' => "Page ID of the page you want to move. Cannot be used together with {$p}from",
|
||||
'to' => 'Title you want to rename the page to',
|
||||
'token' => 'A move token previously retrieved through prop=info',
|
||||
'reason' => 'Reason for the move (optional)',
|
||||
'reason' => 'Reason for the move',
|
||||
'movetalk' => 'Move the talk page, if it exists',
|
||||
'movesubpages' => 'Move subpages, if applicable',
|
||||
'noredirect' => 'Don\'t create a redirect',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 13, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 24, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -52,7 +52,7 @@ class ApiPageSet extends ApiQueryBase {
|
|||
|
||||
/**
|
||||
* Constructor
|
||||
* @param $query ApiQueryBase
|
||||
* @param $query ApiBase
|
||||
* @param $resolveRedirects bool Whether redirects should be resolved
|
||||
* @param $convertTitles bool
|
||||
*/
|
||||
|
|
@ -266,8 +266,8 @@ class ApiPageSet extends ApiQueryBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the number of revisions (requested with revids= parameter)\
|
||||
* @return int
|
||||
* Returns the number of revisions (requested with revids= parameter).
|
||||
* @return int Number of revisions.
|
||||
*/
|
||||
public function getRevisionCount() {
|
||||
return count( $this->getRevisionIDs() );
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Dec 01, 2007
|
||||
*
|
||||
* Copyright © 2008 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2008 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* Created on Dec 01, 2007
|
||||
*
|
||||
* Copyright © 2007 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ class ApiPatrol extends ApiBase {
|
|||
|
||||
public function getAllowedParams() {
|
||||
return array(
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'rcid' => array(
|
||||
ApiBase::PARAM_TYPE => 'integer',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 1, 2007
|
||||
*
|
||||
* Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -139,7 +139,10 @@ class ApiProtect extends ApiBase {
|
|||
'pageid' => array(
|
||||
ApiBase::PARAM_TYPE => 'integer',
|
||||
),
|
||||
'token' => null,
|
||||
'token' => array(
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
),
|
||||
'protections' => array(
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_REQUIRED => true,
|
||||
|
|
@ -176,7 +179,7 @@ class ApiProtect extends ApiBase {
|
|||
'protections' => 'Pipe-separated list of protection levels, formatted action=group (e.g. edit=sysop)',
|
||||
'expiry' => array( 'Expiry timestamps. If only one timestamp is set, it\'ll be used for all protections.',
|
||||
'Use \'infinite\', \'indefinite\' or \'never\', for a neverexpiring protection.' ),
|
||||
'reason' => 'Reason for (un)protecting (optional)',
|
||||
'reason' => 'Reason for (un)protecting',
|
||||
'cascade' => array( 'Enable cascading protection (i.e. protect pages included in this page)',
|
||||
'Ignored if not all protection levels are \'sysop\' or \'protect\'' ),
|
||||
'watch' => 'If set, add the page being (un)protected to your watchlist',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 7, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -103,6 +103,10 @@ class ApiQuery extends ApiBase {
|
|||
|
||||
protected $mAllowedGenerators = array();
|
||||
|
||||
/**
|
||||
* @param $main ApiMain
|
||||
* @param $action string
|
||||
*/
|
||||
public function __construct( $main, $action ) {
|
||||
parent::__construct( $main, $action );
|
||||
|
||||
|
|
@ -202,6 +206,9 @@ class ApiQuery extends ApiBase {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ApiFormatRaw|null
|
||||
*/
|
||||
public function getCustomPrinter() {
|
||||
// If &exportnowrap is set, use the raw formatter
|
||||
if ( $this->getParameter( 'export' ) &&
|
||||
|
|
@ -258,6 +265,9 @@ class ApiQuery extends ApiBase {
|
|||
$this->outputGeneralPageInfo();
|
||||
|
||||
// Execute all requested modules.
|
||||
/**
|
||||
* @var $module ApiQueryBase
|
||||
*/
|
||||
foreach ( $modules as $module ) {
|
||||
$params = $module->extractRequestParams();
|
||||
$cacheMode = $this->mergeCacheMode(
|
||||
|
|
@ -303,6 +313,9 @@ class ApiQuery extends ApiBase {
|
|||
*/
|
||||
private function addCustomFldsToPageSet( $modules, $pageSet ) {
|
||||
// Query all requested modules.
|
||||
/**
|
||||
* @var $module ApiQueryBase
|
||||
*/
|
||||
foreach ( $modules as $module ) {
|
||||
$module->requestExtraData( $pageSet );
|
||||
}
|
||||
|
|
@ -384,6 +397,9 @@ class ApiQuery extends ApiBase {
|
|||
|
||||
// Show redirect information
|
||||
$redirValues = array();
|
||||
/**
|
||||
* @var $titleTo Title
|
||||
*/
|
||||
foreach ( $pageSet->getRedirectTitles() as $titleStrFrom => $titleTo ) {
|
||||
$r = array(
|
||||
'from' => strval( $titleStrFrom ),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on December 12, 2007
|
||||
*
|
||||
* Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
|
||||
* Copyright © 2007 Roan Kattouw "<Firstname>.<Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -58,6 +58,17 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
$this->addTables( 'category' );
|
||||
$this->addFields( 'cat_title' );
|
||||
|
||||
if ( !is_null( $params['continue'] ) ) {
|
||||
$cont = explode( '|', $params['continue'] );
|
||||
if ( count( $cont ) != 1 ) {
|
||||
$this->dieUsage( "Invalid continue param. You should pass the " .
|
||||
"original value returned by the previous query", "_badcontinue" );
|
||||
}
|
||||
$op = $params['dir'] == 'descending' ? '<' : '>';
|
||||
$cont_from = $db->addQuotes( $cont[0] );
|
||||
$this->addWhere( "cat_title $op= $cont_from" );
|
||||
}
|
||||
|
||||
$dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' );
|
||||
$from = ( is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) );
|
||||
$to = ( is_null( $params['to'] ) ? null : $this->titlePartToKey( $params['to'] ) );
|
||||
|
|
@ -104,8 +115,7 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
foreach ( $res as $row ) {
|
||||
if ( ++ $count > $params['limit'] ) {
|
||||
// We've reached the one extra which shows that there are additional cats to be had. Stop here...
|
||||
// TODO: Security issue - if the user has no right to view next title, it will still be shown
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->cat_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->cat_title );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +137,7 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
}
|
||||
$fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $item );
|
||||
if ( !$fit ) {
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->cat_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->cat_title );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -143,6 +153,7 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
public function getAllowedParams() {
|
||||
return array(
|
||||
'from' => null,
|
||||
'continue' => null,
|
||||
'to' => null,
|
||||
'prefix' => null,
|
||||
'dir' => array(
|
||||
|
|
@ -178,6 +189,7 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
public function getParamDescription() {
|
||||
return array(
|
||||
'from' => 'The category to start enumerating from',
|
||||
'continue' => 'When more results are available, use this to continue',
|
||||
'to' => 'The category to stop enumerating at',
|
||||
'prefix' => 'Search for all category titles that begin with this value',
|
||||
'dir' => 'Direction to sort in',
|
||||
|
|
@ -213,6 +225,12 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
|
|||
return 'Enumerate all categories';
|
||||
}
|
||||
|
||||
public function getPossibleErrors() {
|
||||
return array_merge( parent::getPossibleErrors(), array(
|
||||
array( 'code' => '_badcontinue', 'info' => 'Invalid continue param. You should pass the original value returned by the previous query' ),
|
||||
) );
|
||||
}
|
||||
|
||||
public function getExamples() {
|
||||
return array(
|
||||
'api.php?action=query&list=allcategories&acprop=size',
|
||||
|
|
|
|||
|
|
@ -85,6 +85,17 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
|
||||
$params = $this->extractRequestParams();
|
||||
|
||||
if ( !is_null( $params['continue'] ) ) {
|
||||
$cont = explode( '|', $params['continue'] );
|
||||
if ( count( $cont ) != 1 ) {
|
||||
$this->dieUsage( "Invalid continue param. You should pass the " .
|
||||
"original value returned by the previous query", "_badcontinue" );
|
||||
}
|
||||
$op = $params['dir'] == 'descending' ? '<' : '>';
|
||||
$cont_from = $db->addQuotes( $cont[0] );
|
||||
$this->addWhere( "img_name $op= $cont_from" );
|
||||
}
|
||||
|
||||
// Image filters
|
||||
$dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' );
|
||||
$from = ( is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) );
|
||||
|
|
@ -148,8 +159,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
foreach ( $res as $row ) {
|
||||
if ( ++ $count > $limit ) {
|
||||
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
|
||||
// TODO: Security issue - if the user has no right to view next title, it will still be shown
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->img_name ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->img_name );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -161,11 +171,11 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
|
||||
$fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $info );
|
||||
if ( !$fit ) {
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->img_name ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->img_name );
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$titles[] = Title::makeTitle( NS_IMAGE, $row->img_name );
|
||||
$titles[] = Title::makeTitle( NS_FILE, $row->img_name );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +189,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
public function getAllowedParams() {
|
||||
return array (
|
||||
'from' => null,
|
||||
'continue' => null,
|
||||
'to' => null,
|
||||
'prefix' => null,
|
||||
'minsize' => array(
|
||||
|
|
@ -215,6 +226,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
public function getParamDescription() {
|
||||
return array(
|
||||
'from' => 'The image title to start enumerating from',
|
||||
'continue' => 'When more results are available, use this to continue',
|
||||
'to' => 'The image title to stop enumerating at',
|
||||
'prefix' => 'Search for all image titles that begin with this value',
|
||||
'dir' => 'The direction in which to list',
|
||||
|
|
@ -228,7 +240,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
);
|
||||
}
|
||||
|
||||
private $propertyFilter = array( 'archivename' );
|
||||
private $propertyFilter = array( 'archivename', 'thumbmime' );
|
||||
|
||||
public function getResultProperties() {
|
||||
return array_merge(
|
||||
|
|
@ -254,6 +266,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
|
|||
array( 'code' => 'mimesearchdisabled', 'info' => 'MIME search disabled in Miser Mode' ),
|
||||
array( 'code' => 'invalidsha1hash', 'info' => 'The SHA1 hash provided is not valid' ),
|
||||
array( 'code' => 'invalidsha1base36hash', 'info' => 'The SHA1Base36 hash provided is not valid' ),
|
||||
array( 'code' => '_badcontinue', 'info' => 'Invalid continue param. You should pass the original value returned by the previous query' ),
|
||||
) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on July 7, 2007
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -77,16 +77,25 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
}
|
||||
if ( !is_null( $params['continue'] ) ) {
|
||||
$continueArr = explode( '|', $params['continue'] );
|
||||
if ( count( $continueArr ) != 2 ) {
|
||||
$this->dieUsage( 'Invalid continue parameter', 'badcontinue' );
|
||||
$op = $params['dir'] == 'descending' ? '<' : '>';
|
||||
if ( $params['unique'] ) {
|
||||
if ( count( $continueArr ) != 1 ) {
|
||||
$this->dieUsage( 'Invalid continue parameter', 'badcontinue' );
|
||||
}
|
||||
$continueTitle = $db->addQuotes( $continueArr[0] );
|
||||
$this->addWhere( "pl_title $op= $continueTitle" );
|
||||
} else {
|
||||
if ( count( $continueArr ) != 2 ) {
|
||||
$this->dieUsage( 'Invalid continue parameter', 'badcontinue' );
|
||||
}
|
||||
$continueTitle = $db->addQuotes( $continueArr[0] );
|
||||
$continueFrom = intval( $continueArr[1] );
|
||||
$this->addWhere(
|
||||
"pl_title $op $continueTitle OR " .
|
||||
"(pl_title = $continueTitle AND " .
|
||||
"pl_from $op= $continueFrom)"
|
||||
);
|
||||
}
|
||||
$continueTitle = $db->addQuotes( $this->titleToKey( $continueArr[0] ) );
|
||||
$continueFrom = intval( $continueArr[1] );
|
||||
$this->addWhere(
|
||||
"pl_title > $continueTitle OR " .
|
||||
"(pl_title = $continueTitle AND " .
|
||||
"pl_from > $continueFrom)"
|
||||
);
|
||||
}
|
||||
|
||||
$from = ( is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) );
|
||||
|
|
@ -104,12 +113,13 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
$limit = $params['limit'];
|
||||
$this->addOption( 'LIMIT', $limit + 1 );
|
||||
|
||||
$sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
|
||||
$orderBy = array();
|
||||
$orderBy[] = 'pl_title' . $sort;
|
||||
if ( !$params['unique'] ) {
|
||||
$this->addOption( 'ORDER BY', array(
|
||||
'pl_title',
|
||||
'pl_from'
|
||||
));
|
||||
$orderBy[] = 'pl_from' . $sort;
|
||||
}
|
||||
$this->addOption( 'ORDER BY', $orderBy );
|
||||
|
||||
$res = $this->select( __METHOD__ );
|
||||
|
||||
|
|
@ -119,11 +129,10 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
foreach ( $res as $row ) {
|
||||
if ( ++ $count > $limit ) {
|
||||
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
|
||||
// TODO: Security issue - if the user has no right to view next title, it will still be shown
|
||||
if ( $params['unique'] ) {
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->pl_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->pl_title );
|
||||
} else {
|
||||
$this->setContinueEnumParameter( 'continue', $this->keyToTitle( $row->pl_title ) . "|" . $row->pl_from );
|
||||
$this->setContinueEnumParameter( 'continue', $row->pl_title . "|" . $row->pl_from );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -140,9 +149,9 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
$fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
|
||||
if ( !$fit ) {
|
||||
if ( $params['unique'] ) {
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->pl_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->pl_title );
|
||||
} else {
|
||||
$this->setContinueEnumParameter( 'continue', $this->keyToTitle( $row->pl_title ) . "|" . $row->pl_from );
|
||||
$this->setContinueEnumParameter( 'continue', $row->pl_title . "|" . $row->pl_from );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -183,7 +192,14 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
ApiBase::PARAM_MIN => 1,
|
||||
ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
|
||||
ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
|
||||
)
|
||||
),
|
||||
'dir' => array(
|
||||
ApiBase::PARAM_DFLT => 'ascending',
|
||||
ApiBase::PARAM_TYPE => array(
|
||||
'ascending',
|
||||
'descending'
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +218,7 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
|
|||
'namespace' => 'The namespace to enumerate',
|
||||
'limit' => 'How many total links to return',
|
||||
'continue' => 'When more results are available, use this to continue',
|
||||
'dir' => 'The direction in which to list',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Dec 1, 2007
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Sep 25, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -67,6 +67,17 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
// Page filters
|
||||
$this->addTables( 'page' );
|
||||
|
||||
if ( !is_null( $params['continue'] ) ) {
|
||||
$cont = explode( '|', $params['continue'] );
|
||||
if ( count( $cont ) != 1 ) {
|
||||
$this->dieUsage( "Invalid continue param. You should pass the " .
|
||||
"original value returned by the previous query", "_badcontinue" );
|
||||
}
|
||||
$op = $params['dir'] == 'descending' ? '<' : '>';
|
||||
$cont_from = $db->addQuotes( $cont[0] );
|
||||
$this->addWhere( "page_title $op= $cont_from" );
|
||||
}
|
||||
|
||||
if ( $params['filterredir'] == 'redirects' ) {
|
||||
$this->addWhereFld( 'page_is_redirect', 1 );
|
||||
} elseif ( $params['filterredir'] == 'nonredirects' ) {
|
||||
|
|
@ -165,13 +176,22 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
$this->addOption( 'LIMIT', $limit + 1 );
|
||||
$res = $this->select( __METHOD__ );
|
||||
|
||||
//Get gender information
|
||||
if( MWNamespace::hasGenderDistinction( $params['namespace'] ) ) {
|
||||
$users = array();
|
||||
foreach ( $res as $row ) {
|
||||
$users[] = $row->page_title;
|
||||
}
|
||||
GenderCache::singleton()->doQuery( $users, __METHOD__ );
|
||||
$res->rewind(); //reset
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$result = $this->getResult();
|
||||
foreach ( $res as $row ) {
|
||||
if ( ++ $count > $limit ) {
|
||||
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
|
||||
// TODO: Security issue - if the user has no right to view next title, it will still be shown
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->page_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->page_title );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +204,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
);
|
||||
$fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
|
||||
if ( !$fit ) {
|
||||
$this->setContinueEnumParameter( 'from', $this->keyToTitle( $row->page_title ) );
|
||||
$this->setContinueEnumParameter( 'continue', $row->page_title );
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -202,6 +222,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
|
||||
return array(
|
||||
'from' => null,
|
||||
'continue' => null,
|
||||
'to' => null,
|
||||
'prefix' => null,
|
||||
'namespace' => array(
|
||||
|
|
@ -275,6 +296,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
$p = $this->getModulePrefix();
|
||||
return array(
|
||||
'from' => 'The page title to start enumerating from',
|
||||
'continue' => 'When more results are available, use this to continue',
|
||||
'to' => 'The page title to stop enumerating at',
|
||||
'prefix' => 'Search for all page titles that begin with this value',
|
||||
'namespace' => 'The namespace to enumerate',
|
||||
|
|
@ -314,6 +336,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
|
|||
return array_merge( parent::getPossibleErrors(), array(
|
||||
array( 'code' => 'params', 'info' => 'Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator' ),
|
||||
array( 'code' => 'params', 'info' => 'prlevel may not be used without prtype' ),
|
||||
array( 'code' => '_badcontinue', 'info' => 'Invalid continue param. You should pass the original value returned by the previous query' ),
|
||||
) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on July 7, 2007
|
||||
*
|
||||
* Copyright © 2007 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Created on Oct 16, 2006
|
||||
*
|
||||
* Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
||||
* Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* 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
|
||||
|
|
@ -40,7 +40,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
private $rootTitle;
|
||||
|
||||
private $params, $contID, $redirID, $redirect;
|
||||
private $bl_ns, $bl_from, $bl_table, $bl_code, $bl_title, $bl_sort, $bl_fields, $hasNS;
|
||||
private $bl_ns, $bl_from, $bl_table, $bl_code, $bl_title, $bl_fields, $hasNS;
|
||||
|
||||
/**
|
||||
* Maps ns and title to pageid
|
||||
|
|
@ -91,14 +91,12 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
$this->hasNS = $moduleName !== 'imageusage';
|
||||
if ( $this->hasNS ) {
|
||||
$this->bl_title = $prefix . '_title';
|
||||
$this->bl_sort = "{$this->bl_ns}, {$this->bl_title}, {$this->bl_from}";
|
||||
$this->bl_fields = array(
|
||||
$this->bl_ns,
|
||||
$this->bl_title
|
||||
);
|
||||
} else {
|
||||
$this->bl_title = $prefix . '_to';
|
||||
$this->bl_sort = "{$this->bl_title}, {$this->bl_from}";
|
||||
$this->bl_fields = array(
|
||||
$this->bl_title
|
||||
);
|
||||
|
|
@ -144,7 +142,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
$this->addWhereFld( 'page_namespace', $this->params['namespace'] );
|
||||
|
||||
if ( !is_null( $this->contID ) ) {
|
||||
$this->addWhere( "{$this->bl_from}>={$this->contID}" );
|
||||
$op = $this->params['dir'] == 'descending' ? '<' : '>';
|
||||
$this->addWhere( "{$this->bl_from}$op={$this->contID}" );
|
||||
}
|
||||
|
||||
if ( $this->params['filterredir'] == 'redirects' ) {
|
||||
|
|
@ -155,7 +154,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
}
|
||||
|
||||
$this->addOption( 'LIMIT', $this->params['limit'] + 1 );
|
||||
$this->addOption( 'ORDER BY', $this->bl_from );
|
||||
$sort = ( $this->params['dir'] == 'descending' ? ' DESC' : '' );
|
||||
$this->addOption( 'ORDER BY', $this->bl_from . $sort );
|
||||
$this->addOption( 'STRAIGHT_JOIN' );
|
||||
}
|
||||
|
||||
|
|
@ -186,28 +186,35 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
|
||||
// We can't use LinkBatch here because $this->hasNS may be false
|
||||
$titleWhere = array();
|
||||
$allRedirNs = array();
|
||||
$allRedirDBkey = array();
|
||||
foreach ( $this->redirTitles as $t ) {
|
||||
$titleWhere[] = "{$this->bl_title} = " . $db->addQuotes( $t->getDBkey() ) .
|
||||
( $this->hasNS ? " AND {$this->bl_ns} = {$t->getNamespace()}" : '' );
|
||||
$redirNs = $t->getNamespace();
|
||||
$redirDBkey = $t->getDBkey();
|
||||
$titleWhere[] = "{$this->bl_title} = " . $db->addQuotes( $redirDBkey ) .
|
||||
( $this->hasNS ? " AND {$this->bl_ns} = {$redirNs}" : '' );
|
||||
$allRedirNs[] = $redirNs;
|
||||
$allRedirDBkey[] = $redirDBkey;
|
||||
}
|
||||
$this->addWhere( $db->makeList( $titleWhere, LIST_OR ) );
|
||||
$this->addWhereFld( 'page_namespace', $this->params['namespace'] );
|
||||
|
||||
if ( !is_null( $this->redirID ) ) {
|
||||
$op = $this->params['dir'] == 'descending' ? '<' : '>';
|
||||
$first = $this->redirTitles[0];
|
||||
$title = $db->addQuotes( $first->getDBkey() );
|
||||
$ns = $first->getNamespace();
|
||||
$from = $this->redirID;
|
||||
if ( $this->hasNS ) {
|
||||
$this->addWhere( "{$this->bl_ns} > $ns OR " .
|
||||
$this->addWhere( "{$this->bl_ns} $op $ns OR " .
|
||||
"({$this->bl_ns} = $ns AND " .
|
||||
"({$this->bl_title} > $title OR " .
|
||||
"({$this->bl_title} $op $title OR " .
|
||||
"({$this->bl_title} = $title AND " .
|
||||
"{$this->bl_from} >= $from)))" );
|
||||
"{$this->bl_from} $op= $from)))" );
|
||||
} else {
|
||||
$this->addWhere( "{$this->bl_title} > $title OR " .
|
||||
$this->addWhere( "{$this->bl_title} $op $title OR " .
|
||||
"({$this->bl_title} = $title AND " .
|
||||
"{$this->bl_from} >= $from)" );
|
||||
"{$this->bl_from} $op= $from)" );
|
||||
}
|
||||
}
|
||||
if ( $this->params['filterredir'] == 'redirects' ) {
|
||||
|
|
@ -217,7 +224,17 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
}
|
||||
|
||||
$this->addOption( 'LIMIT', $this->params['limit'] + 1 );
|
||||
$this->addOption( 'ORDER BY', $this->bl_sort );
|
||||
$orderBy = array();
|
||||
$sort = ( $this->params['dir'] == 'descending' ? ' DESC' : '' );
|
||||
// Don't order by namespace/title if it's constant in the WHERE clause
|
||||
if( $this->hasNS && count( array_unique( $allRedirNs ) ) != 1 ) {
|
||||
$orderBy[] = $this->bl_ns . $sort;
|
||||
}
|
||||
if( count( array_unique( $allRedirDBkey ) ) != 1 ) {
|
||||
$orderBy[] = $this->bl_title . $sort;
|
||||
}
|
||||
$orderBy[] = $this->bl_from . $sort;
|
||||
$this->addOption( 'ORDER BY', $orderBy );
|
||||
$this->addOption( 'USE INDEX', array( 'page' => 'PRIMARY' ) );
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +294,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
if ( $this->hasNS ) {
|
||||
$parentID = $this->pageMap[$row-> { $this->bl_ns } ][$row-> { $this->bl_title } ];
|
||||
} else {
|
||||
$parentID = $this->pageMap[NS_IMAGE][$row-> { $this->bl_title } ];
|
||||
$parentID = $this->pageMap[NS_FILE][$row-> { $this->bl_title } ];
|
||||
}
|
||||
$this->continueStr = $this->getContinueRedirStr( $parentID, $row->page_id );
|
||||
break;
|
||||
|
|
@ -438,6 +455,13 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TYPE => 'namespace'
|
||||
),
|
||||
'dir' => array(
|
||||
ApiBase::PARAM_DFLT => 'ascending',
|
||||
ApiBase::PARAM_TYPE => array(
|
||||
'ascending',
|
||||
'descending'
|
||||
)
|
||||
),
|
||||
'filterredir' => array(
|
||||
ApiBase::PARAM_DFLT => 'all',
|
||||
ApiBase::PARAM_TYPE => array(
|
||||
|
|
@ -467,6 +491,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
|
|||
'pageid' => "Pageid to search. Cannot be used together with {$this->bl_code}title",
|
||||
'continue' => 'When more results are available, use this to continue',
|
||||
'namespace' => 'The namespace to enumerate',
|
||||
'dir' => 'The direction in which to list',
|
||||
);
|
||||
if ( $this->getModuleName() != 'embeddedin' ) {
|
||||
return array_merge( $retval, array(
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue