<?php
-/**
+/**
* @package MediaWiki
* @addtogroup Ajax
*/
$term = trim( $term );
$term = $wgContLang->checkTitleEncoding( $wgContLang->recodeInput( js_unescape( $term ) ) );
if ( $wgCapitalLinks )
- $term = $wgContLang->ucfirst( $term );
+ $term = $wgContLang->ucfirst( $term );
$term_title = Title::newFromText( $term );
$memckey = $term_title ? wfMemcKey( 'ajaxsearch', md5( $term_title->getFullText() ) ) : wfMemcKey( 'ajaxsearch', md5( $term ) );
$r = $more = '';
$canSearch = true;
-
+
$results = PrefixSearch::titleSearch( $term, $limit + 1 );
foreach( array_slice( $results, 0, $limit ) as $titleText ) {
$r .= '<li>' . $sk->makeKnownLink( $titleText ) . "</li>\n";
}
-
+
// Hack to check for specials
if( $results ) {
$t = Title::newFromText( $results[0] );
* Called for AJAX watch/unwatch requests.
* @param $pagename Prefixed title string for page to watch/unwatch
* @param $watch String 'w' to watch, 'u' to unwatch
- * @return String '<w#>' or '<u#>' on successful watch or unwatch,
+ * @return String '<w#>' or '<u#>' on successful watch or unwatch,
* respectively, followed by an HTML message to display in the alert box; or
* '<err#>' on error
*/
if(wfReadOnly()) {
// redirect to action=(un)watch, which will display the database lock
// message
- return '<err#>';
+ return '<err#>';
}
if('w' !== $watch && 'u' !== $watch) {
return '<u#>'.wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() );
}
}
-
if ( $this->mCacheDuration ) {
- # If squid caches are configured, tell them to cache the response,
+ # If squid caches are configured, tell them to cache the response,
# and tell the client to always check with the squid. Otherwise,
# tell the client to use a cached copy, without a way to purge it.
return true;
}
}
-
}
if( !$outputDone ) {
$wgOut->setRevisionId( $this->getRevIdFetched() );
-
+
// Pages containing custom CSS or JavaScript get special treatment
if( $this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage() ) {
$wgOut->addHtml( wfMsgExt( 'clearyourcache', 'parse' ) );
$wgOut->addHtml( htmlspecialchars( $this->mContent ) );
$wgOut->addHtml( "\n</pre>\n" );
}
-
+
}
-
+
elseif ( $rt = $this->getRedirectTarget() ) {
# Display redirect
$imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
$lastRevision = 0;
$revisionId = 0;
-
+
$changed = ( strcmp( $text, $oldtext ) != 0 );
if ( $changed ) {
# Invalidate cache of this article and all pages using this article
# as a template. Partly deferred.
Article::onArticleEdit( $this->mTitle );
-
+
# Update links tables, site stats, etc.
$this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
}
if ( !($wgUseNPPatrol || $wgUseRCPatrol)) {
$wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
- return;
+ return;
}
# If we haven't been given an rc_id value, we can't do anything
$wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
return;
}
-
+
# Check permissions
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'patrol', $wgUser );
foreach( $limit as $action => $restrictions ) {
# Check if the group level required to edit also can protect pages
# Otherwise, people who cannot normally protect can "protect" pages via transclusion
- $cascade = ( $cascade && isset($wgGroupPermissions[$restrictions]['protect']) &&
- $wgGroupPermissions[$restrictions]['protect'] );
+ $cascade = ( $cascade && isset($wgGroupPermissions[$restrictions]['protect']) &&
+ $wgGroupPermissions[$restrictions]['protect'] );
}
-
+
$cascade_description = '';
if ($cascade) {
$cascade_description = ' ['.wfMsg('protect-summary-cascade').']';
$comment .= "$expiry_description";
if ( $cascade )
$comment .= "$cascade_description";
-
+
# Update restrictions table
foreach( $limit as $action => $restrictions ) {
if ($restrictions != '' ) {
# Update the protection log
$log = new LogPage( 'protect' );
-
-
+
+
if( $protect ) {
$log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle, trim( $reason . " [$updated]$cascade_description$expiry_description" ) );
}
return implode( ':', $bits );
}
-
+
/**
* Auto-generates a deletion reason
* @param bool &$hasHistory Whether the page has a history
else
$reason = wfMsgForContent('excontent', '$1');
}
-
+
// Replace newlines with spaces to prevent uglyness
$contents = preg_replace("/[\n\r]/", ' ', $contents);
// Calculate the maximum amount of chars to get
$confirm = $wgRequest->wasPosted() &&
$wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
-
+
$this->DeleteReasonList = $wgRequest->getText( 'wpDeleteReasonList', 'other' );
$this->DeleteReason = $wgRequest->getText( 'wpReason' );
-
+
$reason = $this->DeleteReasonList;
-
+
if ( $reason != 'other' && $this->DeleteReason != '') {
// Entry from drop down menu + additional comment
$reason .= ': ' . $this->DeleteReason;
$wgOut->readOnlyPage();
return;
}
-
+
# Check permissions
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser );
array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
}
}
-
+
return $this->confirmDelete( '', $reason );
}
-
+
/**
* @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
*/
}
return false;
}
-
+
/**
* @return int approximate revision count
*/
"</td>
<td>" .
Xml::listDropDown( 'wpDeleteReasonList',
- wfMsgForContent( 'deletereason-dropdown' ),
+ wfMsgForContent( 'deletereason-dropdown' ),
wfMsgForContent( 'deletereasonotherlist' ), '', 'wpReasonDropDown', 1 ) .
"</td>
</tr>
} else {
$bitfield = 'rev_deleted';
}
-
+
// For now, shunt the revision data into the archive table.
// Text is *not* removed from the text table; bulk storage
// is left intact to avoid breaking block-compression or
if ( !$dbw->cleanupTriggers() ) {
# Clean up recentchanges entries...
- $dbw->delete( 'recentchanges',
+ $dbw->delete( 'recentchanges',
array( 'rc_namespace' => $ns, 'rc_title' => $t, 'rc_type != '.RC_LOG ),
__METHOD__ );
}
$logtype = $suppress ? 'suppress' : 'delete';
$log = new LogPage( $logtype );
$log->addEntry( 'delete', $this->mTitle, $reason );
-
+
return true;
}
* performs permissions checks on $wgUser, then calls commitRollback()
* to do the dirty work
*
- * @param string $fromP - Name of the user whose edits to rollback.
+ * @param string $fromP - Name of the user whose edits to rollback.
* @param string $summary - Custom summary. Set to default summary if empty.
* @param string $token - Rollback token.
* @param bool $bot - If true, mark all reverted edits as bot.
- *
+ *
* @param array $resultDetails contains result-specific array of additional values
* 'alreadyrolled' : 'current' (rev)
* success : 'summary' (str), 'current' (rev), 'target' (rev)
- *
+ *
* @return array of errors, each error formatted as
* array(messagekey, param1, param2, ...).
* On success, the array is empty. This array can also be passed to
# If there were errors, bail out now
if(!empty($errors))
return $errors;
-
+
return $this->commitRollback($fromP, $summary, $bot, $resultDetails);
}
-
+
/**
* Backend implementation of doRollback(), please refer there for parameter
* and return value documentation
* rollback to the DB Therefore, you should only call this function direct-
* ly if you want to use custom permissions checks. If you don't, use
* doRollback() instead.
- */
+ */
public function commitRollback($fromP, $summary, $bot, &$resultDetails) {
global $wgUseRCPatrol, $wgUser;
$dbw = wfGetDB( DB_MASTER );
# Only admins can see this text
return array(array('notvisiblerev'));
}
-
+
$set = array();
if ( $bot && $wgUser->isAllowed('markbotedits') ) {
# Mark all reverted edits as bot
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
$cdel='';
- if( $wgUser->isAllowed( 'deleterevision' ) ) {
+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
if( $revision->isCurrent() ) {
// We don't handle top deleted edits too well
- $cdel = wfMsgHtml('rev-delundel');
+ $cdel = wfMsgHtml('rev-delundel');
} else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
// If revision was hidden from sysops
- $cdel = wfMsgHtml('rev-delundel');
+ $cdel = wfMsgHtml('rev-delundel');
} else {
$cdel = $sk->makeKnownLinkObj( $revdel,
wfMsgHtml('rev-delundel'),
$infomsg = $current && !wfEmptyMsg( 'revision-info-current', $m ) && $m != '-'
? 'revision-info-current'
: 'revision-info';
-
+
$r = "\n\t\t\t\t<div id=\"mw-{$infomsg}\">" . wfMsg( $infomsg, $td, $userlinks ) . "</div>\n" .
"\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
$printable = $wgRequest->getVal( 'printable' );
$page = $wgRequest->getVal( 'page' );
- //check for non-standard user language; this covers uselang,
+ //check for non-standard user language; this covers uselang,
//and extensions for auto-detecting user language.
- $ulang = $wgLang->getCode();
+ $ulang = $wgLang->getCode();
$clang = $wgContLang->getCode();
$cacheable = $wgUseFileCache
}
$other->invalidateCache();
$other->purgeSquid();
-
+
$title->touchLinks();
$title->purgeSquid();
// Invalidate the caches of all pages which redirect here
$wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'redirect' );
-
+
# Purge squid for this page only
$title->purgeSquid();
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( array( 'categorylinks', 'page_props', 'page' ),
array( 'cl_to' ),
- array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',
+ array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',
'page_namespace' => NS_CATEGORY, 'page_title=cl_to'),
'Article:getHiddenCategories' );
if ( false !== $res ) {
return $username;
}
}
-
-
'ApiUnblock' => 'includes/api/ApiUnblock.php',
'ApiUndelete' => 'includes/api/ApiUndelete.php',
);
-
+
wfProfileIn( __METHOD__ );
if ( isset( $localClasses[$className] ) ) {
$filename = $localClasses[$className];
function wfLoadAllExtensions() {
global $wgAutoloadClasses;
- # It is crucial that SpecialPage.php is included before any special page
+ # It is crucial that SpecialPage.php is included before any special page
# extensions are loaded. Otherwise the parent class will not be available
- # when APC loads the early-bound extension class. Normally this is
- # guaranteed by entering special pages via SpecialPage members such as
+ # when APC loads the early-bound extension class. Normally this is
+ # guaranteed by entering special pages via SpecialPage members such as
# executePath(), but here we have to take a more explicit measure.
-
+
require_once( dirname(__FILE__) . '/SpecialPage.php' );
-
+
foreach( $wgAutoloadClasses as $class => $file ) {
if( !( class_exists( $class ) || interface_exists( $class ) ) ) {
require( $file );
return false;
return true;
} elseif( $cond[0] == '|' ) {
- foreach( array_slice( $cond, 1 ) as $subcond )
+ foreach( array_slice( $cond, 1 ) as $subcond )
if( self::recCheckCondition( $subcond, $user ) )
return true;
return false;
}
if($row=$this->_fetchobject($res)) {
$this->_debug("get: retrieved data; exp time is " . $row->exptime);
- if ( $row->exptime != $this->_maxdatetime() &&
- wfTimestamp( TS_UNIX, $row->exptime ) < time() )
+ if ( $row->exptime != $this->_maxdatetime() &&
+ wfTimestamp( TS_UNIX, $row->exptime ) < time() )
{
$this->_debug("get: key has expired, deleting");
$this->delete($key);
}
return $val;
}
-
+
function set($key, $value, $exptime=0) {
apc_store($key, serialize($value), $exptime);
return true;
}
-
+
function delete($key, $time=0) {
apc_delete($key);
return true;
$val = unserialize( $val );
return $val;
}
-
+
/**
* Store a value in the XCache object cache
*
xcache_set( $key, serialize( $value ), $expire );
return true;
}
-
+
/**
* Remove a value from the XCache object cache
*
xcache_unset( $key );
return true;
}
-
+
}
/**
*/
class DBABagOStuff extends BagOStuff {
var $mHandler, $mFile, $mReader, $mWriter, $mDisabled;
-
+
function __construct( $handler = 'db3', $dir = false ) {
if ( $dir === false ) {
global $wgTmpDirectory;
if ( !is_string( $blob ) ) {
return array( null, 0 );
} else {
- return array(
+ return array(
unserialize( substr( $blob, 11 ) ),
intval( substr( $blob, 0, 10 ) )
);
return $result;
}
}
-
-
class Block
{
/* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry,
- $mRangeStart, $mRangeEnd, $mAnonOnly, $mEnableAutoblock, $mHideName,
+ $mRangeStart, $mRangeEnd, $mAnonOnly, $mEnableAutoblock, $mHideName,
$mBlockEmail, $mByName;
/* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate, $mFromMaster;
-
+
const EB_KEEP_EXPIRED = 1;
const EB_FOR_UPDATE = 2;
const EB_RANGE_ONLY = 4;
function __construct( $address = '', $user = 0, $by = 0, $reason = '',
- $timestamp = '' , $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
+ $timestamp = '' , $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
$hideName = 0, $blockEmail = 0 )
{
$this->mId = 0;
}
}
- static function newFromID( $id )
+ static function newFromID( $id )
{
$dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->resultObject( $dbr->select( 'ipblocks', '*',
+ $res = $dbr->resultObject( $dbr->select( 'ipblocks', '*',
array( 'ipb_id' => $id ), __METHOD__ ) );
$block = new Block;
if ( $block->loadFromResult( $res ) ) {
function clear()
{
$this->mAddress = $this->mReason = $this->mTimestamp = '';
- $this->mId = $this->mAnonOnly = $this->mCreateAccount =
- $this->mEnableAutoblock = $this->mAuto = $this->mUser =
+ $this->mId = $this->mAnonOnly = $this->mCreateAccount =
+ $this->mEnableAutoblock = $this->mAuto = $this->mUser =
$this->mBy = $this->mHideName = $this->mBlockEmail = 0;
$this->mByName = false;
}
# Try user block
if ( $user ) {
- $res = $db->resultObject( $db->select( 'ipblocks', '*', array( 'ipb_user' => $user ),
+ $res = $db->resultObject( $db->select( 'ipblocks', '*', array( 'ipb_user' => $user ),
__METHOD__, $options ) );
if ( $this->loadFromResult( $res, $killExpired ) ) {
return true;
return true;
}
}
-
+
# Give up
$this->clear();
return false;
/**
* Fill in member variables from a result wrapper
*/
- function loadFromResult( ResultWrapper $res, $killExpired = true )
+ function loadFromResult( ResultWrapper $res, $killExpired = true )
{
$ret = false;
if ( 0 != $res->numRows() ) {
"ipb_range_start <= '$iaddr'",
"ipb_range_end >= '$iaddr'"
);
-
+
if ( $user ) {
$conds['ipb_anon_only'] = 0;
}
return $this->mAddress;
}
}
-
+
/**
* Encode expiry for DB
*/
}
}
- /**
+ /**
* Decode expiry which has come from the DB
*/
static function decodeExpiry( $expiry, $timestampType = TS_MW ) {
return wfTimestamp( $timestampType, $expiry );
}
}
-
+
static function getAutoblockExpiry( $timestamp )
{
global $wgAutoblockExpiry;
return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
}
-
- /**
+
+ /**
* Gets rid of uneeded numbers in quad-dotted/octet IP strings
* For example, 127.111.113.151/24 -> 127.111.113.0/24
*/
return $range;
}
- /**
+ /**
* Purge expired blocks from the ipblocks table
*/
static function purgeExpired() {
}
static function infinity() {
- # This is a special keyword for timestamps in PostgreSQL, and
- # works with CHAR(14) as well because "i" sorts after all numbers.
+ # This is a special keyword for timestamps in PostgreSQL, and
+ # works with CHAR(14) as well because "i" sorts after all numbers.
return 'infinity';
/*
}
}
-
<?php
/**
- * This class stores an arbitrary value along with its dependencies.
+ * This class stores an arbitrary value along with its dependencies.
* Users should typically only use DependencyWrapper::getFromCache(), rather
* than instantiating one of these objects directly.
* @addtogroup Cache
$this->deps = $deps;
}
- /**
+ /**
* Returns true if any of the dependencies have expired
*/
function isExpired() {
}
/**
- * Attempt to get a value from the cache. If the value is expired or missing,
+ * Attempt to get a value from the cache. If the value is expired or missing,
* it will be generated with the callback function (if present), and the newly
- * calculated value will be stored to the cache in a wrapper.
+ * calculated value will be stored to the cache in a wrapper.
*
* @param object $cache A cache object such as $wgMemc
* @param string $key The cache key
* @param integer $expiry The expiry timestamp or interval in seconds
* @param mixed $callback The callback for generating the value, or false
* @param array $callbackParams The function parameters for the callback
- * @param array $deps The dependencies to store on a cache miss. Note: these
+ * @param array $deps The dependencies to store on a cache miss. Note: these
* are not the dependencies used on a cache hit! Cache hits use the stored
* dependency array.
*
* @return mixed The value, or null if it was not present in the cache and no
* callback was defined.
*/
- static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false,
- $callbackParams = array(), $deps = array() )
+ static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false,
+ $callbackParams = array(), $deps = array() )
{
$obj = $cache->get( $key );
if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) {
*
* @param string $filename The name of the file, preferably fully qualified
* @param mixed $timestamp The unix last modified timestamp, or false if the
- * file does not exist. If omitted, the timestamp will be loaded from
+ * file does not exist. If omitted, the timestamp will be loaded from
* the file.
*
- * A dependency on a nonexistent file will be triggered when the file is
- * created. A dependency on an existing file will be triggered when the
+ * A dependency on a nonexistent file will be triggered when the file is
+ * created. A dependency on an existing file will be triggered when the
* file is changed.
*/
function __construct( $filename, $timestamp = null ) {
function loadDependencyValues() {
$this->touched = $this->getTitle()->getTouched();
}
-
+
/**
* Get rid of bulky Title object for sleep
*/
function getTitle() {
if ( !isset( $this->titleObj ) ) {
$this->titleObj = Title::makeTitle( $this->ns, $this->dbk );
- }
+ }
return $this->titleObj;
}
class TitleListDependency extends CacheDependency {
var $linkBatch;
var $timestamps;
-
+
/**
* Construct a dependency on a list of titles
*/
if ( count( $timestamps ) ) {
$dbr = wfGetDB( DB_SLAVE );
$where = $this->getLinkBatch()->constructSet( 'page', $dbr );
- $res = $dbr->select( 'page',
+ $res = $dbr->select( 'page',
array( 'page_namespace', 'page_title', 'page_touched' ),
$where, __METHOD__ );
while ( $row = $dbr->fetchObject( $res ) ) {
*/
class GlobalDependency extends CacheDependency {
var $name, $value;
-
+
function __construct( $name ) {
$this->name = $name;
$this->value = $GLOBALS[$name];
return constant( $this->name ) != $this->value;
}
}
-
-
class CategoryViewer {
var $title, $limit, $from, $until,
- $articles, $articles_start_char,
+ $articles, $articles_start_char,
$children, $children_start_char,
$showGallery, $gallery,
$skin;
$this->limit = $wgCategoryPagingLimit;
$this->cat = Category::newFromName( $title->getDBKey() );
}
-
+
/**
* Format the category data list.
*
function addSubcategory( $title, $sortkey, $pageLength ) {
global $wgContLang;
// Subcategory; strip the 'Category' namespace from the link text.
- $this->children[] = $this->getSkin()->makeKnownLinkObj(
+ $this->children[] = $this->getSkin()->makeKnownLinkObj(
$title, $wgContLang->convertHtml( $title->getText() ) );
$this->children_start_char[] = $this->getSubcategorySortChar( $title, $sortkey );
*/
function getSubcategorySortChar( $title, $sortkey ) {
global $wgContLang;
-
+
if( $title->getPrefixedText() == $sortkey ) {
$firstChar = $wgContLang->firstChar( $title->getDBkey() );
} else {
$firstChar = $wgContLang->firstChar( $sortkey );
}
-
+
return $wgContLang->convert( $firstChar );
}
#+ $pageCondition,
__METHOD__,
array( 'ORDER BY' => $this->flip ? 'cl_sortkey DESC' : 'cl_sortkey',
- 'USE INDEX' => 'cl_sortkey',
+ 'USE INDEX' => 'cl_sortkey',
'LIMIT' => $this->limit + 1 ) );
$count = 0;
$wgLang->formatNum( $totalcnt ) );
}
}
-
-
-
}
} # END OF CLASS "Categoryfinder"
-
-
# Called by history lists and recent changes
#
- /**
+ /**
* Changeslist contructor
* @param Skin $skin
*/
wfRunHooks('ChangesListInsertArticleLink',
array(&$this, &$articlelink, &$s, &$rc, $unpatrolled, $watched));
-
+
$s .= ' '.$articlelink;
}
/** Insert links to user page, user talk page and eventually a blocking link */
protected 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">' . wfMsgHtml('rev-deleted-user') . '</span>';
} else {
$s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
$s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
if ( $this->isDeleted($rc,LogPage::DELETED_ACTION) ) {
$s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
} else {
- $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'],
+ $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'],
$rc->getTitle(), $this->skin, LogPage::extractParams($rc->mAttribs['rc_params']), true, true );
}
}
}
}
}
-
+
/**
* Check whether to enable recent changes patrol features
* @return bool
return '';
}
}
-
+
/**
* Determine if said field of a revision is hidden
* @param RCCacheEntry $rc
public static function isDeleted( $rc, $field ) {
return ($rc->mAttribs['rc_deleted'] & $field) == $field;
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this revision, if it's marked as deleted.
$this->insertAction($s, $rc);
# Edit or log comment
$this->insertComment($s, $rc);
-
+
# Mark revision as deleted if so
if ( !$rc_log_type && $this->isDeleted($rc,Revision::DELETED_TEXT) )
$s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
} else {
$clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '' );
}
-
+
# Don't show unusable diff links
if ( !ChangesList::userCan($rc,Revision::DELETED_TEXT) ) {
$showdifflinks = false;
$querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid$rcIdQuery";
$aprops = ' tabindex="'.$baseRC->counter.'"';
$curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['cur'], $querycur, '' ,'', $aprops );
-
+
# Make "diff" an "cur" links
if( !$showdifflinks ) {
$curLink = $this->message['cur'];
} else {
$diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['diff'], $querydiff, '' ,'', $aprops );
}
-
+
# Make "last" link
if( !$showdifflinks ) {
$lastLink = $this->message['last'];
$lastLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['last'],
$curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery );
}
-
+
# Make user links
if( $this->isDeleted($rc,Revision::DELETED_USER) ) {
$rc->userlink = ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-user') . '</span>';
if( !$currentRevision && $rcObj->mAttribs['rc_this_oldid'] ) {
$currentRevision = $rcObj->mAttribs['rc_this_oldid'];
}
-
+
$bot = $rcObj->mAttribs['rc_bot'];
$userlinks[$u]++;
}
}
$r .= ') . . ';
}
-
+
# Character difference (does not apply if only log items)
if( $wgRCShowChangedSize && !$alllogs ) {
$last = 0;
# Get net change
$chardiff = $rcObj->getCharacterDifference( $block[$first]->mAttribs['rc_old_len'],
$block[$last]->mAttribs['rc_new_len'] );
-
+
if( $chardiff == '' ) {
$r .= ' ';
} else {
$r .= '(' . $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
$this->message['history'], $curIdEq.'&action=history' ) . ')';
}
-
+
$r .= $users;
$r .=$this->numberofWatchingusers($block[0]->numberofWatchingusers);
-
+
$r .= "</td></tr></table>\n";
# Sub-entries
$link = '<span class="history-deleted">'.$link.'</span> ';
}
$r .= $link;
-
+
if ( !$rc_type == RC_LOG || $rc_type == RC_NEW ) {
$r .= ' (';
$r .= $rcObj->curlink;
protected function spacerArrow() {
return $this->arrow( '', ' ' );
}
-
+
/**
* Add a set of spaces
* @return string HTML <td> tag
- */
+ */
protected function spacerIndent() {
return ' ';
}
$r = '<table cellspacing="0" cellpadding="0" border="0" style="background: none"><tr>';
$r .= '<td valign="top" style="white-space: nowrap"><tt>' . $this->spacerArrow() . ' ';
-
+
# Flag and Timestamp
if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
$r .= ' '; // 4 flags -> 4 spaces
$r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, ' ', $rc_bot );
}
$r .= ' '.$rcObj->timestamp.' </tt></td><td>';
-
+
# Article or log link
if( $rc_log_type ) {
$logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
} else {
$r .= $this->maybeWatchedLink( $rcObj->link, $rcObj->watched );
}
-
+
# Diff and hist links
if ( $rc_type != RC_LOG ) {
$r .= ' ('. $rcObj->difflink . $this->message['semicolon-separator'] . ' ';
$r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' ) . ')';
}
$r .= ' . . ';
-
+
# Character diff
if( $wgRCShowChangedSize ) {
$r .= ( $rcObj->getCharacterDifference() == '' ? '' : ' ' . $rcObj->getCharacterDifference() . ' . . ' ) ;
$r .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
} else {
$r .= ' ' . LogPage::actionText( $rc_log_type, $rc_log_action, $rcObj->getTitle(), $this->skin, LogPage::extractParams($rc_params), true, true );
- }
+ }
}
# Edit or log comment
class CoreParserFunctions {
static function register( $parser ) {
global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions;
-
+
# Syntax for arguments (see self::setFunctionHook):
# "name for lookup in localized magic words array",
# function callback,
return $mwRaw->match( $param );
}
}
-
+
static function formatRaw( $num, $raw ) {
if( self::isRaw( $raw ) ) {
return $num;
static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw );
}
-
+
static function pagesincategory( $parser, $category = '', $raw = null ) {
global $wgExpensiveParserFunctionLimit;
if ($category == '') {
return wfMsgForContent( 'nosuchspecialpage' );
}
}
-
+
public static function defaultsort( $parser, $text ) {
$text = trim( $text );
if( strlen( $text ) > 0 )
$parser->setDefaultSort( $text );
return '';
}
-
+
public static function filepath( $parser, $name='', $option='' ) {
$file = wfFindFile( $name );
if( $file ) {
$stripList = $parser->getStripList();
if ( !in_array( $tagName, $stripList ) ) {
- return '<span class="error">' .
- wfMsg( 'unknown_extension_tag', $tagName ) .
+ return '<span class="error">' .
+ wfMsg( 'unknown_extension_tag', $tagName ) .
'</span>';
}
return $parser->extensionSubstitution( $params, $frame );
}
}
-
$fname = 'showCreditsPage';
wfProfileIn( $fname );
-
+
$wgOut->setPageTitle( $article->mTitle->getPrefixedText() );
$wgOut->setSubtitle( wfMsg( 'creditspage' ) );
$wgOut->setArticleFlag( false );
$skin = $wgUser->getSkin();
return $skin->makeKnownLink($article->mTitle->getPrefixedText(), wfMsg('others'), 'action=credits');
}
-
-
}
/**
- * The oci8 extension is fairly weak and doesn't support oci_num_rows, among
- * other things. We use a wrapper class to handle that and other
+ * The oci8 extension is fairly weak and doesn't support oci_num_rows, among
+ * other things. We use a wrapper class to handle that and other
* Oracle-specific bits, like converting column names back to lowercase.
* @addtogroup Database
*/
$e = oci_error($this->mConn);
$this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__);
}
-
+
if (oci_execute($stmt, $this->execFlags()) == false) {
$e = oci_error($stmt);
$this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__);
oci_free_statement($stmt);
}
-
+
function tableName( $name ) {
# Replace reserved words with better ones
switch( $name ) {
}
function reportQueryError($error, $errno, $sql, $fname, $tempIgnore = false) {
- # Ignore errors during error handling to avoid infinite
+ # Ignore errors during error handling to avoid infinite
# recursion
$ignore = $this->ignoreErrors(true);
++$this->mErrorCount;
if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}";
if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}";
-
+
if (isset($options['LIMIT'])) {
// $tailOpts .= $this->limitResult('', $options['LIMIT'],
- // isset($options['OFFSET']) ? $options['OFFSET']
+ // isset($options['OFFSET']) ? $options['OFFSET']
// : false);
}
} else {
$useIndex = '';
}
-
+
return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
}
}
} // end DatabaseOracle class
-
-
global $wgDBmwschema;
$q = <<<END
-SELECT
+SELECT
CASE WHEN typname = 'int2' THEN 'smallint'
WHEN typname = 'int4' THEN 'integer'
WHEN typname = 'int8' THEN 'bigint'
dieout('</ul>');
}
$perms = pg_fetch_result($res, 0, 0);
-
+
$SQL = "SELECT 1 FROM pg_catalog.pg_user WHERE usename = " . $this->addQuotes($wgDBuser);
$rows = $this->numRows($this->doQuery($SQL));
if ($rows) {
// Reconnect to check out tsearch2 rights for this user
print "<li>Connecting to \"$wgDBname\" as superuser \"$wgDBsuperuser\" to check rights...";
-
+
$hstring="";
if ($this->mServer!=false && $this->mServer!="") {
$hstring="host=$this->mServer ";
print "Please see <a href='http://www.devx.com/opensource/Article/21674/0/page/2'>this article</a>";
print " for instructions or ask on #postgresql on irc.freenode.net</li>\n";
dieout("</ul>");
- }
+ }
print "OK</li>\n";
print "<li>Ensuring that user \"$wgDBuser\" has select rights on the tsearch2 tables...";
foreach (array('cfg','cfgmap','dict','parser') as $table) {
}
print "OK</li>";
}
-
+
// Install plpgsql if needed
$this->setup_plpgsql();
$wgDBsuperuser = '';
return true; // Reconnect as regular user
-
+
} // end superuser
-
+
if (!defined('POSTGRES_SEARCHPATH')) {
-
+
if ($this->numeric_version < 8.3) {
// Do we have the basic tsearch2 table?
print "<li>Checking for tsearch2 in the schema \"$wgDBts2schema\"...";
dieout("</ul>");
}
print "OK</li>\n";
-
+
// Does this user have the rights to the tsearch2 tables?
$ctype = pg_fetch_result($this->doQuery("SHOW lc_ctype"),0,0);
print "<li>Checking tsearch2 permissions...";
}
print "OK</li>";
}
-
+
// Final test: try out a simple tsearch2 query
$SQL = "SELECT $safetsschema.to_tsvector('default','MediaWiki tsearch2 testing')";
$res = $this->doQuery($SQL);
}
print "OK</li>";
}
-
+
// Install plpgsql if needed
$this->setup_plpgsql();
else {
print "<li>Schema \"$wgDBmwschema\" exists and is owned by \"$wgDBuser\". Excellent.</li>\n";
}
-
+
// Always return GMT time to accomodate the existing integer-based timestamp assumption
print "<li>Setting the timezone to GMT for user \"$wgDBuser\" ...";
$SQL = "ALTER USER $safeuser SET timezone = 'GMT'";
print "<li>Failed to set datestyle</li>\n";
dieout("</ul>");
}
-
+
// Fix up the search paths if needed
print "<li>Setting the search path for user \"$wgDBuser\" ...";
$path = $this->quote_ident($wgDBmwschema);
* Returns -1 if count cannot be found
* Takes same arguments as Database::select()
*/
-
+
function estimateRowCount( $table, $vars='*', $conds='', $fname = 'Database::estimateRowCount', $options = array() ) {
$options['EXPLAIN'] = true;
$res = $this->select( $table, $vars, $conds, $fname, $options );
/**
* INSERT wrapper, inserts an array into a table
*
- * $args may be a single associative array, or an array of these with numeric keys,
+ * $args may be a single associative array, or an array of these with numeric keys,
* for multi-row insert (Postgres version 8.2 and above only).
*
* @param array $table String: Name of the table to insert to.
/**
- * Query whether a given relation exists (in the given schema, or the
+ * Query whether a given relation exists (in the given schema, or the
* default mw one if not given)
*/
function relationExists( $table, $types, $schema = false ) {
}
/*
- * For backward compatibility, this function checks both tables and
+ * For backward compatibility, this function checks both tables and
* views.
*/
function tableExists ($table, $schema = false) {
return $this->relationExists($table, array('r', 'v'), $schema);
}
-
+
function sequenceExists ($sequence, $schema = false) {
return $this->relationExists($sequence, 'S', $schema);
}
global $wgDBmwschema;
$SQL = sprintf("SELECT 1 FROM information_schema.table_constraints ".
"WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
- $this->addQuotes($wgDBmwschema),
- $this->addQuotes($table),
+ $this->addQuotes($wgDBmwschema),
+ $this->addQuotes($table),
$this->addQuotes($constraint));
$res = $this->query($SQL);
if (!$res)
if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY " . $options['GROUP BY'];
if ( isset( $options['HAVING'] ) ) $preLimitTail .= " HAVING {$options['HAVING']}";
if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY " . $options['ORDER BY'];
-
+
//if (isset($options['LIMIT'])) {
// $tailOpts .= $this->limitResult('', $options['LIMIT'],
- // isset($options['OFFSET']) ? $options['OFFSET']
+ // isset($options['OFFSET']) ? $options['OFFSET']
// : false);
//}
if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $postLimitTail .= ' FOR UPDATE';
if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $postLimitTail .= ' LOCK IN SHARE MODE';
if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT';
-
+
return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail );
}
wfDebug( "Function ping() not written for DatabasePostgres.php yet");
return true;
}
-
+
/**
* How lagged is this slave?
*
}
} // end DatabasePostgres class
-
-
var $regexes, $pDays, $pMonths, $pYears;
var $rules, $xMonths, $preferences;
-
+
const ALL = -1;
const NONE = 0;
const MDY = 1;
return $text;
}
}
-
-
/** Name of the site. It must be changed in LocalSettings.php */
$wgSitename = 'MediaWiki';
-/**
- * Name of the project namespace. If left set to false, $wgSitename will be
+/**
+ * Name of the project namespace. If left set to false, $wgSitename will be
* used instead.
*/
$wgMetaNamespace = false;
* File repository structures
*
* $wgLocalFileRepo is a single repository structure, and $wgForeignFileRepo is
- * a an array of such structures. Each repository structure is an associative
- * array of properties configuring the repository.
+ * a an array of such structures. Each repository structure is an associative
+ * array of properties configuring the repository.
*
* Properties required for all repos:
- * class The class name for the repository. May come from the core or an extension.
+ * class The class name for the repository. May come from the core or an extension.
* The core repository classes are LocalRepo, ForeignDBRepo, FSRepo.
*
* name A unique name for the repository.
* url Base public URL
* hashLevels The number of directory levels for hash-based division of files
* thumbScriptUrl The URL for thumb.php (optional, not recommended)
- * transformVia404 Whether to skip media file transformation on parse and rely on a 404
+ * transformVia404 Whether to skip media file transformation on parse and rely on a 404
* handler instead.
- * initialCapital Equivalent to $wgCapitalLinks, determines whether filenames implicitly
+ * initialCapital Equivalent to $wgCapitalLinks, determines whether filenames implicitly
* start with a capital letter. The current implementation may give incorrect
- * description page links when the local $wgCapitalLinks and initialCapital
+ * description page links when the local $wgCapitalLinks and initialCapital
* are mismatched.
* pathDisclosureProtection
- * May be 'paranoid' to remove all parameters from error messages, 'none' to
- * leave the paths in unchanged, or 'simple' to replace paths with
+ * May be 'paranoid' to remove all parameters from error messages, 'none' to
+ * leave the paths in unchanged, or 'simple' to replace paths with
* placeholders. Default for LocalRepo is 'simple'.
*
* These settings describe a foreign MediaWiki installation. They are optional, and will be ignored
* for local repositories:
* descBaseUrl URL of image description pages, e.g. http://en.wikipedia.org/wiki/Image:
- * scriptDirUrl URL of the MediaWiki installation, equivalent to $wgScriptPath, e.g.
+ * scriptDirUrl URL of the MediaWiki installation, equivalent to $wgScriptPath, e.g.
* http://en.wikipedia.org/w
*
* articleUrl Equivalent to $wgArticlePath, e.g. http://en.wikipedia.org/wiki/$1
- * fetchDescription Fetch the text of the remote file description page. Equivalent to
+ * fetchDescription Fetch the text of the remote file description page. Equivalent to
* $wgFetchCommonsDescriptions.
*
* ForeignDBRepo:
* tablePrefix Table prefix, the foreign wiki's $wgDBprefix
* hasSharedCache True if the wiki's shared cache is accessible via the local $wgMemc
*
- * The default is to initialise these arrays from the MW<1.11 backwards compatible settings:
+ * The default is to initialise these arrays from the MW<1.11 backwards compatible settings:
* $wgUploadPath, $wgThumbnailScriptPath, $wgSharedUploadDirectory, etc.
*/
$wgLocalFileRepo = false;
#$wgMimeInfoFile= NULL; #use built-in defaults only.
/** Switch for loading the FileInfo extension by PECL at runtime.
- * This should be used only if fileinfo is installed as a shared object
+ * This should be used only if fileinfo is installed as a shared object
* or a dynamic libary
* @global string $wgLoadFileinfoExtension
*/
/**
* Make all database connections secretly go to localhost. Fool the load balancer
- * thinking there is an arbitrarily large cluster of servers to connect to.
+ * thinking there is an arbitrarily large cluster of servers to connect to.
* Useful for debugging.
*/
$wgAllDBsAreLocalhost = false;
* These and any other user-defined properties will be assigned to the mLBInfo member
* variable of the Database object.
*
- * Leave at false to use the single-server variables above. If you set this
- * variable, the single-server variables will generally be ignored (except
- * perhaps in some command-line scripts).
+ * Leave at false to use the single-server variables above. If you set this
+ * variable, the single-server variables will generally be ignored (except
+ * perhaps in some command-line scripts).
*
- * The first server listed in this array (with key 0) will be the master. The
- * rest of the servers will be slaves. To prevent writes to your slaves due to
- * accidental misconfiguration or MediaWiki bugs, set read_only=1 on all your
+ * The first server listed in this array (with key 0) will be the master. The
+ * rest of the servers will be slaves. To prevent writes to your slaves due to
+ * accidental misconfiguration or MediaWiki bugs, set read_only=1 on all your
* slaves in my.cnf. You can set read_only mode at runtime using:
*
* SET @@read_only=1;
*
* Since the effect of writing to a slave is so damaging and difficult to clean
- * up, we at Wikimedia set read_only=1 in my.cnf on all our DB servers, even
- * our masters, and then set read_only=0 on masters at runtime.
+ * up, we at Wikimedia set read_only=1 in my.cnf on all our DB servers, even
+ * our masters, and then set read_only=0 on masters at runtime.
*/
$wgDBservers = false;
/**
* Load balancer factory configuration
- * To set up a multi-master wiki farm, set the class here to something that
+ * To set up a multi-master wiki farm, set the class here to something that
* can return a LoadBalancer with an appropriate master on a call to getMainLB().
- * The class identified here is responsible for reading $wgDBservers,
+ * The class identified here is responsible for reading $wgDBservers,
* $wgDBserver, etc., so overriding it may cause those globals to be ignored.
*
- * The LBFactory_Multi class is provided for this purpose, please see
+ * The LBFactory_Multi class is provided for this purpose, please see
* includes/LBFactory_Multi.php for configuration information.
*/
$wgLBFactoryConf = array( 'class' => 'LBFactory_Simple' );
/**
* Maximum recursion depth for templates within templates.
- * The current parser adds two levels to the PHP call stack for each template,
+ * The current parser adds two levels to the PHP call stack for each template,
* and xdebug limits the call stack to 100 by default. So this should hopefully
* stop the parser before it hits the xdebug limit.
*/
# directory name unguessable, or use .htaccess to protect it.
$wgWhitelistRead = false;
-/**
+/**
* Should editors be required to have a validated e-mail
* address before being allowed to edit?
*/
* groups at Special:Userrights. Example configuration:
*
* // Bureaucrat can add any group
- * $wgAddGroups['bureaucrat'] = true;
+ * $wgAddGroups['bureaucrat'] = true;
* // Bureaucrats can only remove bots and sysops
- * $wgRemoveGroups['bureaucrat'] = array( 'bot', 'sysop' );
+ * $wgRemoveGroups['bureaucrat'] = array( 'bot', 'sysop' );
* // Sysops can make bots
- * $wgAddGroups['sysop'] = array( 'bot' );
+ * $wgAddGroups['sysop'] = array( 'bot' );
* // Sysops can disable other sysops in an emergency, and disable bots
- * $wgRemoveGroups['sysop'] = array( 'sysop', 'bot' );
+ * $wgRemoveGroups['sysop'] = array( 'sysop', 'bot' );
*/
$wgAddGroups = $wgRemoveGroups = array();
$wgEnotifImpersonal = false;
-# Maximum number of users to mail at once when using impersonal mail. Should
+# Maximum number of users to mail at once when using impersonal mail. Should
# match the limit on your mail server.
$wgEnotifMaxRecips = 500;
# Send mails via the job queue.
$wgEnotifUseJobQ = false;
-/**
+/**
* Array of usernames who will be sent a notification email for every change which occurs on a wiki
*/
$wgUsersNotifiedOnAllChanges = array();
/**
* If the difference between the character counts of the text
- * before and after the edit is below that value, the value will be
+ * before and after the edit is below that value, the value will be
* highlighted on the RC page.
*/
$wgRCChangedSizeThreshold = -500;
# Images settings
#
-/**
+/**
* Plugins for media file type handling.
* Each entry in the array maps a MIME type to a class name
*/
$wgIgnoreImageErrors = false;
/**
- * Allow thumbnail rendering on page view. If this is false, a valid
- * thumbnail URL is still output, but no file will be created at
- * the target location. This may save some time if you have a
- * thumb.php or 404 handler set up which is faster than the regular
- * webserver(s).
+ * Allow thumbnail rendering on page view. If this is false, a valid
+ * thumbnail URL is still output, but no file will be created at
+ * the target location. This may save some time if you have a
+ * thumb.php or 404 handler set up which is faster than the regular
+ * webserver(s).
*/
$wgGenerateThumbnailOnParse = true;
$wgDebugTidy = false;
/**
- * Validate the overall output using tidy and refuse
+ * Validate the overall output using tidy and refuse
* to display the page if it's not valid.
*/
$wgValidateAllHtml = false;
* $wgDefaultUserOptions ['editsection'] = 0;
*
*/
-$wgDefaultUserOptions = array(
+$wgDefaultUserOptions = array(
'quickbar' => 1,
'underline' => 2,
'cols' => 80,
$wgAllowRealName = true;
/*****************************************************************************
- * Extensions
+ * Extensions
*/
/**
$wgExtensionFunctions = array();
/**
- * Extension functions for initialisation of skins. This is called somewhat earlier
+ * Extension functions for initialisation of skins. This is called somewhat earlier
* than $wgExtensionFunctions.
*/
$wgSkinExtensionFunctions = array();
* The file must create a variable called $messages.
* When the messages are needed, the extension should call wfLoadExtensionMessages().
*
- * Example:
+ * Example:
* $wgExtensionMessagesFiles['ConfirmEdit'] = dirname(__FILE__).'/ConfirmEdit.i18n.php';
*
*/
* These will be called as an OutputPageParserOutput hook, if the relevant
* tag has been registered with the parser output object.
*
- * Registration is done with $pout->addOutputHook( $tag, $data ).
+ * Registration is done with $pout->addOutputHook( $tag, $data ).
*
* The callback has the form:
* function outputHook( $outputPage, $parserOutput, $data ) { ... }
/**
* List of valid skin names.
* The key should be the name in all lower case, the value should be a display name.
- * The default skins will be added later, by Skin::getSkinNames(). Use
+ * The default skins will be added later, by Skin::getSkinNames(). Use
* Skin::getSkinNames() as an accessor if you wish to have access to the full list.
*/
$wgValidSkinNames = array();
* Special page list.
* See the top of SpecialPage.php for documentation.
*/
-$wgSpecialPages = array();
+$wgSpecialPages = array();
/**
* Array mapping class names to filenames, for autoloading.
/**
* Namespace aliases
- * These are alternate names for the primary localised namespace names, which
- * are defined by $wgExtraNamespaces and the language file. If a page is
- * requested with such a prefix, the request will be redirected to the primary
- * name.
+ * These are alternate names for the primary localised namespace names, which
+ * are defined by $wgExtraNamespaces and the language file. If a page is
+ * requested with such a prefix, the request will be redirected to the primary
+ * name.
*
* Set this to a map from namespace names to IDs.
* Example:
- * $wgNamespaceAliases = array(
+ * $wgNamespaceAliases = array(
* 'Wikipedian' => NS_USER,
* 'Help' => 100,
* );
* Netscape 2-4 detection
* The minor version may contain strings such as "Gold" or "SGoldC-SGI"
* Lots of non-netscape user agents have "compatible", so it's useful to check for that
- * with a negative assertion. The [UIN] identifier specifies the level of security
- * in a Netscape/Mozilla browser, checking for it rules out a number of fakers.
+ * with a negative assertion. The [UIN] identifier specifies the level of security
+ * in a Netscape/Mozilla browser, checking for it rules out a number of fakers.
* The language string is unreliable, it is missing on NS4 Mac.
- *
+ *
* Reference: http://www.psychedelix.com/agents/index.shtml
*/
'/^Mozilla\/2\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
'/^Mozilla\/3\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
'/^Mozilla\/4\.[^ ]+ [^(]*?\((?!compatible).*; [UIN]/',
-
+
/**
* MSIE on Mac OS 9 is teh sux0r, converts þ to <thorn>, ð to <eth>, Þ to <THORN> and Ð to <ETH>
*
* @link http://en.wikipedia.org/wiki/Template%3AOS9
*/
'/^Mozilla\/4\.0 \(compatible; MSIE \d+\.\d+; Mac_PowerPC\)/',
-
+
/**
* Google wireless transcoder, seems to eat a lot of chars alive
* http://it.wikipedia.org/w/index.php?title=Luciano_Ligabue&diff=prev&oldid=8857361
/**
* Robot policies per article.
* These override the per-namespace robot policies.
- * Must be in the form of an array where the key part is a properly
+ * Must be in the form of an array where the key part is a properly
* canonicalised text form title and the value is a robot policy.
* Example:
* $wgArticleRobotPolicies = array( 'Main Page' => 'noindex' );
* The place to put new revisions, false to put them in the local text table.
* Part of a URL, e.g. DB://cluster1
*
- * Can be an array instead of a single string, to enable data distribution. Keys
+ * Can be an array instead of a single string, to enable data distribution. Keys
* must be consecutive integers, starting at zero. Example:
*
* $wgDefaultExternalStore = array( 'DB://cluster1', 'DB://cluster2' );
$wgUseAjax = true;
/**
- * Enable auto suggestion for the search bar
+ * Enable auto suggestion for the search bar
* Requires $wgUseAjax to be true too.
* Causes wfSajaxSearch to be added to $wgAjaxExportList
*/
$wgAjaxSearch = false;
/**
- * List of Ajax-callable functions.
+ * List of Ajax-callable functions.
* Extensions acting as Ajax callbacks must register here
*/
$wgAjaxExportList = array( );
$wgContentNamespaces = array( NS_MAIN );
/**
- * Maximum amount of virtual memory available to shell processes under linux, in KB.
+ * Maximum amount of virtual memory available to shell processes under linux, in KB.
*/
$wgMaxShellMemory = 102400;
/**
* Path of the djvutoxml executable
- * This works like djvudump except much, much slower as of version 3.5.
+ * This works like djvudump except much, much slower as of version 3.5.
*
* For now I recommend you use djvudump instead. The djvuxml output is
* probably more stable, so we'll switch back to it as soon as they fix
/**
* Break out of framesets. This can be used to prevent external sites from
- * framing your site with ads.
+ * framing your site with ads.
*/
$wgBreakFrames = false;
/**
- * Set this to an array of special page names to prevent
+ * Set this to an array of special page names to prevent
* maintenance/updateSpecialPages.php from updating those pages.
*/
$wgDisableQueryPageUpdate = false;
$wgDisableOutputCompression = false;
/**
- * If lag is higher than $wgSlaveLagWarning, show a warning in some special
+ * If lag is higher than $wgSlaveLagWarning, show a warning in some special
* pages (like watchlist). If the lag is higher than $wgSlaveLagCritical,
* show a more obvious warning.
*/
* don't have this module, you can use Preprocessor_Hash wich
* has not this depedency.
* It has no effect with Parser_OldPP parser class.
- *
- *
- * The entire associative array will be passed through to the constructor as
- * the first parameter. Note that only Setup.php can use this variable --
- * the configuration will change at runtime via $wgParser member functions, so
- * the contents of this variable will be out-of-date. The variable can only be
- * changed during LocalSettings.php, in particular, it can't be changed during
- * an extension setup function.
- */
-$wgParserConf = array(
+ *
+ *
+ * The entire associative array will be passed through to the constructor as
+ * the first parameter. Note that only Setup.php can use this variable --
+ * the configuration will change at runtime via $wgParser member functions, so
+ * the contents of this variable will be out-of-date. The variable can only be
+ * changed during LocalSettings.php, in particular, it can't be changed during
+ * an extension setup function.
+ */
+$wgParserConf = array(
'class' => 'Parser',
'preprocessorClass' => 'Preprocessor_DOM',
);
*/
define( 'EDIT_NEW', 1 );
define( 'EDIT_UPDATE', 2 );
-define( 'EDIT_MINOR', 4 );
+define( 'EDIT_MINOR', 4 );
define( 'EDIT_SUPPRESS_RC', 8 );
define( 'EDIT_FORCE_BOT', 16 );
define( 'EDIT_DEFER_UPDATES', 32 );
define( 'EDIT_AUTOSUMMARY', 64 );
/**#@-*/
-/**
- * Flags for Database::makeList()
+/**
+ * Flags for Database::makeList()
* These are also available as Database class constants
*/
define( 'LIST_COMMA', 0 );
wfProfileOut( __METHOD__ );
return;
}
-
+
wfRunHooks( 'DiffViewHeader', array( $this, $this->mOldRev, $this->mNewRev ) );
if ( $this->mNewRev->isCurrent() ) {
} else {
$rollback = '';
}
-
+
// Prepare a change patrol link, if applicable
if( $wgUseRCPatrol && $wgUser->isAllowed( 'patrol' ) ) {
// If we've been given an explicit change identifier, use it; saves time
if ($this->mNewRev->mMinorEdit == 1) {
$newminor = Xml::span( wfMsg( 'minoreditletter'), 'minor' ) . ' ';
}
-
+
$rdel = ''; $ldel = '';
if( $wgUser->isAllowed( 'deleterevision' ) ) {
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
// We don't currently handle well changing the top revision's settings
if( $this->mNewRev->isCurrent() ) {
// If revision was hidden from sysops
- $rdel = wfMsgHtml('rev-delundel');
+ $rdel = wfMsgHtml('rev-delundel');
} else if( !$this->mNewRev->userCan( Revision::DELETED_RESTRICTED ) ) {
// If revision was hidden from sysops
- $rdel = wfMsgHtml('rev-delundel');
+ $rdel = wfMsgHtml('rev-delundel');
} else {
$rdel = $sk->makeKnownLinkObj( $revdel,
wfMsgHtml('rev-delundel'),
return true;
}
}
-
+
/**
* Add style sheets and supporting JS for diff display.
*/
function showDiffStyle() {
global $wgStylePath, $wgStyleVersion, $wgOut;
$wgOut->addStyle( 'common/diff.css' );
-
+
// JS is needed to detect old versions of Mozilla to work around an annoyance bug.
$wgOut->addScript( "<script type=\"text/javascript\" src=\"$wgStylePath/common/diff.js?$wgStyleVersion\"></script>" );
}
}
$difftext = $this->generateDiffBody( $this->mOldtext, $this->mNewtext );
-
+
// Save to cache for 7 days
if ( $key !== false && $difftext !== false ) {
wfIncrStats( 'diff_cache_miss' );
$otext = str_replace( "\r\n", "\n", $otext );
$ntext = str_replace( "\r\n", "\n", $ntext );
-
+
if ( $wgExternalDiffEngine == 'wikidiff' ) {
# For historical reasons, external diff engine expects
# input text to be HTML-escaped already
}
return $wgContLang->unsegementForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) );
}
-
+
if ( $wgExternalDiffEngine == 'wikidiff2' ) {
# Better external diff engine, the 2 may some day be dropped
# This one does the escaping and segmenting itself
unlink( $tempName2 );
return $difftext;
}
-
+
# Native PHP diff
$ota = explode( "\n", $wgContLang->segmentForDiff( $otext ) );
$nta = explode( "\n", $wgContLang->segmentForDiff( $ntext ) );
$formatter = new TableDiffFormatter();
return $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) );
}
-
+
/**
* Replace line numbers with the text in the user's language
return wfMsgExt( 'lineno', array('parseinline'), $wgLang->formatNum( $matches[1] ) );
}
-
+
/**
* If there are revisions between the ones being compared, return a note saying so.
*/
function getMultiNotice() {
if ( !is_object($this->mOldRev) || !is_object($this->mNewRev) )
return '';
-
+
if( !$this->mOldPage->equals( $this->mNewPage ) ) {
// Comparing two different pages? Count would be meaningless.
return '';
}
-
+
$oldid = $this->mOldRev->getId();
$newid = $this->mNewRev->getId();
if ( $oldid > $newid ) {
: Revision::newFromTitle( $this->mTitle );
if( !$this->mNewRev instanceof Revision )
return false;
-
+
// Update the new revision ID in case it was 0 (makes life easier doing UI stuff)
$this->mNewid = $this->mNewRev->getId();
// Check if page is editable
$editable = $this->mNewRev->getTitle()->userCan( 'edit' );
-
+
// Set assorted variables
$timestamp = $wgLang->timeanddate( $this->mNewRev->getTimestamp(), true );
$this->mNewPage = $this->mNewRev->getTitle();
$oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid );
$oldEdit = $this->mOldPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mOldid );
$this->mOldPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) );
-
+
$this->mOldtitle = "<a href='$oldLink'>{$this->mOldPagetitle}</a>"
. " (<a href='$oldEdit'>" . wfMsgHtml( $editable ? 'editold' : 'viewsourceold' ) . "</a>)";
// Add an "undo" link
$newUndo = $this->mNewPage->escapeLocalUrl( 'action=edit&undoafter=' . $this->mOldid . '&undo=' . $this->mNewid);
if ( $editable && $this->mNewRev->userCan(Revision::DELETED_TEXT) )
$this->mNewtitle .= " (<a href='$newUndo'>" . htmlspecialchars( wfMsg( 'editundo' ) ) . "</a>)";
-
+
if ( !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) {
$this->mOldtitle = "<span class='history-deleted'>{$this->mOldPagetitle}</span>";
} else if ( $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) {
class UnifiedDiffFormatter extends DiffFormatter {
var $leading_context_lines = 2;
var $trailing_context_lines = 2;
-
+
function _added($lines) {
$this->_lines($lines, '+');
}
function contextLine( $line ) {
return $this->wrapLine( ' ', 'diff-context', $line );
}
-
+
private function wrapLine( $marker, $class, $line ) {
if( $line !== '' ) {
// The <div> wrapper is needed for 'overflow: auto' style to scroll properly
wfProfileOut( __METHOD__ );
}
}
-
-
-
function __construct( $filename ) {
$this->mFilename = $filename;
}
-
+
/**
* Check if the given file is indeed a valid DjVu image file
* @return bool
$info = $this->getInfo();
return $info !== false;
}
-
-
+
+
/**
* Return data in the style of getimagesize()
* @return array or false on failure
*/
public function getImageSize() {
$data = $this->getInfo();
-
+
if( $data !== false ) {
$width = $data['width'];
$height = $data['height'];
-
+
return array( $width, $height, 'DjVu',
"width=\"$width\" height=\"$height\"" );
}
return false;
}
-
+
// ---------
-
+
/**
* For debugging; dump the IFF chunk structure
*/
$this->dumpForm( $file, $chunkLength, 1 );
fclose( $file );
}
-
+
private function dumpForm( $file, $length, $indent ) {
$start = ftell( $file );
$secondary = fread( $file, 4 );
// FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
extract( unpack( 'a4chunk/NchunkLength', $chunkHeader ) );
echo str_repeat( ' ', $indent * 4 ) . "$chunk $chunkLength\n";
-
+
if( $chunk == 'FORM' ) {
$this->dumpForm( $file, $chunkLength, $indent + 1 );
} else {
}
}
}
-
+
function getInfo() {
wfSuppressWarnings();
$file = fopen( $this->mFilename, 'rb' );
wfDebug( __METHOD__ . ": missing or failed file read\n" );
return false;
}
-
+
$header = fread( $file, 16 );
$info = false;
-
+
if( strlen( $header ) < 16 ) {
wfDebug( __METHOD__ . ": too short file header\n" );
} else {
// FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
extract( unpack( 'a4magic/a4form/NformLength/a4subtype', $header ) );
-
+
if( $magic != 'AT&T' ) {
wfDebug( __METHOD__ . ": not a DjVu file\n" );
} elseif( $subtype == 'DJVU' ) {
fclose( $file );
return $info;
}
-
+
private function readChunk( $file ) {
$header = fread( $file, 8 );
if( strlen( $header ) < 8 ) {
return array( $chunk, $length );
}
}
-
+
private function skipChunk( $file, $chunkLength ) {
fseek( $file, $chunkLength, SEEK_CUR );
-
+
if( $chunkLength & 0x01 == 1 && !feof( $file ) ) {
// padding byte
fseek( $file, 1, SEEK_CUR );
}
}
-
+
private function getMultiPageInfo( $file, $formLength ) {
// For now, we'll just look for the first page in the file
// and report its information, hoping others are the same size.
if( !$chunk ) {
break;
}
-
+
if( $chunk == 'FORM' ) {
$subtype = fread( $file, 4 );
if( $subtype == 'DJVU' ) {
$this->skipChunk( $file, $length );
}
} while( $length != 0 && !feof( $file ) && ftell( $file ) - $start < $formLength );
-
+
wfDebug( __METHOD__ . ": multi-page DJVU file contained no pages\n" );
return false;
}
-
+
private function getPageInfo( $file, $formLength ) {
list( $chunk, $length ) = $this->readChunk( $file );
if( $chunk != 'INFO' ) {
wfDebug( __METHOD__ . ": expected INFO chunk, got '$chunk'\n" );
return false;
}
-
+
if( $length < 9 ) {
wfDebug( __METHOD__ . ": INFO should be 9 or 10 bytes, found $length\n" );
return false;
wfDebug( __METHOD__ . ": INFO chunk cut off\n" );
return false;
}
-
+
// FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
extract( unpack(
'nwidth/' .
'vresolution/' .
'Cgamma', $data ) );
# Newer files have rotation info in byte 10, but we don't use it yet.
-
+
return array(
'width' => $width,
'height' => $height,
}
if ( preg_match( '/^ *INFO *\[\d*\] *DjVu *(\d+)x(\d+), *\w*, *(\d+) *dpi, *gamma=([0-9.-]+)/', $line, $m ) ) {
- $xml .= Xml::tags( 'OBJECT',
+ $xml .= Xml::tags( 'OBJECT',
array(
#'data' => '',
#'type' => 'image/x.djvu',
'height' => $m[2],
'width' => $m[1],
#'usemap' => '',
- ),
+ ),
"\n" .
Xml::element( 'PARAM', array( 'name' => 'DPI', 'value' => $m[3] ) ) . "\n" .
Xml::element( 'PARAM', array( 'name' => 'GAMMA', 'value' => $m[4] ) ) . "\n"
return false;
}
}
-
-
-?>
public $editFormTextAfterWarn;
public $editFormTextAfterTools;
public $editFormTextBottom;
-
+
/* $didSave should be set to true whenever an article was succesfully altered. */
public $didSave = false;
-
+
public $suppressIntro = false;
/**
$this->editFormTextAfterTools =
$this->editFormTextBottom = "";
}
-
+
/**
* Fetch initial editing page content.
* @private
if( !$this->mTitle->exists() ) {
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
$wgMessageCache->loadAllMessages();
- # If this is a system message, get the default text.
+ # If this is a system message, get the default text.
$text = wfMsgWeirdKey ( $this->mTitle->getText() ) ;
} else {
# If requested, preload some text.
$this->mArticle->mContent = $t ;
$this->mMetaData = $s ;
}
-
+
protected function wasDeletedSinceLastEdit() {
/* Note that we rely on the logging table, which hasn't been always there,
* but that doesn't matter, because this only applies to brand new
- * deletes.
+ * deletes.
*/
if ( $this->deletedSinceEdit )
return true;
wfProfileOut( __METHOD__ );
return;
}
-
+
if( wfReadOnly() ) {
$this->readOnlyPage( $this->getContent() );
wfProfileOut( __METHOD__ );
$permErrors = $this->mTitle->getUserPermissionsErrors('edit', $wgUser);
if( !$this->mTitle->exists() ) {
- $permErrors = array_merge( $permErrors,
+ $permErrors = array_merge( $permErrors,
wfArrayDiff2( $this->mTitle->getUserPermissionsErrors('create', $wgUser), $permErrors ) );
}
# Show applicable editing introductions
if( $this->formtype == 'initial' || $this->firsttime )
$this->showIntro();
-
+
if( $this->mTitle->isTalkPage() ) {
$wgOut->addWikiMsg( 'talkpagetext' );
}
wfProfileOut( __METHOD__ );
return;
}
- if( !$this->mTitle->getArticleId() )
+ if( !$this->mTitle->getArticleId() )
wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
}
global $wgRequest, $wgOut;
if ( $wgRequest->getBool( 'redlink' ) ) {
// The edit page was reached via a red link.
- // Redirect to the article page and let them click the edit tab if
+ // Redirect to the article page and let them click the edit tab if
// they really want a permission error.
$wgOut->redirect( $this->mTitle->getFullUrl() );
} else {
$this->mMetaData = rtrim( $request->getText( 'metadata' ) );
# Truncate for whole multibyte characters. +5 bytes for ellipsis
$this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 250 );
-
+
# Remove extra headings from summaries and new sections.
$this->summary = preg_replace('/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->summary);
$this->allowBlankSummary = $request->getBool( 'wpIgnoreBlankSummary' );
}
- $this->autoSumm = $request->getText( 'wpAutoSummary' );
+ $this->autoSumm = $request->getText( 'wpAutoSummary' );
} else {
# Not a posted form? Start with nothing.
wfDebug( "$fname: Not a posted form.\n" );
$ip = User::isIP( $username );
if ( $id == 0 && !$ip ) {
- $wgOut->wrapWikiMsg( '<div class="mw-userpage-userdoesnotexist error">$1</div>',
+ $wgOut->wrapWikiMsg( '<div class="mw-userpage-userdoesnotexist error">$1</div>',
array( 'userpage-userdoesnotexist', $username ) );
}
}
}
$isComment = ( $this->section == 'new' );
-
+
$this->mArticle->insertNewArticle( $this->textbox1, $this->summary,
$this->minoredit, $this->watchthis, false, $isComment, $bot);
*/
function showEditForm( $formCallback=null ) {
global $wgOut, $wgUser, $wgLang, $wgContLang, $wgMaxArticleSize, $wgTitle;
-
+
# If $wgTitle is null, that means we're in API mode.
# Some hook probably called this function without checking
# for is_null($wgTitle) first. Bail out right here so we don't
$matches );
if( !empty( $matches[2] ) ) {
global $wgParser;
- $this->summary = "/* " .
- $wgParser->stripSectionName(trim($matches[2])) .
+ $this->summary = "/* " .
+ $wgParser->stripSectionName(trim($matches[2])) .
" */ ";
}
}
}
if ( isset( $this->mArticle ) && isset( $this->mArticle->mRevision ) ) {
// Let sysop know that this will make private content public if saved
-
+
if( !$this->mArticle->mRevision->userCan( Revision::DELETED_TEXT ) ) {
$wgOut->addWikiMsg( 'rev-deleted-text-permission' );
} else if( $this->mArticle->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
$wgOut->addWikiMsg( 'rev-deleted-text-view' );
}
-
+
if( !$this->mArticle->mRevision->isCurrent() ) {
$this->mArticle->setOldSubtitle( $this->mArticle->mRevision->getId() );
$wgOut->addWikiMsg( 'editingold' );
global $wgRightsText;
if ( $wgRightsText ) {
- $copywarnMsg = array( 'copyrightwarning',
+ $copywarnMsg = array( 'copyrightwarning',
'[[' . wfMsgForContent( 'copyrightpage' ) . ']]',
$wgRightsText );
} else {
- $copywarnMsg = array( 'copyrightwarning2',
+ $copywarnMsg = array( 'copyrightwarning2',
'[[' . wfMsgForContent( 'copyrightpage' ) . ']]' );
}
# if this is a comment, show a subject line at the top, which is also the edit summary.
# Otherwise, show a summary field at the bottom
$summarytext = htmlspecialchars( $wgContLang->recodeForEdit( $this->summary ) ); # FIXME
-
+
# If a blank edit summary was previously provided, and the appropriate
# user preference is active, pass a hidden tag as wpIgnoreBlankSummary. This will stop the
# user being bounced back more than once in the event that a summary
$previewHTML = $parserOutput->getText();
$wgOut->addParserOutputNoText( $parserOutput );
-
+
# ParserOutput might have altered the page title, so reset it
# Also, use the title defined by DISPLAYTITLE magic word when present
if( ( $dt = $parserOutput->getDisplayTitle() ) !== false ) {
$wgOut->setPageTitle( wfMsg( 'editing', $dt ) );
} else {
- $wgOut->setPageTitle( wfMsg( 'editing', $wgTitle->getPrefixedText() ) );
+ $wgOut->setPageTitle( wfMsg( 'editing', $wgTitle->getPrefixedText() ) );
}
foreach ( $parserOutput->getTemplates() as $ns => $template)
if ( $this->isConflict ) {
$previewhead.='<h2>' . htmlspecialchars( wfMsg( 'previewconflict' ) ) . "</h2>\n";
}
-
+
if( $wgUser->getOption( 'previewontop' ) ) {
// Spacer for the edit toolbar
$previewfoot = '<p><br /></p>';
$sample = $tool['sample'],
$cssId = $tool['id'],
);
-
+
$paramList = implode( ',',
array_map( array( 'Xml', 'encodeJsVar' ), $params ) );
$toolbar.="addButton($paramList);\n";
'title' => wfMsg( 'tooltip-diff' ).' ['.wfMsg( 'accesskey-diff' ).']',
);
$buttons['diff'] = wfElement('input', $temp, '');
-
+
wfRunHooks( 'EditPageBeforeEditButtons', array( &$this, &$buttons ) );
return $buttons;
}
$wgOut->setPageTitle( wfMsg( 'nocreatetitle' ) );
$wgOut->addWikiMsg( 'nocreatetext' );
}
-
+
/**
* If there are rows in the deletion log for this page, show them,
* along with a nice little note for the user
$resultDetails = false;
$value = $this->internalAttemptSave( $resultDetails, $wgUser->isAllowed('bot') && $wgRequest->getBool('bot', true) );
-
+
if( $value == self::AS_SUCCESS_UPDATE || $value == self::AS_SUCCESS_NEW_ARTICLE ) {
$this->didSave = true;
}
case self::AS_NO_CREATE_PERMISSION;
$this->noCreatePermission();
return;
-
+
case self::AS_BLANK_ARTICLE:
$wgOut->redirect( $wgTitle->getFullURL() );
return false;
);
return true;
}
-
-}
+}
);
return true;
}
-
-}
+}
* @return bool
*/
function useOutputPage() {
- return !empty( $GLOBALS['wgFullyInitialised'] ) &&
+ return !empty( $GLOBALS['wgFullyInitialised'] ) &&
!empty( $GLOBALS['wgArticle'] ) && !empty( $GLOBALS['wgTitle'] );
}
*/
function runHooks( $name, $args = array() ) {
global $wgExceptionHooks;
- if( !isset( $wgExceptionHooks ) || !is_array( $wgExceptionHooks ) )
+ if( !isset( $wgExceptionHooks ) || !is_array( $wgExceptionHooks ) )
return; // Just silently ignore
if( !array_key_exists( $name, $wgExceptionHooks ) || !is_array( $wgExceptionHooks[ $name ] ) )
return;
}
/**
- * If $wgShowExceptionDetails is true, return a HTML message with a
+ * If $wgShowExceptionDetails is true, return a HTML message with a
* backtrace to the error, otherwise show a message to ask to set it to true
* to show that information.
*
function getHTML() {
global $wgShowExceptionDetails;
if( $wgShowExceptionDetails ) {
- return '<p>' . htmlspecialchars( $this->getMessage() ) .
+ return '<p>' . htmlspecialchars( $this->getMessage() ) .
'</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) .
"</p>\n";
} else {
}
/**
- * If $wgShowExceptionDetails is true, return a text message with a
+ * If $wgShowExceptionDetails is true, return a text message with a
* backtrace to the error.
*/
function getText() {
*/
class ErrorPageError extends MWException {
public $title, $msg;
-
+
/**
* Note: these arguments are keys into wfMsg(), not text!
*/
// Exit value should be nonzero for the benefit of shell jobs
exit( 1 );
}
-
-
if ( is_array( $in ) ) {
return false;
}
-
+
if ( preg_match( "/[^\x0a\x20-\x7e]/", $in ) ) {
$this->debug( $in, __FUNCTION__, 'found a character not in our whitelist' );
return false;
*
* @private
*
- * @param $in Mixed:
- * @param $fname String:
+ * @param $in Mixed:
+ * @param $fname String:
* @param $action Mixed: , default NULL.
*/
function debug( $in, $fname, $action = NULL ) {
define( 'MW_EXIF_UNDEFINED', Exif::UNDEFINED );
define( 'MW_EXIF_SLONG', Exif::SLONG );
define( 'MW_EXIF_SRATIONAL', Exif::SRATIONAL );
-
-
class WikiExporter {
var $list_authors = false ; # Return distinct author list (when not returning full history)
var $author_list = "" ;
-
+
var $dumpUploads = false;
const FULL = 0;
$this->author_list = "<contributors>";
//rev_deleted
$nothidden = '(rev_deleted & '.Revision::DELETED_USER.') = 0';
-
+
$sql = "SELECT DISTINCT rev_user_text,rev_user FROM {$page},{$revision} WHERE page_id=rev_page AND $nothidden AND " . $cond ;
$result = $this->db->query( $sql, $fname );
$resultset = $this->db->resultObject( $result );
while( $row = $resultset->fetchObject() ) {
- $this->author_list .= "<contributor>" .
- "<username>" .
- htmlentities( $row->rev_user_text ) .
- "</username>" .
- "<id>" .
+ $this->author_list .= "<contributor>" .
+ "<username>" .
+ htmlentities( $row->rev_user_text ) .
+ "</username>" .
+ "<id>" .
$row->rev_user .
- "</id>" .
+ "</id>" .
"</contributor>";
}
wfProfileOut( $fname );
wfProfileOut( $fname );
return $out;
}
-
+
function writeTimestamp( $timestamp ) {
$ts = wfTimestamp( TS_ISO_8601, $timestamp );
return " " . wfElement( 'timestamp', null, $ts ) . "\n";
}
-
+
function writeContributor( $id, $text ) {
$out = " <contributor>\n";
if( $id ) {
$out .= " </contributor>\n";
return $out;
}
-
+
/**
* Warning! This data is potentially inconsistent. :(
*/
}
return '';
}
-
+
function writeUpload( $file ) {
return " <upload>\n" .
$this->writeTimestamp( $file->getTimestamp() ) .
wfProfileOut( $fname );
return $string;
}
-
-
return "DB://$cluster/$id";
}
}
-
* whatever, for initial ext storage
*/
}
-
function trackbackURL() { $this->error(); }
function trackbackRDF() { $this->error(); }
}
-
-
private $oldfile = null;
private $oldimage = '';
-
+
/**
* Constructor
*
$this->title = $file->getTitle();
$this->file = $file;
}
-
+
/**
* Fulfil the request; shows the form or deletes the file,
* pending authentication, confirmation, etc.
if( wfReadOnly() ) {
$wgOut->readOnlyPage();
return;
- }
+ }
$permission_errors = $this->title->getUserPermissionsErrors('delete', $wgUser);
if (count($permission_errors)>0) {
$wgOut->showPermissionsErrorPage( $permission_errors );
return;
}
-
+
$this->oldimage = $wgRequest->getText( 'oldimage', false );
$token = $wgRequest->getText( 'wpEditToken' );
# Flag to hide all contents of the archived revisions
$suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('deleterevision');
-
+
if( $this->oldimage && !self::isValidOldSpec($this->oldimage) ) {
$wgOut->showUnexpectedValueError( 'oldimage', htmlspecialchars( $this->oldimage ) );
return;
}
if( $this->oldimage )
$this->oldfile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->title, $this->oldimage );
-
+
if( !self::haveDeletableFile($this->file, $this->oldfile, $this->oldimage) ) {
$wgOut->addHtml( $this->prepareMessage( 'filedelete-nofile' ) );
$wgOut->addReturnTo( $this->title );
return;
}
-
+
// Perform the deletion if appropriate
if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $token, $this->oldimage ) ) {
$this->DeleteReasonList = $wgRequest->getText( 'wpDeleteReasonList' );
} elseif ( $reason == 'other' ) {
$reason = $this->DeleteReason;
}
-
+
$status = self::doDelete( $this->title, $this->file, $this->oldimage, $reason, $suppress );
-
+
if( !$status->isGood() )
$wgOut->addWikiText( $status->getWikiText( 'filedeleteerror-short', 'filedeleteerror-long' ) );
if( $status->ok ) {
}
return;
}
-
+
$this->showForm();
$this->showLogEntries();
}
-
+
public static function doDelete( &$title, &$file, &$oldimage, $reason, $suppress ) {
$article = null;
if( $oldimage ) {
$status = $file->delete( $reason, $suppress );
if( $status->ok ) {
// Need to delete the associated article
- $article = new Article( $title );
- if( wfRunHooks('ArticleDelete', array(&$article, &$wgUser, &$reason)) ) {
+ $article = new Article( $title );
+ if( wfRunHooks('ArticleDelete', array(&$article, &$wgUser, &$reason)) ) {
if( $article->doDeleteArticle( $reason, $suppress ) )
wfRunHooks('ArticleDeleteComplete', array(&$article, &$wgUser, $reason));
}
}
}
- if( $status->isGood() ) wfRunHooks('FileDeleteComplete', array(
+ if( $status->isGood() ) wfRunHooks('FileDeleteComplete', array(
&$file, &$oldimage, &$article, &$wgUser, &$reason));
-
+
return $status;
}
"</td>
<td>" .
Xml::listDropDown( 'wpDeleteReasonList',
- wfMsgForContent( 'filedelete-reason-dropdown' ),
+ wfMsgForContent( 'filedelete-reason-dropdown' ),
wfMsgForContent( 'filedelete-reason-otherlist' ), '', 'wpReasonDropDown', 1 ) .
"</td>
</tr>
$wgOut->addHtml( '<h2>' . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" );
LogEventsList::showLogExtract( $wgOut, 'delete', $this->title->getPrefixedText() );
}
-
+
/**
* Prepare a message referring to the file being deleted,
* showing an appropriate message depending upon whether
);
}
}
-
+
/**
* Set headers, titles and other bits
*/
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setSubtitle( wfMsg( 'filedelete-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->title ) ) );
}
-
+
/**
* Is the provided `oldimage` value valid?
*
&& strpos( $oldimage, '/' ) === false
&& strpos( $oldimage, '\\' ) === false;
}
-
+
/**
* Could we delete the file specified? If an `oldimage`
* value was provided, does it correspond to an
? $oldfile && $oldfile->exists() && $oldfile->isLocal()
: $file && $file->exists() && $file->isLocal();
}
-
+
/**
* Prepare the form action
*
$q[] = 'oldimage=' . urlencode( $this->oldimage );
return $this->title->getLocalUrl( implode( '&', $q ) );
}
-
+
/**
* Extract the timestamp of the old version
*
private function getTimestamp() {
return $this->oldfile->getTimestamp();
}
-
+
}
protected $archiveName = '';
protected $timestamp = false;
protected $oldFile;
-
+
/**
* Constructor
*
$this->title = $file->getTitle();
$this->file = $file;
}
-
+
/**
* Fulfil the request; shows the form or reverts the file,
* pending authentication, confirmation, etc.
$wgOut->blockedPage();
return;
}
-
+
$this->archiveName = $wgRequest->getText( 'oldimage' );
$token = $wgRequest->getText( 'wpEditToken' );
if( !$this->isValidOldSpec() ) {
$wgOut->showUnexpectedValueError( 'oldimage', htmlspecialchars( $this->archiveName ) );
return;
}
-
+
if( !$this->haveOldVersion() ) {
$wgOut->addHtml( wfMsgExt( 'filerevert-badversion', 'parse' ) );
$wgOut->returnToMain( false, $this->title );
return;
}
-
+
// Perform the reversion if appropriate
if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $token, $this->archiveName ) ) {
$source = $this->file->getArchiveVirtualUrl( $this->archiveName );
}
return;
}
-
+
// Show the form
- $this->showForm();
+ $this->showForm();
}
-
+
/**
* Show the confirmation form
*/
$form .= '<p>' . Xml::submitButton( wfMsg( 'filerevert-submit' ) ) . '</p>';
$form .= '</fieldset>';
$form .= '</form>';
-
+
$wgOut->addHtml( $form );
}
-
+
/**
* Set headers, titles and other bits
*/
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setSubtitle( wfMsg( 'filerevert-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->title ) ) );
}
-
+
/**
* Is the provided `oldimage` value valid?
*
&& strpos( $this->archiveName, '/' ) === false
&& strpos( $this->archiveName, '\\' ) === false;
}
-
+
/**
* Does the provided `oldimage` value correspond
* to an existing, local, old version of this file?
protected function haveOldVersion() {
return $this->getOldFile()->exists();
}
-
+
/**
* Prepare the form action
*
$q[] = 'oldimage=' . urlencode( $this->archiveName );
return $this->title->getLocalUrl( implode( '&', $q ) );
}
-
+
/**
* Extract the timestamp of the old version
*
*/
class FileStore {
const DELETE_ORIGINAL = 1;
-
+
/**
* Fetch the FileStore object for a given storage group
*/
static function get( $group ) {
global $wgFileStore;
-
+
if( isset( $wgFileStore[$group] ) ) {
$info = $wgFileStore[$group];
return new FileStore( $group,
return null;
}
}
-
+
private function __construct( $group, $directory, $path, $hash ) {
$this->mGroup = $group;
$this->mDirectory = $directory;
$this->mPath = $path;
$this->mHashLevel = $hash;
}
-
+
/**
* Acquire a lock; use when performing write operations on a store.
* This is attached to your master database connection, so if you
$result = $dbw->query( "SELECT GET_LOCK($lockname, 5) AS lockstatus", __METHOD__ );
$row = $dbw->fetchObject( $result );
$dbw->freeResult( $result );
-
+
if( $row->lockstatus == 1 ) {
return true;
} else {
return false;
}
}
-
+
/**
* Release the global file store lock.
*/
$dbw->fetchObject( $result );
$dbw->freeResult( $result );
}
-
+
private static function lockName() {
return 'MediaWiki.' . wfWikiID() . '.FileStore';
}
-
+
/**
* Copy a file into the file store from elsewhere in the filesystem.
* Should be protected by FileStore::lock() to avoid race conditions.
$destPath = $this->filePath( $key );
return $this->copyFile( $sourcePath, $destPath, $flags );
}
-
+
/**
* Copy a file from the file store to elsewhere in the filesystem.
* Should be protected by FileStore::lock() to avoid race conditions.
$sourcePath = $this->filePath( $key );
return $this->copyFile( $sourcePath, $destPath, $flags );
}
-
+
private function copyFile( $sourcePath, $destPath, $flags=0 ) {
if( !file_exists( $sourcePath ) ) {
// Abort! Abort!
throw new FSException( "missing source file '$sourcePath'" );
}
-
+
$transaction = new FSTransaction();
-
+
if( $flags & self::DELETE_ORIGINAL ) {
$transaction->addCommit( FSTransaction::DELETE_FILE, $sourcePath );
}
-
+
if( file_exists( $destPath ) ) {
// An identical file is already present; no need to copy.
} else {
wfSuppressWarnings();
$ok = mkdir( dirname( $destPath ), 0777, true );
wfRestoreWarnings();
-
+
if( !$ok ) {
throw new FSException(
"failed to create directory for '$destPath'" );
}
}
-
+
wfSuppressWarnings();
$ok = copy( $sourcePath, $destPath );
wfRestoreWarnings();
-
+
if( $ok ) {
wfDebug( __METHOD__." copied '$sourcePath' to '$destPath'\n" );
$transaction->addRollback( FSTransaction::DELETE_FILE, $destPath );
__METHOD__." failed to copy '$sourcePath' to '$destPath'" );
}
}
-
+
return $transaction;
}
-
+
/**
* Delete a file from the file store.
* Caller's responsibility to make sure it's not being used by another row.
return FileStore::deleteFile( $destPath );
}
}
-
+
/**
* Delete a non-managed file on a transactional basis.
*
throw new FSException( "cannot delete missing file '$path'" );
}
}
-
+
/**
* Stream a contained file directly to HTTP output.
* Will throw a 404 if file is missing; 400 if invalid key.
wfHttpError( 400, "Bad request", "Invalid or badly-formed filename." );
return false;
}
-
+
if( file_exists( $path ) ) {
// Set the filename for more convenient save behavior from browsers
// FIXME: Is this safe?
header( 'Content-Disposition: inline; filename="' . $key . '"' );
-
+
require_once 'StreamFile.php';
wfStreamFile( $path );
} else {
"The requested resource does not exist." );
}
}
-
+
/**
* Confirm that the given file key is valid.
* Note that a valid key may refer to a file that does not exist.
static function validKey( $key ) {
return preg_match( '/^[0-9a-z]{31,32}(\.[0-9a-z]{1,31})?$/', $key );
}
-
-
+
+
/**
* Calculate file storage key from a file on disk.
* You must pass an extension to it, as some files may be calculated
wfDebug( __METHOD__.": couldn't hash file '$path'\n" );
return false;
}
-
+
$base36 = wfBaseConvert( $hash, 16, 36, 31 );
if( $extension == '' ) {
$key = $base36;
} else {
$key = $base36 . '.' . $extension;
}
-
+
// Sanity check
if( self::validKey( $key ) ) {
return $key;
return false;
}
}
-
+
/**
* Return filesystem path to the given file.
* Note that the file may or may not exist.
return false;
}
}
-
+
/**
* Return URL path to the given file, if the store is public.
* @return string or false if not public
return false;
}
}
-
+
private function hashPath( $key, $separator ) {
$parts = array();
for( $i = 0; $i < $this->mHashLevel; $i++ ) {
*/
class FSTransaction {
const DELETE_FILE = 1;
-
+
/**
* Combine more items into a fancier transaction
*/
$this->mOnRollback = array_merge(
$this->mOnRollback, $transaction->mOnRollback );
}
-
+
/**
* Perform final actions for success.
* @return true if actions applied ok, false if errors
function commit() {
return $this->apply( $this->mOnCommit );
}
-
+
/**
* Perform final actions for failure.
* @return true if actions applied ok, false if errors
function rollback() {
return $this->apply( $this->mOnRollback );
}
-
+
// --- Private and friend functions below...
-
+
function __construct() {
$this->mOnCommit = array();
$this->mOnRollback = array();
}
-
+
function addCommit( $action, $path ) {
$this->mOnCommit[] = array( $action, $path );
}
-
+
function addRollback( $action, $path ) {
$this->mOnRollback[] = array( $action, $path );
}
-
+
private function apply( $actions ) {
$result = true;
foreach( $actions as $item ) {
* @addtogroup Exception
*/
class FSException extends MWException { }
-
-
*
* @param $key String: lookup key for the message, usually
* defined in languages/Language.php
- *
- * This function also takes extra optional parameters (not
- * shown in the function definition), which can by used to
+ *
+ * This function also takes extra optional parameters (not
+ * shown in the function definition), which can by used to
* insert variable text into the predefined message.
*/
function wfMsg( $key ) {
}
/**
- * Throw a debugging exception. This function previously once exited the process,
+ * Throw a debugging exception. This function previously once exited the process,
* but now throws an exception instead, with similar results.
*
* @param string $msg Message shown when dieing.
* @param $deflimit Default limit if none supplied
* @param $optionname Name of a user preference to check against
* @return array
- *
+ *
*/
function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
global $wgRequest;
global $wgOut, $parserMemc;
$fname = 'wfGetCachedNotice';
wfProfileIn( $fname );
-
+
$needParse = false;
-
+
if( $name === 'default' ) {
// special case
global $wgSiteNotice;
return( false );
}
}
-
+
$cachedNotice = $parserMemc->get( wfMemcKey( $name ) );
if( is_array( $cachedNotice ) ) {
if( md5( $notice ) == $cachedNotice['hash'] ) {
} else {
$needParse = true;
}
-
+
if( $needParse ) {
if( is_object( $wgOut ) ) {
$parsed = $wgOut->parse( $notice );
$notice = '';
}
}
-
+
wfProfileOut( $fname );
return $notice;
}
function wfGetNamespaceNotice() {
global $wgTitle;
-
+
# Paranoia
if ( !isset( $wgTitle ) || !is_object( $wgTitle ) )
return "";
$fname = 'wfGetNamespaceNotice';
wfProfileIn( $fname );
-
+
$key = "namespacenotice-" . $wgTitle->getNsText();
$namespaceNotice = wfGetCachedNotice( $key );
if ( $namespaceNotice && substr ( $namespaceNotice , 0 ,7 ) != "<p><" ) {
global $wgUser, $wgSiteNotice;
$fname = 'wfGetSiteNotice';
wfProfileIn( $fname );
- $siteNotice = '';
-
+ $siteNotice = '';
+
if( wfRunHooks( 'SiteNoticeBefore', array( &$siteNotice ) ) ) {
if( is_object( $wgUser ) && $wgUser->isLoggedIn() ) {
$siteNotice = wfGetCachedNotice( 'sitenotice' );
return $siteNotice;
}
-/**
+/**
* BC wrapper for MimeMagic::singleton()
* @deprecated
*/
*/
function wfIncrStats( $key ) {
global $wgStatsMethod;
-
+
if( $wgStatsMethod == 'udp' ) {
global $wgUDPProfilerHost, $wgUDPProfilerPort, $wgDBname;
static $socket;
*/
function wfShellExec( $cmd, &$retval=null ) {
global $IP, $wgMaxShellMemory, $wgMaxShellFileSize;
-
+
if( wfIniGetBool( 'safe_mode' ) ) {
wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
$retval = 1;
$cmd = '"' . $cmd . '"';
}
wfDebug( "wfShellExec: $cmd\n" );
-
+
$retval = 1; // error by default?
ob_start();
passthru( $cmd, $retval );
$output = ob_get_contents();
ob_end_clean();
return $output;
-
+
}
/**
*
* 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.
- *
+ *
* @param string $path
* @param string $suffix to remove if present
* @return string
// Normalize mixed input on Windows...
$path = str_replace( '/', DIRECTORY_SEPARATOR, $path );
$from = str_replace( '/', DIRECTORY_SEPARATOR, $from );
-
+
// Trim trailing slashes -- fix for drive root
$path = rtrim( $path, DIRECTORY_SEPARATOR );
$from = rtrim( $from, DIRECTORY_SEPARATOR );
-
+
$pieces = explode( DIRECTORY_SEPARATOR, dirname( $path ) );
$against = explode( DIRECTORY_SEPARATOR, $from );
-
+
if( $pieces[0] !== $against[0] ) {
// Non-matching Windows drive letters?
// Return a full path.
$delimiter = ':';
// parse_url detects for news: and mailto: the host part of an url as path
// We have to correct this wrong detection
- if ( isset ( $bits['path'] ) ) {
+ if ( isset ( $bits['path'] ) ) {
$bits['host'] = $bits['path'];
$bits['path'] = '';
}
$digitChars = ( $lowercase ) ? '0123456789abcdefghijklmnopqrstuvwxyz' : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$inDigits = array();
$outChars = '';
-
+
// Decode and validate input string
$input = strtolower( $input );
for( $i = 0; $i < strlen( $input ); $i++ ) {
}
$inDigits[] = $n;
}
-
+
// Iterate over the input, modulo-ing out an output digit
// at a time until input is gone.
while( count( $inDigits ) ) {
$work = 0;
$workDigits = array();
-
+
// Long division...
foreach( $inDigits as $digit ) {
$work *= $sourceBase;
$work += $digit;
-
+
if( $work < $destBase ) {
// Gonna need to pull another digit.
if( count( $workDigits ) ) {
} else {
// Finally! Actual division!
$workDigits[] = intval( $work / $destBase );
-
+
// Isn't it annoying that most programming languages
// don't have a single divide-and-remainder operator,
// even though the CPU implements it that way?
$work = $work % $destBase;
}
}
-
+
// All that division leaves us with a remainder,
// which is conveniently our next output digit.
$outChars .= $digitChars[$work];
-
+
// And we continue!
$inDigits = $workDigits;
}
-
+
while( strlen( $outChars ) < $pad ) {
$outChars .= '0';
}
-
+
return strrev( $outChars );
}
/**
* Aliases for modularized functions
*/
-function wfGetHTTP( $url, $timeout = 'default' ) {
- return Http::get( $url, $timeout );
+function wfGetHTTP( $url, $timeout = 'default' ) {
+ return Http::get( $url, $timeout );
}
-function wfIsLocalURL( $url ) {
- return Http::isLocalURL( $url );
+function wfIsLocalURL( $url ) {
+ return Http::isLocalURL( $url );
}
/**
}
/**
- * Split a wiki ID into DB name and table prefix
+ * Split a wiki ID into DB name and table prefix
*/
function wfSplitWikiID( $wiki ) {
$bits = explode( '-', $wiki, 2 );
/*
* Get a Database object
- * @param integer $db Index of the connection to get. May be DB_MASTER for the
- * master (for write queries), DB_SLAVE for potentially lagged
+ * @param integer $db Index of the connection to get. May be DB_MASTER for the
+ * master (for write queries), DB_SLAVE for potentially lagged
* read queries, or an integer >= 0 for a particular server.
*
- * @param mixed $groups Query groups. An array of group names that this query
- * belongs to. May contain a single string if the query is only
+ * @param mixed $groups Query groups. An array of group names that this query
+ * belongs to. May contain a single string if the query is only
* in one group.
*
* @param string $wiki The wiki ID, or false for the current wiki
}
/**
- * Find a file.
+ * Find a file.
* Shortcut for RepoGroup::singleton()->findFile()
* @param mixed $title Title object or string. May be interwiki.
- * @param mixed $time Requested time for an archived image, or false for the
- * current version. An image object will be returned which
+ * @param mixed $time Requested time for an archived image, or false for the
+ * current version. An image object will be returned which
* was created at the specified time.
* @return File, or false if the file does not exist
*/
/**
* Displays a maxlag error
- *
+ *
* @param string $host Server that lags the most
* @param int $lag Maxlag (actual)
* @param int $maxLag Maxlag (requested)
*/
function wfGenerateToken( $salt = '' ) {
$salt = serialize($salt);
-
+
return md5( mt_rand( 0, 0x7fffffff ) . $salt );
- }
\ No newline at end of file
+}
* Small numbers of links will be done immediately, large numbers are pushed onto
* the job queue.
*
- * This class is designed to work efficiently with small numbers of links, and
+ * This class is designed to work efficiently with small numbers of links, and
* to work reasonably well with up to ~10^5 links. Above ~10^6 links, the memory
* and time requirements of loading all backlinked IDs in doUpdate() might become
* prohibitive. The requirements measured at Wikimedia are approximately:
- *
+ *
* memory: 48 bytes per row
* time: 16us per row for the query plus processing
*
* The reason this query is done is to support partitioning of the job
- * by backlinked ID. The memory issue could be allieviated by doing this query in
+ * by backlinked ID. The memory issue could be allieviated by doing this query in
* batches, but of course LIMIT with an offset is inefficient on the DB side.
*
- * The class is nevertheless a vast improvement on the previous method of using
+ * The class is nevertheless a vast improvement on the previous method of using
* Image::getLinksTo() and Title::touchArray(), which uses about 2KB of memory per
* link.
*/
break;
}
}
-
+
$params = array(
'table' => $this->mTable,
'start' => $start,
'categorylinks' => 'cl',
'templatelinks' => 'tl',
'redirect' => 'rd',
-
+
# Not needed
# 'externallinks' => 'el',
# 'langlinks' => 'll'
}
return $this->mPrefix;
}
-
+
function getFromField() {
return $this->getPrefix() . '_from';
}
case 'pagelinks':
case 'templatelinks':
case 'redirect':
- return array(
+ return array(
"{$prefix}_namespace" => $this->mTitle->getNamespace(),
"{$prefix}_title" => $this->mTitle->getDBkey()
);
$dbw = wfGetDB( DB_MASTER );
$timestamp = $dbw->timestamp();
$done = false;
-
+
while ( !$done ) {
# Get all IDs in this query into an array
$ids = array();
if ( !count( $ids ) ) {
break;
}
-
+
# Update page_touched
- $dbw->update( 'page',
- array( 'page_touched' => $timestamp ),
+ $dbw->update( 'page',
+ array( 'page_touched' => $timestamp ),
array( 'page_id IN (' . $dbw->makeList( $ids ) . ')' ),
__METHOD__
);
return true;
}
}
-
/**
* Pure virtual parent
- * @todo document (needs a one-sentence top-level class description, that answers the question: "what is a HistoryBlob?")
+ * @todo document (needs a one-sentence top-level class description, that answers the question: "what is a HistoryBlob?")
*/
interface HistoryBlob
{
return $row->cur_text;
}
}
-
-
-
// IPv6 IPs with two "::" strings are ambiguous and thus invalid
return preg_match( '/^' . IP_ADDRESS_STRING . '$/', $ip) && ( substr_count($ip, '::') < 2 );
}
-
+
public static function isIPv6( $ip ) {
if ( !$ip ) return false;
if( is_array( $ip ) ) {
// IPv6 IPs with two "::" strings are ambiguous and thus invalid
return preg_match( '/^' . RE_IPV6_ADD . '(\/' . RE_IPV6_PREFIX . '|)$/', $ip) && ( substr_count($ip, '::') < 2);
}
-
+
public static function isIPv4( $ip ) {
if ( !$ip ) return false;
return preg_match( '/^' . RE_IP_ADD . '(\/' . RE_IP_PREFIX . '|)$/', $ip);
}
-
+
/**
* Given an IP address in dotted-quad notation, returns an IPv6 octet.
* See http://www.answers.com/topic/ipv4-compatible-address
* IPs with the first 92 bits as zeros are reserved from IPv6
* @param $ip quad-dotted IP address.
- * @return string
+ * @return string
*/
public static function IPv4toIPv6( $ip ) {
if ( !$ip ) return null;
$r_ip = wfBaseConvert( $r_ip, 16, 10 );
return $r_ip;
}
-
+
/**
* Given an IPv6 address in octet notation, returns the expanded octet.
* IPv4 IPs will be trimmed, thats it...
* @param $ip octet ipv6 IP address.
- * @return string
- */
+ * @return string
+ */
public static function sanitizeIP( $ip ) {
$ip = trim( $ip );
if ( $ip === '' ) return null;
$ip = preg_replace( '/(^|:)0+' . RE_IPV6_WORD . '/', '$1$2', $ip );
return $ip;
}
-
+
/**
* Given an unsigned integer, returns an IPv6 address in octet notation
* @param $ip integer IP address.
- * @return string
+ * @return string
*/
public static function toOctet( $ip_int ) {
// Convert to padded uppercase hex
}
return array( $network, $bits );
}
-
+
/**
- * Given a string range in a number of formats, return the start and end of
+ * Given a string range in a number of formats, return the start and end of
* the range in hexadecimal. For IPv6.
*
* Formats are:
return array( $start, $end );
}
}
-
+
/**
* Validate an IP address.
* @return boolean True if it is valid.
* Return a zero-padded hexadecimal representation of an IP address.
*
* Hexadecimal addresses are used because they can easily be extended to
- * IPv6 support. To separate the ranges, the return value from this
+ * IPv6 support. To separate the ranges, the return value from this
* function for an IPv6 address will be prefixed with "v6-", a non-
* hexadecimal string which sorts after the IPv4 addresses.
*
}
/**
- * Given a string range in a number of formats, return the start and end of
+ * Given a string range in a number of formats, return the start and end of
* the range in hexadecimal.
*
* Formats are:
* 1.2.3.4/24 CIDR
* 1.2.3.4 - 1.2.3.5 Explicit range
* 1.2.3.4 Single IP
- *
+ *
* 2001:0db8:85a3::7344/96 CIDR
* 2001:0db8:85a3::7344 - 2001:0db8:85a3::7344 Explicit range
* 2001:0db8:85a3::7344 Single IP
}
if ( $start === false || $end === false ) {
return array( false, false );
- } else {
+ } else {
return array( $start, $end );
}
}
return null; // give up
}
}
-
-
}
}
}
-
+
$contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
$bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
wfProfileOut( __METHOD__ );
else
return $roundedUp;
}
-
-
-
private $mPerRow = 4; // How many images wide should the gallery be?
private $mWidths = 120, $mHeights = 120; // How wide/tall each thumbnail should be
-
+
private $mAttribs = array();
/**
function setShowFilename( $f ) {
$this->mShowFilename = ( $f == true);
}
-
+
/**
* Set arbitrary attributes to go on the HTML gallery output element.
* Should be suitable for a <table> element.
- *
+ *
* Note -- if taking from user input, you should probably run through
* Sanitizer::validateAttributes() first.
*
foreach ( $this->mImages as $pair ) {
$nt = $pair[0];
$text = $pair[1];
-
+
# Give extensions a chance to select the file revision for us
$time = false;
wfRunHooks( 'BeforeGalleryFindFile', array( &$this, &$nt, &$time ) );
. htmlspecialchars( $img->getLastError() ) . '</div>';
} else {
$vpad = floor( ( 1.25*$this->mHeights - $thumb->height ) /2 ) - 2;
-
+
$thumbhtml = "\n\t\t\t".
'<div class="thumb" style="padding: ' . $vpad . 'px 0; width: ' .($this->mWidths+30).'px;">'
# Auto-margin centering for block-level elements. Needed now that we have video
public function count() {
return count( $this->mImages );
}
-
+
/**
* Set the contextual title
*
public function setContextTitle( $title ) {
$this->contextTitle = $title;
}
-
+
/**
* Get the contextual title, if applicable
*
}
} //class
-
-
return Article::view();
if ($wgShowEXIF && $this->img->exists()) {
- // FIXME: bad interface, see note on MediaHandler::formatMetadata().
+ // FIXME: bad interface, see note on MediaHandler::formatMetadata().
$formattedMetadata = $this->img->formatMetadata();
$showmeta = $formattedMetadata !== false;
} else {
/**
* Make a table with metadata to be shown in the output page.
*
- * FIXME: bad interface, see note on MediaHandler::formatMetadata().
+ * FIXME: bad interface, see note on MediaHandler::formatMetadata().
*
* @access private
*
/**
* Overloading Article's getContent method.
- *
+ *
* Omit noarticletext if sharedupload; text will be fetched from the
* shared upload server if possible.
*/
if( $this->img->mustRender() ) {
$showLink = true;
} else {
- $anchorclose .=
+ $anchorclose .=
$msgsmall .
'<br />' . Xml::tags( 'a', $linkAttribs, $msgbig ) . "$dirmark " . $longDesc;
}
}
if ( $thumbnail ) {
- $options = array(
+ $options = array(
'alt' => $this->img->getTitle()->getPrefixedText(),
'file-link' => true,
);
- $wgOut->addHTML( '<div class="fullImageLink" id="file">' .
+ $wgOut->addHTML( '<div class="fullImageLink" id="file">' .
$thumbnail->toHtml( $options ) .
$anchorclose . '</div>' );
}
if ( $page > 1 ) {
$label = $wgOut->parse( wfMsg( 'imgmultipageprev' ), false );
$link = $sk->makeKnownLinkObj( $this->mTitle, $label, 'page='. ($page-1) );
- $thumb1 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none',
+ $thumb1 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none',
array( 'page' => $page - 1 ) );
} else {
$thumb1 = '';
if ( $page < $count ) {
$label = wfMsg( 'imgmultipagenext' );
$link = $sk->makeKnownLinkObj( $this->mTitle, $label, 'page='. ($page+1) );
- $thumb2 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none',
+ $thumb2 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none',
array( 'page' => $page + 1 ) );
} else {
$thumb2 = '';
}
global $wgScript;
- $select = '<form name="pageselector" action="' .
+ $select = '<form name="pageselector" action="' .
htmlspecialchars( $wgScript ) .
'" method="get" onchange="document.pageselector.submit();">' .
Xml::hidden( 'title', $this->getTitle()->getPrefixedDbKey() );
return;
$sk = $wgUser->getSkin();
-
+
$wgOut->addHtml( '<br /><ul>' );
-
+
# "Upload a new version of this file" link
if( UploadForm::userCanReUpload($wgUser,$this->img->name) ) {
$ulink = $sk->makeExternalLink( $this->getUploadUrl(), wfMsg( 'uploadnewversion-linktext' ) );
# External editing link
$elink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'edit-externally' ), 'action=edit&externaledit=true&mode=file' );
$wgOut->addHtml( '<li>' . $elink . '<div>' . wfMsgWikiHtml( 'edit-externally-help' ) . '</div></li>' );
-
+
$wgOut->addHtml( '</ul>' );
}
$reverter = new FileRevertForm( $this->img );
$reverter->execute();
}
-
+
/**
* Override handling of action=purge
*/
public function imageHistoryLine( $iscur, $file ) {
global $wgUser, $wgLang, $wgContLang, $wgTitle;
-
+
$timestamp = wfTimestamp(TS_MW, $file->getTimestamp());
$img = $iscur ? $file->getName() : $file->getArchiveName();
$user = $file->getUser('id');
$description = $file->getDescription();
$dims = $file->getDimensionsString();
$sha1 = $file->getSha1();
-
+
$local = $this->img->isLocal();
$row = '';
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
// If file is top revision or locked from this user, don't link
if( $iscur || !$file->userCan(File::DELETED_RESTRICTED) ) {
- $del = wfMsgHtml( 'rev-delundel' );
+ $del = wfMsgHtml( 'rev-delundel' );
} else {
// If the file was hidden, link to sha-1
list($ts,$name) = explode('!',$img,2);
} else if( $file->isDeleted(File::DELETED_FILE) ) {
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
# Make a link to review the image
- $url = $this->skin->makeKnownLinkObj( $revdel, $wgLang->timeAndDate( $timestamp, true ),
+ $url = $this->skin->makeKnownLinkObj( $revdel, $wgLang->timeAndDate( $timestamp, true ),
"target=".$wgTitle->getPrefixedText()."&file=$sha1.".$this->img->getExtension() );
$row .= '<span class="history-deleted">'.$url.'</span>';
} else {
if( $file->isDeleted(File::DELETED_USER) )
$row .= '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
else
- $row .= $this->skin->userLink( $user, $usertext ) .
+ $row .= $this->skin->userLink( $user, $usertext ) .
$this->skin->userToolLinks( $user, $usertext );
} else {
$row .= htmlspecialchars( $usertext );
*/
/**
- * Pop a job of a certain type. This tries less hard than pop() to
- * actually find a job; it may be adversely affected by concurrent job
+ * Pop a job of a certain type. This tries less hard than pop() to
+ * actually find a job; it may be adversely affected by concurrent job
* runners.
*/
static function pop_type($type) {
$dbr = wfGetDB( DB_SLAVE );
- /* Get a job from the slave, start with an offset,
+ /* Get a job from the slave, start with an offset,
scan full set afterwards, avoid hitting purged rows
- NB: If random fetch previously was used, offset
- will always be ahead of few entries
+ NB: If random fetch previously was used, offset
+ will always be ahead of few entries
*/
$row = $dbr->selectRow( 'job', '*', "job_id >= ${offset}", __METHOD__,
}
throw new MWException( "Invalid job command `{$command}`" );
}
-
+
static function makeBlob( $params ) {
if ( $params !== false ) {
return serialize( $params );
return $this->error;
}
}
-
-
}
/**
- * Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
+ * Construct a factory based on a configuration array (typically from $wgLBFactoryConf)
*/
abstract function __construct( $conf );
*
* @param LoadBalancer $lb
*/
- function initLB( $lb ) {
+ function initLB( $lb ) {
if ( $this->startupPos === null ) {
if ( !empty( $_SESSION[__CLASS__] ) ) {
$this->startupPos = $_SESSION[__CLASS__];
*/
function shutdown() {
if ( session_id() != '' && count( $this->shutdownPos ) ) {
- wfDebug( __METHOD__.": saving master pos for " .
+ wfDebug( __METHOD__.": saving master pos for " .
count( $this->shutdownPos ) . " master(s)\n" );
$_SESSION[__CLASS__] = $this->shutdownPos;
}
}
}
-
* A multi-wiki, multi-master factory for Wikimedia and similar installations.
* Ignores the old configuration globals
*
- * Configuration:
+ * Configuration:
* sectionsByDB A map of database names to section names
*
* sectionLoads A 2-d map. For each section, gives a map of server names to load ratios.
*
* externalTemplateOverrides A set of server info keys overriding serverTemplate for external storage
*
- * templateOverridesByServer A 2-d map overriding serverTemplate and externalTemplateOverrides on a
+ * templateOverridesByServer A 2-d map overriding serverTemplate and externalTemplateOverrides on a
* server-by-server basis. Applies to both core and external storage.
*
* templateOverridesByCluster A 2-d map overriding the server info by external storage cluster
$this->chronProt = new ChronologyProtector;
$this->conf = $conf;
$required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' );
- $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName',
+ $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName',
'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer',
'templateOverridesByCluster', 'masterTemplateOverrides' );
if ( isset( $this->groupLoadsBySection[$section] ) ) {
$groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] );
}
- $this->mainLBs[$section] = $this->newLoadBalancer( $this->serverTemplate,
+ $this->mainLBs[$section] = $this->newLoadBalancer( $this->serverTemplate,
$this->sectionLoads[$section], $groupLoads, "main-$section" );
$this->chronProt->initLB( $this->mainLBs[$section] );
}
if ( isset( $this->templateOverridesByCluster[$cluster] ) ) {
$template = $this->templateOverridesByCluster[$cluster] + $template;
}
- $this->extLBs[$cluster] = $this->newLoadBalancer( $template,
+ $this->extLBs[$cluster] = $this->newLoadBalancer( $template,
$this->externalLoads[$cluster], array(), "ext-$cluster" );
}
return $this->extLBs[$cluster];
$this->commitMasterChanges();
}
}
-
<?php
/**
* A License class for use on Special:Upload
- *
+ *
* @addtogroup SpecialPage
*
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
$this->text = strrev( $text );
}
}
-
/**
* Add a ResultWrapper containing IDs and titles to a LinkCache object.
- * As normal, titles will go into the static Title cache field.
- * This function *also* stores extra fields of the title used for link
+ * As normal, titles will go into the static Title cache field.
+ * This function *also* stores extra fields of the title used for link
* parsing to avoid extra DB queries.
*/
public function addResultToCache( $cache, $res ) {
} else {
$sql .= ' OR ';
}
-
+
if (count($dbkeys)==1) { // avoid multiple-reference syntax if simple equality can be used
$singleKey = array_keys($dbkeys);
$sql .= "({$prefix}_namespace=$ns AND {$prefix}_title=".
")";
} else {
$sql .= "({$prefix}_namespace=$ns AND {$prefix}_title IN (";
-
+
$firstTitle = true;
foreach( $dbkeys as $dbkey => $unused ) {
if ( $firstTitle ) {
}
}
}
-
-
<?php
/**
* Cache for article titles (prefixed DB keys) and ids linked from one source
- *
+ *
* @addtogroup Cache
*/
class LinkCache {
return 0;
}
}
-
+
/**
- * Get a field of a title object from cache.
+ * Get a field of a title object from cache.
* If this link is not good, it will return NULL.
* @param Title $title
* @param string $field ('length','redirect')
}
# Some fields heavily used for linking...
$id = NULL;
-
+
if( !is_integer( $id ) ) {
if ( $this->mForUpdate ) {
$db = wfGetDB( DB_MASTER );
$options = array();
}
- $s = $db->selectRow( 'page',
+ $s = $db->selectRow( 'page',
array( 'page_id', 'page_len', 'page_is_redirect' ),
array( 'page_namespace' => $ns, 'page_title' => $t ),
$fname, $options );
$this->mBadLinks = array();
}
}
-
/**
* This function is a shortcut to makeKnownLinkObj(Title::newFromText($title),...). Do not call
* it if you already have a title object handy. See makeKnownLinkObj for further documentation.
- *
+ *
* @param $title String: the text of the title
* @param $text String: link text
* @param $query String: optional query part
/**
* This function is a shortcut to makeBrokenLinkObj(Title::newFromText($title),...). Do not call
* it if you already have a title object handy. See makeBrokenLinkObj for further documentation.
- *
+ *
* @param string $title The text of the title
* @param string $text Link text
* @param string $query Optional query part
/**
* @deprecated use makeColouredLinkObj
- *
+ *
* This function is a shortcut to makeStubLinkObj(Title::newFromText($title),...). Do not call
* it if you already have a title object handy. See makeStubLinkObj for further documentation.
- *
+ *
* @param $title String: the text of the title
* @param $text String: link text
* @param $query String: optional query part
* Make a link for a title which may or may not be in the database. If you need to
* call this lots of times, pre-fill the link cache with a LinkBatch, otherwise each
* call to this will result in a DB query.
- *
+ *
* @param $nt Title: the title object to make the link from, e.g. from
* Title::newFromText.
* @param $text String: link text
/**
* Make a red link to the edit page of a given title.
- *
+ *
* @param $nt Title object of the target page
* @param $text String: Link text
* @param $query String: Optional query part
/**
* @deprecated use makeColouredLinkObj
- *
+ *
* Make a brown link to a short article.
- *
+ *
* @param $nt Title object of the target page
* @param $text String: link text
* @param $query String: optional query part
/**
* Make a coloured link.
- *
+ *
* @param $nt Title object of the target page
* @param $colour Integer: colour of the link
* @param $text String: link text
return $this->makeColouredLinkObj( $nt, $colour, $text, $query, $trail, $prefix );
}
- /**
+ /**
* Make appropriate markup for a link to the current article. This is currently rendered
* as the bold link text. The calling sequence is the same as the other make*LinkObj functions,
* despite $query not being used.
return $s;
}
- /**
+ /**
* Creates the HTML source for images
* @deprecated use makeImageLink2
*
* @param File $file File object, or false if it doesn't exist
*
* @param array $frameParams Associative array of parameters external to the media handler.
- * Boolean parameters are indicated by presence or absence, the value is arbitrary and
+ * Boolean parameters are indicated by presence or absence, the value is arbitrary and
* will often be false.
* thumbnail If present, downscale and frame
* manualthumb Image name to use as a thumbnail, instead of automatic scaling
* upright_factor Fudge factor for "upright" tweak (default 0.75)
* border If present, show a border around the image
* align Horizontal alignment (left, right, center, none)
- * valign Vertical alignment (baseline, sub, super, top, text-top, middle,
+ * valign Vertical alignment (baseline, sub, super, top, text-top, middle,
* bottom, text-bottom)
* alt Alternate text for image (i.e. alt attribute). Plain text.
* caption HTML for image caption.
*
- * @param array $handlerParams Associative array of media handler parameters, to be passed
- * to transform(). Typical keys are "width" and "page".
+ * @param array $handlerParams Associative array of media handler parameters, to be passed
+ * to transform(). Typical keys are "width" and "page".
* @param string $time, timestamp of the file, set as false for current
* @return string HTML for an image, with links, wrappers, etc.
*/
}
// Use width which is smaller: real image width or user preference width
// For caching health: If width scaled down due to upright parameter, round to full __0 pixel to avoid the creation of a lot of odd thumbs
- $prefWidth = isset( $fp['upright'] ) ?
- round( $wgThumbLimits[$wopt] * $fp['upright'], -1 ) :
+ $prefWidth = isset( $fp['upright'] ) ?
+ round( $wgThumbLimits[$wopt] * $fp['upright'], -1 ) :
$wgThumbLimits[$wopt];
if ( $hp['width'] <= 0 || $prefWidth < $hp['width'] ) {
$hp['width'] = $prefWidth;
/**
* Make HTML for a thumbnail including image, border and caption
- * @param Title $title
+ * @param Title $title
* @param File $file File object or false if it doesn't exist
*/
function makeThumbLinkObj( Title $title, $file, $label = '', $alt, $align = 'right', $params = array(), $framed=false , $manualthumb = "" ) {
- $frameParams = array(
+ $frameParams = array(
'alt' => $alt,
'caption' => $label,
'align' => $align
if ( !isset( $fp['caption'] ) ) $fp['caption'] = '';
if ( empty( $hp['width'] ) ) {
- // Reduce width for upright images when parameter 'upright' is used
+ // Reduce width for upright images when parameter 'upright' is used
$hp['width'] = isset( $fp['upright'] ) ? 130 : 180;
}
$thumb = false;
if( $text == '' )
$text = htmlspecialchars( $title->getPrefixedText() );
$redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
- if( $redir ) {
+ if( $redir ) {
return $this->makeKnownLinkObj( $title, $text, $query, $trail, $prefix );
- }
+ }
$q = 'wpDestFile=' . $title->getPartialUrl();
if( $query != '' )
$q .= '&' . $query;
wfMsgHtml( 'blocklink' ) );
return $blockLink;
}
-
+
/**
* Generate a user link if the current user is allowed to view it
* @param $rev Revision object.
}
return $link;
}
-
+
/**
* This function is called by all recent changes variants, by the page history,
* and by the user contributions list. It is responsible for formatting edit
array( $this, 'formatLinksInCommentCallback' ),
$comment );
}
-
+
protected function formatLinksInCommentCallback( $match ) {
global $wgContLang;
$medians = '(?:' . preg_quote( MWNamespace::getCanonicalName( NS_MEDIA ), '/' ) . '|';
$medians .= preg_quote( $wgContLang->getNsText( NS_MEDIA ), '/' ) . '):';
-
+
$comment = $match[0];
# Handle link renaming [[foo|text]] will show link as "text"
} elseif( $hook == 'EditSectionLinkForOther' ) {
wfRunHooks( 'EditSectionLinkForOther', array( &$this, $nt, $section, $url, &$result ) );
}
-
+
// For reverse compatibility, add the brackets *after* the hook is run,
// and even add them to hook-provided text.
if( is_null( $result ) ) {
. $this->buildRollbackLink( $rev )
. ']</span>';
}
-
+
/**
* Build a raw rollback link, useful for collections of "tool" links
*
$title,
wfMsgHtml( 'rollbacklink' ),
'action=rollback&from=' . urlencode( $rev->getUserText() ) . $extra
- );
+ );
}
/**
foreach ( $templates as $titleObj ) {
$r = $titleObj->getRestrictions( 'edit' );
- if ( in_array( 'sysop', $r ) ) {
+ if ( in_array( 'sysop', $r ) ) {
$protected = wfMsgExt( 'template-protected', array( 'parseinline' ) );
} elseif ( in_array( 'autoconfirmed', $r ) ) {
$protected = wfMsgExt( 'template-semiprotected', array( 'parseinline' ) );
<?php
/**
* See docs/deferred.txt
- *
+ *
* @todo document (e.g. one-sentence top-level class description).
*/
class LinksUpdate {
$this->mProperties = $parserOutput->getProperties();
# Convert the format of the interlanguage links
- # I didn't want to change it in the ParserOutput, because that array is passed all
- # the way back to the skin, so either a skin API break would be required, or an
+ # I didn't want to change it in the ParserOutput, because that array is passed all
+ # the way back to the skin, so either a skin API break would be required, or an
# inefficient back-conversion.
$ill = $parserOutput->getLanguageLinks();
$this->mInterlangs = array();
}
$this->mRecursive = $recursive;
-
+
wfRunHooks( 'LinksUpdateConstructed', array( &$this ) );
}
*/
function doUpdate() {
global $wgUseDumbLinkUpdate;
-
+
wfRunHooks( 'LinksUpdate', array( &$this ) );
if ( $wgUseDumbLinkUpdate ) {
$this->doDumbUpdate();
function doIncrementalUpdate() {
wfProfileIn( __METHOD__ );
-
+
# Page links
$existing = $this->getExistingLinks();
$this->incrTableUpdate( 'pagelinks', 'pl', $this->getLinkDeletions( $existing ),
if ( $this->mRecursive ) {
$this->queueRecursiveJobs();
}
-
+
wfProfileOut( __METHOD__ );
}
function queueRecursiveJobs() {
wfProfileIn( __METHOD__ );
-
+
$batchSize = 100;
$dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array( 'templatelinks', 'page' ),
+ $res = $dbr->select( array( 'templatelinks', 'page' ),
array( 'page_namespace', 'page_title' ),
- array(
- 'page_id=tl_from',
+ array(
+ 'page_id=tl_from',
'tl_namespace' => $this->mTitle->getNamespace(),
'tl_title' => $this->mTitle->getDBkey()
), __METHOD__
$dbr->freeResult( $res );
wfProfileOut( __METHOD__ );
}
-
+
/**
* Invalidate the cache of a list of pages from a single namespace
*
if ( !count( $dbkeys ) ) {
return;
}
-
+
/**
* Determine which pages need to be updated
* This is necessary to prevent the job queue from smashing the DB with
*/
$now = $this->mDb->timestamp();
$ids = array();
- $res = $this->mDb->select( 'page', array( 'page_id' ),
- array(
+ $res = $this->mDb->select( 'page', array( 'page_id' ),
+ array(
'page_namespace' => $namespace,
'page_title IN (' . $this->mDb->makeList( $dbkeys ) . ')',
'page_touched < ' . $this->mDb->addQuotes( $now )
if ( !count( $ids ) ) {
return;
}
-
+
/**
* Do the update
- * We still need the page_touched condition, in case the row has changed since
+ * We still need the page_touched condition, in case the row has changed since
* the non-locking select above.
*/
- $this->mDb->update( 'page', array( 'page_touched' => $now ),
- array(
+ $this->mDb->update( 'page', array( 'page_touched' => $now ),
+ array(
'page_id IN (' . $this->mDb->makeList( $ids ) . ')',
'page_touched < ' . $this->mDb->addQuotes( $now )
), __METHOD__
/**
* Get an array of interlanguage link insertions
- * @param array $existing Array mapping existing language codes to titles
+ * @param array $existing Array mapping existing language codes to titles
* @private
*/
function getInterlangInsertions( $existing = array() ) {
return array_diff_key( $existing, $this->mImages );
}
- /**
+ /**
* Given an array of existing external links, returns those links which are not
* in $this and thus should be deleted.
* @private
return array_diff_assoc( $existing, $this->mCategories );
}
- /**
+ /**
* Given an array of existing interlanguage links, returns those links which are not
* in $this and thus should be deleted.
* @private
}
/**
- * Get an array of existing interlanguage links, with the language code in the key and the
+ * Get an array of existing interlanguage links, with the language code in the key and the
* title in the value.
* @private
*/
function getExistingInterlangs() {
- $res = $this->mDb->select( 'langlinks', array( 'll_lang', 'll_title' ),
+ $res = $this->mDb->select( 'langlinks', array( 'll_lang', 'll_title' ),
array( 'll_from' => $this->mId ), __METHOD__, $this->mOptions );
$arr = array();
while ( $row = $this->mDb->fetchObject( $res ) ) {
return $arr;
}
-
+
/**
* Return the title object of the page being updated
- */
+ */
function getTitle() {
return $this->mTitle;
}
}
}
}
-
if ( $sum == 0 ) {
# No loads on any of them
# In previous versions, this triggered an unweighted random selection,
- # but this feature has been removed as of April 2006 to allow for strict
- # separation of query groups.
+ # but this feature has been removed as of April 2006 to allow for strict
+ # separation of query groups.
return false;
}
$max = mt_getrandmax();
*/
function getReaderIndex( $group = false, $wiki = false ) {
global $wgReadOnly, $wgDBClusterTimeout, $wgDBAvgStatusPoll, $wgDBtype;
-
+
# FIXME: For now, only go through all this for mysql databases
if ($wgDBtype != 'mysql') {
return $this->getWriterIndex();
$totalElapsed = 0;
# convert from seconds to microseconds
- $timeout = $wgDBClusterTimeout * 1e6;
+ $timeout = $wgDBClusterTimeout * 1e6;
# Find the relevant load array
if ( $group !== false ) {
$found = false;
$laggedSlaveMode = false;
- # First try quickly looking through the available servers for a server that
+ # First try quickly looking through the available servers for a server that
# meets our criteria
do {
$totalThreadsConnected = 0;
throw new MWException( __METHOD__.": unexpectedly found no overloaded servers" );
}
# Back off for a while
- # Scale the sleep time by the number of connected threads, to produce a
+ # Scale the sleep time by the number of connected threads, to produce a
# roughly constant global poll rate
$avgThreads = $totalThreadsConnected / $overloadedServers;
$totalElapsed += $this->sleep( $wgDBAvgStatusPoll * $avgThreads );
}
# Query groups
- if ( $i == DB_MASTER ) {
+ if ( $i == DB_MASTER ) {
$i = $this->getWriterIndex();
} elseif ( !is_array( $groups ) ) {
$groupIndex = $this->getReaderIndex( $groups, $wiki );
}
/**
- * Mark a foreign connection as being available for reuse under a different
- * DB name or prefix. This mechanism is reference-counted, and must be called
+ * Mark a foreign connection as being available for reuse under a different
+ * DB name or prefix. This mechanism is reference-counted, and must be called
* the same number of times as getConnection() to work.
*/
public function reuseConnection( $conn ) {
* Index must be an actual index into the array.
* If the server is already open, returns it.
*
- * On error, returns false, and the connection which caused the
+ * On error, returns false, and the connection which caused the
* error will be available via $this->mErrorConnection.
*
* @param integer $i Server index
/**
* Open a connection to a foreign DB, or return one if it is already open.
*
- * Increments a reference count on the returned connection which locks the
- * connection to the requested wiki. This reference count can be
+ * Increments a reference count on the returned connection which locks the
+ * connection to the requested wiki. This reference count can be
* decremented by calling reuseConnection().
*
* If a connection is open to the appropriate server already, but with the wrong
* database, it will be switched to the right database and returned, as long as
* it has been freed first with reuseConnection().
*
- * On error, returns false, and the connection which caused the
+ * On error, returns false, and the connection which caused the
* error will be available via $this->mErrorConnection.
*
* @param integer $i Server index
// Reuse a connection from another wiki
$conn = reset( $this->mConns['foreignFree'][$i] );
$oldWiki = key( $this->mConns['foreignFree'][$i] );
-
+
if ( !$conn->selectDB( $dbName ) ) {
global $wguname;
- $this->mLastError = "Error selecting database $dbName on server " .
+ $this->mLastError = "Error selecting database $dbName on server " .
$conn->getServer() . " from client host {$wguname['nodename']}\n";
$this->mErrorConnection = $conn;
$conn = false;
}
}
}
-
+
/* Issue COMMIT only on master, only if queries were done on connection */
function commitMasterChanges() {
// Always 0, but who knows.. :)
return $this->mLagTimes;
}
}
-
-
class LogEventsList {
const NO_ACTION_LINK = 1;
-
+
private $skin;
private $out;
public $flags;
}
}
}
-
+
/**
* Set page title and show header for this log type
* @param strin $type
$action = htmlspecialchars( $wgScript );
$title = SpecialPage::getTitleFor( 'Log' );
$special = htmlspecialchars( $title->getPrefixedDBkey() );
-
+
$this->out->addHTML( "<form action=\"$action\" method=\"get\"><fieldset>" .
Xml::element( 'legend', array(), wfMsg( 'log' ) ) .
Xml::hidden( 'title', $special ) . "\n" .
*/
private function getTypeMenu( $queryType ) {
global $wgLogRestrictions, $wgUser;
-
+
$html = "<select name='type'>\n";
$validTypes = LogPage::validTypes();
private function getTitleInput( $title ) {
return Xml::inputLabel( wfMsg( 'speciallogtitlelabel' ), 'page', 'page', 20, $title );
}
-
+
/**
* @return string Formatted HTML
* @param int $year
Xml::checkLabel( wfMsg( 'log-title-wildcard' ), 'pattern', 'pattern', $pattern ) .
'</span>';
}
-
+
public function beginLogEventsList() {
return "<ul>\n";
}
-
+
public function endLogEventsList() {
return "</ul>\n";
}
-
+
/**
* @param Row $row a single row from the result set
* @return string Formatted HTML list item
*/
public function logLine( $row ) {
global $wgLang, $wgUser, $wgContLang;
-
+
$title = Title::makeTitle( $row->log_namespace, $row->log_title );
$time = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->log_timestamp), true );
// User links
} else if ( self::typeAction($row,'merge','merge') ) {
$merge = SpecialPage::getTitleFor( 'Mergehistory' );
$revert = '(' . $this->skin->makeKnownLinkObj( $merge, $this->message['revertmerge'],
- wfArrayToCGI(
- array('target' => $paramArray[0], 'dest' => $title->getPrefixedText(), 'mergepoint' => $paramArray[1] )
- )
+ wfArrayToCGI(
+ array('target' => $paramArray[0], 'dest' => $title->getPrefixedText(), 'mergepoint' => $paramArray[1] )
+ )
) . ')';
// If an edit was hidden from a page give a review link to the history
} else if( self::typeAction($row,'delete','revision') && $wgUser->isAllowed( 'deleterevision' ) && isset($paramArray[2]) ) {
}
$revert = "($revert)";
} else {
- wfRunHooks( 'LogLine', array( $row->log_type, $row->log_action, $title, $paramArray,
+ wfRunHooks( 'LogLine', array( $row->log_type, $row->log_action, $title, $paramArray,
&$comment, &$revert, $row->log_timestamp ) );
// wfDebug( "Invoked LogLine hook for " $row->log_type . ", " . $row->log_action . "\n" );
// Do nothing. The implementation is handled by the hook modifiying the passed-by-ref parameters.
} else {
$action = LogPage::actionText( $row->log_type, $row->log_action, $title, $this->skin, $paramArray, true );
}
-
+
return "<li>$del$time $userLink $action $comment $revert</li>\n";
}
-
+
/**
* @param Row $row
* @return string
*/
private function showhideLinks( $row ) {
global $wgAllowLogDeletion;
-
+
if( !$wgAllowLogDeletion )
return "";
-
+
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
// If event was hidden from sysops
if( !self::userCan( $row, LogPage::DELETED_RESTRICTED ) ) {
}
return "<tt>(<small>$del</small>)</tt>";
}
-
+
/**
* @param Row $row
* @param string $type
public static function typeAction( $row, $type, $action ) {
return ( $row->log_type == $type && $row->log_action == $action );
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this log row, if it's marked as deleted.
public static function isDeleted( $row, $field ) {
return ($row->log_deleted & $field) == $field;
}
-
+
/**
* Quick function to show a short log extract
* @param OutputPage $out
$out->addWikiMsg( 'logempty' );
}
}
-
+
/**
* SQL clause to skip forbidden log types for this user
* @param Database $db
function __construct( $list, $type='', $user='', $title='', $pattern='', $conds=array(), $y=false, $m=false ) {
parent::__construct();
$this->mConds = $conds;
-
+
$this->mLogEventsList = $list;
-
+
$this->limitType( $type );
$this->limitUser( $user );
$this->limitTitle( $title, $pattern );
$this->limitDate( $y, $m );
}
-
+
function getDefaultQuery() {
$query = parent::getDefaultQuery();
$query['type'] = $this->type;
$query['year'] = $this->year;
return $query;
}
-
+
/**
* Set the log reader to return only entries of the given type.
* Type restrictions enforced here
$this->type = $type;
$this->mConds['log_type'] = $type;
}
-
+
/**
* Set the log reader to return only entries by the given user.
* @param string $name (In)valid user name
/* Fetch userid at first, if known, provides awesome query plan afterwards */
$userid = User::idFromName( $name );
if( !$userid ) {
- /* It should be nicer to abort query at all,
+ /* It should be nicer to abort query at all,
but for now it won't pass anywhere behind the optimizer */
$this->mConds[] = "NULL";
} else {
*/
function limitTitle( $page, $pattern ) {
global $wgMiserMode;
-
+
$title = Title::newFromText( $page );
if( strlen($page) == 0 || !$title instanceof Title )
return false;
-
+
$this->title = $title->getPrefixedText();
$ns = $title->getNamespace();
if( $pattern && !$wgMiserMode ) {
$this->mConds['log_title'] = $title->getDBkey();
}
}
-
+
/**
* Set the log reader to return only entries from given date.
* @param int $year
function limitDate( $year, $month ) {
$year = intval($year);
$month = intval($month);
-
+
$this->year = ($year > 0 && $year < 10000) ? $year : '';
$this->month = ($month > 0 && $month < 13) ? $month : '';
-
+
if( $this->year || $this->month ) {
// Assume this year if only a month is given
if( $this->year ) {
$year_start--;
}
}
-
+
if( $this->month ) {
$month_end = str_pad($this->month + 1, 2, '0', STR_PAD_LEFT);
$year_end = $year_start;
}
return array(
'tables' => array( 'logging', 'user' ),
- 'fields' => array( 'log_type', 'log_action', 'log_user', 'log_namespace', 'log_title', 'log_params',
+ 'fields' => array( 'log_type', 'log_action', 'log_user', 'log_namespace', 'log_title', 'log_params',
'log_comment', $log_id, 'log_deleted', 'log_timestamp', 'user_name', 'user_editcount' ),
'conds' => $this->mConds,
'options' => $index
function getIndexField() {
return 'log_timestamp';
}
-
+
function getStartBody() {
wfProfileIn( __METHOD__ );
# Do a link batch query
function formatRow( $row ) {
return $this->mLogEventsList->logLine( $row );
}
-
+
public function getType() {
return $this->type;
}
-
+
public function getUser() {
return $this->user;
}
-
+
public function getPage() {
return $this->title;
}
-
+
public function getPattern() {
return $this->pattern;
}
-
+
public function getYear() {
return $this->year;
}
-
+
public function getMonth() {
return $this->month;
}
$loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 0 );
$this->pager = new LogPager( $loglist, $type, $user, $title, $pattern, $y, $m );
}
-
+
/**
* Is there at least one row?
* @return bool
# Set title and add header
$this->list->showHeader( $pager->getType() );
# Show form options
- $this->list->showOptions( $this->pager->getType(), $this->pager->getUser(), $this->pager->getPage(),
+ $this->list->showOptions( $this->pager->getType(), $this->pager->getUser(), $this->pager->getPage(),
$this->pager->getPattern(), $this->pager->getYear(), $this->pager->getMonth() );
# Insert list
$logBody = $this->pager->getBody();
if( $logBody ) {
$wgOut->addHTML(
- $this->pager->getNavigationBar() .
+ $this->pager->getNavigationBar() .
$this->list->beginLogEventsList() .
$logBody .
$this->list->endLogEventsList() .
}
}
}
-
global $wgLang, $wgContLang, $wgLogActions;
$key = "$type/$action";
-
+
if( $key == 'patrol/patrol' )
return PatrolLog::makeActionText( $title, $params, $skin );
-
+
if( isset( $wgLogActions[$key] ) ) {
if( is_null( $title ) ) {
$rv=wfMsg( $wgLogActions[$key] );
return explode( "\n", $blob );
}
}
-
+
/**
* Convert a comma-delimited list of block log flags
* into a more readable (and translated) form
return '';
}
}
-
+
/**
* Translate a block log flag if possible
*
* Please avoid reading the data out of one of these objects and then writing
* special case code. If possible, add another match()-like function here.
*
- * To add magic words in an extension, use the LanguageGetMagic hook. For
+ * To add magic words in an extension, use the LanguageGetMagic hook. For
* magic words which are also Parser variables, add a MagicWordwgVariableIDs
* hook. Use string keys.
*
'defaultsort',
'pagesincategory',
);
-
+
/* Array of caching hints for ParserCache */
static public $mCacheTTLs = array (
'currentmonth' => 86400,
}
return self::$mVariableIDs;
}
-
+
/* Allow external reads of TTL array */
static function getCacheTTL($id) {
if (array_key_exists($id,self::$mCacheTTLs)) {
}
return self::$mDoubleUnderscoreArray;
}
-
+
# Initialises this object with an ID
function load( $id ) {
global $wgContLang;
# This was used for matching "$1" variables, but different uses of the feature will have
# different restrictions, which should be checked *after* the MagicWord has been matched,
# not here. - IMSoP
-
+
$escSyn = array();
foreach ( $this->mSynonyms as $synonym )
// In case a magic word contains /, like that's going to happen;)
$escSyn[] = preg_quote( $synonym, '/' );
$this->mBaseRegex = implode( '|', $escSyn );
-
+
$case = $this->mCaseSensitive ? '' : 'iu';
$this->mRegex = "/{$this->mBaseRegex}/{$case}";
$this->mRegexStart = "/^(?:{$this->mBaseRegex})/{$case}";
/**
* Match some text, with parameter capture
- * Returns an array with the magic word name in the first element and the
+ * Returns an array with the magic word name in the first element and the
* parameter in the second element.
* Both elements are false if there was no match.
*/
$this->html );
}
}
-
+
function _attribs( $tag, $defaults=array(), $overrides=array() ) {
$attribs = Sanitizer::validateTagAttributes( $this->params, $tag );
$attribs = Sanitizer::mergeAttributes( $defaults, $attribs );
return $math->render();
}
}
-
*/
function getWidth() {
return $this->width;
- }
+ }
/**
* Get the height of the output box
/**
* Fetch HTML for this transform output
*
- * @param array $options Associative array of options. Boolean options
- * should be indicated with a value of true for true, and false or
+ * @param array $options Associative array of options. Boolean options
+ * should be indicated with a value of true for true, and false or
* absent for false.
*
* alt Alternate text or caption
* valign vertical-align property, if the output is an inline element
* img-class Class applied to the <img> tag, if there is such a tag
*
- * For images, desc-link and file-link are implemented as a click-through. For
- * sounds and videos, they may be displayed in other ways.
+ * For images, desc-link and file-link are implemented as a click-through. For
+ * sounds and videos, they may be displayed in other ways.
*
* @return string
*/
if ( strval( $alt ) === '' ) {
$alt = $title->getText();
}
- return array(
+ return array(
'href' => $this->file->getTitle()->getLocalURL( $query ),
'class' => 'image',
'title' => $alt
/**
* Return HTML <img ... /> tag for the thumbnail, will include
* width and height attributes and a blank alt text (as required).
- *
- * @param array $options Associative array of options. Boolean options
- * should be indicated with a value of true for true, and false or
+ *
+ * @param array $options Associative array of options. Boolean options
+ * should be indicated with a value of true for true, and false or
* absent for false.
*
* alt Alternate text or caption
* valign vertical-align property, if the output is an inline element
* img-class Class applied to the <img> tag, if there is such a tag
*
- * For images, desc-link and file-link are implemented as a click-through. For
- * sounds and videos, they may be displayed in other ways.
+ * For images, desc-link and file-link are implemented as a click-through. For
+ * sounds and videos, they may be displayed in other ways.
*
* @return string
* @public
*/
class TransformParameterError extends MediaTransformError {
function __construct( $params ) {
- parent::__construct( 'thumbnail_error',
- max( isset( $params['width'] ) ? $params['width'] : 0, 180 ),
- max( isset( $params['height'] ) ? $params['height'] : 0, 180 ),
+ parent::__construct( 'thumbnail_error',
+ max( isset( $params['width'] ) ? $params['width'] : 0, 180 ),
+ max( isset( $params['height'] ) ? $params['height'] : 0, 180 ),
wfMsg( 'thumbnail_invalid_params' ) );
}
}
-
-
}
session_set_save_handler( 'memsess_open', 'memsess_close', 'memsess_read', 'memsess_write', 'memsess_destroy', 'memsess_gc' );
-
-
wfDeprecated( __METHOD__ );
$this->loadFromLocal( $hash );
}
-
+
function saveToScript($array, $hash) {
global $wgLocalMessageCache;
if ( $wgLocalMessageCache === false ) {
umask( $oldUmask );
$file = fopen( $filename.'.tmp', 'w');
fwrite($file,"<?php\n//$hash\n\n \$this->mCache = array(");
-
+
foreach ($array as $key => $message) {
fwrite($file, "'". $this->escapeForScript($key).
- "' => '" . $this->escapeForScript($message).
+ "' => '" . $this->escapeForScript($message).
"',\n");
}
fwrite($file,");\n?>");
# Load titles for all oversized pages in the MediaWiki namespace
$res = $dbr->select( 'page', 'page_title',
- array(
+ array(
'page_len > ' . intval( $wgMaxMsgCacheEntrySize ),
'page_is_redirect' => 0,
'page_namespace' => NS_MEDIAWIKI,
- ),
+ ),
__METHOD__ );
while ( $row = $dbr->fetchObject( $res ) ) {
$this->mCache[$row->page_title] = '!TOO BIG';
# Load text for the remaining pages
$res = $dbr->select( array( 'page', 'revision', 'text' ),
array( 'page_title', 'old_text', 'old_flags' ),
- array(
+ array(
'page_is_redirect' => 0,
'page_namespace' => NS_MEDIAWIKI,
'page_latest=rev_id',
'rev_text_id=old_id',
- 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize ) ),
+ 'page_len <= ' . intval( $wgMaxMsgCacheEntrySize ) ),
__METHOD__ );
for ( $row = $dbr->fetchObject( $res ); $row; $row = $dbr->fetchObject( $res ) ) {
*
* @param string $key The message cache key
* @param bool $useDB Get the message from the DB, false to use only the localisation
- * @param bool $forContent Get the message from the content language rather than the
+ * @param bool $forContent Get the message from the content language rather than the
* user language
* @param bool $isFullKey Specifies whether $key is a two part key "lang/msg".
*/
}
/**
- * Get a message from the MediaWiki namespace, with caching. The key must
+ * Get a message from the MediaWiki namespace, with caching. The key must
* first be converted to two-part lang/msg form if necessary.
*
* @param string $title Message cache key with initial uppercase letter
*/
/**
- * TODO: Perhaps make this file into a Metadata class, with static methods (declared
+ * TODO: Perhaps make this file into a Metadata class, with static methods (declared
* as private where indicated), to move these functions out of the global namespace?
*/
define('RDF_TYPE_PREFS', "application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1");
return $knownLicenses;
}
-
-
if(!extension_loaded('fileinfo')) dl('fileinfo.' . PHP_SHLIB_SUFFIX);
}
-/**
+/**
* Implements functions related to mime types such as detection and mapping to
* file extension.
*
if ( $wgMimeTypeFile == 'includes/mime.types' ) {
$wgMimeTypeFile = "$IP/$wgMimeTypeFile";
}
-
+
if ( $wgMimeTypeFile ) {
if ( is_file( $wgMimeTypeFile ) and is_readable( $wgMimeTypeFile ) ) {
wfDebug( __METHOD__.": loading mime types from $wgMimeTypeFile\n" );
'bmp', 'tiff', 'tif', 'jpc', 'jp2',
'jpx', 'jb2', 'swc', 'iff', 'wbmp',
'xbm',
-
+
// Formats we recognize magic numbers for
'djvu', 'ogg', 'mid', 'pdf', 'wmf', 'xcf',
-
+
// XML formats we sure hope we recognize reliably
'svg',
);
* or misinterpreter by the default mime detection (namely xml based formats like XHTML or SVG).
*
* @param string $file The file to check
- * @param mixed $ext The file extension, or true to extract it from the filename.
+ * @param mixed $ext The file extension, or true to extract it from the filename.
* Set it to false to ignore the extension.
*
* @return string the mime type of $file
wfDebug(__METHOD__.": final mime type of $file: $mime\n");
return $mime;
}
-
+
function doGuessMimeType( $file, $ext = true ) {
// Read a chunk of the file
wfSuppressWarnings();
// Multimedia...
'MThd' => 'audio/midi',
'OggS' => 'application/ogg',
-
+
// Image formats...
// Note that WMF may have a bare header, no magic number.
"\x01\x00\x09\x00" => 'application/x-msmetafile', // Possibly prone to false positives?
"\xd7\xcd\xc6\x9a" => 'application/x-msmetafile',
'%PDF' => 'application/pdf',
'gimp xcf' => 'image/x-xcf',
-
+
// Some forbidden fruit...
'MZ' => 'application/octet-stream', // DOS/Windows executable
"\xca\xfe\xba\xbe" => 'application/octet-stream', // Mach-O binary
"\x7fELF" => 'application/octet-stream', // ELF binary
);
-
+
foreach( $headers as $magic => $candidate ) {
if( strncmp( $head, $magic, strlen( $magic ) ) == 0 ) {
wfDebug( __METHOD__ . ": magic header in $file recognized as $candidate\n" );
wfDebug( __METHOD__ . ": recognized $file as application/x-php\n" );
return "application/x-php";
}
-
+
/*
* look for XML formats (XHTML and SVG)
*/
return $mime;
}
}
-
+
wfSuppressWarnings();
$gis = getimagesize( $file );
wfRestoreWarnings();
-
+
if( $gis && isset( $gis['mime'] ) ) {
$mime = $gis['mime'];
wfDebug( __METHOD__.": getimagesize detected $file as $mime\n" );
/** Internal mime type detection, please use guessMimeType() for application code instead.
* Detection is done using an external program, if $wgMimeDetectorCommand is set.
* Otherwise, the fileinfo extension and mime_content_type are tried (in this order), if they are available.
- * If the dections fails and $ext is not false, the mime type is guessed from the file extension, using
+ * If the dections fails and $ext is not false, the mime type is guessed from the file extension, using
* guessTypesForExtension.
* If the mime type is still unknown, getimagesize is used to detect the mime type if the file is an image.
* If no mime type can be determined, this function returns "unknown/unknown".
*
* @param string $file The file to check
- * @param mixed $ext The file extension, or true to extract it from the filename.
+ * @param mixed $ext The file extension, or true to extract it from the filename.
* Set it to false to ignore the extension.
*
* @return string the mime type of $file
if ( !$m ) return MEDIATYPE_UNKNOWN;
$m = explode( ' ', $m );
- } else {
+ } else {
# Normalize mime type
if ( isset( $this->mMimeTypeAliases[$extMime] ) ) {
$extMime = $this->mMimeTypeAliases[$extMime];
return MEDIATYPE_UNKNOWN;
}
}
-
-
return NULL;
}
}
-
+
/**
* Can this namespace ever have a talk namespace?
*
public static function canTalk( $index ) {
return $index >= NS_MAIN;
}
-
+
/**
* Does this namespace contain content, for the purposes
* of calculating statistics, etc?
global $wgContentNamespaces;
return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
}
-
+
/**
* Can pages in a namespace be watched?
*
public static function isWatchable( $index ) {
return $index >= NS_MAIN;
}
-
-}
\ No newline at end of file
+
+}
*/
class Namespace extends MWNamespace {
// ..
-}
\ No newline at end of file
+}
}
$cache =& $wgCaches[CACHE_DBA];
}
-
+
if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) {
if ( !array_key_exists( CACHE_DB, $wgCaches ) ) {
$wgCaches[CACHE_DB] = new MediaWikiBagOStuff('objectcache');
$ret =& wfGetCache( $wgParserCacheType );
return $ret;
}
-
-
// Can't get the path from the server? :(
return '';
}
-
+
$period = strrpos( $path, '.' );
if( $period !== false ) {
return strtolower( substr( $path, $period ) );
if( !function_exists( 'gzencode' ) || headers_sent() ) {
return $s;
}
-
+
$ext = wfRequestExtension();
if( $ext == '.gz' || $ext == '.tgz' ) {
// Don't do gzip compression if the URL path ends in .gz or .tgz
// Bad Safari! Bad!
return $s;
}
-
+
if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
$tokens = preg_split( '/[,; ]/', $_SERVER['HTTP_ACCEPT_ENCODING'] );
if ( in_array( 'gzip', $tokens ) ) {
$s = gzencode( $s, 3 );
}
}
-
+
// Set vary header if it hasn't been set already
$headers = headers_list();
$foundVary = false;
$out .= '</ol></body></html>';
return $out;
}
-
var $mFeedLinksAppendQuery = false;
var $mEnableClientCache = true;
var $mArticleBodyOnly = false;
-
+
var $mNewSectionLink = false;
var $mNoGallery = false;
var $mPageTitleActionText = '';
$this->mNewSectionLink = false;
$this->mTemplateIds = array();
}
-
+
public function redirect( $url, $responsecode = '302' ) {
# Strip newlines as a paranoia check for header injection in PHP<5.1.2
$this->mRedirect = str_replace( "\n", '', $url );
$this->mRedirectCode = $responsecode;
}
-
+
public function getRedirect() {
return $this->mRedirect;
}
$this->mScripts .= "<script type=\"$wgJsMimeType\">/*<![CDATA[*/\n$script\n/*]]>*/</script>";
}
- function getScript() {
- return $this->mScripts . $this->getHeadItems();
+ function getScript() {
+ return $this->mScripts . $this->getHeadItems();
}
function getHeadItems() {
# Wed, 20 Aug 2003 06:51:19 GMT; length=5202
# this breaks strtotime().
$modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
-
+
wfSuppressWarnings(); // E_STRICT system time bitching
$modsinceTime = strtotime( $modsince );
wfRestoreWarnings();
-
+
$ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 );
wfDebug( "$fname: -- client send If-Modified-Since: " . $modsince . "\n", false );
wfDebug( "$fname: -- we might send Last-Modified : $lastmod\n", false );
$this->sendCacheControl();
wfDebug( "$fname: CACHED client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp ; site $wgCacheEpoch\n", false );
$this->disable();
-
+
// Don't output a compressed blob when using ob_gzhandler;
// it's technically against HTTP spec and seems to confuse
// Firefox when the response gets split over two packets.
wfClearOutputBuffers();
-
+
return true;
} else {
wfDebug( "$fname: READY client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp ; site $wgCacheEpoch\n", false );
$parserOutput = $wgParser->parse( $text, $title, $popts,
$linestart, true, $this->mRevisionId );
-
+
$popts->setTidy( $oldTidy );
$this->addParserOutput( $parserOutput );
$this->mHeadItems = array_merge( $this->mHeadItems, (array)$parserOutput->mHeadItems );
// Versioning...
$this->mTemplateIds += (array)$parserOutput->mTemplateIds;
-
+
// Display title
if( ( $dt = $parserOutput->getDisplayTitle() ) !== false )
$this->setPageTitle( $dt );
global $wgCookiePrefix, $wgCacheVaryCookies;
static $cookies;
if ( $cookies === null ) {
- $cookies = array_merge(
+ $cookies = array_merge(
array(
"{$wgCookiePrefix}Token",
"{$wgCookiePrefix}LoggedOut",
$this->enableClientCache( false );
$this->mRedirect = '';
$this->mBodytext = '';
-
+
array_unshift( $params, 'parse' );
array_unshift( $params, $msg );
$this->addHtml( call_user_func_array( 'wfMsgExt', $params ) );
-
+
$this->returnToMain( false );
}
public function errorpage( $title, $msg ) {
throw new ErrorPageError( $title, $msg );
}
-
+
/**
* Display an error page indicating that a given version of MediaWiki is
* required to use it
}
$skin = $wgUser->getSkin();
-
+
$this->setPageTitle( wfMsg( 'loginreqtitle' ) );
$this->setHtmlTitle( wfMsg( 'errorpagetitle' ) );
$this->setRobotPolicy( 'noindex,nofollow' );
$this->setArticleFlag( false );
-
+
$loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
$loginLink = $skin->makeKnownLinkObj( $loginTitle, wfMsgHtml( 'loginreqlink' ), 'returnto=' . $wgTitle->getPrefixedUrl() );
$this->addHtml( wfMsgWikiHtml( 'loginreqpagetext', $loginLink ) );
$this->addHtml( "\n<!--" . $wgTitle->getPrefixedUrl() . "-->" );
-
+
# Don't return to the main page if the user can't read it
# otherwise we'll end up in a pointless loop
$mainPage = Title::newMainPage();
/** @deprecated */
public function fatalError( $message ) {
- throw new FatalError( $message );
+ throw new FatalError( $message );
}
-
+
/** @deprecated */
public function unexpectedValueError( $name, $val ) {
throw new FatalError( wfMsg( 'unexpected', $name, $val ) );
*/
public function returnToMain( $unused = null, $returnto = NULL ) {
global $wgRequest;
-
+
if ( $returnto == NULL ) {
$returnto = $wgRequest->getText( 'returnto' );
}
-
+
if ( '' === $returnto ) {
$returnto = Title::newMainPage();
}
}
$ret .= " />\n";
}
-
+
if( $wgFeed ) {
foreach( $this->getSyndicationLinks() as $format => $link ) {
# Use the page name for the title (accessed through $wgTitle since
# with having the same name for different feeds corresponding to
# the same page, but we can't avoid that at this low a level.
global $wgTitle;
-
+
$ret .= $this->feedLink(
$format,
$link,
wfMsg( "page-{$format}-feed", $wgTitle->getPrefixedText() ) ); # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
}
-
+
# Recent changes feed should appear on every page
# Put it after the per-page feed to avoid changing existing behavior.
# It's still available, probably via a menu in your browser.
return $ret;
}
-
+
/**
* Return URLs for each supported syndication format for this page.
* @return array associating format keys with URLs
public function getSyndicationLinks() {
global $wgTitle, $wgFeedClasses;
$links = array();
-
+
if( $this->isSyndicated() ) {
if( is_string( $this->getFeedAppendQuery() ) ) {
$appendQuery = "&" . $this->getFeedAppendQuery();
}
return $links;
}
-
+
/**
* Generate a <link rel/> for an RSS feed.
*/
$this->returnToMain( false, $wgTitle );
}
-
+
/**
* Show an "add new section" link?
*
public function showNewSectionLink() {
return $this->mNewSectionLink;
}
-
+
/**
* Show a warning about slave lag
*
}
/**
- * This function takes a number of message/argument specifications, wraps them in
+ * This function takes a number of message/argument specifications, wraps them in
* some overall structure, and then parses the result and adds it to the output.
*
- * In the $wrap, $1 is replaced with the first message, $2 with the second, and so
- * on. The subsequent arguments may either be strings, in which case they are the
+ * In the $wrap, $1 is replaced with the first message, $2 with the second, and so
+ * on. The subsequent arguments may either be strings, in which case they are the
* message names, or an arrays, in which case the first element is the message name,
* and subsequent elements are the parameters to that message.
*
* The special named parameter 'options' in a message specification array is passed
- * through to the $options parameter of wfMsgExt().
+ * through to the $options parameter of wfMsgExt().
*
* For example:
*
* $wgOut->wrapWikiMsg( '<div class="error">$1</div>', 'some-error' );
- *
+ *
* Is equivalent to:
*
* $wgOut->addWikiText( '<div class="error">' . wfMsgNoTrans( 'some-error' ) . '</div>' );
class PageHistory {
const DIR_PREV = 0;
const DIR_NEXT = 1;
-
+
var $mArticle, $mTitle, $mSkin;
var $lastdate;
var $linesonpage;
$this->mSkin = $wgUser->getSkin();
$this->preCacheMessages();
}
-
+
/**
* As we use the same small set of messages in various methods and that
* they are called often, we call them once and save them in $this->message
wfRunHooks( 'PageHistoryBeforeList', array( &$this->mArticle ) );
- /**
+ /**
* Do the list
*/
$pager = new PageHistoryPager( $this );
$this->linesonpage = $pager->getNumRows();
$wgOut->addHTML(
- $pager->getNavigationBar() .
- $this->beginHistoryList() .
+ $pager->getNavigationBar() .
+ $this->beginHistoryList() .
$pager->getBody() .
$this->endHistoryList() .
$pager->getNavigationBar()
$lastlink = $this->lastLink( $rev, $next, $counter );
$arbitrary = $this->diffButtons( $rev, $firstInList, $counter );
$link = $this->revLink( $rev );
-
+
$s .= "($curlink) ($lastlink) $arbitrary";
-
+
if( $wgUser->isAllowed( 'deleterevision' ) ) {
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
if( $firstInList ) {
$del = $this->message['rev-delundel'];
} else if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
// If revision was hidden from sysops
- $del = $this->message['rev-delundel'];
+ $del = $this->message['rev-delundel'];
} else {
$del = $this->mSkin->makeKnownLinkObj( $revdel,
$this->message['rev-delundel'],
}
$s .= " <tt>(<small>$del</small>)</tt> ";
}
-
+
$s .= " $link";
$s .= " <span class='history-user'>" . $this->mSkin->revUserTools( $rev, true ) . "</span>";
}
$s .= $this->mSkin->revComment( $rev, false, true );
-
+
if ($notificationtimestamp && ($row->rev_timestamp >= $notificationtimestamp)) {
$s .= ' <span class="updatedmarker">' . wfMsgHtml( 'updatedmarker' ) . '</span>';
}
if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
$s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
}
-
+
$tools = array();
-
+
if ( !is_null( $next ) && is_object( $next ) ) {
if( !$this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser )
&& !$this->mTitle->getUserPermissionsErrors( 'edit', $wgUser )
$tools[] = "<span class=\"mw-history-undo\">{$undolink}</span>";
}
}
-
+
if( $tools ) {
$s .= ' (' . implode( ' | ', $tools ) . ')';
}
-
+
wfRunHooks( 'PageHistoryLineEnding', array( &$row , &$s ) );
return "<li>$s</li>\n";
}
-
- /**
+
+ /**
* Create a link to view this revision of the page
* @param Revision $rev
* @returns string
return $link;
}
- /**
+ /**
* Create a diff-to-current link for this revision for this page
* @param Revision $rev
* @param Bool $latest, this is the latest revision of the page?
}
}
- /**
+ /**
* Create a diff-to-previous link for this revision for this page.
* @param Revision $prevRev, the previous revision
* @param mixed $next, the newer revision
/**
* Fetch an array of revisions, specified by a given limit, offset and
- * direction. This is now only used by the feeds. It was previously
+ * direction. This is now only used by the feeds. It was previously
* used by the main UI but that's now handled by the pager.
*/
function fetchRevisions($limit, $offset, $direction) {
'wl_user' => $wgUser->getID()
),
__METHOD__ );
-
+
// Don't use the special value reserved for telling whether the field is filled
if ( is_null( $this->mNotificationTimestamp ) ) {
$this->mNotificationTimestamp = false;
return $this->mNotificationTimestamp;
}
-
+
/**
* Output a subscription feed listing recent edits to this page.
* @param string $type
*/
function feed( $type ) {
require_once 'SpecialRecentchanges.php';
-
+
global $wgFeed, $wgFeedClasses;
-
+
if ( !$wgFeed ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
return;
}
-
+
if( !isset( $wgFeedClasses[$type] ) ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-invalid' );
return;
}
-
+
$feed = new $wgFeedClasses[$type](
$this->mTitle->getPrefixedText() . ' - ' .
wfMsgForContent( 'history-feed-title' ),
}
$feed->outFooter();
}
-
+
function feedEmpty() {
global $wgOut;
return new FeedItem(
'',
$this->mTitle->getTalkPage()->getFullUrl() );
}
-
+
/**
* Generate a FeedItem object from a given revision table row
* Borrows Recent Changes' feed generation functions for formatting;
$rev->getId(),
$rev->getTimestamp(),
$rev->getComment() );
-
+
if( $rev->getComment() == '' ) {
global $wgContLang;
$title = wfMsgForContent( 'history-feed-item-nocomment',
$rev->getUserText(),
$this->mTitle->getTalkPage()->getFullUrl() );
}
-
+
/**
* Quickie hack... strip out wikilinks to more legible form from the comment.
*/
*/
class PageHistoryPager extends ReverseChronologicalPager {
public $mLastRow = false, $mPageHistory;
-
+
function __construct( $pageHistory ) {
parent::__construct();
$this->mPageHistory = $pageHistory;
if ( $this->mLastRow ) {
$latest = $this->mCounter == 1 && $this->mIsFirst;
$firstInList = $this->mCounter == 1;
- $s = $this->mPageHistory->historyLine( $this->mLastRow, $row, $this->mCounter++,
+ $s = $this->mPageHistory->historyLine( $this->mLastRow, $row, $this->mCounter++,
$this->mPageHistory->getNotificationTimestamp(), $latest, $firstInList );
} else {
$s = '';
$this->mLastRow = $row;
return $s;
}
-
+
function getStartBody() {
$this->mLastRow = false;
$this->mCounter = 1;
# The next row is the past-the-end row
$next = $this->mPastTheEndRow;
}
- $s = $this->mPageHistory->historyLine( $this->mLastRow, $next, $this->mCounter++,
+ $s = $this->mPageHistory->historyLine( $this->mLastRow, $next, $this->mCounter++,
$this->mPageHistory->getNotificationTimestamp(), $latest, $firstInList );
} else {
$s = '';
htmlspecialchars( $wgContLang->convert( $title->getPrefixedText() ) ) );
}
}
-
-
}
/**
- * IndexPager is an efficient pager which uses a (roughly unique) index in the
- * data set to implement paging, rather than a "LIMIT offset,limit" clause.
+ * IndexPager is an efficient pager which uses a (roughly unique) index in the
+ * data set to implement paging, rather than a "LIMIT offset,limit" clause.
* In MySQL, such a limit/offset clause requires counting through the
* specified number of offset rows to find the desired data, which can be
* expensive for large offsets.
- *
+ *
* ReverseChronologicalPager is a child class of the abstract IndexPager, and
* contains some formatting and display code which is specific to the use of
* timestamps as indexes. Here is a synopsis of its operation:
- *
+ *
* * The query is specified by the offset, limit and direction (dir)
- * parameters, in addition to any subclass-specific parameters.
+ * parameters, in addition to any subclass-specific parameters.
* * The offset is the non-inclusive start of the DB query. A row with an
* index value equal to the offset will never be shown.
* * The query may either be done backwards, where the rows are returned by
* user, or forwards. This is specified by the "dir" parameter, dir=prev
* means backwards, anything else means forwards. The offset value
* specifies the start of the database result set, which may be either
- * the start or end of the displayed data set. This allows "previous"
+ * the start or end of the displayed data set. This allows "previous"
* links to be implemented without knowledge of the index value at the
- * start of the previous page.
+ * start of the previous page.
* * An additional row beyond the user-specified limit is always requested.
* This allows us to tell whether we should display a "next" link in the
* case of forwards mode, or a "previous" link in the case of backwards
* mode. Determining whether to display the other link (the one for the
* page before the start of the database result set) can be done
- * heuristically by examining the offset.
+ * heuristically by examining the offset.
*
* * An empty offset indicates that the offset condition should be omitted
* from the query. This naturally produces either the first page or the
- * last page depending on the dir parameter.
+ * last page depending on the dir parameter.
*
* Subclassing the pager to implement concrete functionality should be fairly
- * simple, please see the examples in PageHistory.php and
+ * simple, please see the examples in PageHistory.php and
* SpecialIpblocklist.php. You just need to override formatRow(),
* getQueryInfo() and getIndexField(). Don't forget to call the parent
* constructor if you override it.
/** For pages that support multiple types of ordering, which one to use. */
protected $mOrderType;
/**
- * $mDefaultDirection gives the direction to use when sorting results:
+ * $mDefaultDirection gives the direction to use when sorting results:
* false for ascending, true for descending. If $mIsBackwards is set, we
* start from the opposite end, but we still sort the page itself according
* to $mDefaultDirection. E.g., if $mDefaultDirection is false but we're
public function __construct() {
global $wgRequest, $wgUser;
$this->mRequest = $wgRequest;
-
+
# NB: the offset is quoted, not validated. It is treated as an
# arbitrary string to support the widest variety of index types. Be
# careful outputting it into HTML!
}
/**
- * Do the query, using information from the object context. This function
- * has been kept minimal to make it overridable if necessary, to allow for
+ * Do the query, using information from the object context. This function
+ * has been kept minimal to make it overridable if necessary, to allow for
* result sets formed from multiple DB queries.
*/
function doQuery() {
$this->mResult = $this->reallyDoQuery( $this->mOffset, $queryLimit, $descending );
$this->extractResultInfo( $this->mOffset, $queryLimit, $this->mResult );
$this->mQueryDone = true;
-
+
$this->preprocessResults( $this->mResult );
$this->mResult->rewind(); // Paranoia
}
/**
- * Extract some useful data from the result object for use by
+ * Extract some useful data from the result object for use by
* the navigation bar, put it into $this
*/
function extractResultInfo( $offset, $limit, ResultWrapper $res ) {
protected function preprocessResults( $result ) {}
/**
- * Get the formatted result list. Calls getStartBody(), formatRow() and
+ * Get the formatted result list. Calls getStartBody(), formatRow() and
* getEndBody(), concatenates the results and returns them.
*/
function getBody() {
}
/**
- * Hook into getBody(), allows text to be inserted at the start. This
+ * Hook into getBody(), allows text to be inserted at the start. This
* will be called even if there are no rows in the result set.
*/
function getStartBody() {
}
/**
- * Hook into getBody(), for the bit between the start and the
+ * Hook into getBody(), for the bit between the start and the
* end when there are no rows
*/
function getEmptyBody() {
return '';
}
-
+
/**
- * Title used for self-links. Override this if you want to be able to
+ * Title used for self-links. Override this if you want to be able to
* use a title other than $wgTitle
*/
function getTitle() {
}
/**
- * Get an array of query parameters that should be put into self-links.
- * By default, all parameters passed in the URL are used, except for a
+ * Get an array of query parameters that should be put into self-links.
+ * By default, all parameters passed in the URL are used, except for a
* short blacklist.
*/
function getDefaultQuery() {
if ( !$this->mQueryDone ) {
$this->doQuery();
}
-
+
# Don't announce the limit everywhere if it's the default
$urlLimit = $this->mLimit == $this->mDefaultLimit ? '' : $this->mLimit;
-
+
if ( $this->mIsFirst ) {
$prev = false;
$first = false;
}
/**
- * Abstract formatting function. This should return an HTML string
+ * Abstract formatting function. This should return an HTML string
* representing the result row $row. Rows will be concatenated and
* returned by getBody()
*/
abstract function formatRow( $row );
/**
- * This function should be overridden to provide all parameters
- * needed for the main paged query. It returns an associative
+ * This function should be overridden to provide all parameters
+ * needed for the main paged query. It returns an associative
* array with the following elements:
* tables => Table(s) for passing to Database::select()
* fields => Field(s) for passing to Database::select(), may be *
function __construct() {
parent::__construct();
}
-
- /**
+
+ /**
* Shamelessly stolen bits from ReverseChronologicalPager,
- * didn't want to do class magic as may be still revamped
+ * didn't want to do class magic as may be still revamped
*/
function getNavigationBar() {
global $wgLang;
} else {
$extra .= ' | ';
}
-
+
if( $order == $this->mOrderType ) {
$extra .= wfMsgHTML( $msgs[$order] );
} else {
$limitLinks = $this->getLimitLinks();
$limits = implode( ' | ', $limitLinks );
- $this->mNavigationBar = "({$pagingLinks['first']} | {$pagingLinks['last']}) " .
+ $this->mNavigationBar = "({$pagingLinks['first']} | {$pagingLinks['last']}) " .
wfMsgHtml("viewprevnext", $pagingLinks['prev'], $pagingLinks['next'], $limits);
return $this->mNavigationBar;
}
global $wgStylePath;
$tableClass = htmlspecialchars( $this->getTableClass() );
$sortClass = htmlspecialchars( $this->getSortHeaderClass() );
-
+
$s = "<table border='1' class=\"$tableClass\"><thead><tr>\n";
$fields = $this->getFieldNames();
$alt = htmlspecialchars( wfMsg( 'ascending_abbrev' ) );
}
$image = htmlspecialchars( "$wgStylePath/common/images/$image" );
- $link = $this->makeLink(
+ $link = $this->makeLink(
"<img width=\"12\" height=\"12\" alt=\"$alt\" src=\"$image\" />" .
htmlspecialchars( $name ), $query );
$s .= "<th class=\"$sortClass\">$link</th>\n";
}
}
$s .= "</tr></thead><tbody>\n";
- return $s;
+ return $s;
}
function getEndBody() {
}
/**
- * Get <input type="hidden"> elements for use in a method="get" form.
- * Resubmits all defined elements of the $_GET array, except for a
+ * Get <input type="hidden"> elements for use in a method="get" form.
+ * Resubmits all defined elements of the $_GET array, except for a
* blacklist, passed in the $blacklist parameter.
*/
function getHiddenFields( $blacklist = array() ) {
$url = $this->getTitle()->escapeLocalURL();
$msgSubmit = wfMsgHtml( 'table_pager_limit_submit' );
return
- "<form method=\"get\" action=\"$url\">" .
- wfMsgHtml( 'table_pager_limit', $this->getLimitSelect() ) .
+ "<form method=\"get\" action=\"$url\">" .
+ wfMsgHtml( 'table_pager_limit', $this->getLimitSelect() ) .
"\n<input type=\"submit\" value=\"$msgSubmit\"/>\n" .
- $this->getHiddenFields( 'limit' ) .
+ $this->getHiddenFields( 'limit' ) .
"</form>\n";
}
/**
* Format a table cell. The return value should be HTML, but use an empty
- * string not for empty cells. Do not include the <td> and </td>.
+ * string not for empty cells. Do not include the <td> and </td>.
*
* The current result row is available as $this->mCurrentRow, in case you
* need more context.
/**
- * PHP Parser - Processes wiki markup (which uses a more user-friendly
+ * PHP Parser - Processes wiki markup (which uses a more user-friendly
* syntax, such as "[[link]]" for making links), and provides a one-way
* transformation of that wiki markup it into XHTML output / markup
* (which in turn the browser understands, and can display).
$this->mMarkerIndex = 0;
$this->mFirstCall = true;
}
-
+
/**
* Do various kinds of initialisation on the first call of the parser
*/
return;
}
$this->mFirstCall = false;
-
+
wfProfileIn( __METHOD__ );
$this->setHook( 'pre', array( $this, 'renderPreTag' ) );
* since it shouldn't match when butted up against identifier-like
* string constructs.
*
- * Must not consist of all title characters, or else it will change
+ * Must not consist of all title characters, or else it will change
* the behaviour of <nowiki> in a link.
*/
#$this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString();
global $wgExpensiveParserFunctionLimit;
$max = $this->mOptions->getMaxIncludeSize();
$PFreport = "Expensive parser function count: {$this->mExpensiveFunctionCount}/$wgExpensiveParserFunctionLimit\n";
- $limitReport =
- "NewPP limit report\n" .
+ $limitReport =
+ "NewPP limit report\n" .
"Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->mMaxPPNodeCount}\n" .
"Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .
"Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".
/**
* Use the HTML tidy PECL extension to use the tidy library in-process,
- * saving the overhead of spawning a new process.
+ * saving the overhead of spawning a new process.
*
* 'pear install tidy' should be able to compile the extension module.
*
$cleansource = tidy_get_output( $tidy );
}
if ( $wgDebugTidy && $tidy->getStatus() > 0 ) {
- $cleansource .= "<!--\nTidy reports:\n" .
- str_replace( '-->', '-->', $tidy->errorBuffer ) .
+ $cleansource .= "<!--\nTidy reports:\n" .
+ str_replace( '-->', '-->', $tidy->errorBuffer ) .
"\n-->";
}
} else if ( count ( $td_history ) == 0 ) {
// Don't do any of the following
continue;
- } else if ( substr ( $line , 0 , 2 ) == '|}' ) {
+ } else if ( substr ( $line , 0 , 2 ) == '|}' ) {
// We are ending a table
$line = '</table>' . substr ( $line , 2 );
$last_tag = array_pop ( $last_tag_history );
$oldtz = getenv( 'TZ' );
putenv( 'TZ='.$wgLocaltimezone );
}
-
+
wfSuppressWarnings(); // E_STRICT system time bitching
$localTimestamp = date( 'YmdHis', $ts );
$localMonth = date( 'm', $ts );
/**
* Preprocess some wikitext and return the document tree.
- * This is the ghost of replace_variables().
+ * This is the ghost of replace_variables().
*
* @param string $text The text to parse
* @param integer flags Bitwise combination of:
- * self::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
- * included. Default is to assume a direct page view.
+ * self::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
+ * included. Default is to assume a direct page view.
*
* The generated DOM tree must depend only on the input text and the flags.
- * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
+ * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
*
- * Any flag added to the $flags parameter here, or any other parameter liable to cause a
- * change in the DOM tree for a given text, must be passed through the section identifier
- * in the section edit link and thus back to extractSections().
+ * Any flag added to the $flags parameter here, or any other parameter liable to cause a
+ * change in the DOM tree for a given text, must be passed through the section identifier
+ * in the section edit link and thus back to extractSections().
*
- * The output of this function is currently only cached in process memory, but a persistent
- * cache may be implemented at a later date which takes further advantage of these strict
+ * The output of this function is currently only cached in process memory, but a persistent
+ * cache may be implemented at a later date which takes further advantage of these strict
* dependency requirements.
*
* @private
return $dom;
}
- /*
+ /*
* Return a three-element array: leading whitespace, string contents, trailing whitespace
*/
public static function splitWhitespace( $s ) {
# Title object, where $text came from
$title = NULL;
- # $part1 is the bit before the first |, and must contain only title characters.
- # Various prefixes will be stripped from it later.
+ # $part1 is the bit before the first |, and must contain only title characters.
+ # Various prefixes will be stripped from it later.
$titleWithSpaces = $frame->expand( $piece['title'] );
$part1 = trim( $titleWithSpaces );
$titleText = false;
elseif ( is_string( $text ) && !$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\*)/', $text)) /*}*/{
$text = "\n" . $text;
}
-
+
if ( is_string( $text ) && !$this->incrementIncludeSize( 'post-expand', strlen( $text ) ) ) {
# Error, oversize inclusion
- $text = "[[$originalTitle]]" .
+ $text = "[[$originalTitle]]" .
$this->insertStripItem( '<!-- WARNING: template omitted, post-expand include size too large -->' );
}
function getTemplateDom( $title ) {
$cacheTitle = $title;
$titleText = $title->getPrefixedDBkey();
-
+
if ( isset( $this->mTplRedirCache[$titleText] ) ) {
list( $ns, $dbk ) = $this->mTplRedirCache[$titleText];
$title = Title::makeTitle( $ns, $dbk );
$this->mTplDomCache[ $titleText ] = $dom;
if (! $title->equals($cacheTitle)) {
- $this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =
+ $this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =
array( $title->getNamespace(),$cdb = $title->getDBkey() );
}
$text = $skip = false;
$finalTitle = $title;
$deps = array();
-
+
// Loop to fetch the article, with up to 1 redirect
for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) {
# Give extensions a chance to select the revision instead
$id = false; // Assume current
wfRunHooks( 'BeforeParserFetchTemplateAndtitle', array( false, &$title, &$skip, &$id ) );
-
+
if( $skip ) {
$text = false;
$deps[] = array(
$rev = $id ? Revision::newFromId( $id ) : Revision::newFromTitle( $title );
$rev_id = $rev ? $rev->getId() : 0;
- $deps[] = array(
- 'title' => $title,
- 'page_id' => $title->getArticleID(),
+ $deps[] = array(
+ 'title' => $title,
+ 'page_id' => $title->getArticleID(),
'rev_id' => $rev_id );
if( $rev ) {
$argName = trim( $nameWithSpaces );
$object = false;
$text = $frame->getArgument( $argName );
- if ( $text === false && $parts->getLength() > 0
- && (
- $this->ot['html']
- || $this->ot['pre']
+ if ( $text === false && $parts->getLength() > 0
+ && (
+ $this->ot['html']
+ || $this->ot['pre']
|| ( $this->ot['wiki'] && $frame->isTemplate() )
)
) {
$content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] );
$marker = "{$this->mUniqPrefix}-$name-" . sprintf('%08X', $this->mMarkerIndex++) . self::MARKER_SUFFIX;
-
+
if ( $this->ot['html'] ) {
$name = strtolower( $name );
# give headline the correct <h#> tag
if( $showEditLink && $sectionIndex !== false ) {
if( $isTemplate ) {
- # Put a T flag in the section identifier, to indicate to extractSections()
+ # Put a T flag in the section identifier, to indicate to extractSections()
# that sections inside <includeonly> should be counted.
$editlink = $sk->editSectionLinkForOther($titleText, "T-$sectionIndex");
} else {
if( $numVisible < 1 ) {
$enoughToc = false;
}
-
+
if( $enoughToc ) {
if( $prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel ) {
$toc .= $sk->tocUnindent( $prevtoclevel - 1 );
*/
function getUserSig( &$user ) {
global $wgMaxSigChars;
-
+
$username = $user->getName();
$nickname = $user->getOption( 'nickname' );
$nickname = $nickname === '' ? $username : $nickname;
-
+
if( mb_strlen( $nickname ) > $wgMaxSigChars ) {
$nickname = $username;
wfDebug( __METHOD__ . ": $username has overlong signature.\n" );
if( isset( $params['heights'] ) ) {
$ig->setHeights( $params['heights'] );
}
-
+
wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
$lines = explode( "\n", $text );
// Initialise static lists
static $internalParamNames = array(
'horizAlign' => array( 'left', 'right', 'center', 'none' ),
- 'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',
+ 'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',
'bottom', 'text-bottom' ),
- 'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',
+ 'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',
'upright', 'border' ),
);
static $internalParamMap;
# * middle
# * bottom
# * text-bottom
-
+
$parts = array_map( 'trim', explode( '|', $options) );
$sk = $this->mOptions->getSkin();
# Process the input parameters
$caption = '';
- $params = array( 'frame' => array(), 'handler' => array(),
+ $params = array( 'frame' => array(), 'handler' => array(),
'horizAlign' => array(), 'vertAlign' => array() );
foreach( $parts as $part ) {
list( $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part );
* <flag1> - <flag2> - ... - <section number>
*
* Currently the only recognised flag is "T", which means the target section number
- * was derived during a template inclusion parse, in other words this is a template
- * section edit link. If no flags are given, it was an ordinary section edit link.
- * This flag is required to avoid a section numbering mismatch when a section is
+ * was derived during a template inclusion parse, in other words this is a template
+ * section edit link. If no flags are given, it was an ordinary section edit link.
+ * This flag is required to avoid a section numbering mismatch when a section is
* enclosed by <includeonly> (bug 6563).
*
- * The section number 0 pulls the text before the first heading; other numbers will
- * pull the given section along with its lower-level subsections. If the section is
+ * The section number 0 pulls the text before the first heading; other numbers will
+ * pull the given section along with its lower-level subsections. If the section is
* not found, $mode=get will return $newtext, and $mode=replace will return $text.
*
* @param string $mode One of "get" or "replace"
}
$node = $node->getNextSibling();
} while ( $node );
-
+
// Write out the remainder (in replace mode only)
if ( $mode == 'replace' ) {
// Output the replacement text
- // Add two newlines on -- trailing whitespace in $newText is conventionally
+ // Add two newlines on -- trailing whitespace in $newText is conventionally
// stripped by the editor, so we need both newlines to restore the paragraph gap
$outText .= $newText . "\n\n";
while ( $node ) {
}
/**
- * Try to guess the section anchor name based on a wikitext fragment
- * presumably extracted from a heading, for example "Header" from
+ * Try to guess the section anchor name based on a wikitext fragment
+ * presumably extracted from a heading, for example "Header" from
* "== Header ==".
*/
public function guessSectionNameFromWikiText( $text ) {
/**
* Strips a text string of wikitext for use in a section anchor
- *
+ *
* Accepts a text string and then removes all wikitext from the
* string and leaves only the resultant text (i.e. the result of
* [[User:WikiSysop|Sysop]] would be "Sysop" and the result of
* [[User:WikiSysop]] would be "User:WikiSysop") - this is intended
* to create valid section anchors by mimicing the output of the
* parser when headings are parsed.
- *
+ *
* @param $text string Text string to be stripped of wikitext
* for use in a Section anchor
* @return Filtered text string
# Strip internal link markup
$text = preg_replace('/\[\[:?([^[|]+)\|([^[]+)\]\]/','$2',$text);
$text = preg_replace('/\[\[:?([^[]+)\|?\]\]/','$1',$text);
-
+
# Strip external link markup (FIXME: Not Tolerant to blank link text
# I.E. [http://www.mediawiki.org] will render as [1] or something depending
# on how many empty links there are on the page - need to figure that out.
$text = preg_replace('/\[(?:' . wfUrlProtocols() . ')([^ ]+?) ([^[]+)\]/','$2',$text);
-
+
# Parse wikitext quotes (italics & bold)
$text = $this->doQuotes($text);
-
+
# Strip HTML tags
$text = StringUtils::delimiterReplace( '<', '>', '', $text );
return $text;
class OnlyIncludeReplacer {
var $output = '';
- function replace( $matches ) {
+ function replace( $matches ) {
if ( substr( $matches[1], -1 ) == "\n" ) {
$this->output .= substr( $matches[1], 0, -1 );
} else {
}
}
}
-
return $this->mDateFormat;
}
- function getTimestamp() {
+ function getTimestamp() {
if ( !isset( $this->mTimestamp ) ) {
$this->mTimestamp = wfTimestampNow();
}
- return $this->mTimestamp;
+ return $this->mTimestamp;
}
function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); }
wfProfileOut( $fname );
}
}
-
-
function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; }
function addWarning( $s ) { $this->mWarnings[] = $s; }
- function addOutputHook( $hook, $data = false ) {
+ function addOutputHook( $hook, $data = false ) {
$this->mOutputHooks[] = array( $hook, $data );
}
}
$this->mLinks[$ns][$dbk] = $id;
}
-
+
function addImage( $name ) {
$this->mImages[$name] = 1;
}
}
/**
- * Add some text to the <head>.
- * If $tag is set, the section with that tag will only be included once
+ * Add some text to the <head>.
+ * If $tag is set, the section with that tag will only be included once
* in a given page.
*/
function addHeadItem( $section, $tag = false ) {
$this->mHeadItems[] = $section;
}
}
-
+
/**
* Override the title to be used for display
* -- this is assumed to have been validated
public function setDisplayTitle( $text ) {
$this->displayTitle = $text;
}
-
+
/**
* Get the title to be used for display
*
public function getDisplayTitle() {
return $this->displayTitle;
}
-
+
/**
* Fairly generic flag setter thingy.
*/
public function setFlag( $flag ) {
$this->mFlags[$flag] = true;
}
-
+
public function getFlag( $flag ) {
return isset( $this->mFlags[$flag] );
}
$this->mProperties[$name] = $value;
}
- public function getProperty( $name ){
+ public function getProperty( $name ){
return isset( $this->mProperties[$name] ) ? $this->mProperties[$name] : false;
}
return $this->mProperties;
}
}
-
-
}
if ( $mismatch ) {
throw new MWException( "Parser_DiffTest: results mismatch on call to $name\n" .
- 'Arguments: ' . var_export( $args, true ) . "\n" .
+ 'Arguments: ' . var_export( $args, true ) . "\n" .
'Results: ' . var_export( $results, true ) . "\n" );
}
return $lastResult;
return true;
}
}
-
# Persistent:
var $mTagHooks, $mTransparentTagHooks, $mFunctionHooks, $mFunctionSynonyms, $mVariables,
$mImageParams, $mImageParamsMagicArray, $mExtLinkBracketedRegex;
-
+
# Cleared with clearState():
var $mOutput, $mAutonumber, $mDTopen, $mStripState;
var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
$this->mExtLinkBracketedRegex = '/\[(\b(' . wfUrlProtocols() . ')'.
'[^][<>"\\x00-\\x20\\x7F]+) *([^\]\\x0a\\x0d]*?)\]/S';
}
-
+
/**
* Do various kinds of initialisation on the first call of the parser
*/
return;
}
$this->mFirstCall = false;
-
+
wfProfileIn( __METHOD__ );
global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions;
-
+
$this->setHook( 'pre', array( $this, 'renderPreTag' ) );
-
+
# Syntax for arguments (see self::setFunctionHook):
# "name for lookup in localized magic words array",
# function callback,
# Information on include size limits, for the benefit of users who try to skirt them
if ( $this->mOptions->getEnableLimitReport() ) {
$max = $this->mOptions->getMaxIncludeSize();
- $limitReport =
+ $limitReport =
"Pre-expand include size: {$this->mIncludeSizes['pre-expand']}/$max bytes\n" .
"Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .
"Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n";
}
}
# Add the new items to the state
- # We do this after the loop instead of during it to avoid slowing
+ # We do this after the loop instead of during it to avoid slowing
# down the recursive unstrip
$state->nowiki->mergeArray( $nowikiItems );
$state->general->mergeArray( $generalItems );
/**
* Use the HTML tidy PECL extension to use the tidy library in-process,
- * saving the overhead of spawning a new process.
+ * saving the overhead of spawning a new process.
*
* 'pear install tidy' should be able to compile the extension module.
*
} else if ( count ( $td_history ) == 0 ) {
// Don't do any of the following
continue;
- } else if ( substr ( $line , 0 , 2 ) == '|}' ) {
+ } else if ( substr ( $line , 0 , 2 ) == '|}' ) {
// We are ending a table
$line = '</table>' . substr ( $line , 2 );
$last_tag = array_pop ( $last_tag_history );
$oldtz = getenv( 'TZ' );
putenv( 'TZ='.$wgLocaltimezone );
}
-
+
wfSuppressWarnings(); // E_STRICT system time bitching
$localTimestamp = date( 'YmdHis', $ts );
$localMonth = date( 'm', $ts );
$titleText = $title->getPrefixedText();
//used by edit section links
$replaceHeadings = true;
-
+
}
}
# If there are any <onlyinclude> tags, only include them
if ( in_string( '<onlyinclude>', $text ) && in_string( '</onlyinclude>', $text ) ) {
$replacer = new OnlyIncludeReplacer;
- StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>',
+ StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>',
array( &$replacer, 'replace' ), $text );
$text = $replacer->output;
}
$text = $skip = false;
$finalTitle = $title;
$deps = array();
-
+
// Loop to fetch the article, with up to 1 redirect
for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) {
# Give extensions a chance to select the revision instead
$id = false; // Assume current
wfRunHooks( 'BeforeParserFetchTemplateAndtitle', array( false, &$title, &$skip, &$id ) );
-
+
if( $skip ) {
$text = false;
$deps[] = array(
$rev = $id ? Revision::newFromId( $id ) : Revision::newFromTitle( $title );
$rev_id = $rev ? $rev->getId() : 0;
- $deps[] = array(
- 'title' => $title,
- 'page_id' => $title->getArticleID(),
+ $deps[] = array(
+ 'title' => $title,
+ 'page_id' => $title->getArticleID(),
'rev_id' => $rev_id );
if( $rev ) {
if( $numVisible < 1 ) {
$enoughToc = false;
}
-
+
if( $enoughToc ) {
if( $prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel ) {
$toc .= $sk->tocUnindent( $prevtoclevel - 1 );
$username = $user->getName();
$nickname = $user->getOption( 'nickname' );
$nickname = $nickname === '' ? $username : $nickname;
-
+
if( mb_strlen( $nickname ) > $wgMaxSigChars ) {
$nickname = $username;
wfDebug( __METHOD__ . ": $username has overlong signature.\n" );
if( isset( $params['heights'] ) ) {
$ig->setHeights( $params['heights'] );
}
-
+
wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
$lines = explode( "\n", $text );
// Initialise static lists
static $internalParamNames = array(
'horizAlign' => array( 'left', 'right', 'center', 'none' ),
- 'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',
+ 'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',
'bottom', 'text-bottom' ),
- 'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',
+ 'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',
'upright', 'border' ),
);
static $internalParamMap;
# * middle
# * bottom
# * text-bottom
-
+
$parts = array_map( 'trim', explode( '|', $options) );
$sk = $this->mOptions->getSkin();
# Process the input parameters
$caption = '';
- $params = array( 'frame' => array(), 'handler' => array(),
+ $params = array( 'frame' => array(), 'handler' => array(),
'horizAlign' => array(), 'vertAlign' => array() );
foreach( $parts as $part ) {
list( $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part );
if ( isset( $paramMap[$magicName] ) ) {
list( $type, $paramName ) = $paramMap[$magicName];
$params[$type][$paramName] = $value;
-
+
// Special case; width and height come in one variable together
if( $type == 'handler' && $paramName == 'width' ) {
$m = array();
# I.... _hope_ this is right.
# Otherwise, sometimes we don't have things initialized properly.
$this->clearState();
-
+
# strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
# comments to be stripped as well)
$stripState = new StripState;
}
/**
- * Try to guess the section anchor name based on a wikitext fragment
- * presumably extracted from a heading, for example "Header" from
+ * Try to guess the section anchor name based on a wikitext fragment
+ * presumably extracted from a heading, for example "Header" from
* "== Header ==".
*/
public function guessSectionNameFromWikiText( $text ) {
/**
* Strips a text string of wikitext for use in a section anchor
- *
+ *
* Accepts a text string and then removes all wikitext from the
* string and leaves only the resultant text (i.e. the result of
* [[User:WikiSysop|Sysop]] would be "Sysop" and the result of
* [[User:WikiSysop]] would be "User:WikiSysop") - this is intended
* to create valid section anchors by mimicing the output of the
* parser when headings are parsed.
- *
+ *
* @param $text string Text string to be stripped of wikitext
* for use in a Section anchor
* @return Filtered text string
# Strip internal link markup
$text = preg_replace('/\[\[:?([^[|]+)\|([^[]+)\]\]/','$2',$text);
$text = preg_replace('/\[\[:?([^[]+)\|?\]\]/','$1',$text);
-
+
# Strip external link markup (FIXME: Not Tolerant to blank link text
# I.E. [http://www.mediawiki.org] will render as [1] or something depending
# on how many empty links there are on the page - need to figure that out.
$text = preg_replace('/\[(?:' . wfUrlProtocols() . ')([^ ]+?) ([^[]+)\]/','$2',$text);
-
+
# Parse wikitext quotes (italics & bold)
$text = $this->doQuotes($text);
-
+
# Strip HTML tags
$text = StringUtils::delimiterReplace( '<', '>', '', $text );
return $text;
return $text;
}
}
-
return false;
}
}
-
+
/**
* Generate the log action text corresponding to a patrol log item
*
return '';
}
}
-
+
/**
* Prepare log parameters for a patrolled change
*
(int)$auto
);
}
-
}
-
return self::searchBackend( 0, $search, $limit );
}
-
-
+
+
/**
* Do a prefix search of titles and return a list of matching page names.
* @param string $search
} elseif( $ns == NS_SPECIAL ) {
return self::specialSearch( $search, $limit );
}
-
+
$srchres = array();
if( wfRunHooks( 'PrefixSearchBackend', array( $ns, $search, $limit, &$srchres ) ) ) {
return self::defaultSearchBackend( $ns, $search, $limit );
}
return $srchres;
}
-
+
/**
* Prefix search special-case for Special: namespace.
*/
protected static function specialSearch( $search, $limit ) {
global $wgContLang;
$searchKey = $wgContLang->caseFold( $search );
-
+
// Unlike SpecialPage itself, we want the canonical forms of both
// canonical and alias title forms...
SpecialPage::initList();
}
}
ksort( $keys );
-
+
$srchres = array();
foreach( $keys as $pageKey => $page ) {
if( $searchKey === '' || strpos( $pageKey, $searchKey ) === 0 ) {
}
return $srchres;
}
-
+
/**
* Unless overridden by PrefixSearchBackend hook...
* This is case-sensitive except the first letter (per $wgCapitalLinks)
*/
protected static function defaultSearchBackend( $ns, $search, $limit ) {
global $wgCapitalLinks, $wgContLang;
-
+
if( $wgCapitalLinks ) {
$search = $wgContLang->ucfirst( $search );
}
-
+
// Prepare nested request
$req = new FauxRequest(array (
'action' => 'query',
// because it does not support lists of unnamed items
$srchres[] = $pageinfo['title'];
}
-
+
return $srchres;
}
}
-
-?>
\ No newline at end of file
* Expand a document tree node
*/
function expand( $root, $flags = 0 );
-
+
/**
* Implode with flags for expand()
*/
function implode( $sep /*, ... */ );
/**
- * Makes an object that, when expand()ed, will be the same as one obtained
+ * Makes an object that, when expand()ed, will be the same as one obtained
* with implode()
- */
+ */
function virtualImplode( $sep /*, ... */ );
/**
function isEmpty();
/**
- * Get an argument to this frame by name
+ * Get an argument to this frame by name
*/
function getArgument( $name );
* * Leaf nodes, which contain the actual data
*
* This interface provides access to the tree structure and to the contents of array nodes,
- * but it does not provide access to the internal structure of leaf nodes. Access to leaf
+ * but it does not provide access to the internal structure of leaf nodes. Access to leaf
* data is provided via two means:
* * PPFrame::expand(), which provides expanded text
* * The PPNode::split*() functions, which provide metadata about certain types of tree node
*/
interface PPNode {
- /**
+ /**
* Get an array-type node containing the children of this node.
* Returns false if this is not a tree node.
*/
*/
function item( $i );
- /**
+ /**
* Get the name of this node. The following names are defined here:
*
* h A heading node.
* Split a <part> node into an associative array containing:
* name PPNode name
* index String index
- * value PPNode value
+ * value PPNode value
*/
function splitArg();
*/
function splitHeading();
}
-
/**
* Preprocess some wikitext and return the document tree.
- * This is the ghost of Parser::replace_variables().
+ * This is the ghost of Parser::replace_variables().
*
* @param string $text The text to parse
* @param integer flags Bitwise combination of:
- * Parser::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
- * included. Default is to assume a direct page view.
+ * Parser::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
+ * included. Default is to assume a direct page view.
*
* The generated DOM tree must depend only on the input text and the flags.
- * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
+ * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
*
- * Any flag added to the $flags parameter here, or any other parameter liable to cause a
- * change in the DOM tree for a given text, must be passed through the section identifier
- * in the section edit link and thus back to extractSections().
+ * Any flag added to the $flags parameter here, or any other parameter liable to cause a
+ * change in the DOM tree for a given text, must be passed through the section identifier
+ * in the section edit link and thus back to extractSections().
*
- * The output of this function is currently only cached in process memory, but a persistent
- * cache may be implemented at a later date which takes further advantage of these strict
+ * The output of this function is currently only cached in process memory, but a persistent
+ * cache may be implemented at a later date which takes further advantage of these strict
* dependency requirements.
*
* @private
// Use "A" modifier (anchored) instead of "^", because ^ doesn't work with an offset
$elementsRegex = "~($xmlishRegex)(?:\s|\/>|>)|(!--)~iA";
-
+
$stack = new PPDStack;
$searchBase = "[{<\n"; #}
// To avoid leaving blank lines, when a comment is both preceded
// and followed by a newline (ignoring spaces), trim leading and
// trailing spaces and one of the newlines.
-
+
// Find the end
$endPos = strpos( $text, '-->', $i + 4 );
if ( $endPos === false ) {
// $wsEnd will be the position of the last space
$wsEnd = $endPos + 2 + strspn( $text, ' ', $endPos + 3 );
// Eat the line if possible
- // TODO: This could theoretically be done if $wsStart == 0, i.e. for comments at
- // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
+ // TODO: This could theoretically be done if $wsStart == 0, i.e. for comments at
+ // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
// it's a possible beneficial b/c break.
- if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
+ if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
&& substr( $text, $wsEnd + 1, 1 ) == "\n" )
{
$startPos = $wsStart;
}
// <includeonly> and <noinclude> just become <ignore> tags
if ( in_array( $lowerName, $ignoredElements ) ) {
- $accum .= '<ignore>' . htmlspecialchars( substr( $text, $tagStartPos, $i - $tagStartPos ) )
+ $accum .= '<ignore>' . htmlspecialchars( substr( $text, $tagStartPos, $i - $tagStartPos ) )
. '</ignore>';
continue;
}
$attr = substr( $text, $attrStart, $attrEnd - $attrStart );
}
$accum .= '<name>' . htmlspecialchars( $name ) . '</name>' .
- // Note that the attr element contains the whitespace between name and attribute,
+ // Note that the attr element contains the whitespace between name and attribute,
// this is necessary for precise reconstruction during pre-save transform.
'<attr>' . htmlspecialchars( $attr ) . '</attr>';
if ( $inner !== null ) {
}
elseif ( $found == 'line-start' ) {
- // Is this the start of a heading?
+ // Is this the start of a heading?
// Line break belongs before the heading element in any case
if ( $fakeLineStart ) {
$fakeLineStart = false;
$accum .= $curChar;
$i++;
}
-
+
$count = strspn( $text, '=', $i, 6 );
if ( $count == 1 && $findEquals ) {
// DWIM: This looks kind of like a name/value separator
// Append the result to the enclosing accumulator
$accum .= $element;
// Note that we do NOT increment the input pointer.
- // This is because the closing linebreak could be the opening linebreak of
+ // This is because the closing linebreak could be the opening linebreak of
// another heading. Infinite loops are avoided because the next iteration MUST
- // hit the heading open case above, which unconditionally increments the
+ // hit the heading open case above, which unconditionally increments the
// input pointer.
}
-
+
elseif ( $found == 'open' ) {
# count opening brace characters
$count = strspn( $text, $curChar, $i );
$title = $parts[0]->out;
unset( $parts[0] );
- # The invocation is at the start of the line if lineStart is set in
+ # The invocation is at the start of the line if lineStart is set in
# the stack, and all opening brackets are used up.
if ( $maxCount == $matchingCount && !empty( $piece->lineStart ) ) {
$attr = ' lineStart="1"';
# Add XML element to the enclosing accumulator
$accum .= $element;
}
-
+
elseif ( $found == 'pipe' ) {
$findEquals = true; // shortcut for getFlags()
$stack->addPart();
$accum =& $stack->getAccum();
++$i;
}
-
+
elseif ( $found == 'equals' ) {
$findEquals = false; // shortcut for getFlags()
$stack->getCurrentPart()->eqpos = strlen( $accum );
var $stack, $rootAccum, $top;
var $out;
var $elementClass = 'PPDStackElement';
-
+
static $false = false;
function __construct() {
function getFlags() {
if ( !count( $this->stack ) ) {
- return array(
- 'findEquals' => false,
+ return array(
+ 'findEquals' => false,
'findPipe' => false,
'inHeading' => false,
);
class PPDPart {
var $out; // Output accumulator string
- // Optional member variables:
+ // Optional member variables:
// eqpos Position of equals sign in output accumulator
// commentEnd Past-the-end input pointer for the last comment encountered
// visualEnd Past-the-end input pointer for the end of the accumulator minus comments
return $root;
}
- if ( ++$this->parser->mPPNodeCount > $this->parser->mOptions->mMaxPPNodeCount )
+ if ( ++$this->parser->mPPNodeCount > $this->parser->mOptions->mMaxPPNodeCount )
{
return '<span class="error">Node-count limit exceeded</span>';
}
$index++;
}
} else {
- // Copy to $contextNode and then delete from iterator stack,
+ // Copy to $contextNode and then delete from iterator stack,
// because this is not an iterator but we do have to execute it once
$contextNode = $iteratorStack[$level];
$iteratorStack[$level] = false;
$newIterator = $this->virtualBracketedImplode( '{{', '|', '}}', $title, $parts );
} else {
$lineStart = $contextNode->getAttribute( 'lineStart' );
- $params = array(
- 'title' => new PPNode_DOM( $title ),
- 'parts' => new PPNode_DOM( $parts ),
+ $params = array(
+ 'title' => new PPNode_DOM( $title ),
+ 'parts' => new PPNode_DOM( $parts ),
'lineStart' => $lineStart );
$ret = $this->parser->braceSubstitution( $params, $this );
if ( isset( $ret['object'] ) ) {
if ( $flags & self::NO_ARGS ) {
$newIterator = $this->virtualBracketedImplode( '{{{', '|', '}}}', $title, $parts );
} else {
- $params = array(
- 'title' => new PPNode_DOM( $title ),
+ $params = array(
+ 'title' => new PPNode_DOM( $title ),
'parts' => new PPNode_DOM( $parts ) );
$ret = $this->parser->argSubstitution( $params, $this );
if ( isset( $ret['object'] ) ) {
} elseif ( $contextNode->nodeName == 'comment' ) {
# HTML-style comment
# Remove it in HTML, pre+remove and STRIP_COMMENTS modes
- if ( $this->parser->ot['html']
- || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
- || ( $flags & self::STRIP_COMMENTS ) )
+ if ( $this->parser->ot['html']
+ || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
+ || ( $flags & self::STRIP_COMMENTS ) )
{
$out .= '';
}
} elseif ( $contextNode->nodeName == 'ignore' ) {
# Output suppression used by <includeonly> etc.
# OT_WIKI will only respect <ignore> in substed templates.
- # The other output types respect it unless NO_IGNORE is set.
+ # The other output types respect it unless NO_IGNORE is set.
# extractSections() sets NO_IGNORE and so never respects it.
if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) || ( $flags & self::NO_IGNORE ) ) {
$out .= $contextNode->textContent;
# Insert a heading marker only for <h> children of <root>
# This is to stop extractSections from going over multiple tree levels
- if ( $contextNode->parentNode->nodeName == 'root'
- && $this->parser->ot['html'] )
+ if ( $contextNode->parentNode->nodeName == 'root'
+ && $this->parser->ot['html'] )
{
# Insert heading index marker
$headingIndex = $contextNode->getAttribute( 'i' );
}
/**
- * Makes an object that, when expand()ed, will be the same as one obtained
+ * Makes an object that, when expand()ed, will be the same as one obtained
* with implode()
*/
function virtualImplode( $sep /*, ... */ ) {
} else {
$s .= ', ';
}
- $s .= "\"$name\":\"" .
+ $s .= "\"$name\":\"" .
str_replace( '"', '\\"', $value->ownerDocument->saveXML( $value ) ) . '"';
}
$s .= '}';
}
if ( !isset( $this->namedExpansionCache[$name] ) ) {
# Trim named arguments post-expand, for backwards compatibility
- $this->namedExpansionCache[$name] = trim(
+ $this->namedExpansionCache[$name] = trim(
$this->parent->expand( $this->namedArgs[$name], self::STRIP_COMMENTS ) );
}
return $this->namedExpansionCache[$name];
* Split a <part> node into an associative array containing:
* name PPNode name
* index String index
- * value PPNode value
+ * value PPNode value
*/
function splitArg() {
$names = $this->xpath->query( 'name', $this->node );
}
$name = $names->item( 0 );
$index = $name->getAttribute( 'index' );
- return array(
+ return array(
'name' => new self( $name ),
- 'index' => $index,
+ 'index' => $index,
'value' => new self( $values->item( 0 ) ) );
}
-
+
/**
* Split an <ext> node into an associative array containing name, attr, inner and close
* All values in the resulting array are PPNodes. Inner and close are optional.
/**
* Preprocess some wikitext and return the document tree.
- * This is the ghost of Parser::replace_variables().
+ * This is the ghost of Parser::replace_variables().
*
* @param string $text The text to parse
* @param integer flags Bitwise combination of:
- * Parser::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
- * included. Default is to assume a direct page view.
+ * Parser::PTD_FOR_INCLUSION Handle <noinclude>/<includeonly> as if the text is being
+ * included. Default is to assume a direct page view.
*
* The generated DOM tree must depend only on the input text and the flags.
- * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
+ * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
*
- * Any flag added to the $flags parameter here, or any other parameter liable to cause a
- * change in the DOM tree for a given text, must be passed through the section identifier
- * in the section edit link and thus back to extractSections().
+ * Any flag added to the $flags parameter here, or any other parameter liable to cause a
+ * change in the DOM tree for a given text, must be passed through the section identifier
+ * in the section edit link and thus back to extractSections().
*
- * The output of this function is currently only cached in process memory, but a persistent
- * cache may be implemented at a later date which takes further advantage of these strict
+ * The output of this function is currently only cached in process memory, but a persistent
+ * cache may be implemented at a later date which takes further advantage of these strict
* dependency requirements.
*
* @private
// Use "A" modifier (anchored) instead of "^", because ^ doesn't work with an offset
$elementsRegex = "~($xmlishRegex)(?:\s|\/>|>)|(!--)~iA";
-
+
$stack = new PPDStack_Hash;
$searchBase = "[{<\n";
// To avoid leaving blank lines, when a comment is both preceded
// and followed by a newline (ignoring spaces), trim leading and
// trailing spaces and one of the newlines.
-
+
// Find the end
$endPos = strpos( $text, '-->', $i + 4 );
if ( $endPos === false ) {
// $wsEnd will be the position of the last space
$wsEnd = $endPos + 2 + strspn( $text, ' ', $endPos + 3 );
// Eat the line if possible
- // TODO: This could theoretically be done if $wsStart == 0, i.e. for comments at
- // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
+ // TODO: This could theoretically be done if $wsStart == 0, i.e. for comments at
+ // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
// it's a possible beneficial b/c break.
- if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
+ if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
&& substr( $text, $wsEnd + 1, 1 ) == "\n" )
{
$startPos = $wsStart;
// Remove leading whitespace from the end of the accumulator
// Sanity check first though
$wsLength = $i - $wsStart;
- if ( $wsLength > 0
+ if ( $wsLength > 0
&& $accum->lastNode instanceof PPNode_Hash_Text
- && substr( $accum->lastNode->value, -$wsLength ) === str_repeat( ' ', $wsLength ) )
+ && substr( $accum->lastNode->value, -$wsLength ) === str_repeat( ' ', $wsLength ) )
{
$accum->lastNode->value = substr( $accum->lastNode->value, 0, -$wsLength );
}
if ( $attrEnd <= $attrStart ) {
$attr = '';
} else {
- // Note that the attr element contains the whitespace between name and attribute,
+ // Note that the attr element contains the whitespace between name and attribute,
// this is necessary for precise reconstruction during pre-save transform.
$attr = substr( $text, $attrStart, $attrEnd - $attrStart );
}
}
elseif ( $found == 'line-start' ) {
- // Is this the start of a heading?
+ // Is this the start of a heading?
// Line break belongs before the heading element in any case
if ( $fakeLineStart ) {
$fakeLineStart = false;
$accum->addLiteral( $curChar );
$i++;
}
-
+
$count = strspn( $text, '=', $i, 6 );
if ( $count == 1 && $findEquals ) {
// DWIM: This looks kind of like a name/value separator
$accum->addAccum( $element );
}
// Note that we do NOT increment the input pointer.
- // This is because the closing linebreak could be the opening linebreak of
+ // This is because the closing linebreak could be the opening linebreak of
// another heading. Infinite loops are avoided because the next iteration MUST
- // hit the heading open case above, which unconditionally increments the
+ // hit the heading open case above, which unconditionally increments the
// input pointer.
}
-
+
elseif ( $found == 'open' ) {
# count opening brace characters
$count = strspn( $text, $curChar, $i );
$element = new PPNode_Hash_Tree( $name );
- # The invocation is at the start of the line if lineStart is set in
+ # The invocation is at the start of the line if lineStart is set in
# the stack, and all opening brackets are used up.
if ( $maxCount == $matchingCount && !empty( $piece->lineStart ) ) {
$element->addChild( new PPNode_Hash_Attr( 'lineStart', 1 ) );
$accum->addAccum( $element );
}
}
-
+
elseif ( $found == 'pipe' ) {
$findEquals = true; // shortcut for getFlags()
$stack->addPart();
$accum =& $stack->getAccum();
++$i;
}
-
+
elseif ( $found == 'equals' ) {
$findEquals = false; // shortcut for getFlags()
$accum->addNodeWithText( 'equals', '=' );
/**
* Append a PPAccum_Hash
- * Takes over ownership of the nodes in the source argument. These nodes may
+ * Takes over ownership of the nodes in the source argument. These nodes may
* subsequently be modified, especially nextSibling.
*/
function addAccum( $accum ) {
return $root;
}
- if ( ++$this->parser->mPPNodeCount > $this->parser->mOptions->mMaxPPNodeCount )
+ if ( ++$this->parser->mPPNodeCount > $this->parser->mOptions->mMaxPPNodeCount )
{
return '<span class="error">Node-count limit exceeded</span>';
}
$index++;
}
} else {
- // Copy to $contextNode and then delete from iterator stack,
+ // Copy to $contextNode and then delete from iterator stack,
// because this is not an iterator but we do have to execute it once
$contextNode = $iteratorStack[$level];
$iteratorStack[$level] = false;
} elseif ( $contextNode->name == 'comment' ) {
# HTML-style comment
# Remove it in HTML, pre+remove and STRIP_COMMENTS modes
- if ( $this->parser->ot['html']
- || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
- || ( $flags & self::STRIP_COMMENTS ) )
+ if ( $this->parser->ot['html']
+ || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
+ || ( $flags & self::STRIP_COMMENTS ) )
{
$out .= '';
}
} elseif ( $contextNode->name == 'ignore' ) {
# Output suppression used by <includeonly> etc.
# OT_WIKI will only respect <ignore> in substed templates.
- # The other output types respect it unless NO_IGNORE is set.
+ # The other output types respect it unless NO_IGNORE is set.
# extractSections() sets NO_IGNORE and so never respects it.
if ( ( !isset( $this->parent ) && $this->parser->ot['wiki'] ) || ( $flags & self::NO_IGNORE ) ) {
$out .= $contextNode->firstChild->value;
}
/**
- * Makes an object that, when expand()ed, will be the same as one obtained
+ * Makes an object that, when expand()ed, will be the same as one obtained
* with implode()
*/
function virtualImplode( $sep /*, ... */ ) {
} else {
$s .= ', ';
}
- $s .= "\"$name\":\"" .
+ $s .= "\"$name\":\"" .
str_replace( '"', '\\"', $value->__toString() ) . '"';
}
$s .= '}';
}
if ( !isset( $this->namedExpansionCache[$name] ) ) {
# Trim named arguments post-expand, for backwards compatibility
- $this->namedExpansionCache[$name] = trim(
+ $this->namedExpansionCache[$name] = trim(
$this->parent->expand( $this->namedArgs[$name], self::STRIP_COMMENTS ) );
}
return $this->namedExpansionCache[$name];
* Split a <part> node into an associative array containing:
* name PPNode name
* index String index
- * value PPNode value
+ * value PPNode value
*/
function splitArg() {
$bits = array();
}
if ( $child->name === 'name' ) {
$bits['name'] = $child;
- if ( $child->firstChild instanceof PPNode_Hash_Attr
+ if ( $child->firstChild instanceof PPNode_Hash_Attr
&& $child->firstChild->name === 'index' )
{
$bits['index'] = $child->firstChild->value;
}
return $bits;
}
-
+
/**
* Split an <ext> node into an associative array containing name, attr, inner and close
* All values in the resulting array are PPNodes. Inner and close are optional.
return var_export( $this, true );
}
- function getLength() {
- return count( $this->value );
+ function getLength() {
+ return count( $this->value );
}
- function item( $i ) {
- return $this->value[$i];
+ function item( $i ) {
+ return $this->value[$i];
}
function getName() { return '#nodelist'; }
return "<@{$this->name}>" . htmlspecialchars( $this->value ) . "</@{$this->name}>";
}
- function getName() {
+ function getName() {
return $this->name;
}
function splitExt() { throw new MWException( __METHOD__ . ': not supported' ); }
function splitHeading() { throw new MWException( __METHOD__ . ': not supported' ); }
}
-
$name = substr($name, 0, 255);
$encname = $dbw->strencode($name);
-
+
if ($wgProfilePerHost) {
$pfhost = $wguname['nodename'];
} else {
$elt = end($this->mWorkStack);
return $elt[0];
}
-
+
static function getCaller( $level ) {
$backtrace = wfDebugBacktrace();
if ( isset( $backtrace[$level] ) ) {
}
}
-
-
if ( function_exists( 'getrusage' ) ) {
if ( $ru == null )
$ru = getrusage();
- return ($ru['ru_utime.tv_sec'] + $ru['ru_stime.tv_sec'] + ($ru['ru_utime.tv_usec'] +
+ return ($ru['ru_utime.tv_sec'] + $ru['ru_stime.tv_sec'] + ($ru['ru_utime.tv_usec'] +
$ru['ru_stime.tv_usec']) * 1e-6);
} else {
return 0;
}
}
}
-
}
/* dense is good */
static function sort($a,$b) { return $a['real']<$b['real']; /* sort descending by time elapsed */ }
- static function format($item,$key) { printf("%3.6f %6d - %s\n",$item['real'],$item['count'], $key); }
+ static function format($item,$key) { printf("%3.6f %6d - %s\n",$item['real'],$item['count'], $key); }
}
-?>
socket_sendto($sock,$packet,$plength,0x100,$wgUDPProfilerHost,$wgUDPProfilerPort);
}
}
-
function wfGetProfilingOutput( $s, $e ) {}
function wfProfileClose() {}
$wgProfiling = false;
-
-
}
}
}
-
+
function execute() {
global $wgRequest, $wgOut;
if( $wgRequest->wasPosted() ) {
function save() {
global $wgRequest, $wgUser, $wgOut;
-
+
if( $this->disabled ) {
$this->show();
return false;
$edit_restriction = $this->mRestrictions['edit'];
- if ($this->mCascade && ($edit_restriction != 'protect') &&
+ if ($this->mCascade && ($edit_restriction != 'protect') &&
!(isset($wgGroupPermissions[$edit_restriction]['protect']) && $wgGroupPermissions[$edit_restriction]['protect'] ) )
$this->mCascade = false;
if( !$ok ) {
throw new FatalError( "Unknown error at restriction save time." );
}
-
+
if( $wgRequest->getCheck( 'mwProtectWatch' ) ) {
$this->mArticle->doWatch();
} elseif( $this->mTitle->userIsWatching() ) {
$this->mArticle->doUnwatch();
}
-
+
return $ok;
}
$out->addHTML( Xml::element( 'h2', null, LogPage::logName( 'protect' ) ) );
LogEventsList::showLogExtract( $out, 'protect', $this->mTitle->getPrefixedText() );
}
-
}
$index = 'HTTP_X_FORWARDED_FOR';
$index2 = 'CLIENT-IP';
}
-
+
#Try a couple of headers
if( isset( $set[$index] ) ) {
return $set[$index];
$xff = array_reverse( $xff );
$ipchain = array_merge( $ipchain, $xff );
}
-
+
# Step through XFF list and find the last address in the list which is a trusted server
# Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private)
foreach ( $ipchain as $i => $curIP ) {
function wfIsTrustedProxy( $ip ) {
global $wgSquidServers, $wgSquidServersNoPurge;
- if ( in_array( $ip, $wgSquidServers ) ||
- in_array( $ip, $wgSquidServersNoPurge ) ||
- wfIsAOLProxy( $ip )
+ if ( in_array( $ip, $wgSquidServers ) ||
+ in_array( $ip, $wgSquidServersNoPurge ) ||
+ wfIsAOLProxy( $ip )
) {
$trusted = true;
} else {
}
return false;
}
-
-
-
-
*/
/**
- * List of query page classes and their associated special pages,
+ * List of query page classes and their associated special pages,
* for periodic updates.
*
- * DO NOT CHANGE THIS LIST without testing that
+ * DO NOT CHANGE THIS LIST without testing that
* maintenance/updateSpecialPages.php still works.
*/
global $wgQueryPages; // not redundant
# Fetch the timestamp of this update
$tRes = $dbr->select( 'querycache_info', array( 'qci_timestamp' ), array( 'qci_type' => $type ), $fname );
$tRow = $dbr->fetchObject( $tRes );
-
+
if( $tRow ) {
$updated = $wgLang->timeAndDate( $tRow->qci_timestamp, true, true );
$wgOut->addMeta( 'Data-Cache-Time', $tRow->qci_timestamp );
} else {
$wgOut->addWikiMsg( 'perfcached' );
}
-
+
# If updates on this page have been disabled, let the user know
# that the data set won't be refreshed for now
global $wgDisableQueryPageUpdate;
if( is_array( $wgDisableQueryPageUpdate ) && in_array( $this->getName(), $wgDisableQueryPageUpdate ) ) {
$wgOut->addWikiMsg( 'querypage-no-updates' );
}
-
+
}
}
$this->preprocessResults( $dbr, $res );
$wgOut->addHtml( XML::openElement( 'div', array('class' => 'mw-spcontent') ) );
-
+
# Top header and navigation
if( $shownavigation ) {
$wgOut->addHtml( $this->getPageHeader() );
return;
}
}
-
+
# The actual results; specialist subclasses will want to handle this
# with more than a straight list, so we hand them the info, plus
# an OutputPage, and let them get on with it
}
$wgOut->addHtml( XML::closeElement( 'div' ) );
-
+
return $num;
}
-
+
/**
* Format and output report results using the given information plus
* OutputPage
*/
protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
global $wgContLang;
-
+
if( $num > 0 ) {
$html = array();
if( !$this->listoutput )
$html[] = $this->openList( $offset );
-
+
# $res might contain the whole 1,000 rows, so we read up to
# $num [should update this to use a Pager]
for( $i = 0; $i < $num && $row = $dbr->fetchObject( $res ); $i++ ) {
: "<li{$attr}>{$line}</li>\n";
}
}
-
+
# Flush the final result
if( $this->tryLastResult() ) {
$row = null;
: "<li{$attr}>{$line}</li>\n";
}
}
-
+
if( !$this->listoutput )
$html[] = $this->closeList();
-
+
$html = $this->listoutput
? $wgContLang->listToText( $html )
: implode( '', $html );
-
+
$out->addHtml( $html );
}
}
-
+
function openList( $offset ) {
return "\n<ol start='" . ( $offset + 1 ) . "' class='special'>\n";
}
-
+
function closeList() {
return "</ol>\n";
}
*/
function doFeed( $class = '', $limit = 50 ) {
global $wgFeed, $wgFeedClasses;
-
+
if ( !$wgFeed ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
return $title->getFullURL();
}
}
-
-
$ctype = $this->mRequest->getVal( 'ctype' );
$smaxage = $this->mRequest->getIntOrNull( 'smaxage', $wgSquidMaxage );
$maxage = $this->mRequest->getInt( 'maxage', $wgSquidMaxage );
-
+
$this->mExpandTemplates = $this->mRequest->getVal( 'templates' ) === 'expand';
$this->mUseMessageCache = $this->mRequest->getBool( 'usemsgcache' );
break;
}
$this->mOldId = $oldid;
-
+
# special case for 'generated' raw things: user css/js
$gen = $this->mRequest->getVal( 'gen' );
$this->mGen = false;
}
$this->mCharset = $wgInputEncoding;
-
+
# Force caching for CSS and JS raw content, default: 5 minutes
if (is_null($smaxage) and ($ctype=='text/css' or $ctype==$wgJsMimeType)) {
$this->mSmaxage = intval($wgForcedRawSMaxage);
$this->mSmaxage = intval( $smaxage );
}
$this->mMaxage = $maxage;
-
- # Output may contain user-specific data;
+
+ # Output may contain user-specific data;
# vary generated content for open sessions and private wikis
if ($this->mGen or !$wgGroupPermissions['*']['read']) {
$this->mPrivateCache = ( $this->mSmaxage == 0 ) ||
} else {
$this->mPrivateCache = false;
}
-
+
if ( $ctype == '' or ! in_array( $ctype, $allowedCTypes ) ) {
$this->mContentType = 'text/x-wiki';
} else {
} else {
$url = $_SERVER['PHP_SELF'];
}
-
+
if( strcmp( $wgScript, $url ) ) {
# Internet Explorer will ignore the Content-Type header if it
# thinks it sees a file extension it recognizes. Make sure that
# have the pages.
header( "HTTP/1.0 404 Not Found" );
}
-
+
// Special-case for empty CSS/JS
//
// Internet Explorer for Mac handles empty files badly;
$this->mContentType == 'text/javascript' ) ) {
return "/* Empty */";
}
-
+
return $this->parseArticleText( $text );
}
return $text;
}
}
-
$rc->numberofWatchingusers = false;
return $rc;
}
-
+
/**
* Obtain the recent change with a given rc_id value
*
return NULL;
}
}
-
+
/**
* Find the first recent change matching some specific conditions
*
}
}
}
-
-
}
/**
- * Return the list of revision fields that should be selected to create
+ * Return the list of revision fields that should be selected to create
* a new revision.
*/
static function selectFields() {
- return array(
+ return array(
'rev_id',
'rev_page',
'rev_text_id',
$this->mMinorEdit = intval( $row->rev_minor_edit );
$this->mTimestamp = $row->rev_timestamp;
$this->mDeleted = intval( $row->rev_deleted );
-
+
if( !isset( $row->rev_parent_id ) )
$this->mParentId = is_null($row->rev_parent_id) ? null : 0;
else
$this->mParentId = intval( $row->rev_parent_id );
-
+
if( !isset( $row->rev_len ) || is_null( $row->rev_len ) )
$this->mSize = null;
else
- $this->mSize = intval( $row->rev_len );
+ $this->mSize = intval( $row->rev_len );
if( isset( $row->page_latest ) ) {
$this->mCurrent = ( $row->rev_id == $row->page_latest );
$this->mDeleted = isset( $row['deleted'] ) ? intval( $row['deleted'] ) : 0;
$this->mSize = isset( $row['len'] ) ? intval( $row['len'] ) : null;
$this->mParentId = isset( $row['parent_id'] ) ? intval( $row['parent_id'] ) : null;
-
+
// Enforce spacing trimming on supplied text
$this->mComment = isset( $row['comment'] ) ? trim( strval( $row['comment'] ) ) : null;
$this->mText = isset( $row['text'] ) ? rtrim( strval( $row['text'] ) ) : null;
public function getTextId() {
return $this->mTextId;
}
-
+
/**
* Get parent revision ID (the original previous page revision)
* @return int
public function getRawUserText() {
return $this->mUserText;
}
-
+
/**
* Fetch revision comment if it's available to all users
* @return string
return $this->getRawText();
}
}
-
+
/**
* Fetch revision text without regard for view restrictions
* @return string
}
return $this->mText;
}
-
+
/**
* Fetch revision text if it's available to THIS user
* @return string
return null;
}
}
-
+
/**
* Get previous revision Id for this page_id
* This is used to populate rev_parent_id on save
*/
private function loadText() {
wfProfileIn( __METHOD__ );
-
+
// Caching may be beneficial for massive use of external storage
global $wgRevisionCacheExpiry, $wgMemc;
$key = wfMemcKey( 'revisiontext', 'textid', $this->getTextId() );
return $text;
}
}
-
+
// If we kept data for lazy extraction, use it now...
if ( isset( $this->mTextRow ) ) {
$row = $this->mTextRow;
} else {
$row = null;
}
-
+
if( !$row ) {
// Text data is immutable; check slaves first.
$dbr = wfGetDB( DB_SLAVE );
}
$text = self::getRevisionText( $row );
-
+
if( $wgRevisionCacheExpiry ) {
$wgMemc->set( $key, $text, $wgRevisionCacheExpiry );
}
-
+
wfProfileOut( __METHOD__ );
return $text;
wfProfileOut( __METHOD__ );
return $revision;
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this revision, if it's marked as deleted.
*/
static function getTimestampFromID( $id ) {
$dbr = wfGetDB( DB_SLAVE );
- $timestamp = $dbr->selectField( 'revision', 'rev_timestamp',
+ $timestamp = $dbr->selectField( 'revision', 'rev_timestamp',
array( 'rev_id' => $id ), __METHOD__ );
if ( $timestamp === false ) {
# Not in slave, try master
$dbw = wfGetDB( DB_MASTER );
- $timestamp = $dbw->selectField( 'revision', 'rev_timestamp',
+ $timestamp = $dbw->selectField( 'revision', 'rev_timestamp',
array( 'rev_id' => $id ), __METHOD__ );
}
return $timestamp;
}
-
+
/**
* Get count of revisions per page...not very efficient
* @param Database $db
}
return 0;
}
-
+
/**
* Get count of revisions per page...not very efficient
* @param Database $db
define( 'MW_REV_DELETED_COMMENT', Revision::DELETED_COMMENT );
define( 'MW_REV_DELETED_USER', Revision::DELETED_USER );
define( 'MW_REV_DELETED_RESTRICTED', Revision::DELETED_RESTRICTED );
-
-
-
$htmlelements = array_merge( $htmlsingle, $htmlpairs, $htmlnest );
# Convert them all to hashtables for faster lookup
- $vars = array( 'htmlpairs', 'htmlsingle', 'htmlsingleonly', 'htmlnest', 'tabletags',
+ $vars = array( 'htmlpairs', 'htmlsingle', 'htmlsingleonly', 'htmlnest', 'tabletags',
'htmllist', 'listtags', 'htmlsingleallowed', 'htmlelements' );
foreach ( $vars as $var ) {
$$var = array_flip( $$var );
$optstack = array();
array_push ($optstack, $ot);
while ( ( ( $ot = @array_pop( $tagstack ) ) != $t ) &&
- isset( $htmlsingleallowed[$ot] ) )
+ isset( $htmlsingleallowed[$ot] ) )
{
array_push ($optstack, $ot);
}
return Sanitizer::validateAttributes( $attribs,
Sanitizer::attributeWhitelist( $element ) );
}
-
+
/**
* Take an array of attribute names and values and normalize or discard
* illegal values for the given whitelist.
}
return $out;
}
-
+
/**
* Merge two sets of HTML attributes.
* Conflicting items in the second set will override those
if( isset( $a['class'] )
&& isset( $b['class'] )
&& $a['class'] !== $b['class'] ) {
-
+
$out['class'] = implode( ' ',
array_unique(
preg_split( '/\s+/',
}
return $out;
}
-
+
/**
* Pick apart some CSS and check it for forbidden or unsafe structures.
* Returns a sanitized string, or false if it was just too evil.
// Remove any comments; IE gets token splitting wrong
$stripped = StringUtils::delimiterReplace( '/*', '*/', ' ', $stripped );
-
+
$value = $stripped;
// ... and continue checks
# haxx0r
return false;
}
-
+
return $value;
}
self::normalizeWhitespace(
Sanitizer::normalizeCharReferences( $text ) ) );
}
-
+
private static function normalizeWhitespace( $text ) {
return preg_replace(
'/\r\n|[\x20\x0d\x0a\x09]/',
/**
* If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
- * return the named entity reference as is. If the entity is a
- * MediaWiki-specific alias, returns the HTML equivalent. Otherwise,
+ * return the named entity reference as is. If the entity is a
+ * MediaWiki-specific alias, returns the HTML equivalent. Otherwise,
* returns HTML-escaped text of pseudo-entity source (eg &foo;)
*
* @param string $name
# 11.2.6
'td' => array_merge( $common, $tablecell, $tablealign ),
'th' => array_merge( $common, $tablecell, $tablealign ),
-
+
# 13.2
# Not usually allowed, but may be used for extension-style hooks
# such as <math> when it is rasterized
'rb' => $common,
'rt' => $common, #array_merge( $common, array( 'rbspan' ) ),
'rp' => $common,
-
+
# MathML root element, where used for extensions
# 'title' may not be 100% valid here; it's XHTML
# http://www.w3.org/TR/REC-MathML/
}
}
-
-
if($wgContLang->hasVariants()){
$allSearchTerms = array_merge($allSearchTerms,$wgContLang->convertLinkToAllVariants($searchterm));
}
-
+
foreach($allSearchTerms as $term){
# Exact match? No need to look further.
if ( $title->getNamespace() == NS_USER ) {
return $title;
}
-
+
# Go to images that exist even if there's no local page.
# There may have been a funny upload, or it may be on a shared
# file repository such as Wikimedia Commons.
if( preg_match( '/^"([^"]+)"$/', $searchterm, $matches ) ) {
return SearchEngine::getNearMatch( $matches[1] );
}
-
+
return NULL;
}
function setNamespaces( $namespaces ) {
$this->namespaces = $namespaces;
}
-
+
/**
* Parse some common prefixes: all (search everything)
* or namespace names
*/
function replacePrefixes( $query ){
global $wgContLang;
-
+
if( strpos($query,':') === false )
return $query; // nothing to do
-
+
$parsed = $query;
$allkeyword = wfMsg('searchall').":";
if( strncmp($query, $allkeyword, strlen($allkeyword)) == 0 ){
}
if(trim($parsed) == '')
return $query; // prefix was the whole query
-
+
return $parsed;
}
function getSuggestionQuery(){
return null;
}
-
+
/**
* @return string highlighted suggested query, '' if none
*/
function next() {
return false;
}
-
+
/**
* Frees the result set, if applicable.
* @ access public
function getScore() {
return null;
}
-
+
/**
- * @return string highlighted text snippet, null if not supported
+ * @return string highlighted text snippet, null if not supported
*/
function getTextSnippet(){
- return null;
+ return null;
}
-
+
/**
* @return string highlighted title, '' if not supported
*/
function getTitleSnippet(){
return '';
}
-
+
/**
* @return string highlighted redirect name (redirect to this page), '' if none or not supported
*/
function getRedirectSnippet(){
return '';
}
-
+
/**
* @return Title object for the redirect to this page, null if none or not supported
*/
function getRedirectTitle(){
return null;
}
-
+
/**
* @return string highlighted relevant section name, null if none or not supported
*/
function getSectionSnippet(){
return '';
}
-
+
/**
- * @return Title object (pagename+fragment) for the section, null if none or not supported
+ * @return Title object (pagename+fragment) for the section, null if none or not supported
*/
function getSectionTitle(){
return null;
}
-
+
/**
* @return string timestamp, null if not supported
*/
function getTimestamp(){
return null;
}
-
+
/**
* @return int number of words, null if not supported
*/
function getWordCount(){
return null;
}
-
+
/**
* @return int size in bytes, null if not supported
*/
function searchtitle() {}
function searchtext() {}
}
-
return new SearchResult( $row );
}
}
-
+
function free() {
$this->mResultSet->free();
}
}
-
-
return new SearchResult($row);
}
}
-
-
/**
* Perform a full text search query via tsearch2 and return a result set.
- * Currently searches a page's current title (page.page_title) and
+ * Currently searches a page's current title (page.page_title) and
* latest revision article text (pagecontent.old_text)
*
* @param string $term - Raw search term
}
}
}
-
-
-
$dbw->query( $sql, __METHOD__ );
}
-
}
-
-
wfProfileOut( "$fname-regexps" );
wfRunHooks( 'SearchUpdate', array( $this->mId, $this->mNamespace, $this->mTitle, &$text ) );
-
+
# Perform the actual update
$search->update($this->mId, Title::indexTitle( $this->mNamespace, $this->mTitle ),
$text);
-
+
wfProfileOut( $fname );
}
}
class SearchUpdateMyISAM extends SearchUpdate {
# Inherits everything
}
-
-
if( !defined( 'MEDIAWIKI' ) ) {
echo "This file is part of MediaWiki, it is not a valid entry point.\n";
exit( 1 );
-}
+}
# The main wiki script and things like database
# conversion and maintenance scripts all share a
* Initialise $wgLocalFileRepo from backwards-compatible settings
*/
if ( !$wgLocalFileRepo ) {
- $wgLocalFileRepo = array(
+ $wgLocalFileRepo = array(
'class' => 'LocalRepo',
'name' => 'local',
'directory' => $wgUploadDirectory,
'fetchDescription' => $wgFetchCommonsDescriptions,
);
} else {
- $wgForeignFileRepos[] = array(
+ $wgForeignFileRepos[] = array(
'class' => 'FSRepo',
'name' => 'shared',
'directory' => $wgSharedUploadDirectory,
$wgOut = new StubObject( 'wgOut', 'OutputPage' );
$wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParserConf ) );
-$wgMessageCache = new StubObject( 'wgMessageCache', 'MessageCache',
+$wgMessageCache = new StubObject( 'wgMessageCache', 'MessageCache',
array( $parserMemc, $wgUseDatabaseMessages, $wgMsgCacheExpiry, wfWikiID() ) );
wfProfileOut( $fname.'-globals' );
# Skin setup functions
# Entries can be added to this variable during the inclusion
# of the extension file. Skins can then perform any necessary initialisation.
-#
+#
foreach ( $wgSkinExtensionFunctions as $func ) {
call_user_func( $func );
}
$wgFullyInitialised = true;
wfProfileOut( $fname.'-extensions' );
wfProfileOut( $fname );
-
-
}
return $retval;
}
-
+
/** Type-safe string replace; won't do replacements on non-strings */
function doReplace( $from, $to, $in ) {
if( is_string( $in ) ) {
}
}
}
-
-
$dbr = wfGetDB( DB_SLAVE );
self::$row = $dbr->selectRow( 'site_stats', '*', false, __METHOD__ );
}
-
+
self::$loaded = true;
}
-
+
static function loadAndLazyInit() {
wfDebug( __METHOD__ . ": reading site_stats from slave\n" );
$row = self::doLoad( wfGetDB( DB_SLAVE ) );
wfDebug( __METHOD__ . ": site_stats damaged or missing on slave\n" );
$row = self::doLoad( wfGetDB( DB_MASTER ) );
}
-
+
if( !self::isSane( $row ) ) {
// Normally the site_stats table is initialized at install time.
// Some manual construction scenarios may leave the table empty or
// broken, however, for instance when importing from a dump into a
// clean schema with mwdumper.
wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
-
+
global $IP;
require_once "$IP/maintenance/initStats.inc";
-
+
ob_start();
wfInitStats();
ob_end_clean();
-
+
$row = self::doLoad( wfGetDB( DB_MASTER ) );
}
-
+
if( !self::isSane( $row ) ) {
wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
}
self::load();
return self::$row->ss_users;
}
-
+
static function images() {
self::load();
return self::$row->ss_images;
}
return self::$jobs;
}
-
+
static function pagesInNs( $ns ) {
wfProfileIn( __METHOD__ );
if( !isset( self::$pageCount[$ns] ) ) {
*/
}
}
-
*/
static function &newFromKey( $key ) {
global $wgStyleDirectory;
-
+
$key = Skin::normalizeKey( $key );
$skinNames = Skin::getSkinNames();
if( false !== $wgFavicon ) {
$out->addLink( array( 'rel' => 'shortcut icon', 'href' => $wgFavicon ) );
}
-
+
if( false !== $wgAppleTouchIcon ) {
$out->addLink( array( 'rel' => 'apple-touch-icon', 'href' => $wgAppleTouchIcon ) );
- }
+ }
# OpenSearch description link
- $out->addLink( array(
- 'rel' => 'search',
+ $out->addLink( array(
+ 'rel' => 'search',
'type' => 'application/opensearchdescription+xml',
'href' => "$wgScriptPath/opensearch_desc{$wgScriptExtension}",
'title' => wfMsgForContent( 'opensearch-desc' ),
$this->addMetadataLinks($out);
$this->mRevisionId = $out->mRevisionId;
-
+
$this->preloadExistence();
wfProfileOut( __METHOD__ );
$lb = new LinkBatch( $titles );
$lb->execute();
}
-
+
function addMetadataLinks( &$out ) {
global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf;
global $wgRightsPage, $wgRightsUrl;
$ns = $wgTitle->getNamespace();
$nsname = isset( $wgCanonicalNamespaceNames[ $ns ] ) ? $wgCanonicalNamespaceNames[ $ns ] : $wgTitle->getNsText();
- $vars = array(
+ $vars = array(
'skin' => $data['skinname'],
'stylepath' => $wgStylePath,
'wgArticlePath' => $wgArticlePath,
$colon = wfMsgExt( 'colon-separator', 'escapenoentities' );
if ( !empty( $allCats['normal'] ) ) {
$t = $embed . implode ( "{$pop} {$sep} {$embed}" , $allCats['normal'] ) . $pop;
-
+
$msg = wfMsgExt( 'pagecategories', array( 'parsemag', 'escapenoentities' ), count( $allCats['normal'] ) );
$s .= '<div id="mw-normal-catlinks">' .
$this->makeLinkObj( Title::newFromText( wfMsgForContent('pagecategorieslink') ), $msg )
} else {
$class = 'mw-hidden-cats-hidden';
}
- $s .= "<div id=\"mw-hidden-catlinks\" class=\"$class\">" .
- wfMsgExt( 'hidden-categories', array( 'parsemag', 'escapenoentities' ), count( $allCats['hidden'] ) ) .
+ $s .= "<div id=\"mw-hidden-catlinks\" class=\"$class\">" .
+ wfMsgExt( 'hidden-categories', array( 'parsemag', 'escapenoentities' ), count( $allCats['hidden'] ) ) .
$colon . $embed . implode( "$pop $sep $embed", $allCats['hidden'] ) . $pop .
"</div>";
}
function getCategories() {
$catlinks=$this->getCategoryLinks();
-
+
$classes = 'catlinks';
-
+
if(FALSE === strpos($catlinks,'<div id="mw-normal-catlinks">')) {
$classes .= ' catlinks-allhidden';
}
-
+
if(!empty($catlinks)) {
return "<div id='catlinks' class='$classes'>{$catlinks}</div>";
}
/**
* This gets called shortly before the \</body\> tag.
- * @return String HTML to be put before \</body\>
+ * @return String HTML to be put before \</body\>
*/
function afterContent() {
$printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
/**
* 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() {
global $wgJsMimeType;
}
# Many people don't like this dropdown box
#$s .= $sep . $this->specialPagesList();
-
+
$s .= $this->variantLinks();
-
+
$s .= $this->extensionTabLinks();
return $s;
}
-
+
/**
* Compatibility for extensions adding functionality through tabs.
* Eventually these old skins should be replaced with SkinTemplate-based
}
return $s;
}
-
+
/**
* Language/charset variant links for classic-style skins
* @return string
function whatLinksHere() {
global $wgTitle;
- return $this->makeKnownLinkObj(
- SpecialPage::getTitleFor( 'Whatlinkshere', $wgTitle->getPrefixedDBkey() ),
+ return $this->makeKnownLinkObj(
+ SpecialPage::getTitleFor( 'Whatlinkshere', $wgTitle->getPrefixedDBkey() ),
wfMsg( 'whatlinkshere' ) );
}
function userContribsLink() {
global $wgTitle;
- return $this->makeKnownLinkObj(
+ return $this->makeKnownLinkObj(
SpecialPage::getTitleFor( 'Contributions', $wgTitle->getDBkey() ),
wfMsg( 'contributions' ) );
}
function emailUserLink() {
global $wgTitle;
- return $this->makeKnownLinkObj(
+ return $this->makeKnownLinkObj(
SpecialPage::getTitleFor( 'Emailuser', $wgTitle->getDBkey() ),
wfMsg( 'emailuser' ) );
}
if ( ! $wgOut->isArticleRelated() ) {
return '(' . wfMsg( 'notanarticle' ) . ')';
} else {
- return $this->makeKnownLinkObj(
- SpecialPage::getTitleFor( 'Recentchangeslinked', $wgTitle->getPrefixedDBkey() ),
+ return $this->makeKnownLinkObj(
+ SpecialPage::getTitleFor( 'Recentchangeslinked', $wgTitle->getPrefixedDBkey() ),
wfMsg( 'recentchangeslinked' ) );
}
}
if ( $wgTitle->getNamespace() == NS_SPECIAL ) {
return '';
}
-
+
# __NEWSECTIONLINK___ changes behaviour here
# If it's present, the link points to this page, otherwise
# it points to the talk page
} else {
$title = $wgTitle->getTalkPage();
}
-
+
return $this->makeKnownLinkObj( $title, wfMsg( 'postcomment' ), 'action=edit§ion=new' );
}
$key = wfMemcKey( 'sidebar' );
$cacheSidebar = $wgEnableSidebarCache &&
($wgLang->getCode() == $wgContLang->getCode());
-
+
if ($cacheSidebar) {
$cachedsidebar = $parserMemc->get( $key );
if ($cachedsidebar!="") {
wfProfileOut( $fname );
return $bar;
}
-
}
'href' => $href,
'active' => ( $href == $pageurl )
);
-
+
# We need to do an explicit check for Special:Contributions, as we
# have to match both the title, and the target (which could come
# from request values or be specified in "sub page" form. The plot
# thickens, because $wgTitle is altered for special pages, so doesn't
# contain the original alias-with-subpage.
$title = Title::newFromText( $wgRequest->getText( 'title' ) );
- if( $title instanceof Title && $title->getNamespace() == NS_SPECIAL ) {
+ if( $title instanceof Title && $title->getNamespace() == NS_SPECIAL ) {
list( $spName, $spPar ) =
SpecialPage::resolveAliasWithSubpage( $title->getText() );
$active = $spName == 'Contributions'
} else {
$active = false;
}
-
+
$href = self::makeSpecialUrlSubpage( 'Contributions', $this->username );
$personal_urls['mycontris'] = array(
'text' => wfMsg( 'mycontris' ),
global $wgContLang;
$text = $wgContLang->getFormattedNsText( MWNamespace::getSubject( $title->getNamespace() ) );
}
-
+
$result = array();
if( !wfRunHooks('SkinTemplateTabAction', array(&$this,
$title, $message, $selected, $checkEdit,
);
}
}
-
+
wfRunHooks( 'SkinTemplateTabs', array( &$this , &$content_actions ) ) ;
} else {
'href' => $wgTitle->getLocalURL( "oldid=$this->mRevisionId" )
);
}
-
+
// Copy in case this undocumented, shady hook tries to mess with internals
$revid = $this->mRevisionId;
wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink', array( &$this, &$nav_urls, &$revid, &$revid ) );
$nav_urls['contributions'] = array(
'href' => self::makeSpecialUrlSubpage( 'Contributions', $this->mTitle->getText() )
);
-
+
if( $id ) {
$logPage = SpecialPage::getTitleFor( 'Log' );
$nav_urls['log'] = array( 'href' => $logPage->getLocalUrl( 'user='
return ($msg != '-') && ($msg != ''); # ????
}
}
-
-
-
-
$navText = wfMsg( 'allmessagestext' );
# Make sure all extension messages are available
-
+
$wgMessageCache->loadAllMessages();
$sortedArray = array_merge( Language::getMessagesFor( 'en' ), $wgMessageCache->getExtensionMessagesFor( 'en' ) );
wfProfileIn( __METHOD__ . '-output' );
if ( $ot == 'php' ) {
$navText .= wfAllMessagesMakePhp( $messages );
- $wgOut->addHTML( 'PHP | <a href="' . $wgTitle->escapeLocalUrl( 'ot=html' ) . '">HTML</a> | ' .
- '<a href="' . $wgTitle->escapeLocalUrl( 'ot=xml' ) . '">XML</a>' .
+ $wgOut->addHTML( 'PHP | <a href="' . $wgTitle->escapeLocalUrl( 'ot=html' ) . '">HTML</a> | ' .
+ '<a href="' . $wgTitle->escapeLocalUrl( 'ot=xml' ) . '">XML</a>' .
'<pre>' . htmlspecialchars( $navText ) . '</pre>' );
} else if ( $ot == 'xml' ) {
$wgOut->disable();
header( 'Content-type: text/xml' );
echo wfAllMessagesMakeXml( $messages );
} else {
- $wgOut->addHTML( '<a href="' . $wgTitle->escapeLocalUrl( 'ot=php' ) . '">PHP</a> | ' .
+ $wgOut->addHTML( '<a href="' . $wgTitle->escapeLocalUrl( 'ot=php' ) . '">PHP</a> | ' .
'HTML | <a href="' . $wgTitle->escapeLocalUrl( 'ot=xml' ) . '">XML</a>' );
$wgOut->addWikiText( $navText );
$wgOut->addHTML( wfAllMessagesMakeHTMLText( $messages ) );
} else {
$talkLink = $sk->makeBrokenLinkObj( $talkPage, htmlspecialchars( $talk ) );
}
-
+
$anchor = 'msg_' . htmlspecialchars( strtolower( $title ) );
$anchor = "<a id=\"$anchor\" name=\"$anchor\"></a>";
wfProfileOut( __METHOD__ );
return $txt;
}
-
-
$wgOut->addHTML( '</p>' );
}
-
+
}
-
+
/**
* @param int $ns the namespace of the article
* @param string $text the name of the article
}
}
}
-
-?>
$app->doQuery( $offset, $limit );
}
-
-
if ( "" != $err ) {
$wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
- $wgOut->addHTML( Xml::tags( 'p', array( 'class' => 'error' ), $err ) );
+ $wgOut->addHTML( Xml::tags( 'p', array( 'class' => 'error' ), $err ) );
}
$scBlockExpiryOptions = wfMsgForContent( 'ipboptions' );
}
$reasonDropDown = Xml::listDropDown( 'wpBlockReasonList',
- wfMsgForContent( 'ipbreason-dropdown' ),
+ wfMsgForContent( 'ipbreason-dropdown' ),
wfMsgForContent( 'ipbreasonotherlist' ), '', 'wpBlockDropDown', 4 );
global $wgStylePath, $wgStyleVersion;
{$mIpbexpiry}
</td>
<td class='mw-input'>" .
- Xml::tags( 'select',
+ Xml::tags( 'select',
array(
'id' => 'wpBlockExpiry',
'name' => 'wpBlockExpiry',
$rxIP4 = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
$rxIP6 = '\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}';
$rxIP = "($rxIP4|$rxIP6)";
-
+
# Check for invalid specifications
if ( !preg_match( "/^$rxIP$/", $this->BlockAddress ) ) {
$matches = array();
}
}
}
-
global $wgRequest, $wgBlockOpenProxies, $wgOut, $wgProxyKey;
$ip = wfGetIP();
-
+
if( !$wgBlockOpenProxies || $wgRequest->getText( 'ip' ) != md5( $ip . $wgProxyKey ) ) {
$wgOut->addWikiMsg( 'proxyblocker-disabled' );
return;
$wgOut->addWikiMsg( "proxyblocksuccess" );
}
-
$wgOut->addHtml( '</ul>' );
return true;
}
-
+
/**
* Format a book source list item
*
$url = str_replace( '$1', $this->isbn, $url );
return '<li><a href="' . htmlspecialchars( $url ) . '">' . htmlspecialchars( $label ) . '</a></li>';
}
-
}
-
-
function formatResult( $skin, $result ) {
global $wgUser, $wgContLang;
-
+
$fromObj = Title::makeTitle( $result->namespace, $result->title );
if ( isset( $result->rd_title ) ) {
$toObj = Title::makeTitle( $result->rd_namespace, $result->rd_title );
$edit = $skin->makeKnownLinkObj( $fromObj, wfMsgHtml( 'brokenredirects-edit' ), 'action=edit' );
$to = $skin->makeBrokenLinkObj( $toObj );
$arr = $wgContLang->getArrow();
-
+
$out = "{$from} {$edit}";
-
+
if( $wgUser->isAllowed( 'delete' ) ) {
$delete = $skin->makeKnownLinkObj( $fromObj, wfMsgHtml( 'brokenredirects-delete' ), 'action=delete' );
$out .= " {$delete}";
}
-
+
$out .= " {$arr} {$to}";
return $out;
}
$sbr = new BrokenRedirectsPage();
return $sbr->doQuery( $offset, $limit );
-
}
-
global $wgOut;
$cap = new CategoryPager();
- $wgOut->addHTML(
+ $wgOut->addHTML(
wfMsgExt( 'categoriespagetext', array( 'parse' ) ) .
$cap->getNavigationBar()
. '<ul>' . $cap->getBody() . '</ul>' .
'conds' => array( 'cat_pages > 0' )
);
}
-
+
function getIndexField() {
# return array( 'abc' => 'cat_title', 'count' => 'cat_pages' );
return 'cat_title';
# return array( 'abc' => false, 'count' => true );
return false;
}
-
+
/* Override getBody to apply LinksBatch on resultset before actually outputting anything. */
public function getBody() {
if (!$this->mQueryDone) {
$this->doQuery();
}
$batch = new LinkBatch;
-
+
$this->mResult->rewind();
-
+
while ( $row = $this->mResult->fetchObject() ) {
$batch->addObj( Title::makeTitleSafe( NS_CATEGORY, $row->cat_title ) );
}
$this->mResult->rewind();
return parent::getBody();
}
-
+
function formatRow($result) {
global $wgLang;
$title = Title::makeTitle( NS_CATEGORY, $result->cat_title );
return Xml::tags('li', null, "$titleText ($count)" ) . "\n";
}
}
-
-
* @author Rob Church <robchur@gmail.com>
*/
class EmailConfirmation extends UnlistedSpecialPage {
-
+
/**
* Constructor
*/
public function __construct() {
parent::__construct( 'Confirmemail' );
}
-
+
/**
* Main execution point
*
$this->attemptConfirm( $code );
}
}
-
+
/**
* Show a nice form for the user to request a confirmation mail
*/
$wgOut->addWikiMsg( 'confirmemail_pending' );
}
$wgOut->addWikiMsg( 'confirmemail_text' );
- $self = SpecialPage::getTitleFor( 'Confirmemail' );
+ $self = SpecialPage::getTitleFor( 'Confirmemail' );
$form = wfOpenElement( 'form', array( 'method' => 'post', 'action' => $self->getLocalUrl() ) );
$form .= wfHidden( 'token', $wgUser->editToken() );
$form .= wfSubmitButton( wfMsgHtml( 'confirmemail_send' ) );
$form .= wfCloseElement( 'form' );
$wgOut->addHtml( $form );
- }
+ }
}
-
+
/**
* Attempt to confirm the user's email address and show success or failure
* as needed; if successful, take the user to log in
$wgOut->addWikiMsg( 'confirmemail_invalid' );
}
}
-
+
}
/**
- * Special page allows users to cancel an email confirmation using the e-mail
+ * Special page allows users to cancel an email confirmation using the e-mail
* confirmation code
*
* @addtogroup SpecialPage
*/
class EmailInvalidation extends UnlistedSpecialPage {
-
+
public function __construct() {
parent::__construct( 'Invalidateemail' );
}
-
+
function execute( $code ) {
$this->setHeaders();
$this->attemptInvalidate( $code );
}
-
+
/**
* Attempt to invalidate the user's email address and show success or failure
* as needed; if successful, link to main page
} else {
$wgOut->addWikiMsg( 'confirmemail_invalid' );
}
- }
+ }
}
}
$this->target = $target;
$this->namespace = $namespace;
-
+
$year = intval($year);
$month = intval($month);
-
+
$this->year = ($year > 0 && $year < 10000) ? $year : false;
$this->month = ($month > 0 && $month < 13) ? $month : false;
$this->getDateCond();
-
+
$this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
}
return array(
'tables' => array( 'page', 'revision' ),
- 'fields' => array(
- 'page_namespace', 'page_title', 'page_is_new', 'page_latest', 'rev_id', 'rev_page',
- 'rev_text_id', 'rev_timestamp', 'rev_comment', 'rev_minor_edit', 'rev_user',
+ 'fields' => array(
+ 'page_namespace', 'page_title', 'page_is_new', 'page_latest', 'rev_id', 'rev_page',
+ 'rev_text_id', 'rev_timestamp', 'rev_comment', 'rev_minor_edit', 'rev_user',
'rev_user_text', 'rev_parent_id', 'rev_deleted'
),
'conds' => $conds,
return array();
}
}
-
+
function getDateCond() {
if ( $this->year || $this->month ) {
// Assume this year if only a month is given
$year_start--;
}
}
-
+
if ( $this->month ) {
$month_end = str_pad($this->month + 1, 2, '0', STR_PAD_LEFT);
$year_end = $year_start;
$comment = $wgContLang->getDirMark() . $sk->revComment( $rev, false, true );
$d = $wgLang->timeanddate( wfTimestamp( TS_MW, $row->rev_timestamp ), true );
-
+
if( $this->target == 'newbies' ) {
$userlink = ' . . ' . $sk->userLink( $row->rev_user, $row->rev_user_text );
$userlink .= ' (' . $sk->userTalkLink( $row->rev_user, $row->rev_user_text ) . ') ';
if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
$d = '<span class="history-deleted">' . $d . '</span>';
}
-
+
if( $rev->getParentId() === 0 ) {
$nflag = '<span class="newpage">' . $this->messages['newpageletter'] . '</span>';
} else {
wfProfileOut( __METHOD__ );
return $ret;
}
-
+
/**
* Get the Database object in use
*
public function getDatabase() {
return $this->mDb;
}
-
+
}
/**
global $wgUser, $wgOut, $wgLang, $wgRequest;
$options = array();
-
+
if ( isset( $par ) && $par == 'newbies' ) {
$target = 'newbies';
$options['contribs'] = 'newbie';
} else {
$wgOut->setSubtitle( wfMsgHtml( 'sp-contributions-newbies-sub') );
}
-
+
if ( ( $ns = $wgRequest->getVal( 'namespace', null ) ) !== null && $ns !== '' ) {
$options['namespace'] = intval( $ns );
} else {
if ( $wgUser->isAllowed( 'markbotedit' ) && $wgRequest->getBool( 'bot' ) ) {
$options['bot'] = '1';
}
-
+
$skip = $wgRequest->getText( 'offset' ) || $wgRequest->getText( 'dir' ) == 'prev';
# Offset overrides year/month selection
if ( ( $month = $wgRequest->getIntOrNull( 'month' ) ) !== null && $month !== -1 ) {
if( ( $lag = $pager->getDatabase()->getLag() ) > 0 )
$wgOut->showLagWarning( $lag );
- $wgOut->addHTML(
+ $wgOut->addHTML(
'<p>' . $pager->getNavigationBar() . '</p>' .
$pager->getBody() .
'<p>' . $pager->getNavigationBar() . '</p>' );
-
+
# If there were contributions, and it was a valid user or IP, show
# the appropriate "footer" message - WHOIS tools, etc.
if( $target != 'newbies' ) {
- $message = IP::isIPAddress( $target )
+ $message = IP::isIPAddress( $target )
? 'sp-contributions-footer-anon'
: 'sp-contributions-footer';
if ( !isset( $options['contribs'] ) ) {
$options['contribs'] = 'user';
}
-
+
if ( !isset( $options['year'] ) ) {
$options['year'] = '';
}
'</span>' .
Xml::submitButton( wfMsg( 'sp-contributions-submit' ) ) .
Xml::closeElement( 'p' );
-
+
$explain = wfMsgExt( 'sp-contributions-explain', 'parseinline' );
if( !wfEmptyMsg( 'sp-contributions-explain', $explain ) )
$f .= "<p>{$explain}</p>";
-
+
$f .= '</fieldset>' .
Xml::closeElement( 'form' );
return $f;
return $depp->doQuery( $offset, $limit );
}
-
-
return $sd->doQuery( $offset, $limit );
}
-
}
function getSQLText( &$dbr, $namespace = null, $title = null ) {
-
+
list( $page, $redirect ) = $dbr->tableNamesN( 'page', 'redirect' );
$limitToTitle = !( $namespace === null && $title === null );
return $sql;
}
-
+
function getSQL() {
$dbr = wfGetDB( DB_SLAVE );
return $this->getSQLText( $dbr );
function formatResult( $skin, $result ) {
global $wgContLang;
-
+
$fname = 'DoubleRedirectsPage::formatResult';
$titleA = Title::makeTitle( $result->namespace, $result->title );
return $sdr->doQuery( $offset, $limit );
}
-
if ( "success" == $action ) {
$f->showSuccess( $nu );
} else if ( "submit" == $action && $wgRequest->wasPosted() &&
- $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) )
+ $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) )
{
# Check against the rate limiter
if( $wgUser->pingLimiter( 'emailuser' ) ) {
$subject = $this->subject;
if( wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$this->text ) ) ) {
-
+
if( $wgUserEmailUseReplyTo ) {
// Put the generic wiki autogenerated address in the From:
// header and reserve the user for Reply-To.
$mailFrom = $from;
$replyTo = null;
}
-
+
$this->text .= wfMsgForContent( 'emailuser-footer' );
$mailResult = UserMailer::send( $to, $mailFrom, $subject, $this->text, $replyTo );
$wgOut->addHTML( wfMsg( "usermailererror" ) .
' ' . htmlspecialchars( $mailResult->getMessage() ) );
} else {
-
+
// if the user requested a copy of this mail, do this now,
// unless they are emailing themselves, in which case one copy of the message is sufficient.
if ($this->cc_me && $to != $from) {
if( wfRunHooks( 'EmailUser', array( &$from, &$from, &$cc_subject, &$this->text ) ) ) {
$ccResult = UserMailer::send( $from, $from, $cc_subject, $this->text );
if( WikiError::isError( $ccResult ) ) {
- // At this stage, the user's CC mail has failed, but their
+ // At this stage, the user's CC mail has failed, but their
// original mail has succeeded. It's unlikely, but still, what to do?
// We can either show them an error, or we can say everything was fine,
- // or we can say we sort of failed AND sort of succeeded. Of these options,
+ // or we can say we sort of failed AND sort of succeeded. Of these options,
// simply saying there was an error is probably best.
$wgOut->addHTML( wfMsg( "usermailererror" ) .
' ' . htmlspecialchars( $ccResult->getMessage() ) );
}
}
}
-
+
$titleObj = SpecialPage::getTitleFor( "Emailuser" );
$encTarget = wfUrlencode( $this->target->getName() );
$wgOut->redirect( $titleObj->getFullURL( "target={$encTarget}&action=success" ) );
*/
function wfExportGetTemplates( $inputPages, $pageSet ) {
return wfExportGetLinks( $inputPages, $pageSet,
- 'templatelinks',
+ 'templatelinks',
array( 'tl_namespace AS namespace', 'tl_title AS title' ),
array( 'page_id=tl_from' ) );
}
if ( $wgRequest->getCheck( 'addcat' ) ) {
$page = $wgRequest->getText( 'pages' );
$catname = $wgRequest->getText( 'catname' );
-
+
if ( $catname !== '' && $catname !== NULL && $catname !== false ) {
$t = Title::makeTitleSafe( NS_CATEGORY, $catname );
if ( $t ) {
$history['dir'] = 'desc';
}
}
-
+
if( $page != '' ) $doexport = true;
} else {
// Default to current-only for GET requests
} else {
$history = WikiExporter::CURRENT;
}
-
+
if( $page != '' ) $doexport = true;
}
// Override
$history = WikiExporter::CURRENT;
}
-
+
$list_authors = $wgRequest->getCheck( 'listauthors' );
if ( !$curonly || !$wgExportAllowListContributors ) $list_authors = false ;
-
+
if ( $doexport ) {
$wgOut->disable();
-
+
// Cancel output buffering and gzipping if set
// This should provide safer streaming for pages with history
wfResetOutputBuffers();
$filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' );
$wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
}
-
+
/* Split up the input and look up linked pages */
$inputPages = array_filter( explode( "\n", $page ), 'wfFilterPage' );
$pageSet = array_flip( $inputPages );
$pageSet = wfExportGetImages( $inputPages, $pageSet );
}
*/
-
+
$pages = array_keys( $pageSet );
-
+
/* Ok, let's get to it... */
$db = wfGetDB( DB_SLAVE );
$exporter = new WikiExporter( $db, $history );
$exporter->list_authors = $list_authors ;
$exporter->openStream();
-
+
foreach( $pages as $page ) {
/*
if( $wgExportMaxHistory && !$curonly ) {
$exporter->pageByTitle( $title );
}
-
+
$exporter->closeStream();
return;
}
$self = SpecialPage::getTitleFor( 'Export' );
$wgOut->addHtml( wfMsgExt( 'exporttext', 'parse' ) );
-
+
$form = Xml::openElement( 'form', array( 'method' => 'post',
'action' => $self->getLocalUrl( 'action=submit' ) ) );
-
+
$form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . ' ';
$form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />';
-
+
$form .= Xml::openElement( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ) );
$form .= htmlspecialchars( $page );
$form .= Xml::closeElement( 'textarea' );
$form .= '<br />';
-
+
if( $wgExportAllowHistory ) {
$form .= Xml::checkLabel( wfMsg( 'exportcuronly' ), 'curonly', 'curonly', true ) . '<br />';
} else {
// Enable this when we can do something useful exporting/importing image information. :)
//$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />';
$form .= Xml::checkLabel( wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', true ) . '<br />';
-
+
$form .= Xml::submitButton( wfMsg( 'export-submit' ) );
$form .= Xml::closeElement( 'form' );
$wgOut->addHtml( $form );
-}
\ No newline at end of file
+}
$frp = new FewestrevisionsPage();
$frp->doQuery( $offset, $limit );
}
-
-
if( $thumb ) {
$wgOut->addHTML( '<div style="float:' . $align . '" id="mw-fileduplicatesearch-icon">' .
$thumb->toHtml( array( 'desc-link' => false ) ) . '<br />' .
- wfMsgExt( 'fileduplicatesearch-info', array( 'parse' ),
+ wfMsgExt( 'fileduplicatesearch-info', array( 'parse' ),
$wgLang->formatNum( $img->getWidth() ),
$wgLang->formatNum( $img->getHeight() ),
$wgLang->formatSize( $img->getSize() ),
# Cache messages used in each row
$this->mMessages['imgdesc'] = wfMsgHtml( 'imgdesc' );
$this->mMessages['imgfile'] = wfMsgHtml( 'imgfile' );
-
+
return parent::getStartBody();
}
return "$link ($download)";
case 'img_user_text':
if ( $this->mCurrentRow->img_user ) {
- $link = $this->getSkin()->makeLinkObj( Title::makeTitle( NS_USER, $value ),
+ $link = $this->getSkin()->makeLinkObj( Title::makeTitle( NS_USER, $value ),
htmlspecialchars( $value ) );
} else {
$link = htmlspecialchars( $value );
return 'imagelist_sort ' . parent::getSortHeaderClass();
}
}
-
-
if( $wgUser->isAllowed( 'importupload' ) ) {
$wgOut->addWikiMsg( "importtext" );
- $wgOut->addHTML(
+ $wgOut->addHTML(
Xml::openElement( 'fieldset' ).
Xml::element( 'legend', null, wfMsg( 'upload' ) ) .
Xml::openElement( 'form', array( 'enctype' => 'multipart/form-data', 'method' => 'post', 'action' => $action ) ) .
Xml::hidden( 'action', 'submit' ) .
Xml::hidden( 'source', 'upload' ) .
Xml::input( 'xmlimport', 50, '', array( 'type' => 'file' ) ) . ' ' .
- Xml::submitButton( wfMsg( 'uploadbtn' ) ) .
+ Xml::submitButton( wfMsg( 'uploadbtn' ) ) .
Xml::closeElement( 'form' ) .
Xml::closeElement( 'fieldset' )
);
<td>
</td>
<td>" .
- Xml::submitButton( wfMsg( 'import-interwiki-submit' ) ) .
+ Xml::submitButton( wfMsg( 'import-interwiki-submit' ) ) .
"</td>
</tr>" .
Xml::closeElement( 'table' ).
function setMinor( $minor ) {
$this->minor = (bool)$minor;
}
-
+
function setSrc( $src ) {
$this->src = $src;
}
-
+
function setFilename( $filename ) {
$this->filename = $filename;
}
-
+
function setSize( $size ) {
$this->size = intval( $size );
}
function getMinor() {
return $this->minor;
}
-
+
function getSrc() {
return $this->src;
}
-
+
function getFilename() {
return $this->filename;
}
-
+
function getSize() {
return $this->size;
}
return true;
}
-
+
function importUpload() {
wfDebug( __METHOD__ . ": STUB\n" );
-
+
/**
// from file revert...
$source = $this->file->getArchiveVirtualUrl( $this->oldimage );
$status = $this->file->upload( $source, $comment, $comment );
if( $status->isGood() ) {
*/
-
+
/**
// from file upload...
$this->mLocalFile = wfLocalFile( $nt );
if ( !$status->isGood() ) {
$resultDetails = array( 'internal' => $status->getWikiText() );
*/
-
+
// @fixme upload() uses $wgUser, which is wrong here
// it may also create a page without our desire, also wrong potentially.
// and, it will record a *current* upload, but we might want an archive version here
-
+
$file = wfLocalFile( $this->getTitle() );
if( !$file ) {
var_dump( $file );
wfDebug( "IMPORT: Bad file. :(\n" );
return false;
}
-
+
$source = $this->downloadSource();
if( !$source ) {
wfDebug( "IMPORT: Could not fetch remote file. :(\n" );
return false;
}
-
+
$status = $file->upload( $source,
$this->getComment(),
$this->getComment(), // Initial page, if none present...
File::DELETE_SOURCE,
false, // props...
$this->getTimestamp() );
-
+
if( $status->isGood() ) {
// yay?
wfDebug( "IMPORT: is ok?\n" );
return true;
}
-
+
wfDebug( "IMPORT: is bad? " . $status->getXml() . "\n" );
return false;
}
-
+
function downloadSource() {
global $wgEnableUploads;
if( !$wgEnableUploads ) {
return false;
}
-
+
$tempo = tempnam( wfTempDir(), 'download' );
$f = fopen( $tempo, 'wb' );
if( !$f ) {
wfDebug( "IMPORT: couldn't write to temp file $tempo\n" );
return false;
}
-
+
// @fixme!
$src = $this->getSrc();
$data = Http::get( $src );
unlink( $tempo );
return false;
}
-
+
fwrite( $f, $data );
fclose( $f );
-
+
return $tempo;
}
$wgOut->addHTML( "<li>" . htmlspecialchars( $data ) . "</li>\n" );
}
}
-
+
/**
* Set debug mode...
*/
$this->mRevisionCallback = $callback;
return $previous;
}
-
+
/**
* Sets the action to perform as each file upload version is reached.
* @param callable callback
$dbw = wfGetDB( DB_MASTER );
return $dbw->deadlockLoop( array( $revision, 'importOldRevision' ) );
}
-
+
/**
* Dummy for now...
*/
}
$this->appendfield = "";
$this->appenddata = "";
-
+
$parent = $this->parentTag();
xml_set_element_handler( $parser, "in_$parent", "out_$parent" );
xml_set_character_data_handler( $parser, "donothing" );
}
}
}
-
+
function in_upload( $parser, $name, $attribs ) {
$this->debug( "in_upload $name" );
switch( $name ) {
return $this->throwXMLerror( "Element <$name> not allowed in an <upload>." );
}
}
-
+
function out_upload( $parser, $name ) {
$this->debug( "out_revision $name" );
$this->pop();
return $this->throwXMLerror( "Expected </upload>, got </$name>" );
}
xml_set_element_handler( $parser, "in_page", "out_page" );
-
+
if( $this->workRevision ) {
$ok = call_user_func_array( $this->mUploadCallback,
array( $this->workRevision, $this ) );
$parent = $this->parentTag();
xml_set_element_handler( $parser, "in_$parent", "out_$parent" );
}
-
+
private function push( $name ) {
array_push( $this->tagStack, $name );
$this->debug( "PUSH $name" );
}
-
+
private function pop() {
$name = array_pop( $this->tagStack );
$this->debug( "POP $name" );
return $name;
}
-
+
private function parentTag() {
$name = $this->tagStack[count( $this->tagStack ) - 1];
$this->debug( "PARENT $name" );
}
if( !empty( $upload['error'] ) ) {
switch($upload['error']){
- case 1: # The uploaded file exceeds the upload_max_filesize directive in php.ini.
+ case 1: # The uploaded file exceeds the upload_max_filesize directive in php.ini.
return new WikiErrorMsg( 'importuploaderrorsize' );
case 2: # The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
return new WikiErrorMsg( 'importuploaderrorsize' );
return new WikiErrorMsg( 'importuploaderrortemp' );
# case else: # Currently impossible
}
-
+
}
$fname = $upload['tmp_name'];
if( is_uploaded_file( $fname ) ) {
public static function newFromInterwiki( $interwiki, $page, $history=false ) {
if( $page == '' ) {
return new WikiErrorMsg( 'import-noarticle' );
- }
+ }
$link = Title::newFromText( "$interwiki:Special:Export/$page" );
if( is_null( $link ) || $link->getInterwiki() == '' ) {
return new WikiErrorMsg( 'importbadinterwiki' );
*/
function wfSpecialIpblocklist() {
global $wgUser, $wgOut, $wgRequest;
-
+
$ip = $wgRequest->getVal( 'wpUnblockAddress', $wgRequest->getVal( 'ip' ) );
$id = $wgRequest->getVal( 'id' );
$reason = $wgRequest->getText( 'wpUnblockReason' );
</tr>
<tr>
<td align='$alignRight'>" .
- Xml::label( wfMsg( 'ipbreason' ), 'wpUnblockReason' ) .
+ Xml::label( wfMsg( 'ipbreason' ), 'wpUnblockReason' ) .
"</td>
<td>" .
Xml::input( 'wpUnblockReason', 40, $this->reason, array( 'type' => 'text', 'tabindex' => '2' ) ) .
$ip = $block->getRedactedName();
} else {
$block = Block::newFromDB( $ip );
- if ( !$block ) {
+ if ( !$block ) {
return array('ipb_cant_unblock', htmlspecialchars($id));
}
if( $block->mRangeStart != $block->mRangeEnd
$target = $sk->userLink( $block->mUser, $block->mAddress )
. $sk->userToolLinks( $block->mUser, $block->mAddress, false, Linker::TOOL_LINKS_NOBLOCK );
}
-
+
$formattedTime = $wgLang->timeanddate( $block->mTimestamp, true );
$properties = array();
$titleObj = SpecialPage::getTitleFor( "Ipblocklist" );
$unblocklink = ' (' . $sk->makeKnownLinkObj($titleObj, $msg['unblocklink'], 'action=unblock&id=' . urlencode( $block->mId ) ) . ')';
}
-
+
$comment = $sk->commentBlock( $block->mReason );
-
- $s = "{$line} $comment";
+
+ $s = "{$line} $comment";
if ( $block->mHideName )
$s = '<span class="history-deleted">' . $s . '</span>';
-
+
wfProfileOut( __METHOD__ );
return "<li>$s $unblocklink</li>\n";
}
wfProfileOut( __METHOD__ );
return '';
}
-
+
function formatRow( $row ) {
$block = new Block;
$block->initFromRow( $row );
return 'ipb_timestamp';
}
}
-
-
</tr>'
);
}
- $wgOut->addHTML(
+ $wgOut->addHTML(
Xml::closeElement( 'table' ) . "\n"
);
}
function formatResult( $skin, $result ) {
global $wgContLang;
-
+
# Make a link to the redirect itself
$rd_title = Title::makeTitle( $result->namespace, $result->title );
$rd_link = $skin->makeLinkObj( $rd_title, '', 'redirect=no' );
return "<s>$rd_link</s>";
}
}
-
}
function wfSpecialListredirects() {
$lrp = new ListredirectsPage();
$lrp->doQuery( $offset, $limit );
}
-
-
'tables' => " $user LEFT JOIN $user_groups ON user_id=ug_user LEFT JOIN $ipblocks ON user_id=ipb_user AND ipb_auto=0 ",
'fields' => array('user_name',
'MAX(user_id) AS user_id',
- 'COUNT(ug_group) AS numgroups',
+ 'COUNT(ug_group) AS numgroups',
'MAX(ug_group) AS singlegroup'),
- 'options' => array('GROUP BY' => 'user_name'),
+ 'options' => array('GROUP BY' => 'user_name'),
'conds' => $conds
);
} else {
$groups = '';
}
-
+
$item = wfSpecialList( $name, $groups );
wfRunHooks( 'SpecialListusersFormatRow', array( &$item, $row ) );
return "<li>{$item}</li>";
$wgOut->permissionRequired( 'siteadmin' );
return;
}
-
+
# If the lock file isn't writable, we can do sweet bugger all
global $wgReadOnlyFile;
if( !is_writable( dirname( $wgReadOnlyFile ) ) ) {
$wgOut->setSubtitle( wfMsg( 'lockdbsuccesssub' ) );
$wgOut->addWikiMsg( 'lockdbsuccesstext' );
}
-
+
public static function notWritable() {
global $wgOut;
$wgOut->showErrorPage( 'lockdb', 'lockfilenotwritable' );
}
-
}
-
-
# Set title and add header
$loglist->showHeader( $pager->getType() );
# Show form options
- $loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(),
+ $loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(),
$pager->getYear(), $pager->getMonth() );
# Insert list
$logBody = $pager->getBody();
if( $logBody ) {
$wgOut->addHTML(
- $pager->getNavigationBar() .
+ $pager->getNavigationBar() .
$loglist->beginLogEventsList() .
$logBody .
$loglist->endLogEventsList() .
$wgOut->addWikiMsg( 'logempty' );
}
}
-
return $lpp->doQuery( $offset, $limit );
}
-
-
$lpp->doQuery( $offset, $limit );
}
-
-
<?php
/**
- * Special page allowing users with the appropriate permissions to
+ * Special page allowing users with the appropriate permissions to
* merge article histories, with some restrictions
*
* @addtogroup SpecialPage
function MergehistoryForm( $request, $par = "" ) {
global $wgUser;
-
+
$this->mAction = $request->getVal( 'action' );
$this->mTarget = $request->getVal( 'target' );
$this->mDest = $request->getVal( 'dest' );
$this->mSubmitted = $request->getBool( 'submitted' );
-
+
$this->mTargetID = intval( $request->getVal( 'targetID' ) );
$this->mDestID = intval( $request->getVal( 'destID' ) );
$this->mTimestamp = $request->getVal( 'mergepoint' );
$this->mTimestamp = '';
}
$this->mComment = $request->getText( 'wpComment' );
-
+
$this->mMerge = $request->wasPosted() && $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
// target page
if( $this->mSubmitted ) {
$this->mTargetObj = null;
$this->mDestObj = null;
}
-
+
$this->preCacheMessages();
}
-
+
/**
* As we use the same small set of messages in various methods and that
* they are called often, we call them once and save them in $this->message
function execute() {
global $wgOut, $wgUser;
-
+
$wgOut->setPagetitle( wfMsgHtml( "mergehistory" ) );
-
+
if( $this->mTargetID && $this->mDestID && $this->mAction=="submit" && $this->mMerge ) {
return $this->merge();
}
function showMergeForm() {
global $wgOut, $wgScript;
-
+
$wgOut->addWikiMsg( 'mergehistory-header' );
-
+
$wgOut->addHtml(
Xml::openElement( 'form', array(
'method' => 'get',
wfMsg( 'mergehistory-box' ) ) .
Xml::hidden( 'title',
SpecialPage::getTitleFor( 'Mergehistory' )->getPrefixedDbKey() ) .
- Xml::hidden( 'submitted', '1' ) .
- Xml::hidden( 'mergepoint', $this->mTimestamp ) .
+ Xml::hidden( 'submitted', '1' ) .
+ Xml::hidden( 'mergepoint', $this->mTimestamp ) .
Xml::openElement( 'table' ) .
"<tr>
<td>".Xml::label( wfMsg( 'mergehistory-from' ), 'target' )."</td>
global $wgLang, $wgContLang, $wgUser, $wgOut;
$this->sk = $wgUser->getSkin();
-
+
$wgOut->setPagetitle( wfMsg( "mergehistory" ) );
$this->showMergeForm();
# Show relevant lines from the deletion log:
$wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'merge' ) ) . "</h2>\n" );
LogEventsList::showLogExtract( $wgOut, 'merge', $this->mTargetObj->getPrefixedText() );
-
+
# When we submit, go by page ID to avoid some nasty but unlikely collisions.
# Such would happen if a page was renamed after the form loaded, but before submit
$misc = Xml::hidden( 'targetID', $this->mTargetObj->getArticleID() );
return true;
}
-
+
function formatRevisionRow( $row ) {
global $wgUser, $wgLang;
-
+
$rev = new Revision( $row );
-
- $stxt = '';
+
+ $stxt = '';
$last = $this->message['last'];
-
+
$ts = wfTimestamp( TS_MW, $row->rev_timestamp );
$checkBox = wfRadio( "mergepoint", $ts, false );
-
- $pageLink = $this->sk->makeKnownLinkObj( $rev->getTitle(),
+
+ $pageLink = $this->sk->makeKnownLinkObj( $rev->getTitle(),
htmlspecialchars( $wgLang->timeanddate( $ts ) ), 'oldid=' . $rev->getID() );
if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
$pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
}
-
+
# Last link
if( !$rev->userCan( Revision::DELETED_TEXT ) )
$last = $this->message['last'];
else if( isset($this->prevId[$row->rev_id]) )
- $last = $this->sk->makeKnownLinkObj( $rev->getTitle(), $this->message['last'],
+ $last = $this->sk->makeKnownLinkObj( $rev->getTitle(), $this->message['last'],
"diff=" . $row->rev_id . "&oldid=" . $this->prevId[$row->rev_id] );
-
+
$userLink = $this->sk->revUserTools( $rev );
-
+
if(!is_null($size = $row->rev_len)) {
if($size == 0)
$stxt = wfMsgHtml('historyempty');
$stxt = wfMsgHtml('historysize', $wgLang->formatNum( $size ) );
}
$comment = $this->sk->revComment( $rev );
-
+
return "<li>$checkBox ($last) $pageLink . . $userLink $stxt $comment</li>";
}
*/
function getPageLink( $row, $titleObj, $ts, $target ) {
global $wgLang;
-
+
if( !$this->userCan($row, Revision::DELETED_TEXT) ) {
return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
} else {
- $link = $this->sk->makeKnownLinkObj( $titleObj,
+ $link = $this->sk->makeKnownLinkObj( $titleObj,
$wgLang->timeanddate( $ts, true ), "target=$target×tamp=$ts" );
if( $this->isDeleted($row, Revision::DELETED_TEXT) )
$link = '<span class="history-deleted">' . $link . '</span>';
function merge() {
global $wgOut, $wgUser;
- # Get the titles directly from the IDs, in case the target page params
- # were spoofed. The queries are done based on the IDs, so it's best to
+ # Get the titles directly from the IDs, in case the target page params
+ # were spoofed. The queries are done based on the IDs, so it's best to
# keep it consistent...
$targetTitle = Title::newFromID( $this->mTargetID );
$destTitle = Title::newFromID( $this->mDestID );
return false;
}
# Get the latest timestamp of the source
- $lasttimestamp = $dbw->selectField( array('page','revision'),
+ $lasttimestamp = $dbw->selectField( array('page','revision'),
'rev_timestamp',
array('page_id' => $this->mTargetID, 'page_latest = rev_id' ),
__METHOD__ );
array( 'rev_page' => $this->mTargetID,
$timewhere ),
__METHOD__ );
-
+
$count = $dbw->affectedRows();
# Make the source page a redirect if no revisions are left
- $haveRevisions = $dbw->selectField( 'revision',
+ $haveRevisions = $dbw->selectField( 'revision',
'rev_timestamp',
array( 'rev_page' => $this->mTargetID ),
__METHOD__,
array( 'FOR UPDATE' ) );
if( !$haveRevisions ) {
if( $this->mComment ) {
- $comment = wfMsgForContent( 'mergehistory-comment', $targetTitle->getPrefixedText(),
+ $comment = wfMsgForContent( 'mergehistory-comment', $targetTitle->getPrefixedText(),
$destTitle->getPrefixedText(), $this->mComment );
} else {
- $comment = wfMsgForContent( 'mergehistory-autocomment', $targetTitle->getPrefixedText(),
+ $comment = wfMsgForContent( 'mergehistory-autocomment', $targetTitle->getPrefixedText(),
$destTitle->getPrefixedText() );
}
$mwRedir = MagicWord::get( 'redirect' );
}
# Update our logs
$log = new LogPage( 'merge' );
- $log->addEntry( 'merge', $targetTitle, $this->mComment,
+ $log->addEntry( 'merge', $targetTitle, $this->mComment,
array($destTitle->getPrefixedText(),$TimestampLimit) );
-
+
$wgOut->addHtml( wfMsgExt( 'mergehistory-success', array('parseinline'),
$targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count ) );
-
+
wfRunHooks( 'ArticleMergeComplete', array( $targetTitle, $destTitle ) );
-
+
return true;
}
}
$this->mConds = $conds;
$this->title = $source;
$this->articleID = $source->getArticleID();
-
+
$dbr = wfGetDB( DB_SLAVE );
$maxtimestamp = $dbr->selectField( 'revision', 'MIN(rev_timestamp)',
array('rev_page' => $dest->getArticleID() ),
__METHOD__ );
- $this->maxTimestamp = $maxtimestamp;
-
+ $this->maxTimestamp = $maxtimestamp;
+
parent::__construct();
}
-
+
function getStartBody() {
wfProfileIn( __METHOD__ );
# Do a link batch query
while( $row = $this->mResult->fetchObject() ) {
$batch->addObj( Title::makeTitleSafe( NS_USER, $row->rev_user_text ) );
$batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->rev_user_text ) );
-
+
$rev_id = isset($rev_id) ? $rev_id : $row->rev_id;
if( $rev_id > $row->rev_id )
$this->mForm->prevId[$rev_id] = $row->rev_id;
else if( $rev_id < $row->rev_id )
$this->mForm->prevId[$row->rev_id] = $rev_id;
-
+
$rev_id = $row->rev_id;
}
-
+
$batch->execute();
$this->mResult->seek( 0 );
wfProfileOut( __METHOD__ );
return '';
}
-
+
function formatRow( $row ) {
$block = new Block;
return $this->mForm->formatRevisionRow( $row );
$conds = $this->mConds;
$conds['rev_page'] = $this->articleID;
$conds[] = "rev_timestamp < {$this->maxTimestamp}";
-
+
return array(
'tables' => array('revision'),
- 'fields' => array( 'rev_minor_edit', 'rev_timestamp', 'rev_user', 'rev_user_text', 'rev_comment',
+ 'fields' => array( 'rev_minor_edit', 'rev_timestamp', 'rev_user', 'rev_user_text', 'rev_comment',
'rev_id', 'rev_page', 'rev_text_id', 'rev_len', 'rev_deleted' ),
'conds' => $conds
);
$wpp->doQuery( $offset, $limit );
}
-
-
function getCellHtml( $row ) {
global $wgLang;
- return wfMsgExt( 'nlinks', array( 'parsemag', 'escape' ),
+ return wfMsgExt( 'nlinks', array( 'parsemag', 'escape' ),
$wgLang->formatNum( $row->value ) ) . '<br />';
}
$wpp->doQuery( $offset, $limit );
}
-
-
$wpp->doQuery( $offset, $limit );
}
-
-
$wpp->doQuery( $offset, $limit );
}
-
-
$wpp->doQuery( $offset, $limit );
}
-
-
$wgOut->addHTML( "
<tr>
<td></td>
- <td>" .
- Xml::checkLabel( wfMsg( 'movetalk' ), 'wpMovetalk', 'wpMovetalk', $moveTalkChecked ) .
+ <td>" .
+ Xml::checkLabel( wfMsg( 'movetalk' ), 'wpMovetalk', 'wpMovetalk', $moveTalkChecked ) .
"</td>
</tr>"
);
# Delete to make way if requested
if ( $wgUser->isAllowed( 'delete' ) && $this->deleteAndMove ) {
$article = new Article( $nt );
-
+
# Disallow deletions of big articles
$bigHistory = $article->isBigDeletion();
if( $bigHistory && !$nt->userCan( 'bigdelete' ) ) {
$this->showForm( array('delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
return;
}
-
+
// This may output an error message and exit
$article->doDelete( wfMsgForContent( 'delete_and_move_reason' ) );
}
$wgOut->addWikiMsg( 'noimages' );
}
}
-
-
*/
function wfSpecialNewPages( $par ) {
$page = new NewPagesForm();
-
+
$page->showList( $par );
}
/* int */ 'limit' => 50,
);
$options = $defaults;
-
+
// Override all values from requests, if specified
foreach ( $defaults as $v => $t ) {
if ( is_bool($t) ) {
$options[$v] = $wgRequest->getText( $v, $options[$v] );
}
}
-
+
$wgOut->setSyndicated( true );
$wgOut->setFeedAppendQuery( "namespace={$options['namespace']}&username={$options['username']}" );
$wgOut->addHTML( $form );
- $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
- $options['hidepatrolled'], $options['hidebots'], $options['username'] );
+ $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
+ $options['hidepatrolled'], $options['hidebots'], $options['username'] );
if( $pager->getNumRows() ) {
$wgOut->addHTML( $pager->getNavigationBar() .
$wgOut->addHTML( '<p>' . wfMsgHtml( 'specialpage-empty' ) . '</p>' );
}
}
-
+
/**
* Format a row, providing the timestamp, links to the page/history, size, user links, and a comment
*
public function formatRow( $result ) {
global $wgLang, $wgContLang, $wgUser;
$dm = $wgContLang->getDirMark();
-
+
static $skin=null;
if( is_null( $skin ) )
$time = $wgLang->timeAndDate( $result->rc_timestamp, true );
$plink = $skin->makeKnownLinkObj( $title, '', $this->patrollable( $result ) ? 'rcid=' . $result->rc_id : '' );
$hist = $skin->makeKnownLinkObj( $title, wfMsgHtml( 'hist' ), 'action=history' );
- $length = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ),
+ $length = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ),
$wgLang->formatNum( htmlspecialchars( $result->length ) ) );
- $ulink = $skin->userLink( $result->rc_user, $result->rc_user_text ) . ' ' .
+ $ulink = $skin->userLink( $result->rc_user, $result->rc_user_text ) . ' ' .
$skin->userToolLinks( $result->rc_user, $result->rc_user_text );
$comment = $skin->commentBlock( $result->rc_comment );
$css = $this->patrollable( $result ) ? 'not-patrolled' : '';
global $wgUser;
return ( $wgUser->useNPPatrol() && !$result->rc_patrolled );
}
-
+
/**
* Output a subscription feed listing recent edits to this page.
* @param string $type
*/
protected function feed( $type, $options ) {
require_once 'SpecialRecentchanges.php';
-
+
global $wgFeed, $wgFeedClasses;
-
+
if ( !$wgFeed ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
return;
}
-
+
if( !isset( $wgFeedClasses[$type] ) ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-invalid' );
return;
}
-
+
$self = SpecialPage::getTitleFor( 'NewPages' );
$feed = new $wgFeedClasses[$type](
$this->feedTitle(),
wfMsg( 'tagline' ),
$self->getFullUrl() );
- $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
- $options['hidepatrolled'], $options['hidebots'], $options['username'] );
-
+ $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
+ $options['hidepatrolled'], $options['hidebots'], $options['username'] );
+
$feed->outHeader();
if( $pager->getNumRows() > 0 ) {
while( $row = $pager->mResult->fetchObject() ) {
}
$feed->outFooter();
}
-
+
protected function feedTitle() {
global $wgContLanguageCode, $wgSitename;
$page = SpecialPage::getPage( 'Newpages' );
return NULL;
}
}
-
+
/**
* Quickie hack... strip out wikilinks to more legible form from the comment.
*/
function stripComment( $text ) {
return preg_replace( '/\[\[([^]]*\|)?([^]]+)\]\]/', '\2', $text );
}
-
+
function feedItemAuthor( $row ) {
return isset( $row->rc_user_text ) ? $row->rc_user_text : '';
}
-
+
protected function feedItemDesc( $row ) {
$revision = Revision::newFromId( $row->rev_id );
if( $revision ) {
*/
class NewPagesPager extends ReverseChronologicalPager {
private $hideliu, $hidepatrolled, $hidebots, $namespace, $user;
-
+
function __construct( $form, $conds=array(), $namespace, $hliu=false, $hpatrolled=false, $hbots=1, $user='' ) {
parent::__construct();
$this->mForm = $form;
$this->mConds = $conds;
-
+
$this->namespace = ($namespace === "all") ? false : intval($namespace);
$this->user = $user;
-
+
$this->hideliu = (bool)$hliu;
$this->hidepatrolled = (bool)$hpatrolled;
$this->hidebots = (bool)$hbots;
}
$conds[] = 'page_id = rc_cur_id';
$conds['page_is_redirect'] = 0;
-
+
global $wgGroupPermissions, $wgUser;
# If anons cannot make new pages, don't query for it!
if( $wgGroupPermissions['*']['createpage'] && $this->hideliu ) {
function formatRow( $row ) {
return $this->mForm->formatRow( $row );
}
-
+
function getStartBody() {
# Do a batch existence check on pages
$linkBatch = new LinkBatch();
/**
* SpecialPage: handling special pages and lists thereof.
*
- * To add a special page in an extension, add to $wgSpecialPages either
- * an object instance or an array containing the name and constructor
- * parameters. The latter is preferred for performance reasons.
+ * To add a special page in an extension, add to $wgSpecialPages either
+ * an object instance or an array containing the name and constructor
+ * parameters. The latter is preferred for performance reasons.
*
- * The object instantiated must be either an instance of SpecialPage or a
- * sub-class thereof. It must have an execute() method, which sends the HTML
- * for the special page to $wgOut. The parent class has an execute() method
- * which distributes the call to the historical global functions. Additionally,
- * execute() also checks if the user has the necessary access privileges
+ * The object instantiated must be either an instance of SpecialPage or a
+ * sub-class thereof. It must have an execute() method, which sends the HTML
+ * for the special page to $wgOut. The parent class has an execute() method
+ * which distributes the call to the historical global functions. Additionally,
+ * execute() also checks if the user has the necessary access privileges
* and bails out if not.
*
- * To add a core special page, use the similar static list in
+ * To add a core special page, use the similar static list in
* SpecialPage::$mList. To remove a core static special page at runtime, use
* a SpecialPage_initList hook.
*
'Listadmins' => array( 'SpecialRedirectToSpecial', 'Listadmins', 'Listusers', 'sysop' ),
'MergeHistory' => array( 'SpecialPage', 'MergeHistory', 'mergehistory' ),
'Listbots' => array( 'SpecialRedirectToSpecial', 'Listbots', 'Listusers', 'bot' ),
- );
+ );
static public $mAliases;
static public $mListInitialised = false;
'Newimages' => 'changes',
'Newpages' => 'changes',
'Log' => 'changes',
-
+
'Upload' => 'media',
'Imagelist' => 'media',
'MIMEsearch' => 'media',
'FileDuplicateSearch' => 'media',
'Filepath' => 'media',
-
+
'Listusers' => 'users',
'Listgrouprights' => 'users',
'Ipblocklist' => 'users',
'Emailuser' => 'users',
'Listadmins' => 'users',
'Listbots' => 'users',
-
+
'Wantedpages' => 'needy',
'Wantedcategories' => 'needy',
'Shortpages' => 'needy',
'Ancientpages' => 'needy',
'Deadendpages' => 'needy',
-
+
'Mostlinked' => 'highuse',
'Mostlinkedcategories' => 'highuse',
'Mostlinkedtemplates' => 'highuse',
'Mostcategories' => 'highuse',
'Mostimages' => 'highuse',
'Mostrevisions' => 'highuse',
-
+
'Userrights' => 'permissions',
'Blockip' => 'permissions',
-
+
'Statistics' => 'other',
'Fewestrevisions' => 'other',
'Randompage' => 'other',
'Mypage' => 'other',
'Mytalk' => 'other',
'Mycontributions' => 'other',
- );
+ );
/**#@-*/
return;
}
wfProfileIn( __METHOD__ );
-
+
# Better to set this now, to avoid infinite recursion in carelessly written hooks
self::$mListInitialised = true;
}
/**
- * Given a special page name with a possible subpage, return an array
+ * Given a special page name with a possible subpage, return an array
* where the first element is the special page name and the second is the
* subpage.
*/
}
/**
- * Add a page to the list of valid special pages. This used to be the preferred
- * method for adding special pages in extensions. It's now suggested that you add
+ * Add a page to the list of valid special pages. This used to be the preferred
+ * method for adding special pages in extensions. It's now suggested that you add
* an associative record to $wgSpecialPages. This avoids autoloading SpecialPage.
*
- * @param mixed $page Must either be an array specifying a class name and
+ * @param mixed $page Must either be an array specifying a class name and
* constructor parameters, or an object. The object,
* when constructed, must have an execute() method which
* sends HTML to $wgOut.
}
self::$mList[$page->mName] = $page;
}
-
+
/**
* Add a page to a certain display group for Special:SpecialPages
*
- * @param mixed $page Must either be an array specifying a class name and
+ * @param mixed $page Must either be an array specifying a class name and
* constructor parameters, or an object.
* @param string $group
* @static
}
self::$mGroupsList[$page->mName] = $group;
}
-
+
/**
* Add a page to a certain display group for Special:SpecialPages
*
- * @param mixed $page Must either be an array specifying a class name and
+ * @param mixed $page Must either be an array specifying a class name and
* constructor parameters, or an object.
* @static
*/
if ( !self::$mListInitialised ) {
self::initList();
}
- $group = isset(self::$mGroupsList[$page->mName]) ?
+ $group = isset(self::$mGroupsList[$page->mName]) ?
self::$mGroupsList[$page->mName] : 'other';
return $group;
}
/**
* Remove a special page from the list
- * Formerly used to disable expensive or dangerous special pages. The
+ * Formerly used to disable expensive or dangerous special pages. The
* preferred method is now to add a SpecialPage_initList hook.
- *
+ *
* @static
*/
static function removePage( $name ) {
}
# Redirect to canonical alias for GET commands
- # Not for POST, we'd lose the post data, so it's best to just distribute
- # the request. Such POST requests are possible for old extensions that
- # generate self-links without being aware that their default name has
+ # Not for POST, we'd lose the post data, so it's best to just distribute
+ # the request. Such POST requests are possible for old extensions that
+ # generate self-links without being aware that their default name has
# changed.
if ( !$including && $name != $page->getLocalName() && !$wgRequest->wasPosted() ) {
$query = $_GET;
* Default execute method
* Checks user permissions, calls the function given in mFunction
*
- * This may be overridden by subclasses.
+ * This may be overridden by subclasses.
*/
function execute( $par ) {
global $wgUser;
if(!is_callable($func) and $this->mFile) {
require_once( $this->mFile );
}
- # FIXME: these hooks are broken for extensions and anything else that subclasses SpecialPage.
+ # FIXME: these hooks are broken for extensions and anything else that subclasses SpecialPage.
if ( wfRunHooks( 'SpecialPageExecuteBeforeHeader', array( &$this, &$par, &$func ) ) )
$this->outputHeader();
if ( ! wfRunHooks( 'SpecialPageExecuteBeforePage', array( &$this, &$par, &$func ) ) )
}
/**
- * If the special page is a redirect, then get the Title object it redirects to.
+ * If the special page is a redirect, then get the Title object it redirects to.
* False otherwise.
*/
function getRedirect( $subpage ) {
if( $val = $wgRequest->getVal( $arg, false ) )
$params[] = $arg . '=' . $val;
}
-
+
return count( $params ) ? implode( '&', $params ) : false;
}
}
$dbr = wfGetDB( DB_SLAVE );
$page = $dbr->tableName( 'page' );
- $query =
+ $query =
"SELECT 'Popularpages' as type,
page_namespace as namespace,
page_title as title,
return $ppp->doQuery( $offset, $limit );
}
-
-
global $wgLang, $wgContLang;
if ( $val !== false && (
in_array( $val, (array)$wgLang->getDatePreferences() ) ||
- in_array( $val, (array)$wgContLang->getDatePreferences() ) ) )
+ in_array( $val, (array)$wgContLang->getDatePreferences() ) ) )
{
return $val;
} else {
$this->mainPrefsForm( 'error', wfMsg( 'wrongpassword' ) );
return;
}
-
+
try {
$wgUser->setPassword( $this->mNewpass );
wfRunHooks( 'PrefsPasswordAudit', array( $wgUser, $this->mNewpass, 'success' ) );
}
return Xml::tags( 'tr', null, $td1 . $td2 ). $td3 . "\n";
-
+
}
/**
}
# Password
- if( $wgAuth->allowPasswordChange() ) {
+ if( $wgAuth->allowPasswordChange() ) {
$wgOut->addHTML(
$this->tableRow( Xml::element( 'h2', null, wfMsg( 'changepassword' ) ) ) .
$this->tableRow(
# Recent changes
$wgOut->addHtml( '<fieldset><legend>' . wfMsgHtml( 'prefs-rc' ) . '</legend>' );
-
+
$rc = '<table><tr>';
$rc .= '<td>' . Xml::label( wfMsg( 'recentchangesdays' ), 'wpRecentDays' ) . '</td>';
- $rc .= '<td>' . Xml::input( 'wpRecentDays', 3, $this->mRecentDays, array( 'id' => 'wpRecentDays' ) ) . '</td>';
+ $rc .= '<td>' . Xml::input( 'wpRecentDays', 3, $this->mRecentDays, array( 'id' => 'wpRecentDays' ) ) . '</td>';
$rc .= '</tr><tr>';
$rc .= '<td>' . Xml::label( wfMsg( 'recentchangescount' ), 'wpRecent' ) . '</td>';
$rc .= '<td>' . Xml::input( 'wpRecent', 3, $this->mRecent, array( 'id' => 'wpRecent' ) ) . '</td>';
$rc .= '</tr></table>';
$wgOut->addHtml( $rc );
-
+
$wgOut->addHtml( '<br />' );
-
+
$toggles[] = 'hideminor';
if( $wgRCShowWatchingUsers )
$toggles[] = 'shownumberswatching';
# Watchlist
$wgOut->addHtml( '<fieldset><legend>' . wfMsgHtml( 'prefs-watchlist' ) . '</legend>' );
-
+
$wgOut->addHtml( wfInputLabel( wfMsg( 'prefs-watchlist-days' ), 'wpWatchlistDays', 'wpWatchlistDays', 3, $this->mWatchlistDays ) );
$wgOut->addHtml( '<br /><br />' );
$wgOut->addHtml( '<br /><br />' );
$wgOut->addHtml( $this->getToggles( array( 'watchlisthideown', 'watchlisthidebots', 'watchlisthideminor' ) ) );
-
+
if( $wgUser->isAllowed( 'createpage' ) || $wgUser->isAllowed( 'createtalk' ) )
$wgOut->addHtml( $this->getToggle( 'watchcreations' ) );
foreach( array( 'edit' => 'watchdefault', 'move' => 'watchmoves', 'delete' => 'watchdeletion' ) as $action => $toggle ) {
$this->mUsedToggles['watchdefault'] = true;
$this->mUsedToggles['watchmoves'] = true;
$this->mUsedToggles['watchdeletion'] = true;
-
+
$wgOut->addHtml( '</fieldset>' );
# Search
$wgOut->addHtml( Xml::tags( 'div', array( 'class' => "prefcache" ),
wfMsgExt( 'clearyourcache', 'parseinline' ) )
);
-
}
}
-
}
/**
- * implements Special:Prefixindex
+ * implements Special:Prefixindex
* @addtogroup SpecialPage
*/
class SpecialPrefixindex extends SpecialAllpages {
protected $name = 'Prefixindex';
protected $nsfromMsg = 'allpagesprefix';
-/**
- * @param integer $namespace (Default NS_MAIN)
- * @param string $from list all pages from this name (default FALSE)
- */
-function showChunk( $namespace = NS_MAIN, $prefix, $including = false, $from = null ) {
- global $wgOut, $wgUser, $wgContLang;
-
- $fname = 'indexShowChunk';
-
- $sk = $wgUser->getSkin();
-
- if (!isset($from)) $from = $prefix;
-
- $fromList = $this->getNamespaceKeyAndText($namespace, $from);
- $prefixList = $this->getNamespaceKeyAndText($namespace, $prefix);
- $namespaces = $wgContLang->getNamespaces();
- $align = $wgContLang->isRtl() ? 'left' : 'right';
-
- if ( !$prefixList || !$fromList ) {
- $out = wfMsgWikiHtml( 'allpagesbadtitle' );
- } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) {
- // Show errormessage and reset to NS_MAIN
- $out = wfMsgExt( 'allpages-bad-ns', array( 'parseinline' ), $namespace );
- $namespace = NS_MAIN;
- } else {
- list( $namespace, $prefixKey, $prefix ) = $prefixList;
- list( /* $fromNs */, $fromKey, $from ) = $fromList;
-
- ### FIXME: should complain if $fromNs != $namespace
-
- $dbr = wfGetDB( DB_SLAVE );
-
- $res = $dbr->select( 'page',
- array( 'page_namespace', 'page_title', 'page_is_redirect' ),
- array(
- 'page_namespace' => $namespace,
- 'page_title LIKE \'' . $dbr->escapeLike( $prefixKey ) .'%\'',
- 'page_title >= ' . $dbr->addQuotes( $fromKey ),
- ),
- $fname,
- array(
- 'ORDER BY' => 'page_title',
- 'LIMIT' => $this->maxPerPage + 1,
- 'USE INDEX' => 'name_title',
- )
- );
-
- ### FIXME: side link to previous
-
- $n = 0;
- $out = '<table style="background: inherit;" border="0" width="100%">';
-
- while( ($n < $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
- $t = Title::makeTitle( $s->page_namespace, $s->page_title );
- if( $t ) {
- $link = ($s->page_is_redirect ? '<div class="allpagesredirect">' : '' ) .
- $sk->makeKnownLinkObj( $t, htmlspecialchars( $t->getText() ), false, false ) .
- ($s->page_is_redirect ? '</div>' : '' );
- } else {
- $link = '[[' . htmlspecialchars( $s->page_title ) . ']]';
- }
- if( $n % 3 == 0 ) {
- $out .= '<tr>';
+ /**
+ * @param integer $namespace (Default NS_MAIN)
+ * @param string $from list all pages from this name (default FALSE)
+ */
+ function showChunk( $namespace = NS_MAIN, $prefix, $including = false, $from = null ) {
+ global $wgOut, $wgUser, $wgContLang;
+
+ $fname = 'indexShowChunk';
+
+ $sk = $wgUser->getSkin();
+
+ if (!isset($from)) $from = $prefix;
+
+ $fromList = $this->getNamespaceKeyAndText($namespace, $from);
+ $prefixList = $this->getNamespaceKeyAndText($namespace, $prefix);
+ $namespaces = $wgContLang->getNamespaces();
+ $align = $wgContLang->isRtl() ? 'left' : 'right';
+
+ if ( !$prefixList || !$fromList ) {
+ $out = wfMsgWikiHtml( 'allpagesbadtitle' );
+ } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) {
+ // Show errormessage and reset to NS_MAIN
+ $out = wfMsgExt( 'allpages-bad-ns', array( 'parseinline' ), $namespace );
+ $namespace = NS_MAIN;
+ } else {
+ list( $namespace, $prefixKey, $prefix ) = $prefixList;
+ list( /* $fromNs */, $fromKey, $from ) = $fromList;
+
+ ### FIXME: should complain if $fromNs != $namespace
+
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $res = $dbr->select( 'page',
+ array( 'page_namespace', 'page_title', 'page_is_redirect' ),
+ array(
+ 'page_namespace' => $namespace,
+ 'page_title LIKE \'' . $dbr->escapeLike( $prefixKey ) .'%\'',
+ 'page_title >= ' . $dbr->addQuotes( $fromKey ),
+ ),
+ $fname,
+ array(
+ 'ORDER BY' => 'page_title',
+ 'LIMIT' => $this->maxPerPage + 1,
+ 'USE INDEX' => 'name_title',
+ )
+ );
+
+ ### FIXME: side link to previous
+
+ $n = 0;
+ $out = '<table style="background: inherit;" border="0" width="100%">';
+
+ while( ($n < $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
+ $t = Title::makeTitle( $s->page_namespace, $s->page_title );
+ if( $t ) {
+ $link = ($s->page_is_redirect ? '<div class="allpagesredirect">' : '' ) .
+ $sk->makeKnownLinkObj( $t, htmlspecialchars( $t->getText() ), false, false ) .
+ ($s->page_is_redirect ? '</div>' : '' );
+ } else {
+ $link = '[[' . htmlspecialchars( $s->page_title ) . ']]';
+ }
+ if( $n % 3 == 0 ) {
+ $out .= '<tr>';
+ }
+ $out .= "<td>$link</td>";
+ $n++;
+ if( $n % 3 == 0 ) {
+ $out .= '</tr>';
+ }
}
- $out .= "<td>$link</td>";
- $n++;
- if( $n % 3 == 0 ) {
+ if( ($n % 3) != 0 ) {
$out .= '</tr>';
}
+ $out .= '</table>';
}
- if( ($n % 3) != 0 ) {
- $out .= '</tr>';
- }
- $out .= '</table>';
- }
- if ( $including ) {
- $out2 = '';
- } else {
- $nsForm = $this->namespaceForm ( $namespace, $prefix );
- $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">';
- $out2 .= '<tr valign="top"><td>' . $nsForm;
- $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' .
- $sk->makeKnownLink( $wgContLang->specialPage( $this->name ),
- wfMsg ( 'allpages' ) );
- if ( isset($dbr) && $dbr && ($n == $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
- $namespaceparam = $namespace ? "&namespace=$namespace" : "";
- $out2 .= " | " . $sk->makeKnownLink(
- $wgContLang->specialPage( $this->name ),
- wfMsg ( 'nextpage', $s->page_title ),
- "from=" . wfUrlEncode ( $s->page_title ) .
- "&prefix=" . wfUrlEncode ( $prefix ) . $namespaceparam );
+ if ( $including ) {
+ $out2 = '';
+ } else {
+ $nsForm = $this->namespaceForm ( $namespace, $prefix );
+ $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">';
+ $out2 .= '<tr valign="top"><td>' . $nsForm;
+ $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' .
+ $sk->makeKnownLink( $wgContLang->specialPage( $this->name ),
+ wfMsg ( 'allpages' ) );
+ if ( isset($dbr) && $dbr && ($n == $this->maxPerPage) && ($s = $dbr->fetchObject( $res )) ) {
+ $namespaceparam = $namespace ? "&namespace=$namespace" : "";
+ $out2 .= " | " . $sk->makeKnownLink(
+ $wgContLang->specialPage( $this->name ),
+ wfMsg ( 'nextpage', $s->page_title ),
+ "from=" . wfUrlEncode ( $s->page_title ) .
+ "&prefix=" . wfUrlEncode ( $prefix ) . $namespaceparam );
+ }
+ $out2 .= "</td></tr></table><hr />";
}
- $out2 .= "</td></tr></table><hr />";
- }
- $wgOut->addHtml( $out2 . $out );
-}
+ $wgOut->addHtml( $out2 . $out );
+ }
}
-
-
$NS = $wgRequest->getIntOrNull( 'namespace' );
$indefOnly = $wgRequest->getBool( 'indefonly' ) ? 1 : 0;
- $pager = new ProtectedPagesPager( $this, array(), $type, $level, $NS, $sizetype, $size, $indefOnly );
+ $pager = new ProtectedPagesPager( $this, array(), $type, $level, $NS, $sizetype, $size, $indefOnly );
$wgOut->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size, $indefOnly ) );
if ( $pager->getNumRows() ) {
$s = $pager->getNavigationBar();
- $s .= "<ul>" .
+ $s .= "<ul>" .
$pager->getBody() .
"</ul>";
$s .= $pager->getNavigationBar();
if( is_null( $skin ) )
$skin = $wgUser->getSkin();
-
+
$title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
$link = $skin->makeLinkObj( $title );
if ( $row->pr_expiry != 'infinity' && strlen($row->pr_expiry) ) {
$expiry = Block::decodeExpiry( $row->pr_expiry );
-
+
$expiry_description = wfMsgForContent( 'protect-expiring', $wgLang->timeanddate( $expiry ) );
$description_items[] = $expiry_description;
}
-
+
if (!is_null($size = $row->page_len)) {
if ($size == 0)
$stxt = ' <small>' . wfMsgHtml('historyempty') . '</small>';
return '<li>' . wfSpecialList( $link . $stxt, implode( $description_items, ', ' ) ) . "</li>\n";
}
-
+
/**
* @param $namespace int
* @param $type string
" " . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
"</fieldset></form>";
}
-
+
/**
* Prepare the namespace filter drop-down; standard namespace
* selector, sans the MediaWiki namespace
Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' '
. Xml::namespaceSelector( $namespace, '' ) . "</span>";
}
-
+
/**
* @return string Formatted HTML
*/
$out .= Xml::label( wfMsg("protectedpages-indef"), 'indefonly' ) . "\n";
return $out;
}
-
+
/**
* @return string Formatted HTML
*/
- protected function getSizeLimit( $sizetype, $size ) {
+ protected function getSizeLimit( $sizetype, $size ) {
$out = Xml::radio( 'sizetype', 'min', ($sizetype=='min'), array('id' => 'wpmin') );
$out .= Xml::label( wfMsg("minimum-size"), 'wpmin' );
$out .= " ".Xml::radio( 'sizetype', 'max', ($sizetype=='max'), array('id' => 'wpmax') );
$out .= ' '.wfMsgHtml('pagesize');
return $out;
}
-
+
/**
* @return string Formatted HTML
*/
protected function getTypeMenu( $pr_type ) {
global $wgRestrictionTypes;
-
+
$m = array(); // Temporary array
$options = array();
/**
* @return string Formatted HTML
- */
+ */
protected function getLevelMenu( $pr_level ) {
global $wgRestrictionLevels;
$lb->add( $row->page_namespace, $row->page_title );
}
$lb->execute();
-
+
wfProfileOut( __METHOD__ );
return '';
}
-
+
function formatRow( $row ) {
return $this->mForm->formatRow( $row );
}
$conds[] = 'pr_expiry>' . $this->mDb->addQuotes( $this->mDb->timestamp() );
$conds[] = 'page_id=pr_page';
$conds[] = 'pr_type=' . $this->mDb->addQuotes( $this->type );
-
+
if( $this->sizetype=='min' ) {
$conds[] = 'page_len>=' . $this->size;
} else if( $this->sizetype=='max' ) {
$conds[] = 'page_len<=' . $this->size;
}
-
+
if( $this->indefonly ) {
$conds[] = "pr_expiry = 'infinity' OR pr_expiry IS NULL";
}
-
+
if( $this->level )
$conds[] = 'pr_level=' . $this->mDb->addQuotes( $this->level );
if( !is_null($this->namespace) )
$ppForm->showList();
}
-
-
-
$size = $wgRequest->getIntOrNull( 'size' );
$NS = $wgRequest->getIntOrNull( 'namespace' );
- $pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size );
+ $pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size );
$wgOut->addHTML( $this->showOptions( $NS, $type, $level, $sizetype, $size ) );
if ( $pager->getNumRows() ) {
$s = $pager->getNavigationBar();
- $s .= "<ul>" .
+ $s .= "<ul>" .
$pager->getBody() .
"</ul>";
$s .= $pager->getNavigationBar();
if( is_null( $skin ) )
$skin = $wgUser->getSkin();
-
+
$title = Title::makeTitleSafe( $row->pt_namespace, $row->pt_title );
$link = $skin->makeLinkObj( $title );
if ( $row->pt_expiry != 'infinity' && strlen($row->pt_expiry) ) {
$expiry = Block::decodeExpiry( $row->pt_expiry );
-
+
$expiry_description = wfMsgForContent( 'protect-expiring', $wgLang->timeanddate( $expiry ) );
$description_items[] = $expiry_description;
}
-
+
wfProfileOut( __METHOD__ );
return '<li>' . wfSpecialList( $link . $stxt, implode( $description_items, ', ' ) ) . "</li>\n";
}
-
+
/**
* @param $namespace int
* @param $type string
" " . Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
"</fieldset></form>";
}
-
+
/**
* Prepare the namespace filter drop-down; standard namespace
* selector, sans the MediaWiki namespace
/**
* @return string Formatted HTML
* @private
- */
+ */
function getLevelMenu( $pr_level ) {
global $wgRestrictionLevels;
wfProfileOut( __METHOD__ );
return '';
}
-
+
function formatRow( $row ) {
return $this->mForm->formatRow( $row );
}
function getQueryInfo() {
$conds = $this->mConds;
$conds[] = 'pt_expiry>' . $this->mDb->addQuotes( $this->mDb->timestamp() );
-
+
if( !is_null($this->namespace) )
$conds[] = 'pt_namespace=' . $this->mDb->addQuotes( $this->namespace );
return array(
$ppForm->showList();
}
-
-
-
private $namespace = NS_MAIN; // namespace to select pages from
function __construct( $name = 'Randompage' ){
- parent::__construct( $name );
+ parent::__construct( $name );
}
public function getNamespace() {
return $this->namespace;
}
-
+
public function setNamespace ( $ns ) {
if( $ns < NS_MAIN ) $ns = NS_MAIN;
$this->namespace = $ns;
}
-
+
// select redirects instead of normal pages?
// Overriden by SpecialRandomredirect
public function isRedirect(){
return false;
}
-
+
public function execute( $par ) {
global $wgOut, $wgContLang;
return $dbr->fetchObject( $res );
}
}
-
-
*/
class SpecialRandomredirect extends RandomPage {
function __construct(){
- parent::__construct( 'Randomredirect' );
+ parent::__construct( 'Randomredirect' );
}
// Override parent::isRedirect()
return true;
}
}
-
/* order of selection: url > preferences > default */
$hideminor = $wgRequest->getBool( 'hideminor', $wgUser->getOption( 'hideminor') ? true : $defaults['hideminor'] );
-
+
# As a feed, use limited settings only
if( $feedFormat ) {
global $wgFeedLimit;
if ( is_numeric( $bit ) ) {
$limit = $bit;
}
-
+
$m = array();
if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) ) {
$limit = $m[1];
// And now for the content
$wgOut->setSyndicated( true );
-
+
$list = ChangesList::newFromUser( $wgUser );
-
+
if ( $wgAllowCategorizedRecentChanges ) {
$categories = trim ( $wgRequest->getVal ( 'categories' , "" ) ) ;
$categories = str_replace ( "|" , "\n" , $categories ) ;
if( empty( $categories ) ) {
return;
}
-
+
# Filter categories
$cats = array () ;
foreach ( $categories AS $cat ) {
if ( $cat == "" ) continue ;
$cats[] = $cat ;
}
-
+
# Filter articles
$articles = array () ;
$a2r = array () ;
}
$a2r[$id][] = $k ;
}
-
+
# Shortcut?
if ( count ( $articles ) == 0 OR count ( $cats ) == 0 )
return ;
-
+
# Look up
$c = new Categoryfinder ;
$c->seed ( $articles , $cats , $any ? "OR" : "AND" ) ;
$match = $c->run () ;
-
+
# Filter
$newrows = array () ;
foreach ( $match AS $id ) {
global $messageMemc, $wgFeedCacheTimeout;
global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode;
global $wgFeed;
-
+
if ( !$wgFeed ) {
global $wgOut;
$wgOut->addWikiMsg( 'feed-unavailable' );
rcDaysLink( $limit, 14, $page, $more ) . ' | ' .
rcDaysLink( $limit, 30, $page, $more ) .
( $doall ? ( ' | ' . rcDaysLink( $limit, 0, $page, $more ) ) : '' );
-
+
$linkParts = array( 'minorLink' => 'minor', 'botLink' => 'bots', 'liuLink' => 'liu', 'patrLink' => 'patr', 'myselfLink' => 'mine' );
foreach( $linkParts as $linkVar => $linkMsg ) {
if( $$linkVar != '' )
$links[] = wfMsgHtml( 'rcshowhide' . $linkMsg, $$linkVar );
}
-
+
$shm = implode( ' | ', $links );
$note = wfMsg( 'rclinks', $cl, $dl, $shm );
return $note;
array( 'hidepatrolled' => 1-$options['hidepatrolled'] ), $nondefaults);
$myselfLink = makeOptionsLink( $showhide[1-$options['hidemyself']],
array( 'hidemyself' => 1-$options['hidemyself'] ), $nondefaults);
-
+
$links[] = wfMsgHtml( 'rcshowhideminor', $minorLink );
$links[] = wfMsgHtml( 'rcshowhidebots', $botLink );
$links[] = wfMsgHtml( 'rcshowhideanons', $anonsLink );
$links[] = wfMsgHtml( 'rcshowhidepatr', $patrLink );
$links[] = wfMsgHtml( 'rcshowhidemine', $myselfLink );
$hl = implode( ' | ', $links );
-
+
// show from this onward link
$now = $wgLang->timeanddate( wfTimestampNow(), true );
$tl = makeOptionsLink( $now, array( 'from' => wfTimestampNow()), $nondefaults );
$namespaceselect = HTMLnamespaceselector($namespace, '');
$submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . "\" />\n";
$invertbox = "<input type='checkbox' name='invert' value='1' id='nsinvert'" . ( $invert ? ' checked="checked"' : '' ) . ' />';
-
+
if ( $wgAllowCategorizedRecentChanges ) {
$categories = trim ( $wgRequest->getVal ( 'categories' , "" ) ) ;
$cb_arr = array( 'type' => 'checkbox', 'name' => 'categories_any', 'value' => "1" ) ;
} else {
$catbox = "" ;
}
-
+
$out = "<div class='namespacesettings'><form method='get' action='{$wgScript}'>\n";
foreach ( $nondefaults as $key => $value ) {
if( $row->rc_deleted & LogPage::DELETED_ACTION ) {
$actiontext = wfMsgHtml('rev-deleted-event');
} else {
- $actiontext = LogPage::actionText( $row->rc_log_type, $row->rc_log_action,
+ $actiontext = LogPage::actionText( $row->rc_log_type, $row->rc_log_action,
$titleObj, $wgUser->getSkin(), LogPage::extractParams($row->rc_params,true,true) );
}
}
wfMsg( 'previousrevision' ), // hack
wfMsg( 'revisionasof',
$wgContLang->timeanddate( $timestamp ) ) );
-
+
if ( strlen( $diffText ) > $wgFeedDiffCutoff ) {
// Omit large diffs
'diff-context' => 'background: #eee; color:black; font-size: smaller;',
'diffchange' => 'color: red; font-weight: bold; text-decoration: none;',
);
-
+
foreach( $styles as $class => $style ) {
$text = preg_replace( "/(<[^>]+)class=(['\"])$class\\2([^>]*>)/",
"\\1style=\"$style\"\\3", $text );
}
-
+
return $text;
}
-
-
$wgOut->setPagetitle( wfMsg( 'recentchangeslinked' ) );
$sk = $wgUser->getSkin();
- $wgOut->addHTML(
+ $wgOut->addHTML(
Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', array(), wfMsg( 'recentchangeslinked' ) ) . "\n" .
Xml::inputLabel( wfMsg( 'recentchangeslinked-page' ), 'target', 'recentchangeslinked-target', 40, $target ) .
- " <span style='white-space: nowrap'>" .
+ " <span style='white-space: nowrap'>" .
Xml::check( 'showlinkedto', $showlinkedto, array('id' => 'showlinkedto') ) . ' ' .
- Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) .
+ Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) .
"</span><br/>\n" .
Xml::hidden( 'title', $wgTitle->getPrefixedText() ). "\n" .
Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
$cmq = 'AND rc_minor=0';
} else { $cmq = ''; }
- list($recentchanges, $categorylinks, $pagelinks, $watchlist) =
+ list($recentchanges, $categorylinks, $pagelinks, $watchlist) =
$dbr->tableNamesN( 'recentchanges', 'categorylinks', 'pagelinks', "watchlist" );
$uid = $wgUser->getID();
} else {
$joinConds = "AND pl_namespace=rc_namespace AND pl_title=rc_title AND pl_from=$id";
}
-
+
$sql =
"SELECT /* wfSpecialRecentchangeslinked */
rc_id,
$feedTitle = $wgSitename . ' - ' . wfMsgForContent( 'recentchangeslinked-title', $nt->getPrefixedText() ) . ' [' . $wgContLanguageCode . ']';
$feed = new $wgFeedClasses[$feedFormat]( $feedTitle,
htmlspecialchars( wfMsgForContent('recentchangeslinked') ), $wgTitle->getFullUrl() );
-
+
require_once( "SpecialRecentchanges.php" );
$wgOut->disable();
rcDoOutputFeed( $rchanges, $feed );
}
}
-
-
$this->mTemporaryPassword = $wgRequest->getVal( 'wpPassword' );
}
}
-
+
/**
* Main execution point
*/
function execute( $par ) {
global $wgUser, $wgAuth, $wgOut, $wgRequest;
-
+
if( !$wgAuth->allowPasswordChange() ) {
$this->error( wfMsg( 'resetpass_forbidden' ) );
return;
}
-
+
if( $this->mName === null && !$wgRequest->wasPosted() ) {
$this->error( wfMsg( 'resetpass_missing' ) );
return;
try {
$this->attemptReset( $newpass, $retype );
$wgOut->addWikiMsg( 'resetpass_success' );
-
+
$data = array(
'action' => 'submitlogin',
'wpName' => $this->mName,
}
$login = new LoginForm( new FauxRequest( $data, true ) );
$login->execute();
-
+
return;
} catch( PasswordError $e ) {
$this->error( $e->getMessage() );
}
$this->showForm();
}
-
+
function error( $msg ) {
global $wgOut;
$wgOut->addHtml( '<div class="errorbox">' .
htmlspecialchars( $msg ) .
'</div>' );
}
-
+
function showForm() {
global $wgOut, $wgUser, $wgRequest;
$wgOut->disallowUserJs();
-
- $self = SpecialPage::getTitleFor( 'Resetpass' );
+
+ $self = SpecialPage::getTitleFor( 'Resetpass' );
$form =
'<div id="userloginForm">' .
wfOpenElement( 'form',
'</div>';
$wgOut->addHtml( $form );
}
-
+
function pretty( $fields ) {
$out = '';
foreach( $fields as $list ) {
}
return $out;
}
-
+
/**
* @throws PasswordError when cannot set the new password because requirements not met.
*/
if( $user->isAnon() ) {
throw new PasswordError( 'no such user' );
}
-
+
if( !$user->checkTemporaryPassword( $this->mTemporaryPassword ) ) {
throw new PasswordError( wfMsg( 'resetpass_bad_temporary' ) );
}
-
+
if( $newpass !== $retype ) {
throw new PasswordError( wfMsg( 'badretype' ) );
}
-
+
$user->setPassword( $newpass );
$user->saveSettings();
}
}
-
-
} else if( $logid ) {
$form->showLogItems( $wgRequest );
}
- # Show relevant lines from the deletion log. This will show even if said ID
+ # Show relevant lines from the deletion log. This will show even if said ID
# does not exist...might be helpful
if( !is_null($page) ) {
$wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" );
# Give a link to the log for this page
if( !is_null($this->page) && $this->page->getNamespace() > -1 ) {
$links = array();
-
+
$logtitle = SpecialPage::getTitleFor( 'Log' );
$links[] = $this->skin->makeKnownLinkObj( $logtitle, wfMsgHtml( 'viewpagelogs' ),
wfArrayToCGI( array( 'page' => $this->page->getPrefixedUrl() ) ) );
- # Give a link to the page history
+ # Give a link to the page history
$links[] = $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml( 'pagehist' ),
wfArrayToCGI( array( 'action' => 'history' ) ) );
# Link to deleted edits
$hide_content_name = array( 'revdelete-hide-name', 'wpHideName', LogPage::DELETED_ACTION );
$this->deleteKey='logid';
}
- // Our checkbox messages depends one what we are doing,
+ // Our checkbox messages depends one what we are doing,
// e.g. we don't hide "text" for logs or images
$this->checks = array(
$hide_content_name,
array( 'revdelete-hide-user', 'wpHideUser', Revision::DELETED_USER ),
array( 'revdelete-hide-restricted', 'wpHideRestricted', Revision::DELETED_RESTRICTED ) );
}
-
+
/**
* Show a deleted file version requested by the visitor.
*/
private function showFile( $key ) {
global $wgOut, $wgRequest;
$wgOut->disable();
-
+
# We mustn't allow the output to be Squid cached, otherwise
# if an admin previews a deleted image, and it's cached, then
# a user without appropriate permissions can toddle off and
$wgRequest->response()->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
$wgRequest->response()->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
$wgRequest->response()->header( 'Pragma: no-cache' );
-
+
$store = FileStore::get( 'deleted' );
$store->stream( $key );
}
-
+
/**
* This lets a user set restrictions for live and archived revisions
* @param WebRequest $request
global $wgOut, $wgUser, $action;
$UserAllowed = true;
-
- $count = ($this->deleteKey=='oldid') ?
+
+ $count = ($this->deleteKey=='oldid') ?
count($this->revisions) : count($this->archrevs);
$wgOut->addWikiMsg( 'revdelete-selected', $this->page->getPrefixedText(), $count );
-
+
$bitfields = 0;
$wgOut->addHtml( "<ul>" );
-
+
$where = $revObjs = array();
$dbr = wfGetDB( DB_SLAVE );
// Live revisions...
}
$whereClause = 'rev_id IN(' . implode(',',$where) . ')';
$result = $dbr->select( array('revision','page'), '*',
- array( 'rev_page' => $this->page->getArticleID(),
+ array( 'rev_page' => $this->page->getArticleID(),
$whereClause, 'rev_page = page_id' ),
__METHOD__ );
while( $row = $dbr->fetchObject( $result ) ) {
} else if( !$revObjs[$revid]->userCan(Revision::DELETED_RESTRICTED) ) {
// If a rev is hidden from sysops
if( $action != 'submit') {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return;
}
$UserAllowed = false;
$whereClause = 'ar_timestamp IN(' . implode(',',$where) . ')';
$result = $dbr->select( 'archive', '*',
array( 'ar_namespace' => $this->page->getNamespace(),
- 'ar_title' => $this->page->getDBKey(),
+ 'ar_title' => $this->page->getDBKey(),
$whereClause ),
__METHOD__ );
while( $row = $dbr->fetchObject( $result ) ) {
if( !$rev->userCan(Revision::DELETED_RESTRICTED) ) {
// If a rev is hidden from sysops
if( $action != 'submit') {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return;
}
$UserAllowed = false;
foreach( $hidden as $item ) {
$wgOut->addHtml( $item );
}
- $wgOut->addHtml(
+ $wgOut->addHtml(
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' ) . "\n"
);
global $wgOut, $wgUser, $action;
$UserAllowed = true;
-
+
$count = ($this->deleteKey=='oldimage') ? count($this->ofiles) : count($this->afiles);
- $wgOut->addWikiText( wfMsgExt( 'revdelete-selected', array('parsemag'),
+ $wgOut->addWikiText( wfMsgExt( 'revdelete-selected', array('parsemag'),
$this->page->getPrefixedText(), $count ) );
-
+
$bitfields = 0;
$wgOut->addHtml( "<ul>" );
-
+
$where = $filesObjs = array();
$dbr = wfGetDB( DB_SLAVE );
// Live old revisions...
// Inject history info
$wgOut->addHtml( $this->fileLine( $file ) );
$bitfields |= $file->deleted;
- }
+ }
// Archived files...
} else {
// Run through and pull all our data in one query
while( $row = $dbr->fetchObject( $result ) ) {
$filesObjs[$row->fa_id] = ArchivedFile::newFromRow( $row );
}
-
+
foreach( $this->afiles as $fileid ) {
if( !isset($filesObjs[$fileid]) ) {
$wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
$hidden[] = wfHidden( 'fileid[]', $fileid );
}
$special = SpecialPage::getTitleFor( 'Revisiondelete' );
- $wgOut->addHtml(
+ $wgOut->addHtml(
Xml::openElement( 'form', array( 'method' => 'post', 'action' => $special->getLocalUrl( 'action=submit' ), 'id' => 'mw-revdel-form-filerevisions' ) ) .
Xml::openElement( 'fieldset' ) .
xml::element( 'legend', null, wfMsg( 'revdelete-legend' ) )
$wgOut->addHtml( $item );
}
- $wgOut->addHtml(
+ $wgOut->addHtml(
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' ) . "\n"
);
$UserAllowed = true;
$wgOut->addWikiText( wfMsgExt( 'logdelete-selected', array('parsemag'), count($this->events) ) );
-
+
$bitfields = 0;
$wgOut->addHtml( "<ul>" );
-
+
$where = $logRows = array();
$dbr = wfGetDB( DB_SLAVE );
// Run through and pull all our data in one query
$where[] = intval($logid);
}
$whereClause = 'log_id IN(' . implode(',',$where) . ')';
- $result = $dbr->select( 'logging', '*',
+ $result = $dbr->select( 'logging', '*',
array( $whereClause ),
__METHOD__ );
while( $row = $dbr->fetchObject( $result ) ) {
$wgOut->addHtml( $item );
}
- $wgOut->addHtml(
+ $wgOut->addHtml(
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' ) . "\n"
);
*/
private function historyLine( $rev ) {
global $wgContLang;
-
+
$date = $wgContLang->timeanddate( $rev->getTimestamp() );
$difflink = $del = '';
// Live revisions
if( $this->deleteKey=='oldid' ) {
$revlink = $this->skin->makeLinkObj( $this->page, $date, 'oldid=' . $rev->getId() );
- $difflink = '(' . $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml('diff'),
+ $difflink = '(' . $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml('diff'),
'diff=' . $rev->getId() . '&oldid=prev' ) . ')';
// Archived revisions
} else {
$undelete = SpecialPage::getTitleFor( 'Undelete' );
$target = $this->page->getPrefixedText();
- $revlink = $this->skin->makeLinkObj( $undelete, $date,
+ $revlink = $this->skin->makeLinkObj( $undelete, $date,
"target=$target×tamp=" . $rev->getTimestamp() );
- $difflink = '(' . $this->skin->makeKnownLinkObj( $undelete, wfMsgHtml('diff'),
+ $difflink = '(' . $this->skin->makeKnownLinkObj( $undelete, wfMsgHtml('diff'),
"target=$target&diff=prev×tamp=" . $rev->getTimestamp() ) . ')';
}
-
+
if( $rev->isDeleted(Revision::DELETED_TEXT) ) {
$revlink = '<span class="history-deleted">'.$revlink.'</span>';
$del = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
$difflink = '(' . wfMsgHtml('diff') . ')';
}
}
-
+
return "<li> $difflink $revlink ".$this->skin->revUserLink( $rev )." ".$this->skin->revComment( $rev )."$del</li>";
}
-
+
/**
* @param File $file
* @returns string
- */
+ */
private function fileLine( $file ) {
global $wgContLang, $wgTitle;
-
+
$target = $this->page->getPrefixedText();
$date = $wgContLang->timeanddate( $file->getTimestamp(), true );
-
+
$del = '';
# Hidden files...
if( $file->isDeleted(File::DELETED_FILE) ) {
if( !$file->userCan(File::DELETED_FILE) ) {
$pageLink = $date;
} else {
- $pageLink = $this->skin->makeKnownLinkObj( $wgTitle, $date,
+ $pageLink = $this->skin->makeKnownLinkObj( $wgTitle, $date,
"target=$target&file=$file->sha1.".$file->getExtension() );
}
$pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
$url = $file->getUrlRel();
$pageLink = "<a href=\"{$url}\">{$date}</a>";
}
-
+
$data = wfMsgHtml( 'widthheight',
$wgContLang->formatNum( $file->getWidth() ),
$wgContLang->formatNum( $file->getHeight() ) ) .
- ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->getSize() ) ) . ')';
-
+ ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->getSize() ) ) . ')';
+
return "<li>$pageLink ".$this->fileUserTools( $file )." $data ".$this->fileComment( $file )."$del</li>";
}
-
+
/**
* @param ArchivedFile $file
* @returns string
- */
+ */
private function archivedfileLine( $file ) {
global $wgContLang, $wgTitle;
-
+
$target = $this->page->getPrefixedText();
$date = $wgContLang->timeanddate( $file->getTimestamp(), true );
-
+
$undelete = SpecialPage::getTitleFor( 'Undelete' );
$pageLink = $this->skin->makeKnownLinkObj( $undelete, $date, "target=$target&file={$file->getKey()}" );
-
+
$del = '';
if( $file->isDeleted(File::DELETED_FILE) ) {
$del = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
}
-
+
$data = wfMsgHtml( 'widthheight',
$wgContLang->formatNum( $file->getWidth() ),
$wgContLang->formatNum( $file->getHeight() ) ) .
- ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->getSize() ) ) . ')';
-
+ ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->getSize() ) ) . ')';
+
return "<li> $pageLink ".$this->fileUserTools( $file )." $data ".$this->fileComment( $file )."$del</li>";
}
-
+
/**
* @param Array $row row
* @returns string
$date = $wgContLang->timeanddate( $row->log_timestamp );
$paramArray = LogPage::extractParams( $row->log_params );
$title = Title::makeTitle( $row->log_namespace, $row->log_title );
-
+
$logtitle = SpecialPage::getTitleFor( 'Log' );
$loglink = $this->skin->makeKnownLinkObj( $logtitle, wfMsgHtml( 'log' ),
wfArrayToCGI( array( 'page' => $title->getPrefixedUrl() ) ) );
// Action text
if( !LogEventsList::userCan($row,LogPage::DELETED_ACTION) ) {
- $action = '<span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
+ $action = '<span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
} else {
- $action = LogPage::actionText( $row->log_type, $row->log_action, $title,
+ $action = LogPage::actionText( $row->log_type, $row->log_action, $title,
$this->skin, $paramArray, true, true );
if( $row->log_deleted & LogPage::DELETED_ACTION )
$action = '<span class="history-deleted">' . $action . '</span>';
}
return "<li>($loglink) $date $userLink $action $comment</li>";
}
-
+
/**
* Generate a user tool link cluster if the current user is allowed to view it
* @param ArchivedFile $file
}
return $link;
}
-
+
/**
* Wrap and format the given file's comment block, if the current
* user is allowed to view it.
}
return $block;
}
-
+
/**
* @param WebRequest $request
*/
function submit( $request ) {
$bitfield = $this->extractBitfield( $request );
$comment = $request->getText( 'wpReason' );
-
+
$this->target = $request->getText( 'target' );
$this->title = Title::newFromURL( $this->target );
-
+
if( $this->save( $bitfield, $comment, $this->title ) ) {
$this->success( $request );
} else if( $request->getCheck( 'oldid' ) || $request->getCheck( 'artimestamp' ) ) {
global $wgOut;
$wgOut->setPagetitle( wfMsgHtml( 'actioncomplete' ) );
-
+
if( $this->deleteKey=='logid' ) {
$wgOut->addWikiText( Xml::element( 'span', array( 'class' => 'success' ), wfMsg( 'logdelete-success' ) ), false );
$this->showLogItems( $request );
}
return $bitfield;
}
-
+
private function save( $bitfield, $reason, $title ) {
$dbw = wfGetDB( DB_MASTER );
// Don't allow simply locking the interface for no reason
function __construct( $db ) {
$this->dbw = $db;
}
-
+
/**
* @param $title, the page these events apply to
* @param array $items list of revision ID numbers
*/
function setRevVisibility( $title, $items, $bitfield, $comment ) {
global $wgOut;
-
+
$userAllowedAll = $success = true;
$revIDs = array();
$revCount = 0;
}
$whereClause = 'rev_id IN(' . implode(',',$where) . ')';
$result = $this->dbw->select( 'revision', '*',
- array( 'rev_page' => $title->getArticleID(),
+ array( 'rev_page' => $title->getArticleID(),
$whereClause ),
__METHOD__ );
while( $row = $this->dbw->fetchObject( $result ) ) {
$success = false;
continue; // Must exist
} else if( !$revObjs[$revid]->userCan(Revision::DELETED_RESTRICTED) ) {
- $userAllowedAll=false;
+ $userAllowedAll=false;
continue;
}
// For logging, maintain a count of revisions
if( $revObjs[$revid]->mDeleted != $bitfield ) {
$revCount++;
$revIDs[]=$revid;
-
+
$this->updateRevision( $revObjs[$revid], $bitfield );
$this->updateRecentChangesEdits( $revObjs[$revid], $bitfield, false );
}
// Clear caches...
// Don't log or touch if nothing changed
if( $revCount > 0 ) {
- $this->updateLog( $title, $revCount, $bitfield, $revObjs[$revid]->mDeleted,
+ $this->updateLog( $title, $revCount, $bitfield, $revObjs[$revid]->mDeleted,
$comment, $title, 'oldid', $revIDs );
$this->updatePage( $title );
}
$wgOut->permissionRequired( 'hiderevision' );
return false;
}
-
+
return $success;
}
-
+
/**
* @param $title, the page these events apply to
* @param array $items list of revision ID numbers
*/
function setArchiveVisibility( $title, $items, $bitfield, $comment ) {
global $wgOut;
-
+
$userAllowedAll = $success = true;
- $count = 0;
+ $count = 0;
$Id_set = array();
// Run through and pull all our data in one query
foreach( $items as $timestamp ) {
$whereClause = 'ar_timestamp IN(' . implode(',',$where) . ')';
$result = $this->dbw->select( 'archive', '*',
array( 'ar_namespace' => $title->getNamespace(),
- 'ar_title' => $title->getDBKey(),
+ 'ar_title' => $title->getDBKey(),
$whereClause ),
__METHOD__ );
while( $row = $this->dbw->fetchObject( $result ) ) {
// To work!
foreach( $items as $timestamp ) {
// This will only select the first revision with this timestamp.
- // Since they are all selected/deleted at once, we can just check the
+ // Since they are all selected/deleted at once, we can just check the
// permissions of one. UPDATE is done via timestamp, so all revs are set.
if( !is_object($revObjs[$timestamp]) ) {
$success = false;
if( $revObjs[$timestamp]->mDeleted != $bitfield ) {
$Id_set[]=$timestamp;
$count++;
-
+
$this->updateArchive( $revObjs[$timestamp], $title, $bitfield );
}
}
// For logging, maintain a count of revisions
if( $count > 0 ) {
- $this->updateLog( $title, $count, $bitfield, $revObjs[$timestamp]->mDeleted,
+ $this->updateLog( $title, $count, $bitfield, $revObjs[$timestamp]->mDeleted,
$comment, $title, 'artimestamp', $Id_set );
}
// Where all revs allowed to be set?
if( !$userAllowedAll ) {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return false;
}
-
+
return $success;
}
-
+
/**
* @param $title, the page these events apply to
* @param array $items list of revision ID numbers
*/
function setOldImgVisibility( $title, $items, $bitfield, $comment ) {
global $wgOut;
-
+
$userAllowedAll = $success = true;
- $count = 0;
+ $count = 0;
$set = array();
// Run through and pull all our data in one query
foreach( $items as $timestamp ) {
$userAllowedAll=false;
continue;
}
-
+
$transaction = true;
// Which revisions did we change anything about?
if( $filesObjs[$archivename]->deleted != $bitfield ) {
$count++;
-
+
$this->dbw->begin();
$this->updateOldFiles( $filesObjs[$archivename], $bitfield );
// If this image is currently hidden...
$this->dbw->commit();
}
}
-
+
// Log if something was changed
if( $count > 0 ) {
- $this->updateLog( $title, $count, $bitfield, $filesObjs[$archivename]->deleted,
+ $this->updateLog( $title, $count, $bitfield, $filesObjs[$archivename]->deleted,
$comment, $title, 'oldimage', $set );
# Purge page/history
$file = wfLocalFile( $title );
}
// Where all revs allowed to be set?
if( !$userAllowedAll ) {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return false;
}
-
+
return $success;
}
-
+
/**
* @param $title, the page these events apply to
* @param array $items list of revision ID numbers
*/
function setArchFileVisibility( $title, $items, $bitfield, $comment ) {
global $wgOut;
-
+
$userAllowedAll = $success = true;
- $count = 0;
+ $count = 0;
$Id_set = array();
-
+
// Run through and pull all our data in one query
foreach( $items as $id ) {
$where[] = intval($id);
if( $filesObjs[$fileid]->deleted != $bitfield ) {
$Id_set[]=$fileid;
$count++;
-
+
$this->updateArchFiles( $filesObjs[$fileid], $bitfield );
}
}
// Log if something was changed
if( $count > 0 ) {
- $this->updateLog( $title, $count, $bitfield, $comment,
+ $this->updateLog( $title, $count, $bitfield, $comment,
$filesObjs[$fileid]->deleted, $title, 'fileid', $Id_set );
}
// Where all revs allowed to be set?
$wgOut->permissionRequired( 'hiderevision' );
return false;
}
-
+
return $success;
}
*/
function setEventVisibility( $items, $bitfield, $comment ) {
global $wgOut;
-
+
$userAllowedAll = $success = true;
- $logs_count = array();
+ $logs_count = array();
$logs_Ids = array();
-
+
// Run through and pull all our data in one query
foreach( $items as $logid ) {
$where[] = intval($logid);
}
$whereClause = 'log_id IN(' . implode(',',$where) . ')';
- $result = $this->dbw->select( 'logging', '*',
+ $result = $this->dbw->select( 'logging', '*',
array( $whereClause ),
__METHOD__ );
while( $row = $this->dbw->fetchObject( $result ) ) {
if( $logRows[$logid]->log_deleted != $bitfield ) {
$logs_Ids[$logtype][]=$logid;
$logs_count[$logtype]++;
-
+
$this->updateLogs( $logRows[$logid], $bitfield );
$this->updateRecentChangesLog( $logRows[$logid], $bitfield, true );
}
// Don't log or touch if nothing changed
if( $count > 0 ) {
$target = SpecialPage::getTitleFor( 'Log', $logtype );
- $this->updateLog( $target, $count, $bitfield, $logRows[$logid]->log_deleted,
+ $this->updateLog( $target, $count, $bitfield, $logRows[$logid]->log_deleted,
$comment, $target, 'logid', $logs_Ids[$logtype] );
}
}
// Where all revs allowed to be set?
if( !$userAllowedAll ) {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return false;
}
-
+
return $success;
}
* Caller is responsible for clearing caches
* @param File $oimage
* @returns mixed, timestamp string on success, false on failure
- */
+ */
function makeOldImagePrivate( $oimage ) {
global $wgFileStore, $wgUseSquid;
-
+
$transaction = new FSTransaction();
if( !FileStore::lock() ) {
wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" );
throw new MWException( "Could not archive and delete file $oldpath" );
return false;
}
-
+
wfDebug( __METHOD__.": set db items, applying file transactions\n" );
$transaction->commit();
FileStore::unlock();
-
+
$m = explode('!',$oimage->archive_name,2);
$timestamp = $m[0];
-
+
return $timestamp;
}
* Caller is responsible for clearing caches
* @param File $oimage
* @returns mixed, string timestamp on success, false on failure
- */
+ */
function makeOldImagePublic( $oimage ) {
global $wgFileStore;
-
+
$transaction = new FSTransaction();
if( !FileStore::lock() ) {
wfDebug( __METHOD__." could not acquire filestore lock\n" );
return false;
}
-
+
$store = FileStore::get( 'deleted' );
if( !$store ) {
wfDebug( __METHOD__.": skipping row with no file.\n" );
return false;
}
-
+
$key = $oimage->sha1.'.'.$oimage->getExtension();
$destDir = $oimage->getArchivePath();
if( !is_dir( $destDir ) ) {
array( 'oi_sha1' => $oimage->sha1,
'oi_deleted & '.File::DELETED_FILE => File::DELETED_FILE ),
__METHOD__, array( 'FOR UPDATE' ) );
- // Check the rest of the deleted archives too.
+ // Check the rest of the deleted archives too.
// (these are the ones that don't show in the image history)
if( !$useCount ) {
- $useCount = $this->dbw->selectField( 'filearchive', '1',
+ $useCount = $this->dbw->selectField( 'filearchive', '1',
array( 'fa_storage_group' => 'deleted', 'fa_storage_key' => $key ),
__METHOD__, array( 'FOR UPDATE' ) );
}
-
+
if( $useCount == 0 ) {
wfDebug( __METHOD__.": nothing else using {$oimage->sha1}, will deleting after\n" );
$flags = FileStore::DELETE_ORIGINAL;
$flags = 0;
}
$transaction->add( $store->export( $key, $destPath, $flags ) );
-
+
wfDebug( __METHOD__.": set db items, applying file transactions\n" );
$transaction->commit();
FileStore::unlock();
-
+
$m = explode('!',$oimage->archive_name,2);
$timestamp = $m[0];
-
+
return $timestamp;
}
-
+
/**
* Update the revision's rev_deleted field
* @param Revision $rev
'rev_page' => $rev->getPage() ),
__METHOD__ );
}
-
+
/**
* Update the revision's rev_deleted field
* @param Revision $rev
'oi_timestamp' => $this->dbw->timestamp( $file->getTimestamp() ) ),
__METHOD__ );
}
-
+
/**
* Update the images's fa_deleted field
* @param ArchivedFile $file
array( 'fa_deleted' => $bitfield ),
array( 'fa_id' => $file->getID() ),
__METHOD__ );
- }
-
+ }
+
/**
* Update the logging log_deleted field
* @param Row $row
array( 'log_deleted' => $bitfield ),
array( 'log_id' => $row->log_id ),
__METHOD__ );
- }
-
+ }
+
/**
* Update the revision's recentchanges record if fields have been hidden
* @param Revision $rev
'rc_timestamp' => $this->dbw->timestamp( $rev->getTimestamp() ) ),
__METHOD__ );
}
-
+
/**
* Update the revision's recentchanges record if fields have been hidden
* @param Row $row
'rc_timestamp' => $row->log_timestamp ),
__METHOD__ );
}
-
+
/**
* Touch the page's cache invalidation timestamp; this forces cached
* history views to refresh, so any newly hidden or shown fields will
function updatePage( $title ) {
$title->invalidateCache();
$title->purgeSquid();
-
+
// Extensions that require referencing previous revisions may need this
wfRunHooks( 'ArticleRevisionVisiblitySet', array( &$title ) );
}
* Checks for a change in the bitfield for a certain option and updates the
* provided array accordingly.
*
- * @param String $desc Description to add to the array if the option was
+ * @param String $desc Description to add to the array if the option was
* enabled / disabled.
* @param int $field The bitmask describing the single option.
* @param int $diff The xor of the old and new bitfields.
* If the resulting array is $arr, then $arr[0] will contain an array of strings
* describing the items that were hidden, $arr[2] will contain an array of strings
* describing the items that were unhidden, and $arr[3] will contain an array with
- * a single string, which can be one of "applied restrictions to sysops",
+ * a single string, which can be one of "applied restrictions to sysops",
* "removed restrictions from sysops", or null.
*
* @param int $n The new bitfield.
$diff = $n ^ $o;
$ret = array ( 0 => array(), 1 => array(), 2 => array() );
- $this->checkItem ( wfMsgForContent ( 'revdelete-content' ),
+ $this->checkItem ( wfMsgForContent ( 'revdelete-content' ),
Revision::DELETED_TEXT, $diff, $n, $ret );
- $this->checkItem ( wfMsgForContent ( 'revdelete-summary' ),
+ $this->checkItem ( wfMsgForContent ( 'revdelete-summary' ),
Revision::DELETED_COMMENT, $diff, $n, $ret );
- $this->checkItem ( wfMsgForContent ( 'revdelete-uname' ),
+ $this->checkItem ( wfMsgForContent ( 'revdelete-uname' ),
Revision::DELETED_USER, $diff, $n, $ret );
// Restriction application to sysops
/**
* Gets a log message to describe the given revision visibility change. This
- * message will be of the form "[hid {content, edit summary, username}];
+ * message will be of the form "[hid {content, edit summary, username}];
* [unhid {...}][applied restrictions to sysops] for $count revisions: $comment".
*
* @param int $count The number of effected revisions.
}
$msg = $isForLog ? 'logdelete-log-message' : 'revdelete-log-message';
- $ret = wfMsgExt ( $msg, array( 'parsemag', 'content' ),
+ $ret = wfMsgExt ( $msg, array( 'parsemag', 'content' ),
$s, $wgContLang->formatNum( $count ) );
if ( $comment )
// Put things hidden from sysops in the oversight log
$logtype = ( ($nbitfield | $obitfield) & Revision::DELETED_RESTRICTED ) ? 'suppress' : 'delete';
$log = new LogPage( $logtype );
-
+
$reason = $this->getLogMessage ( $count, $nbitfield, $obitfield, $comment, $param == 'logid' );
if( $param == 'logid' ) {
if ( $wgGoToEdit ) {
$wgOut->redirect( $t->getFullURL( 'action=edit' ) );
return;
- }
+ }
}
if( $t->quickUserCan( 'create' ) && $t->quickUserCan( 'edit' ) ) {
$wgOut->addWikiMsg( 'noexactmatch', wfEscapeWikiText( $term ) );
return;
}
global $wgInputEncoding;
- $wgOut->addHTML(
+ $wgOut->addHTML(
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'search-external' ) ) .
Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) .
wfProfileOut( $fname );
return;
}
-
+
$wgOut->addHTML( $this->shortDialog( $term ) );
$search = SearchEngine::create();
$search->setLimitOffset( $this->limit, $this->offset );
$search->setNamespaces( $this->namespaces );
- $search->showRedirects = $this->searchRedirects;
+ $search->showRedirects = $this->searchRedirects;
$rewritten = $search->replacePrefixes($term);
-
+
$titleMatches = $search->searchTitle( $rewritten );
// Sometimes the search engine knows there are too many hits
return;
}
$textMatches = $search->searchText( $rewritten );
-
+
// did you mean...
if($textMatches && $textMatches->hasSuggestion()){
global $wgScript;
urlencode($textMatches->getSuggestionQuery()).'&fulltext='.$fulltext.'">'
.$textMatches->getSuggestionSnippet().'</a>';
$wgOut->addHTML('<div class="searchdidyoumean">'.wfMsg('search-suggest',$suggestLink).'</div>');
- }
-
+ }
+
$num = ( $titleMatches ? $titleMatches->numRows() : 0 )
+ ( $textMatches ? $textMatches->numRows() : 0);
if( $textMatches ) {
if( $textMatches->numRows() ) {
- if($titleMatches)
+ if($titleMatches)
$wgOut->wrapWikiMsg( "==$1==\n", 'textmatches' );
else // if no title matches the heading is redundant
$wgOut->addHTML("<hr/>");
$opt['redirs'] = $this->searchRedirects ? 1 : 0;
return $opt;
}
-
+
/**
//$contextlines = $wgUser->getOption( 'contextlines', 5 );
$contextlines = 2; // Hardcode this. Old defaults sucked. :)
$contextchars = $wgUser->getOption( 'contextchars', 50 );
-
+
$link = $sk->makeKnownLinkObj( $t, $result->getTitleSnippet());
//If page content is not readable, just return the title.
if (!$t->userCanRead()) {
return "<li>{$link}</li>\n";
}
-
+
$revision = Revision::newFromTitle( $t );
// If the page doesn't *exist*... our search index is out of date.
// The least confusing at this point is to drop the result.
return "<!-- missing page " .
htmlspecialchars( $t->getPrefixedText() ) . "-->\n";
}
-
+
if( is_null( $result->getScore() ) ) {
// Search engine doesn't report scoring info
$score = '';
$score = wfMsg( 'search-result-score', $wgLang->formatNum( $percent ) )
. ' - ';
}
-
+
// try to fetch everything from the search engine backend
// then fill-in what couldn't be fetched
$extract = $result->getTextSnippet();
if( is_null($timestamp) ){
$timestamp = $revision->getTimestamp();
}
-
- // format description
+
+ // format description
$size = wfMsgExt( 'search-result-size', array( 'parsemag', 'escape' ),
$sk->formatSize( $byteSize ),
$wordCount );
$date = $wgLang->timeanddate( $timestamp );
-
+
// format redirects / sections
$redirect = '';
if( !is_null($redirectTitle) )
."</span>";
$section = '';
if( !is_null($sectionTitle) )
- $section = "<span class='searchalttitle'>"
+ $section = "<span class='searchalttitle'>"
.wfMsg('search-section', $sk->makeKnownLinkObj( $sectionTitle, $sectionText))
."</span>";
// wrap extract
$extract = "<div class='searchresult'>".$extract."</div>";
-
+
// Include a thumbnail for media files...
if( $t->getNamespace() == NS_IMAGE ) {
$img = wfFindFile( $t );
"</li>\n";
}
-
+
private function extractText( $text, $terms, $contextlines, $contextchars ) {
global $wgLang, $wgContLang;
$fname = __METHOD__;
-
+
$lines = explode( "\n", $text );
$max = intval( $contextchars ) + 1;
$extract .= "${line}\n";
}
wfProfileOut( "$fname-extract" );
-
+
return $extract;
}
$name = wfMsg( 'blanknamespace' );
}
$namespaces .= Xml::openElement( 'span', array( 'style' => 'white-space: nowrap' ) ) .
- Xml::checkLabel( $name, "ns{$ns}", $name, in_array( $ns, $this->namespaces ) ) .
+ Xml::checkLabel( $name, "ns{$ns}", $name, in_array( $ns, $this->namespaces ) ) .
Xml::closeElement( 'span' ) . "\n";
}
"document.getElementById('powerSearchText').focus();" .
"</script>";
}
-
+
function shortDialog($term) {
global $wgScript;
-
+
$out = Xml::openElement( 'form', array(
'id' => 'search',
'method' => 'get',
}
$out .= Xml::submitButton( wfMsg( 'searchbutton' ), array( 'name' => 'fulltext' ) );
$out .= Xml::closeElement( 'form' );
-
+
return $out;
}
}
function formatResult( $skin, $result ) {
global $wgLang, $wgContLang;
$dm = $wgContLang->getDirMark();
-
+
$title = Title::makeTitleSafe( $result->namespace, $result->title );
if ( !$title ) {
return '<!-- Invalid title ' . htmlspecialchars( "{$result->namespace}:{$result->title}" ). '-->';
? $skin->makeLinkObj( $title )
: $skin->makeKnownLinkObj( $title );
$size = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ), $wgLang->formatNum( htmlspecialchars( $result->value ) ) );
-
+
return $title->exists()
? "({$hlink}) {$dm}{$plink} {$dm}[{$size}]"
: "<s>({$hlink}) {$dm}{$plink} {$dm}[{$size}]</s>";
return $spp->doQuery( $offset, $limit );
}
-
-
ksort( $groups[$group] );
}
}
-
+
/** Always move "other" to end */
if( array_key_exists('other',$groups) ) {
$other = $groups['other'];
$middle = ceil( count($sortedPages)/2 );
$total = count($sortedPages);
$count = 0;
-
+
$wgOut->addHTML( "<h4 class='mw-specialpagesgroup'>".wfMsgHtml("specialpages-group-$group")."</h4>\n" );
$wgOut->addHTML( "<table style='width: 100%;' class='mw-specialpages-table'><tr>" );
$wgOut->addHTML( "<td width='30%' valign='top'><ul>\n" );
foreach ( $sortedPages as $desc => $title ) {
$link = $sk->makeKnownLinkObj( $title , htmlspecialchars( $desc ) );
$wgOut->addHTML( "<li>{$link}</li>\n" );
-
+
# Slit up the larger groups
$count++;
if( $total > 3 && $count == $middle ) {
$wgOut->addHTML( "</ul></td><td width='30%' valign='top'></td></tr></table>\n" );
}
}
-
-
$res->free();
}
}
-
+
$footer = wfMsgNoTrans( 'statistics-footer' );
if( !wfEmptyMsg( 'statistics-footer', $footer ) && $footer != '' )
$text .= "\n" . $footer;
-
- $wgOut->addWikiText( $text );
+
+ $wgOut->addWikiText( $text );
}
-
}
return $lpp->doQuery( $offset, $limit );
}
-
-
list( $limit, $offset ) = wfCheckLimits();
return $uip->doQuery( $offset, $limit );
}
-
-
return $lpp->doQuery( $offset, $limit );
}
-
-
$utp = new UncategorizedTemplatesPage();
$utp->doQuery( $offset, $limit );
}
-
-
$dbr = wfGetDB( DB_SLAVE );
return self::listPages( $dbr, '' );
}
-
+
/**
* List deleted pages recorded in the archive table matching the
* given title prefix.
*/
public static function listPagesByPrefix( $prefix ) {
$dbr = wfGetDB( DB_SLAVE );
-
+
$title = Title::newFromText( $prefix );
if( $title ) {
$ns = $title->getNamespace();
)
);
}
-
+
/**
* List the revisions of the given page. Returns result wrapper with
* (ar_minor_edit, ar_timestamp, ar_user, ar_user_text, ar_comment) fields.
$ret = $dbr->resultObject( $res );
return $ret;
}
-
+
/**
* List the deleted file revisions for this page, if it's a file page.
* Returns a result wrapper with various filearchive fields, or null
return null;
}
}
-
+
/**
* Return the most-previous revision, either live or deleted, against
* the deleted revision given by timestamp.
*/
function getPreviousRevision( $timestamp ) {
$dbr = wfGetDB( DB_SLAVE );
-
+
// Check the previous deleted revision...
$row = $dbr->selectRow( 'archive',
'ar_timestamp',
'ORDER BY' => 'ar_timestamp DESC',
'LIMIT' => 1 ) );
$prevDeleted = $row ? wfTimestamp( TS_MW, $row->ar_timestamp ) : false;
-
+
$row = $dbr->selectRow( array( 'page', 'revision' ),
array( 'rev_id', 'rev_timestamp' ),
array(
'LIMIT' => 1 ) );
$prevLive = $row ? wfTimestamp( TS_MW, $row->rev_timestamp ) : false;
$prevLiveId = $row ? intval( $row->rev_id ) : null;
-
+
if( $prevLive && $prevLive > $prevDeleted ) {
// Most prior revision was live
return Revision::newFromId( $prevLiveId );
// If both the set of text revisions and file revisions are empty,
// restore everything. Otherwise, just restore the requested items.
$restoreAll = empty( $timestamps ) && empty( $fileVersions );
-
+
$restoreText = $restoreAll || !empty( $timestamps );
$restoreFiles = $restoreAll || !empty( $fileVersions );
-
+
if( $restoreFiles && $this->title->getNamespace() == NS_IMAGE ) {
$img = wfLocalFile( $this->title );
$this->fileStatus = $img->restore( $fileVersions, $unsuppress );
} else {
$filesRestored = 0;
}
-
+
if( $restoreText ) {
$textRestored = $this->undeleteRevisions( $timestamps, $unsuppress );
if($textRestored === false) // It must be one of UNDELETE_*
// Touch the log!
global $wgContLang;
$log = new LogPage( 'delete' );
-
+
if( $textRestored && $filesRestored ) {
$reason = wfMsgExt( 'undeletedrevisions-files', array( 'content', 'parsemag' ),
$wgContLang->formatNum( $textRestored ),
wfDebug( "Undelete: nothing undeleted...\n" );
return false;
}
-
+
if( trim( $comment ) != '' )
$reason .= ": {$comment}";
$log->addEntry( 'restore', $this->title, $reason );
return array($textRestored, $filesRestored, $reason);
}
-
+
/**
* This is the meaty bit -- restores archived revisions of the given page
* to the cur/old tables. If the page currently exists, all revisions will
if ( wfReadOnly() )
return false;
$restoreAll = empty( $timestamps );
-
+
$dbw = wfGetDB( DB_MASTER );
# Does this page already exist? We'll have to update it...
'ORDER BY' => 'ar_timestamp' )
);
$ret = $dbw->resultObject( $result );
-
- $rev_count = $dbw->numRows( $result );
+
+ $rev_count = $dbw->numRows( $result );
if( $rev_count ) {
# We need to seek around as just using DESC in the ORDER BY
# would leave the revisions inserted in the wrong order
}
$ret->seek( 0 );
}
-
+
if( $makepage ) {
$newid = $article->insertOn( $dbw );
$pageId = $newid;
$revision = null;
$restored = 0;
-
+
while( $row = $ret->fetchObject() ) {
if( $row->ar_text_id ) {
// Revision was deleted in 1.5+; text is in
) );
$revision->insertOn( $dbw );
$restored++;
-
+
wfRunHooks( 'ArticleRevisionUndeleted', array( &$this->title, $revision, $row->ar_page_id ) );
}
// Was anything restored at all?
$time = $request->getVal( 'timestamp' );
$this->mTimestamp = $time ? wfTimestamp( TS_MW, $time ) : '';
$this->mFile = $request->getVal( 'file' );
-
+
$posted = $request->wasPosted() &&
$wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
$this->mRestore = $request->getCheck( 'restore' ) && $posted;
$this->mDiff = $request->getCheck( 'diff' );
$this->mComment = $request->getText( 'wpComment' );
$this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'suppress' );
-
+
if( $par != "" ) {
$this->mTarget = $par;
}
if( preg_match( '/^ts(\d{14})$/', $key, $matches ) ) {
array_push( $timestamps, $matches[1] );
}
-
+
if( preg_match( '/^fileid(\d+)$/', $key, $matches ) ) {
$this->mFileVersions[] = intval( $matches[1] );
}
} else {
$wgOut->setPagetitle( wfMsg( "viewdeletedpage" ) );
}
-
+
if( is_null( $this->mTargetObj ) ) {
# Not all users can just browse every deleted page from the list
if( $wgUser->isAllowed( 'browsearchive' ) ) {
$file = new ArchivedFile( $this->mTargetObj, '', $this->mFile );
// Check if user is allowed to see this file
if( !$file->userCan( File::DELETED_FILE ) ) {
- $wgOut->permissionRequired( 'hiderevision' );
+ $wgOut->permissionRequired( 'hiderevision' );
return false;
} else {
return $this->showFile( $this->mFile );
function showSearchForm() {
global $wgOut, $wgScript;
$wgOut->addWikiMsg( 'undelete-header' );
-
+
$wgOut->addHtml(
Xml::openElement( 'form', array(
'method' => 'get',
// Generic list of deleted pages
private function showList( $result ) {
global $wgLang, $wgContLang, $wgUser, $wgOut;
-
+
if( $result->numRows() == 0 ) {
$wgOut->addWikiMsg( 'undelete-no-results' );
return;
$wgOut->addHTML( "<ul>\n" );
while( $row = $result->fetchObject() ) {
$title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
- $link = $sk->makeKnownLinkObj( $undelete, htmlspecialchars( $title->getPrefixedText() ),
+ $link = $sk->makeKnownLinkObj( $undelete, htmlspecialchars( $title->getPrefixedText() ),
'target=' . $title->getPrefixedUrl() );
#$revs = wfMsgHtml( 'undeleterevisions', $wgLang->formatNum( $row->count ) );
$revs = wfMsgExt( 'undeleterevisions',
$archive = new PageArchive( $this->mTargetObj );
$rev = $archive->getRevision( $timestamp );
-
+
if( !$rev ) {
$wgOut->addWikiMsg( 'undeleterevision-missing' );
return;
}
-
+
if( $rev->isDeleted(Revision::DELETED_TEXT) ) {
if( !$rev->userCan(Revision::DELETED_TEXT) ) {
$wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) );
// and we are allowed to see...
}
}
-
+
$wgOut->setPageTitle( wfMsg( 'undeletepage' ) );
-
+
$link = $skin->makeKnownLinkObj(
SpecialPage::getTitleFor( 'Undelete', $this->mTargetObj->getPrefixedDBkey() ),
htmlspecialchars( $this->mTargetObj->getPrefixedText() )
$wgOut->addHtml( wfMsgHtml( 'undelete-nodiff' ) );
}
}
-
+
$wgOut->addHtml( '<p>' . wfMsgHtml( 'undelete-revision', $link, $time, $user ) . '</p>' );
-
+
wfRunHooks( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) );
-
+
if( $this->mPreview ) {
$wgOut->addHtml( "<hr />\n" );
$wgOut->addWikiTextTitleTidy( $rev->revText(), $this->mTargetObj, false );
wfCloseElement( 'form' ) .
wfCloseElement( 'div' ) );
}
-
+
/**
* Build a diff display between this and the previous either deleted
* or non-deleted edit.
*/
function showDiff( $previousRev, $currentRev ) {
global $wgOut, $wgUser;
-
+
$diffEngine = new DifferenceEngine();
$diffEngine->showDiffStyle();
$wgOut->addHtml(
"</div>\n" );
}
-
+
private function diffHeader( $rev ) {
global $wgUser, $wgLang, $wgLang;
$sk = $wgUser->getSkin();
$sk->revComment( $rev ) . '<br/>' .
'</div>';
}
-
+
/**
* Show a deleted file version requested by the visitor.
*/
private function showFile( $key ) {
global $wgOut, $wgRequest;
$wgOut->disable();
-
+
# We mustn't allow the output to be Squid cached, otherwise
# if an admin previews a deleted image, and it's cached, then
# a user without appropriate permissions can toddle off and
$wgRequest->response()->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
$wgRequest->response()->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
$wgRequest->response()->header( 'Pragma: no-cache' );
-
+
$store = FileStore::get( 'deleted' );
$store->stream( $key );
}
} else {
$wgOut->setPagetitle( wfMsg( 'viewdeletedpage' ) );
}
-
+
$wgOut->addWikiText( wfMsgHtml( 'undeletepagetitle', $this->mTargetObj->getPrefixedText()) );
$archive = new PageArchive( $this->mTargetObj );
# in a nice little table
$align = $wgContLang->isRtl() ? 'left' : 'right';
if( $wgUser->isAllowed( 'suppress' ) ) {
- $unsuppressBox =
+ $unsuppressBox =
"<tr>
<td> </td>
<td>" .
private function formatRevisionRow( $row, $earliestLiveTime, $remaining, $sk ) {
global $wgUser, $wgLang;
-
+
$rev = new Revision( array(
'page' => $this->mTargetObj->getArticleId(),
'comment' => $row->ar_comment,
'minor_edit' => $row->ar_minor_edit,
'deleted' => $row->ar_deleted,
'len' => $row->ar_len ) );
-
+
$stxt = '';
$ts = wfTimestamp( TS_MW, $row->ar_timestamp );
if( $this->mAllowed ) {
if( !$rev->userCan( Revision::DELETED_TEXT ) ) {
$last = wfMsgHtml('diff');
} else if( $remaining > 0 || ($earliestLiveTime && $ts > $earliestLiveTime) ) {
- $last = $sk->makeKnownLinkObj( $titleObj, wfMsgHtml('diff'),
+ $last = $sk->makeKnownLinkObj( $titleObj, wfMsgHtml('diff'),
"target=" . $this->mTargetObj->getPrefixedUrl() . "×tamp=$ts&diff=prev" );
} else {
$last = wfMsgHtml('diff');
$last = wfMsgHtml('diff');
}
$userLink = $sk->revUserTools( $rev );
-
+
if(!is_null($size = $row->ar_len)) {
if($size == 0)
$stxt = wfMsgHtml('historyempty');
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
// If revision was hidden from sysops
- $del = wfMsgHtml('rev-delundel');
+ $del = wfMsgHtml('rev-delundel');
} else {
$ts = wfTimestamp( TS_MW, $row->ar_timestamp );
$del = $sk->makeKnownLinkObj( $revdel,
}
$revdlink = "<tt>(<small>$del</small>)</tt>";
}
-
+
return "<li>$checkBox $revdlink ($last) $pageLink . . $userLink $stxt $comment</li>";
}
-
+
private function formatFileRow( $row, $sk ) {
global $wgUser, $wgLang;
-
+
$file = ArchivedFile::newFromRow( $row );
-
+
$ts = wfTimestamp( TS_MW, $row->fa_timestamp );
if( $this->mAllowed && $row->fa_storage_key ) {
$checkBox = Xml::check( "fileid" . $row->fa_id );
}
return "<li>$checkBox $revdlink $pageLink . . $userLink $data $comment</li>\n";
}
-
+
private function getEarliestTime( $title ) {
$dbr = wfGetDB( DB_SLAVE );
if( $title->exists() ) {
*/
function getPageLink( $rev, $titleObj, $ts, $sk ) {
global $wgLang;
-
+
if( !$rev->userCan(Revision::DELETED_TEXT) ) {
return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
} else {
- $link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
+ $link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
"target=".$this->mTargetObj->getPrefixedUrl()."×tamp=$ts" );
if( $rev->isDeleted(Revision::DELETED_TEXT) )
$link = '<span class="history-deleted">' . $link . '</span>';
return $link;
}
}
-
+
/**
* Fetch image view link if it's available to all users
* @return string
if( !$file->userCan(File::DELETED_FILE) ) {
return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
} else {
- $link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
+ $link = $sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ),
"target=".$this->mTargetObj->getPrefixedUrl()."&file=$key" );
if( $file->isDeleted(File::DELETED_FILE) )
$link = '<span class="history-deleted">' . $link . '</span>';
* Fetch file's user id if it's available to this user
* @return string
*/
- function getFileUser( $file, $sk ) {
+ function getFileUser( $file, $sk ) {
if( !$file->userCan(File::DELETED_USER) ) {
return '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
} else {
- $link = $sk->userLink( $file->getRawUser(), $file->getRawUserText() ) .
+ $link = $sk->userLink( $file->getRawUser(), $file->getRawUserText() ) .
$sk->userToolLinks( $file->getRawUser(), $file->getRawUserText() );
if( $file->isDeleted(File::DELETED_USER) )
$link = '<span class="history-deleted">' . $link . '</span>';
if( is_array($ok) ) {
if ( $ok[1] ) // Undeleted file count
wfRunHooks( 'FileUndeleteComplete', array(
- $this->mTargetObj, $this->mFileVersions,
+ $this->mTargetObj, $this->mFileVersions,
$wgUser, $this->mComment) );
-
+
$skin = $wgUser->getSkin();
$link = $skin->makeKnownLinkObj( $this->mTargetObj );
$wgOut->addHtml( wfMsgWikiHtml( 'undeletedpage', $link ) );
$wgOut->addWikiMsg( "unlockdbsuccesstext", $ip );
}
}
-
-
$uc = new UnusedCategoriesPage();
return $uc->doQuery( $offset, $limit );
}
-
* @addtogroup SpecialPage
*/
class UnusedimagesPage extends ImageQueryPage {
-
+
function isExpensive() { return true; }
-
+
function getName() {
return 'Unusedimages';
}
} else {
list( $image, $imagelinks ) = $dbr->tableNamesN( 'image','imagelinks' );
- return "SELECT 'Unusedimages' as type, 6 as namespace, img_name as title, img_timestamp as value,
+ return "SELECT 'Unusedimages' as type, 6 as namespace, img_name as title, img_timestamp as value,
img_user, img_user_text, img_description
FROM $image LEFT JOIN $imagelinks ON img_name=il_to WHERE il_to IS NULL ";
}
return $uip->doQuery( $offset, $limit );
}
-
$utp = new UnusedtemplatesPage();
$utp->doQuery( $offset, $limit );
}
-
-
$wpp->doQuery( $offset, $limit );
}
-
-
$this->mSessionKey = $request->getInt( 'wpSessionKey' );
if( !empty( $this->mSessionKey ) &&
- isset( $_SESSION['wsUploadData'][$this->mSessionKey]['version'] ) &&
+ isset( $_SESSION['wsUploadData'][$this->mSessionKey]['version'] ) &&
$_SESSION['wsUploadData'][$this->mSessionKey]['version'] == self::SESSION_VERSION ) {
/**
* Confirming a temporarily stashed upload.
case self::FILETYPE_BADTYPE:
$finalExt = $details['finalExt'];
- $this->uploadError(
+ $this->uploadError(
wfMsgExt( 'filetype-banned-type',
array( 'parseinline' ),
htmlspecialchars( $finalExt ),
$file->getName(), $align, array(), false, true );
} elseif ( !$file->allowInlineDisplay() && $file->isSafeFile() ) {
$icon = $file->iconThumb();
- $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
+ $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
$icon->toHtml( array( 'desc-link' => true ) ) . '<br />' . $dlink . '</div>';
} else {
$dlink2 = '';
$nt_lc->getText(), $align, array(), false, true );
} elseif ( !$file_lc->allowInlineDisplay() && $file_lc->isSafeFile() ) {
$icon = $file_lc->iconThumb();
- $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
+ $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
$icon->toHtml( array( 'desc-link' => true ) ) . '<br />' . $dlink . '</div>';
} else {
$dlink2 = '';
}
- $warning .= '<li>' . wfMsgExt( 'fileexists-extension', 'parsemag', $file->getName(), $dlink ) . '</li>' . $dlink2;
+ $warning .= '<li>' . wfMsgExt( 'fileexists-extension', 'parsemag', $file->getName(), $dlink ) . '</li>' . $dlink2;
- } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' )
+ } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' )
&& ereg( "[0-9]{2}" , substr( $partname , 0, 2) ) )
{
# Check for filenames like 50px- or 180px-, these are mostly thumbnails
# Check if an image without leading '180px-' (or similiar) exists
$dlink = $sk->makeKnownLinkObj( $nt_thb);
if ( $file_thb->allowInlineDisplay() ) {
- $dlink2 = $sk->makeImageLinkObj( $nt_thb,
+ $dlink2 = $sk->makeImageLinkObj( $nt_thb,
wfMsgExt( 'fileexists-thumb', 'parseinline' ),
$nt_thb->getText(), $align, array(), false, true );
} elseif ( !$file_thb->allowInlineDisplay() && $file_thb->isSafeFile() ) {
$icon = $file_thb->iconThumb();
- $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
- $icon->toHtml( array( 'desc-link' => true ) ) . '<br />' .
+ $dlink2 = '<div style="float:' . $align . '" id="mw-media-icon">' .
+ $icon->toHtml( array( 'desc-link' => true ) ) . '<br />' .
$dlink . '</div>';
} else {
$dlink2 = '';
}
- $warning .= '<li>' . wfMsgExt( 'fileexists-thumbnail-yes', 'parsemag', $dlink ) .
- '</li>' . $dlink2;
+ $warning .= '<li>' . wfMsgExt( 'fileexists-thumbnail-yes', 'parsemag', $dlink ) .
+ '</li>' . $dlink2;
} else {
# Image w/o '180px-' does not exists, but we do not like these filenames
- $warning .= '<li>' . wfMsgExt( 'file-thumbnail-no', 'parseinline' ,
+ $warning .= '<li>' . wfMsgExt( 'file-thumbnail-no', 'parseinline' ,
substr( $partname , 0, strpos( $partname , '-' ) +1 ) ) . '</li>';
}
}
# If the file existed before and was deleted, warn the user of this
# Don't bother doing so if the file exists now, however
$ltitle = SpecialPage::getTitleFor( 'Log' );
- $llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ),
+ $llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ),
'type=delete&page=' . $file->getTitle()->getPrefixedUrl() );
$warning .= '<li>' . wfMsgWikiHtml( 'filewasdeleted', $llink ) . '</li>';
}
}
return $s;
}
-
+
/**
* Render a preview of a given license for the AJAX preview on upload
*
$text = '{{' . $license . '}}';
$title = Title::makeTitle( NS_IMAGE, 'Sample.jpg' );
$options = ParserOptions::newFromUser( $wgUser );
-
+
// Expand subst: first, then live templates...
$text = $wgParser->preSaveTransform( $text, $title, $wgUser, $options );
$output = $wgParser->parse( $text, $title, $options );
-
+
return $output->getText();
}
}
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL( 'action=submit' ),
+ Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL( 'action=submit' ),
'enctype' => 'multipart/form-data', 'id' => 'uploadwarning' ) ) . "\n" .
Xml::hidden( 'wpIgnoreWarning', '1' ) . "\n" .
Xml::hidden( 'wpSessionKey', $this->mSessionKey ) . "\n" .
"<input type='radio' id='wpSourceTypeFile' name='wpSourceType' value='file' " .
"onchange='toggle_element_activation(\"wpUploadFileURL\",\"wpUploadFile\")' checked='checked' />" .
"<input tabindex='1' type='file' name='wpUploadFile' id='wpUploadFile' " .
- "onfocus='" .
+ "onfocus='" .
"toggle_element_activation(\"wpUploadFileURL\",\"wpUploadFile\");" .
"toggle_element_check(\"wpSourceTypeFile\",\"wpSourceTypeURL\")' " .
"onchange='fillDestFilename(\"wpUploadFile\")' size='60' />" .
$encComment = htmlspecialchars( $this->mComment );
$wgOut->addHTML(
- Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL(),
+ Xml::openElement( 'form', array( 'method' => 'post', 'action' => $titleObj->getLocalURL(),
'enctype' => 'multipart/form-data', 'id' => 'mw-upload-form' ) ) .
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, wfMsg( 'upload' ) ) .
<label for='wpDestFile'>{$destfilename}</label>
</td>
<td class='mw-input'>
- <input tabindex='2' type='text' name='wpDestFile' id='wpDestFile' size='60'
+ <input tabindex='2' type='text' name='wpDestFile' id='wpDestFile' size='60'
value=\"{$encDestName}\" onchange='toggleFilenameFiller()' $destOnkeyup />
</td>
</tr>
<label for='wpUploadDescription'>{$summary}</label>
</td>
<td class='mw-input'>
- <textarea tabindex='3' name='wpUploadDescription' id='wpUploadDescription' rows='6'
+ <textarea tabindex='3' name='wpUploadDescription' id='wpUploadDescription' rows='6'
cols='{$cols}'{$width}>$encComment</textarea>
{$this->uploadFormTextAfterSummary}
</td>
<td class='mw-label' style='white-space: nowrap;'>
<label for='wpUploadCopyStatus'>$filestatus</label></td>
<td class='mw-input'>
- <input tabindex='5' type='text' name='wpUploadCopyStatus' id='wpUploadCopyStatus'
+ <input tabindex='5' type='text' name='wpUploadCopyStatus' id='wpUploadCopyStatus'
value=\"$copystatus\" size='60' />
</td>
</tr>
<label for='wpUploadCopyStatus'>$filesource</label>
</td>
<td class='mw-input'>
- <input tabindex='6' type='text' name='wpUploadSource' id='wpUploadCopyStatus'
+ <input tabindex='6' type='text' name='wpUploadSource' id='wpUploadCopyStatus'
value=\"$uploadsource\" size='60' />
</td>
</tr>
}
}
- /**
+ /**
* Heuristic for detecting files that *could* contain JavaScript instructions or
* things that may look like HTML to a browser and are thus
* potentially harmful. The present implementation will produce false positives in some situations.
return false;
}
- /**
+ /**
* Generic wrapper function for a virus scanner program.
* This relies on the $wgAntivirus and $wgAntivirusSetup variables.
* $wgAntivirusRequired may be used to deny upload if the scan fails.
if ( !$wgAntivirusSetup[$wgAntivirus] ) {
wfDebug( __METHOD__.": unknown virus scanner: $wgAntivirus\n" );
# @TODO: localise
- $wgOut->addHTML( "<div class='error'>Bad configuration: unknown virus scanner: <i>$wgAntivirus</i></div>\n" );
+ $wgOut->addHTML( "<div class='error'>Bad configuration: unknown virus scanner: <i>$wgAntivirus</i></div>\n" );
return "unknown antivirus: $wgAntivirus";
}
if ( strpos( $command,"%f" ) === false ) {
# simple pattern: append file to scan
- $command .= " " . wfEscapeShellArg( $file );
+ $command .= " " . wfEscapeShellArg( $file );
} else {
# complex pattern: replace "%f" with file to scan
- $command = str_replace( "%f", wfEscapeShellArg( $file ), $command );
+ $command = str_replace( "%f", wfEscapeShellArg( $file ), $command );
}
wfDebug( __METHOD__.": running virus scan: $command \n" );
# map exit code to AV_xxx constants.
$mappedCode = $exitCode;
- if ( $exitCodeMap ) {
+ if ( $exitCodeMap ) {
if ( isset( $exitCodeMap[$exitCode] ) ) {
$mappedCode = $exitCodeMap[$exitCode];
} elseif ( isset( $exitCodeMap["*"] ) ) {
}
}
- if ( $mappedCode === AV_SCAN_FAILED ) {
+ if ( $mappedCode === AV_SCAN_FAILED ) {
# scan failed (code was mapped to false by $exitCodeMap)
wfDebug( __METHOD__.": failed to scan $file (code $exitCode).\n" );
- if ( $wgAntivirusRequired ) {
- return "scan failed (code $exitCode)";
- } else {
- return NULL;
+ if ( $wgAntivirusRequired ) {
+ return "scan failed (code $exitCode)";
+ } else {
+ return NULL;
}
- } else if ( $mappedCode === AV_SCAN_ABORTED ) {
+ } else if ( $mappedCode === AV_SCAN_ABORTED ) {
# scan failed because filetype is unknown (probably imune)
wfDebug( __METHOD__.": unsupported file type $file (code $exitCode).\n" );
return NULL;
return true; // non-conditional
if( !$user->isAllowed( 'reupload-own' ) )
return false;
-
+
$dbr = wfGetDB( DB_SLAVE );
$row = $dbr->selectRow('image',
/* SELECT */ 'img_user',
if( !wfRunHooks( 'AbortLogin', array( $u, $this->mPassword, &$abort ) ) ) {
return $abort;
}
-
+
if (!$u->checkPassword( $this->mPassword )) {
if( $u->checkTemporaryPassword( $this->mPassword ) ) {
// The e-mailed temporary password should not be used
global $wgOut, $wgUser;
# Let's be nice about this, it's likely that this feature will be used
- # for blocking large numbers of innocent people, e.g. range blocks on
- # schools. Don't blame it on the user. There's a small chance that it
- # really is the user's fault, i.e. the username is blocked and they
- # haven't bothered to log out before trying to create an account to
+ # for blocking large numbers of innocent people, e.g. range blocks on
+ # schools. Don't blame it on the user. There's a small chance that it
+ # really is the user's fault, i.e. the username is blocked and they
+ # haven't bothered to log out before trying to create an account to
# evade it, but we'll leave that to their guilty conscience to figure
# out.
return $skin->makeKnownLinkObj( $self, htmlspecialchars( $text ), implode( '&', $attr ) );
}
}
-
-
$wgUser->logout();
$wgOut->setRobotpolicy( 'noindex,nofollow' );
-
+
// Hook.
$injected_html = '';
wfRunHooks( 'UserLogoutComplete', array(&$wgUser, &$injected_html) );
-
+
$wgOut->addHTML( wfMsgExt( 'logouttext', array( 'parse' ) ) . $injected_html );
$wgOut->returnToMain();
-}
\ No newline at end of file
+}
public function userCanExecute( $user ) {
$available = $this->changeableGroups();
- return !empty( $available['add'] )
+ return !empty( $available['add'] )
or !empty( $available['remove'] )
- or ($this->isself and
+ or ($this->isself and
(!empty( $available['add-self'] )
or !empty( $available['remove-self'] )));
}
if( !$user ) {
return;
}
-
+
$allgroups = User::getAllGroups();
$addgroup = array();
$removegroup = array();
-
- // This could possibly create a highly unlikely race condition if permissions are changed between
+
+ // This could possibly create a highly unlikely race condition if permissions are changed between
// when the form is loaded and when the form is saved. Ignoring it for the moment.
foreach ($allgroups as $group) {
// We'll tell it to remove all unchecked groups, and add all checked groups.
$removegroup[] = $group;
}
}
-
+
// Validate input set...
$changeable = $this->changeableGroups();
if ($wgUser->getId() != 0 && $wgUser->getId() == $user->getId()) {
}
$groups = $user->getGroups();
-
+
$this->showEditUserGroupsForm( $user, $groups );
// This isn't really ideal logging behavior, but let's not hide the
return null;
}
}
-
+
if( $name == '' ) {
$wgOut->addWikiMsg( 'nouserspecified' );
return false;
}
-
+
if( $name{0} == '#' ) {
// Numeric ID can be specified...
// We'll do a lookup for the name internally.
$id = intval( substr( $name, 1 ) );
-
+
if( $database == '' ) {
$name = User::whoIs( $id );
} else {
$name = UserRightsProxy::whoIs( $database, $id );
}
-
+
if( !$name ) {
$wgOut->addWikiMsg( 'noname' );
return null;
}
}
-
+
if( $database == '' ) {
$user = User::newFromName( $name );
} else {
$user = UserRightsProxy::newFromName( $database, $name );
}
-
+
if( !$user || $user->isAnon() ) {
$wgOut->addWikiMsg( 'nosuchusershort', $username );
return null;
}
-
+
return $user;
}
Xml::closeElement( 'form' ) . "\n"
);
}
-
+
/**
* Go through used and available groups and return the ones that this
* form will be able to manipulate based on the current user's system
protected function splitGroups( $groups ) {
global $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf;
list($addable, $removable) = array_values( $this->changeableGroups() );
-
+
$removable = array_intersect(
- array_merge($this->isself ? $wgGroupsRemoveFromSelf : array(), $removable),
+ array_merge($this->isself ? $wgGroupsRemoveFromSelf : array(), $removable),
$groups ); // Can't remove groups the user doesn't have
$addable = array_diff(
array_merge($this->isself ? $wgGroupsAddToSelf : array(), $addable),
$groups ); // Can't add groups the user does have
-
+
return array( $addable, $removable );
}
Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) .
wfMsgExt( 'editinguser', array( 'parse' ), wfEscapeWikiText( $user->getName() ) ) .
$grouplist .
- Xml::tags( 'p', null, $this->groupCheckboxes( $groups ) ) .
+ Xml::tags( 'p', null, $this->groupCheckboxes( $groups ) ) .
Xml::openElement( 'table', array( 'border' => '0', 'id' => 'mw-userrights-table-outer' ) ) .
"<tr>
<td colspan='2'>" .
}
// Okay, it's not so simple, we will have to go through the arrays
- $groups = array(
- 'add' => array(),
+ $groups = array(
+ 'add' => array(),
'remove' => array(),
'add-self' => $wgGroupsAddToSelf,
'remove-self' => $wgGroupsRemoveFromSelf);
} elseif( is_array($wgAddGroups[$group]) ) {
$groups['add'] = $wgAddGroups[$group];
}
-
+
// Same thing for remove
if( empty($wgRemoveGroups[$group]) ) {
} elseif($wgRemoveGroups[$group] === true ) {
}
return $groups;
}
-
+
/**
* Show a rights log fragment for the specified user
*
$wpp->doQuery( $offset, $limit );
}
-
-
return "Invalid title in result set; {$tsafe}";
}
}
-
+
/**
* Make a "what links here" link for a specified result if required
*
return null;
}
}
-
+
}
/**
$wpp->doQuery( $offset, $limit, !$inc );
}
-
-
$wgOut->addHtml( wfMsgWikiHtml( 'watchlistanontext', $llink ) );
return;
}
-
+
$wgOut->setPageTitle( wfMsg( 'watchlist' ) );
-
+
$sub = wfMsgExt( 'watchlistfor', 'parseinline', $wgUser->getName() );
$sub .= '<br />' . WatchlistEditor::buildTools( $wgUser->getSkin() );
$wgOut->setSubtitle( $sub );
$editor->execute( $wgUser, $wgOut, $wgRequest, $mode );
return;
}
-
+
$uid = $wgUser->getId();
if( $wgEnotifWatchlist && $wgRequest->getVal( 'reset' ) && $wgRequest->wasPosted() ) {
$wgUser->clearAllNotifications( $uid );
if( ! wfRunHooks('BeforeWatchlist', array($nondefaults, $wgUser, &$hookSql)) ) {
return;
}
-
+
if($nitems == 0) {
$wgOut->addWikiMsg( 'nowatchlist' );
return;
$label = $hideBots ? wfMsgHtml( 'watchlist-show-bots' ) : wfMsgHtml( 'watchlist-hide-bots' );
$linkBits = wfArrayToCGI( array( 'hideBots' => 1 - (int)$hideBots ), $nondefaults );
$links[] = $skin->makeKnownLinkObj( $thisTitle, $label, $linkBits );
-
+
# Hide/show own edits
$label = $hideOwn ? wfMsgHtml( 'watchlist-show-own' ) : wfMsgHtml( 'watchlist-hide-own' );
$linkBits = wfArrayToCGI( array( 'hideOwn' => 1 - (int)$hideOwn ), $nondefaults );
$from = (int)$from; // just in case
$tlConds[] = "tl_from >= $from";
$plConds[] = "pl_from >= $from";
- }
+ }
// Read an extra row as an at-end check
$queryLimit = $limit + 1;
- // enforce join order, sometimes namespace selector may
+ // enforce join order, sometimes namespace selector may
// trigger filesorts which are far less efficient than scanning many entries
$options[] = 'STRAIGHT_JOIN';
$rows[$row->page_id] = $row;
}
$dbr->freeResult( $plRes );
-
+
}
if( !$this->hidetrans ) {
while ( $row = $dbr->fetchObject( $tlRes ) ) {
'target=' . $nt->getPrefixedUrl()
);
$wgOut->addHtml( ' <span class="mw-whatlinkshere-tools">(' . $wlh . ')</span>' );
-
+
if ( $row->page_is_redirect ) {
if ( $level < 2 ) {
$this->showIndirectLinks( $level + 1, $nt, $wgMaxRedirectLinksRetrieved );
}
return '<p>' . implode( ' | ', $links ) . '</p>';
}
-
}
$wip->setPrefix( $prefix );
$wip->doQuery( $offset, $limit );
}
-
-
echo implode("<br />\n", $urlArr) . "<br />\n";
return;
}*/
-
+
if( empty( $urlArr ) ) {
return;
}
throw new MWException( 'Bad purge URL' );
}
$url = SquidUpdate::expand( $url );
-
+
// Construct a minimal HTCP request diagram
// as per RFC 2756
// Opcode 'CLR', no response desired, no auth
wfDebug( $text );
}
}
-
+
/**
* Expand local URLs to fully-qualified URLs using the internal protocol
* and host defined in $wgInternalServer. Input that's already fully-
return $url;
}
}
-
* Generic operation result class
* Has warning/error list, boolean status and arbitrary value
*
- * "Good" means the operation was completed with no warnings or errors.
+ * "Good" means the operation was completed with no warnings or errors.
*
* "OK" means the operation was partially or wholly completed.
*
- * An operation which is not OK should have errors so that the user can be
- * informed as to what went wrong. Calling the fatal() function sets an error
+ * An operation which is not OK should have errors so that the user can be
+ * informed as to what went wrong. Calling the fatal() function sets an error
* message and simultaneously switches off the OK flag.
*/
class Status {
}
function warning( $message /*, parameters... */ ) {
- $params = array_slice( func_get_args(), 1 );
- $this->errors[] = array(
- 'type' => 'warning',
- 'message' => $message,
+ $params = array_slice( func_get_args(), 1 );
+ $this->errors[] = array(
+ 'type' => 'warning',
+ 'message' => $message,
'params' => $params );
}
* This can be used for non-fatal errors
*/
function error( $message /*, parameters... */ ) {
- $params = array_slice( func_get_args(), 1 );
- $this->errors[] = array(
- 'type' => 'error',
- 'message' => $message,
+ $params = array_slice( func_get_args(), 1 );
+ $this->errors[] = array(
+ 'type' => 'error',
+ 'message' => $message,
'params' => $params );
}
* Add an error and set OK to false, indicating that the operation as a whole was fatal
*/
function fatal( $message /*, parameters... */ ) {
- $params = array_slice( func_get_args(), 1 );
- $this->errors[] = array(
- 'type' => 'error',
- 'message' => $message,
+ $params = array_slice( func_get_args(), 1 );
+ $this->errors[] = array(
+ 'type' => 'error',
+ 'message' => $message,
'params' => $params );
$this->ok = false;
}
protected function getItemXML( $item ) {
$params = $this->cleanParams( $item['params'] );
- $xml = "<{$item['type']}>\n" .
+ $xml = "<{$item['type']}>\n" .
Xml::element( 'message', null, $item['message'] ) . "\n" .
Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
foreach ( $params as $param ) {
/**
* Get the error list as a wikitext formatted list
- * @param string $shortContext A short enclosing context message name, to be used
+ * @param string $shortContext A short enclosing context message name, to be used
* when there is a single error
* @param string $longContext A long enclosing context message name, for a list
*/
$this->fatal( 'internalerror_info',
__METHOD__." called for a good result, this is incorrect\n" );
} else {
- $this->fatal( 'internalerror_info',
+ $this->fatal( 'internalerror_info',
__METHOD__.": Invalid result object: no error text but not OK\n" );
}
}
$this->failCount += $other->failCount;
}
}
-
$encScript = htmlspecialchars( $_SERVER['SCRIPT_NAME'] );
echo "<html><body>
<h1>File not found</h1>
-<p>Although this PHP script ($encScript) exists, the file requested for output
+<p>Although this PHP script ($encScript) exists, the file requested for output
($encFile) does not.</p>
</body></html>
";
// Cancel output buffering and gzipping if set
wfResetOutputBuffers();
-
+
$type = wfGetType( $fname );
if ( $type and $type!="unknown/unknown") {
header("Content-type: $type");
return $magic->guessMimeType($filename); //full fancy mime detection
}
}
-
-
*/
class StringUtils {
/**
- * Perform an operation equivalent to
+ * Perform an operation equivalent to
*
* preg_replace( "!$startDelim(.*?)$endDelim!", $replace, $subject );
*
* except that it's worst-case O(N) instead of O(N^2)
*
* Compared to delimiterReplace(), this implementation is fast but memory-
- * hungry and inflexible. The memory requirements are such that I don't
+ * hungry and inflexible. The memory requirements are such that I don't
* recommend using it on anything but guaranteed small chunks of text.
*/
static function hungryDelimiterReplace( $startDelim, $endDelim, $replace, $subject ) {
}
return $output;
}
-
+
/**
- * Perform an operation equivalent to
+ * Perform an operation equivalent to
*
* preg_replace_callback( "!$startDelim(.*)$endDelim!s$flags", $callback, $subject )
*
*/
# If the start delimiter ends with an initial substring of the end delimiter,
# e.g. in the case of C-style comments, the behaviour differs from the model
- # regex. In this implementation, the end must share no characters with the
- # start, so e.g. /*/ is not considered to be both the start and end of a
- # comment. /*/xy/*/ is considered to be a single comment with contents /xy/.
+ # regex. In this implementation, the end must share no characters with the
+ # start, so e.g. /*/ is not considered to be both the start and end of a
+ # comment. /*/xy/*/ is considered to be a single comment with contents /xy/.
static function delimiterReplaceCallback( $startDelim, $endDelim, $callback, $subject, $flags = '' ) {
$inputPos = 0;
$outputPos = 0;
$strcmp = strpos( $flags, 'i' ) === false ? 'strcmp' : 'strcasecmp';
$endLength = strlen( $endDelim );
$m = array();
-
- while ( $inputPos < strlen( $subject ) &&
- preg_match( "!($encStart)|($encEnd)!S$flags", $subject, $m, PREG_OFFSET_CAPTURE, $inputPos ) )
+
+ while ( $inputPos < strlen( $subject ) &&
+ preg_match( "!($encStart)|($encEnd)!S$flags", $subject, $m, PREG_OFFSET_CAPTURE, $inputPos ) )
{
$tokenOffset = $m[0][1];
if ( $m[1][0] != '' ) {
- if ( $foundStart &&
+ if ( $foundStart &&
$strcmp( $endDelim, substr( $subject, $tokenOffset, $endLength ) ) == 0 )
{
# An end match is present at the same location
}
/*
- * Perform an operation equivalent to
+ * Perform an operation equivalent to
*
* preg_replace( "!$startDelim(.*)$endDelim!$flags", $replace, $subject )
*
* @param string $startDelim Start delimiter regular expression
* @param string $endDelim End delimiter regular expression
- * @param string $replace Replacement string. May contain $1, which will be
+ * @param string $replace Replacement string. May contain $1, which will be
* replaced by the text between the delimiters
* @param string $subject String to search
* @return string The string with the matches replaced
*/
static function explodeMarkup( $separator, $text ) {
$placeholder = "\x00";
-
+
// Remove placeholder instances
$text = str_replace( $placeholder, '', $text );
-
+
// Replace instances of the separator inside HTML-like tags with the placeholder
$replacer = new DoubleReplacer( $separator, $placeholder );
$cleaned = StringUtils::delimiterReplaceCallback( '<', '>', $replacer->cb(), $text );
foreach( $items as $i => $str ) {
$items[$i] = str_replace( $placeholder, $separator, $str );
}
-
+
return $items;
}
}
/**
- * Base class for "replacers", objects used in preg_replace_callback() and
+ * Base class for "replacers", objects used in preg_replace_callback() and
* StringUtils::delimiterReplaceCallback()
*/
class Replacer {
$this->to = $to;
$this->index = $index;
}
-
+
function replace( $matches ) {
return str_replace( $this->from, $this->to, $matches[$this->index] );
}
return $result;
}
}
-
-
/**
* Class to implement stub globals, which are globals that delay loading the
- * their associated module code by deferring initialisation until the first
- * method call.
+ * their associated module code by deferring initialisation until the first
+ * method call.
*
- * Note on unstub loops:
+ * Note on unstub loops:
*
- * Unstub loops (infinite recursion) sometimes occur when a constructor calls
- * another function, and the other function calls some method of the stub. The
+ * Unstub loops (infinite recursion) sometimes occur when a constructor calls
+ * another function, and the other function calls some method of the stub. The
* best way to avoid this is to make constructors as lightweight as possible,
- * deferring any initialisation which depends on other modules. As a last
- * resort, you can use StubObject::isRealObject() to break the loop, but as a
- * general rule, the stub object mechanism should be transparent, and code
+ * deferring any initialisation which depends on other modules. As a last
+ * resort, you can use StubObject::isRealObject() to break the loop, but as a
+ * general rule, the stub object mechanism should be transparent, and code
* which refers to it should be kept to a minimum.
*/
class StubObject {
/**
* This function creates a new object of the real class and replace it in
* the global variable.
- * This is public, for the convenience of external callers wishing to access
+ * This is public, for the convenience of external callers wishing to access
* properties, e.g. eval.php
*
* @param String $name name of the method called in this object.
$variant = $wgContLang->getPreferredVariant();
if( $variant != $wgContLanguageCode )
$code = $variant;
- }
+ }
# Validate $code
if( empty( $code ) || !preg_match( '/^[a-z-]+$/', $code ) ) {
function __call( $name, $args ) {
return $this->_call( $name, $args );
}
-
+
function _newObject() {
global $wgCommandLineMode;
if( $wgCommandLineMode ) {
*/
static private $titleCache=array();
static private $interwikiCache=array();
-
-
+
+
/**
* All member variables should be considered private
* Please use the accessor functions
}
/**
- * Make an array of titles from an array of IDs
+ * Make an array of titles from an array of IDs
*/
public static function newFromIDs( $ids ) {
if ( !count( $ids ) ) {
}
return $titles;
}
-
+
/**
* Make a Title object from a DB row
* @param Row $row (needs at least page_title,page_namespace)
return $s->iw_url;
}
-
+
/**
* Fetch interwiki prefix data from local cache in constant database
*
$url = "{$wgScript}?title={$dbkey}&{$query}";
}
}
-
+
// FIXME: this causes breakage in various places when we
// actually expected a local URL and end up with dupe prefixes.
if ($wgRequest->getVal('action') == 'render') {
return true;
# Check regular protection levels
- foreach( $wgRestrictionTypes as $type ){
+ foreach( $wgRestrictionTypes as $type ){
if( $action == $type || $action == '' ) {
$r = $this->getRestrictions( $type );
foreach( $wgRestrictionLevels as $level ) {
if( NS_SPECIAL == $this->mNamespace ) {
$errors[] = array('ns-specialprotected');
}
-
+
if ( $this->isNamespaceProtected() ) {
$ns = $this->getNamespace() == NS_MAIN
? wfMsg( 'nstab-main' )
: $this->getNsText();
- $errors[] = (NS_MEDIAWIKI == $this->mNamespace
- ? array('protectedinterface')
+ $errors[] = (NS_MEDIAWIKI == $this->mNamespace
+ ? array('protectedinterface')
: array( 'namespaceprotected', $ns ) );
}
&& !preg_match('/^'.preg_quote($user->getName(), '/').'\//', $this->mTextform) ) {
$errors[] = array('customcssjsprotected');
}
-
+
if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) {
# We /could/ use the protection level on the source page, but it's fairly ugly
# as we have to establish a precedence hierarchy for pages included by multiple
}
}
}
-
+
foreach( $this->getRestrictions($action) as $right ) {
// Backwards compatibility, rewrite sysop -> protect
if ( $right == 'sysop' ) {
}
}
- if ($action == 'create') {
+ if ($action == 'create') {
$title_protection = $this->getTitleProtection();
if (is_array($title_protection)) {
}
$dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'protected_titles', '*',
+ $res = $dbr->select( 'protected_titles', '*',
array ('pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBkey()) );
if ($row = $dbr->fetchRow( $res )) {
public function deleteTitleProtection() {
$dbw = wfGetDB( DB_MASTER );
- $dbw->delete( 'protected_titles',
+ $dbw->delete( 'protected_titles',
array ('pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBkey()), __METHOD__ );
}
} else {
global $wgWhitelistRead;
- /**
+ /**
* Always grant access to the login page.
* Even anons need to be able to log in.
*/
*/
public function isSubpage() {
global $wgNamespacesWithSubpages;
-
+
if( isset( $wgNamespacesWithSubpages[ $this->mNamespace ] ) ) {
return ( strpos( $this->getText(), '/' ) !== false && $wgNamespacesWithSubpages[ $this->mNamespace ] == true );
} else {
return false;
}
}
-
+
/**
* Could this page contain custom CSS or JavaScript, based
* on the title?
$sources = $get_pages ? array() : false;
$now = wfTimestampNow();
$purgeExpired = false;
-
+
while( $row = $dbr->fetchObject( $res ) ) {
$expiry = Block::decodeExpiry( $row->pr_expiry );
if( $expiry > $now ) {
while ($row = $dbr->fetchObject( $res ) ) {
# Cycle through all the restrictions.
-
+
// Don't take care of restrictions types that aren't in $wgRestrictionTypes
if( !in_array( $row->pr_type, $wgRestrictionTypes ) )
continue;
}
return $this->mArticleID;
}
-
+
/**
* Is this an article that is a redirect page?
* Uses link cache, adding it if necessary
public function isRedirect( $flags = 0 ) {
if( !is_null($this->mRedirect) )
return $this->mRedirect;
- # Zero for special pages.
+ # Zero for special pages.
# Also, calling getArticleID() loads the field from cache!
if( !$this->getArticleID($flags) || $this->getNamespace() == NS_SPECIAL ) {
return false;
return $this->mRedirect;
}
-
+
/**
* What is the length of this page?
* Uses link cache, adding it if necessary
public function getLength( $flags = 0 ) {
if( $this->mLength != -1 )
return $this->mLength;
- # Zero for special pages.
+ # Zero for special pages.
# Also, calling getArticleID() loads the field from cache!
if( !$this->getArticleID($flags) || $this->getNamespace() == NS_SPECIAL ) {
return 0;
$this->mInterwiki = $this->mFragment = '';
$this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN
-
+
$dbkey = $this->mDbkeyform;
# Strip Unicode bidi override characters.
# override chars get included in list displays.
$dbkey = str_replace( "\xE2\x80\x8E", '', $dbkey ); // 200E LEFT-TO-RIGHT MARK
$dbkey = str_replace( "\xE2\x80\x8F", '', $dbkey ); // 200F RIGHT-TO-LEFT MARK
-
+
# Clean up whitespace
#
$dbkey = preg_replace( '/[ _]+/', '_', $dbkey );
{
return false;
}
-
+
/**
* Magic tilde sequences? Nu-uh!
*/
* Limit the size of titles to 255 bytes.
* This is typically the size of the underlying database field.
* We make an exception for special pages, which don't need to be stored
- * in the database, and may edge over 255 bytes due to subpage syntax
+ * in the database, and may edge over 255 bytes due to subpage syntax
* for long titles, e.g. [[Special:Block/Long name]]
*/
if ( ( $this->mNamespace != NS_SPECIAL && strlen( $dbkey ) > 255 ) ||
- strlen( $dbkey ) > 512 )
+ strlen( $dbkey ) > 512 )
{
return false;
}
return false;
}
// Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles.
- // IP names are not allowed for accounts, and can only be referring to
- // edits from the IP. Given '::' abbreviations and caps/lowercaps,
- // there are numerous ways to present the same IP. Having sp:contribs scan
- // them all is silly and having some show the edits and others not is
+ // IP names are not allowed for accounts, and can only be referring to
+ // edits from the IP. Given '::' abbreviations and caps/lowercaps,
+ // there are numerous ways to present the same IP. Having sp:contribs scan
+ // them all is silly and having some show the edits and others not is
// inconsistent. Same for talk/userpages. Keep them normalized instead.
- $dbkey = ($this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK) ?
+ $dbkey = ($this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK) ?
IP::sanitizeIP( $dbkey ) : $dbkey;
// Any remaining initial :s are illegal.
if ( $dbkey !== '' && ':' == $dbkey{0} ) {
return false;
}
-
+
# Fill fields
$this->mDbkeyform = $dbkey;
$this->mUrlform = wfUrlencode( $dbkey );
/**
* Set the fragment for this title
* This is kind of bad, since except for this rarely-used function, Title objects
- * are immutable. The reason this is here is because it's better than setting the
+ * are immutable. The reason this is here is because it's better than setting the
* members directly, which is what Linker::formatComment was doing previously.
*
* @param string $fragment text
$newarticle = new Article( $nt );
$wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() );
}
-
+
global $wgUser;
wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) );
return true;
} else {
$this->resetArticleID( 0 );
}
-
+
# Log the move
$log = new LogPage( 'move' );
$log->addEntry( 'move_redir', $this, $reason, array( 1 => $nt->getPrefixedText() ) );
# Return true if there was no history
return $row === false;
}
-
+
/**
* Can this title be added to a user's watchlist?
*
&& $this->getNamespace() == $title->getNamespace()
&& $this->getDBkey() === $title->getDBkey();
}
-
+
/**
* Return a string representation of this title
*
/**
* Update page_touched timestamps and send squid purge messages for
- * pages linking to this title. May be sent to the job queue depending
+ * pages linking to this title. May be sent to the job queue depending
* on the number of links. Typically called on create and delete.
*/
public function touchLinks() {
public function getTouched() {
$dbr = wfGetDB( DB_SLAVE );
$touched = $dbr->selectField( 'page', 'page_touched',
- array(
+ array(
'page_namespace' => $this->getNamespace(),
'page_title' => $this->getDBkey()
), __METHOD__
}
/**
- * If the Title refers to a special page alias which is not the local default,
+ * If the Title refers to a special page alias which is not the local default,
* returns a new Title which points to the local default. Otherwise, returns $this.
*/
public function fixSpecialName() {
class User {
/**
- * A list of default user toggles, i.e. boolean user preferences that are
- * displayed by Special:Preferences as checkboxes. This list can be
+ * A list of default user toggles, i.e. boolean user preferences that are
+ * displayed by Special:Preferences as checkboxes. This list can be
* extended via the UserToggles hook or $wgContLang->getExtraUserToggles().
*/
static public $mToggles = array(
/**
* List of member variables which are saved to the shared cache (memcached).
- * Any operation which changes the corresponding database fields must
+ * Any operation which changes the corresponding database fields must
* call a cache-clearing function.
*/
static $mCacheVars = array(
/**
* The cache variable declarations
*/
- var $mId, $mName, $mRealName, $mPassword, $mNewpassword, $mNewpassTime,
- $mEmail, $mOptions, $mTouched, $mToken, $mEmailAuthenticated,
+ var $mId, $mName, $mRealName, $mPassword, $mNewpassword, $mNewpassTime,
+ $mEmail, $mOptions, $mTouched, $mToken, $mEmailAuthenticated,
$mEmailToken, $mEmailTokenExpires, $mRegistration, $mGroups;
/**
var $mNewtalk, $mDatePreference, $mBlockedby, $mHash, $mSkin, $mRights,
$mBlockreason, $mBlock, $mEffectiveGroups;
- /**
+ /**
* Lightweight constructor for anonymous user
* Use the User::newFrom* factory functions for other kinds of users
*/
if ( $this->mId == 0 ) {
$this->loadDefaults();
return false;
- }
+ }
# Try cache
$key = wfMemcKey( 'user', 'id', $this->mId );
# Object is expired, load from DB
$data = false;
}
-
+
if ( !$data ) {
wfDebug( "Cache miss for user {$this->mId}\n" );
# Load from DB
* Static factory method for creation from username.
*
* This is slightly less efficient than newFromId(), so use newFromId() if
- * you have both an ID and a name handy.
+ * you have both an ID and a name handy.
*
* @param string $name Username, validated by Title:newFromText()
- * @param mixed $validate Validate username. Takes the same parameters as
- * User::getCanonicalName(), except that true is accepted as an alias
+ * @param mixed $validate Validate username. Takes the same parameters as
+ * User::getCanonicalName(), except that true is accepted as an alias
* for 'valid', for BC.
- *
- * @return User object, or null if the username is invalid. If the username
+ *
+ * @return User object, or null if the username is invalid. If the username
* is not present in the database, the result will be a user object with
- * a name, zero user ID and default settings.
+ * a name, zero user ID and default settings.
* @static
*/
static function newFromName( $name, $validate = 'valid' ) {
return null;
}
}
-
+
/**
* Create a new user object using data from session or cookies. If the
* login credentials are invalid, the result is an anonymous user.
*
* This function exists for username validation, in order to reject
* usernames which are similar in form to IP addresses. Strings such
- * as 300.300.300.300 will return true because it looks like an IP
+ * 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
* address because the usemod software would "cloak" anonymous IP
* addresses like this, if we allowed accounts like this to be created
* Check if $name is an IPv6 IP.
*/
static function isIPv6($name) {
- /*
- * if it has any non-valid characters, it can't be a valid IPv6
+ /*
+ * if it has any non-valid characters, it can't be a valid IPv6
* address.
*/
if (preg_match("/[^:a-fA-F0-9]/", $name))
": '$name' invalid due to ambiguous prefixes" );
return false;
}
-
+
// Check an additional blacklist of troublemaker characters.
// Should these be merged into the title char list?
$unicodeBlacklist = '/[' .
": '$name' invalid due to blacklisted characters" );
return false;
}
-
+
return true;
}
-
+
/**
* Usernames which fail to pass this function will be blocked
* from user login and new account registrations, but may be used
return
// Must be a valid username, obviously ;)
self::isValidUserName( $name ) &&
-
+
// Certain names may be reserved for batch processes.
!in_array( $name, $wgReservedUsernames );
}
-
+
/**
* Usernames which fail to pass this function will be blocked
* from new account registrations, but may be used internally
static function isCreatableName( $name ) {
return
self::isUsableName( $name ) &&
-
+
// Registration-time character blacklisting...
strpos( $name, '@' ) === false;
}
return $result;
if( $result === false )
return false;
-
+
// Password needs to be long enough, and can't be the same as the username
return strlen( $password ) >= $wgMinimalPasswordLength
&& $wgContLang->lc( $password ) !== $wgContLang->lc( $this->mName );
}
/**
- * Given unvalidated user input, return a canonical username, or false if
+ * Given unvalidated user input, return a canonical username, or false if
* the username is invalid.
* @param string $name
* @param mixed $validate Type of validation to use:
* Count the number of edits of a user
*
* It should not be static and some day should be merged as proper member function / deprecated -- domas
- *
+ *
* @param int $uid The user ID to check
* @return int
* @static
}
/**
- * Set cached properties to default. Note: this no longer clears
+ * Set cached properties to default. Note: this no longer clears
* uncached lazy-initialised properties. The constructor does that instead.
*
* @private
wfProfileOut( __METHOD__ );
}
-
+
/**
* Initialise php session
* @deprecated use wfSetupSession()
# Not a valid ID, loadFromId has switched the object to anon for us
return false;
}
-
+
if ( isset( $_SESSION['wsToken'] ) ) {
$passwordCorrect = $_SESSION['wsToken'] == $this->mToken;
$from = 'session';
return false;
}
}
-
+
/**
* Load user and user_group data from the database
* $this->mId must be set, this is how the user is identified.
- *
+ *
* @return true if the user exists, false if the user is anonymous
* @private
*/
$this->mEmailToken = $s->user_email_token;
$this->mEmailTokenExpires = wfTimestampOrNull( TS_MW, $s->user_email_token_expires );
$this->mRegistration = wfTimestampOrNull( TS_MW, $s->user_registration );
- $this->mEditCount = $s->user_editcount;
+ $this->mEditCount = $s->user_editcount;
$this->getEditCount(); // revalidation for nulls
# Load group data
}
/**
- * Clear various cached data stored in this object.
- * @param string $reloadFrom Reload user and user_groups table data from a
- * given source. May be "name", "id", "defaults", "session" or false for
+ * Clear various cached data stored in this object.
+ * @param string $reloadFrom Reload user and user_groups table data from a
+ * given source. May be "name", "id", "defaults", "session" or false for
* no reload.
*/
function clearInstanceCache( $reloadFrom = false ) {
wfProfileIn( __METHOD__ );
wfDebug( __METHOD__.": checking...\n" );
- $this->mBlockedby = 0;
+ $this->mBlockedby = 0;
$this->mHideName = 0;
$ip = wfGetIP();
}
/**
- * Set the user name.
+ * Set the user name.
*
- * This does not reload fields from the database according to the given
+ * This does not reload fields from the database according to the given
* name. Rather, it is used to create a temporary "nonexistent user" for
- * later addition to the database. It can also be used to set the IP
- * address for an anonymous user to something other than the current
+ * later addition to the database. It can also be used to set the IP
+ * address for an anonymous user to something other than the current
* remote IP.
*
* User::newFromName() has rougly the same function, when the named user
return array(array("wiki" => wfWikiID(), "link" => $utp->getLocalURL()));
}
-
+
/**
- * Perform a user_newtalk check, uncached.
+ * Perform a user_newtalk check, uncached.
* Use getNewtalk for a cached check.
- *
+ *
* @param string $field
* @param mixed $id
* @param bool $fromMaster True to fetch from the master, false for a slave
$this->invalidateCache();
}
}
-
+
/**
* Generate a current or new-future timestamp to be stored in the
* user_touched field when we update things.
global $wgClockSkewFudge;
return wfTimestamp( TS_MW, time() + $wgClockSkewFudge );
}
-
+
/**
* Clear user data from memcached.
* Use after applying fun updates to the database; caller's
$this->load();
if( $this->mId ) {
$this->mTouched = self::newTouchedTimestamp();
-
+
$dbw = wfGetDB( DB_MASTER );
$dbw->update( 'user',
array( 'user_touched' => $dbw->timestamp( $this->mTouched ) ),
array( 'user_id' => $this->mId ),
__METHOD__ );
-
+
$this->clearSharedCache();
}
}
*/
function setPassword( $str ) {
global $wgAuth;
-
+
if( $str !== null ) {
if( !$wgAuth->allowPasswordChange() ) {
throw new PasswordError( wfMsg( 'password-change-forbidden' ) );
}
-
+
if( !$this->isValidPassword( $str ) ) {
global $wgMinimalPasswordLength;
throw new PasswordError( wfMsg( 'passwordtooshort',
if( !$wgAuth->setPassword( $this, $str ) ) {
throw new PasswordError( wfMsg( 'externaldberror' ) );
}
-
+
$this->setInternalPassword( $str );
return true;
function setInternalPassword( $str ) {
$this->load();
$this->setToken();
-
+
if( $str === null ) {
// Save an invalid hash...
$this->mPassword = '';
$expiry = wfTimestamp( TS_UNIX, $this->mNewpassTime ) + $wgPasswordReminderResendTime * 3600;
return time() < $expiry;
}
-
+
function getEmail() {
$this->load();
return $this->mEmail;
}
/**
- * Get the user's date preference, including some important migration for
+ * Get the user's date preference, including some important migration for
* old user rows.
*/
function getDatePreference() {
function getBoolOption( $oname ) {
return (bool)$this->getOption( $oname );
}
-
+
/**
* Get an option as an integer value from the source string.
* @param string $oname The option to check
}
return $this->mEffectiveGroups;
}
-
+
/* Return the edit count for the user. This is where User::edits should have been */
function getEditCount() {
if ($this->mId) {
if ( !isset( $this->mEditCount ) ) {
/* Populate the count, if it has not been populated yet */
$this->mEditCount = User::edits($this->mId);
- }
+ }
return $this->mEditCount;
} else {
/* nil */
return null;
}
}
-
+
/**
* Add the user to the given group.
* This takes immediate effect.
return in_array( $action, $this->getRights() );
}
-
+
/**
* Check whether to enable recent changes patrol features for this user
* @return bool
global $wgUseRCPatrol;
return( $wgUseRCPatrol && ($this->isAllowed('patrol') || $this->isAllowed('patrolmarks')) );
}
-
+
/**
* Check whether to enable recent changes patrol features for this user
* @return bool
$this->load();
if ( wfReadOnly() ) { return; }
if ( 0 == $this->mId ) { return; }
-
+
$this->mTouched = self::newTouchedTimestamp();
$dbw = wfGetDB( DB_MASTER );
}
return $newUser;
}
-
+
/**
* Add an existing user object to the database
*/
}
return false;
}
-
+
/**
* Check if the given clear-text password matches the temporary password
* sent by e-mail for password reset operations.
}
/**
- * Return a URL the user can use to confirm their email address.
+ * Return a URL the user can use to confirm their email address.
* @param $token: accepts the email confirmation token
* @return string
* @private
$this->saveSettings();
return true;
}
-
+
/**
* Invalidate the user's email confirmation, unauthenticate the email
* if it was already confirmed and save.
return $confirmed;
}
}
-
+
/**
* Return true if there is an outstanding request for e-mail confirmation.
* @return bool
$this->mEmailToken &&
$this->mEmailTokenExpires > wfTimestamp();
}
-
+
/**
* Get the timestamp of account creation, or false for
* non-existent/anonymous user accounts
return $text;
}
}
-
+
/**
* Increment the user's edit-count field.
* Will have no effect for anonymous users.
array( 'user_editcount=user_editcount+1' ),
array( 'user_id' => $this->getId() ),
__METHOD__ );
-
+
// Lazy initialization check...
if( $dbw->affectedRows() == 0 ) {
// Pull from a slave to be less cruel to servers
'COUNT(rev_user)',
array( 'rev_user' => $this->getId() ),
__METHOD__ );
-
+
// Now here's a goddamn hack...
if( $dbr !== $dbw ) {
// If we actually have a slave server, the count is
// count we just read includes the revision that was
// just added in the working transaction.
}
-
+
$dbw->update( 'user',
array( 'user_editcount' => $count ),
array( 'user_id' => $this->getId() ),
$this->invalidateCache();
}
}
-
-
-
# In the following $headers = expression we removed "Reply-To: {$from}\r\n" , because it is treated differently
# (fifth parameter of the PHP mail function, see some lines below)
- # Line endings need to be different on Unix and Windows due to
+ # Line endings need to be different on Unix and Windows due to
# the bug described at http://trac.wordpress.org/ticket/2603
if ( wfIsWindows() ) {
$body = str_replace( "\n", "\r\n", $body );
/**@}}*/
/**
- * Send emails corresponding to the user $editor editing the page $title.
+ * Send emails corresponding to the user $editor editing the page $title.
* Also updates wl_notificationtimestamp.
*
* May be deferred via the job queue.
*/
function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) {
global $wgEnotifUseJobQ;
-
+
if( $title->getNamespace() < 0 )
return;
}
/*
- * Immediate version of notifyOnPageChange().
+ * Immediate version of notifyOnPageChange().
*
- * Send emails corresponding to the user $editor editing the page $title.
+ * Send emails corresponding to the user $editor editing the page $title.
* Also updates wl_notificationtimestamp.
*
* @param $editor User object
// Send updates to watchers other than the current editor
$userCondition = 'wl_user <> ' . intval( $editor->getId() );
if ( $userTalkId !== false ) {
- // Already sent an email to this person
+ // Already sent an email to this person
$userCondition .= ' AND wl_user <> ' . intval( $userTalkId );
}
$dbr = wfGetDB( DB_SLAVE );
foreach ( $res as $row ) {
$watchingUser = User::newFromId( $row->wl_user );
- if ( $watchingUser->getOption( 'enotifwatchlistpages' ) &&
- ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) &&
- $watchingUser->isEmailConfirmed() )
+ if ( $watchingUser->getOption( 'enotifwatchlistpages' ) &&
+ ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) &&
+ $watchingUser->isEmailConfirmed() )
{
$this->compose( $watchingUser );
}
if ($wgEnotifImpersonal && $this->oldid)
/*
- * For impersonal mail, show a diff link to the last
+ * For impersonal mail, show a diff link to the last
* revision.
*/
$keys['$NEWPAGE'] = wfMsgForContent('enotif_lastdiff',
}
/**
- * Same as sendPersonalised but does impersonal mail suitable for bulk
+ * Same as sendPersonalised but does impersonal mail suitable for bulk
* mailing. Takes an array of MailAddress objects.
*/
function sendImpersonal( $addresses ) {
array( wfMsgForContent('enotif_impersonal_salutation'),
$wgLang->timeanddate($this->timestamp, true, false, false)),
$this->body);
-
+
return UserMailer::send($addresses, $this->from, $this->subject, $body, $this->replyto);
}
function wfRFC822Phrase( $s ) {
return UserMailer::rfc822Phrase( $s );
}
+
function userMailer( $to, $from, $subject, $body, $replyto=null ) {
return UserMailer::send( $to, $from, $subject, $body, $replyto );
}
$this->name = $name;
$this->id = intval( $id );
}
-
+
/**
* Confirm the selected database name is a valid local interwiki database name.
* @return bool
global $wgLocalDatabases;
return in_array( $database, $wgLocalDatabases );
}
-
+
public static function whoIs( $database, $id ) {
$user = self::newFromId( $database, $id );
if( $user ) {
return false;
}
}
-
+
/**
* Factory function; get a remote user entry by ID number.
* @return UserRightsProxy or null if doesn't exist
public static function newFromName( $database, $name ) {
return self::newFromLookup( $database, 'user_name', $name );
}
-
+
private static function newFromLookup( $database, $field, $value ) {
$db = self::getDB( $database );
if( $db ) {
}
return null;
}
-
+
public function getId() {
return $this->id;
}
-
+
public function isAnon() {
return $this->getId() == 0;
}
-
+
public function getName() {
return $this->name . '@' . $this->database;
}
-
+
public function getUserPage() {
return Title::makeTitle( NS_USER, $this->getName() );
}
-
+
// Replaces getUserGroups()
function getGroups() {
$res = $this->db->select( 'user_groups',
}
return $groups;
}
-
+
// replaces addUserGroup
function addGroup( $group ) {
$this->db->insert( 'user_groups',
__METHOD__,
array( 'IGNORE' ) );
}
-
+
// replaces removeUserGroup
function removeGroup( $group ) {
$this->db->delete( 'user_groups',
),
__METHOD__ );
}
-
+
// replaces touchUser
function invalidateCache() {
$this->db->update( 'user',
$wgMemc->delete( $key );
}
}
-
-?>
"\xf0\x90\x90\xa4" => "\xf0\x90\x91\x8c",
"\xf0\x90\x90\xa5" => "\xf0\x90\x91\x8d"
);
-
-
$dbw->replace( 'watchlist', array(array( 'wl_user', 'wl_namespace', 'wl_title')), $values, $fname );
return true;
}
-
-
}
-
-
$this->showNormalForm( $output, $user );
}
}
-
+
/**
* Check the edit token from a form submission
*
* @return bool
*/
private function checkToken( $request, $user ) {
- return $user->matchEditToken( $request->getVal( 'token' ), 'watchlistedit' );
+ return $user->matchEditToken( $request->getVal( 'token' ), 'watchlistedit' );
}
-
+
/**
* Extract a list of titles from a blob of text, returning
* (prefixed) strings; unwatchable titles are ignored
}
return array_unique( $titles );
}
-
+
/**
* Print out a list of linked titles
*
*/
private function showTitles( $titles, $output, $skin ) {
$talk = wfMsgHtml( 'talkpagelinktext' );
- // Do a batch existence check
+ // Do a batch existence check
$batch = new LinkBatch();
foreach( $titles as $title ) {
if( !$title instanceof Title )
}
$output->addHtml( "</ul>\n" );
}
-
+
/**
* Count the number of titles on a user's watchlist, excluding talk pages
*
$row = $dbr->fetchObject( $res );
return ceil( $row->count / 2 ); // Paranoia
}
-
+
/**
* Prepare a list of titles on a user's watchlist (excluding talk pages)
* and return an array of (prefixed) strings
* @return array
*/
private function getWatchlist( $user ) {
- $list = array();
+ $list = array();
$dbr = wfGetDB( DB_MASTER );
$res = $dbr->select(
'watchlist',
if( $title instanceof Title && !$title->isTalkPage() )
$list[] = $title->getPrefixedText();
}
- $res->free();
+ $res->free();
}
return $list;
}
-
+
/**
* Get a list of titles on a user's watchlist, excluding talk pages,
* and return as a two-dimensional array with namespace, title and
}
return $titles;
}
-
+
/**
* Show a message indicating the number of items on the user's watchlist,
* and return this count for additional checking
}
return $count;
}
-
+
/**
* Remove all titles from a user's watchlist
*
}
}
}
-
+
/**
* Show the standard watchlist editing form
*
$output->addHtml( $form );
}
}
-
+
/**
* Get the correct "heading" for a namespace
*
? wfMsgHtml( 'blanknamespace' )
: htmlspecialchars( $GLOBALS['wgContLang']->getFormattedNsText( $namespace ) );
}
-
+
/**
* Build a single list item containing a check box selecting a title
* and a link to that title, with various additional bits
. Xml::check( 'titles[]', false, array( 'value' => $title->getPrefixedText() ) )
. $link . ' (' . implode( ' | ', $tools ) . ')' . '</li>';
}
-
+
/**
* Show a form for editing the watchlist in "raw" mode
*
$form .= '</fieldset></form>';
$output->addHtml( $form );
}
-
+
/**
* Determine whether we are editing the watchlist, and if so, what
* kind of editing operation
return false;
}
}
-
+
/**
* Build a set of links for convenient navigation
* between watchlist viewing and editing modes
}
return implode( ' | ', $tools );
}
-
}
/**
- * Some entry points may use this file without first enabling the
+ * Some entry points may use this file without first enabling the
* autoloader.
*/
if ( !function_exists( '__autoload' ) ) {
var $data = array();
var $headers;
private $_response;
-
+
function __construct() {
/// @fixme This preemptive de-quoting can interfere with other web libraries
/// and increases our memory footprint. It would be cleaner to do on
/// demand; but currently we have no wrapper for $_SERVER etc.
$this->checkMagicQuotes();
-
+
// POST overrides GET data
// We don't use $_REQUEST here to avoid interference from cookies...
$this->data = wfArrayMerge( $_GET, $_POST );
}
-
+
/**
* Check for title, action, and/or variant data in the URL
* and interpolate it into the GET variables.
$a = parse_url( $url );
if( $a ) {
$path = isset( $a['path'] ) ? $a['path'] : '';
-
+
global $wgScript;
if( $path == $wgScript ) {
// Script inside a rewrite path?
}
// Raw PATH_INFO style
$matches = $this->extractTitle( $path, "$wgScript/$1" );
-
+
global $wgArticlePath;
if( !$matches && $wgArticlePath ) {
$matches = $this->extractTitle( $path, $wgArticlePath );
}
-
+
global $wgActionPaths;
if( !$matches && $wgActionPaths ) {
$matches = $this->extractTitle( $path, $wgActionPaths, 'action' );
}
-
+
global $wgVariantArticlePath, $wgContLang;
if( !$matches && $wgVariantArticlePath ) {
$variantPaths = array();
// http://bugs.php.net/bug.php?id=31892
// Also reported when ini_get('cgi.fix_pathinfo')==false
$matches['title'] = substr( $_SERVER['ORIG_PATH_INFO'], 1 );
-
+
} elseif ( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') ) {
// Regular old PATH_INFO yay
$matches['title'] = substr( $_SERVER['PATH_INFO'], 1 );
}
}
}
-
+
/**
* Internal URL rewriting function; tries to extract page title and,
* optionally, one other fixed parameter value from a URL path.
/**
* Fetch a scalar from the input or return $default if it's not set.
- * Returns a string. Arrays are discarded. Useful for
- * non-freeform text inputs (e.g. predefined internal text keys
+ * Returns a string. Arrays are discarded. Useful for
+ * non-freeform text inputs (e.g. predefined internal text keys
* selected by a drop-down menu). For freeform input, see getText().
*
* @param string $name
return (array)$val;
}
}
-
+
/**
* Fetch an array of integers, or return $default if it's not set.
* If source was scalar, will return an array with a single element.
* set. \r is 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
+ * input (for which input transformations may be required - e.g. Esperanto
* x-coding).
*
* @param string $name
*
* Other than this the name is not verified for being a safe filename.
*
- * @param $key String:
+ * @param $key String:
* @return string or NULL if no such file.
*/
function getFileName( $key ) {
wfDebug( "WebRequest::getFileName() '" . $_FILES[$key]['name'] . "' normalized to '$name'\n" );
return $name;
}
-
+
/**
- * Return a handle to WebResponse style object, for setting cookies,
+ * Return a handle to WebResponse style object, for setting cookies,
* headers and other stuff, for Request being worked on.
*/
function response() {
/* Lazy initialization of response object for this request */
if (!is_object($this->_response)) {
$this->_response = new WebResponse;
- }
+ }
return $this->_response;
}
}
}
-
-
setcookie($name,$value,$expire, $wgCookiePath, $wgCookieDomain, $wgCookieSecure);
}
}
-
-
<?php
-# This does the initial setup for a web request. It does some security checks,
-# starts the profiler and loads the configuration, and optionally loads
+# This does the initial setup for a web request. It does some security checks,
+# starts the profiler and loads the configuration, and optionally loads
# Setup.php depending on whether MW_NO_SETUP is defined.
# Test for PHP bug which breaks PHP 5.0.x on 64-bit...
if ( !defined( 'MW_NO_SETUP' ) ) {
require_once( './includes/Setup.php' );
}
-
// Compatibility with old search URLs which didn't use Special:Search
// Just check for presence here, so blank requests still
// show the search page when using ugly URLs (bug 8054).
-
+
// Do this above the read whitelist check for security...
$title = SpecialPage::getTitleFor( 'Search' );
}
$title = SpecialPage::getTitleFor( 'Badtitle' );
throw new ErrorPageError( 'badtitle', 'badtitletext' );
}
- } else if ( ( $action == 'view' ) && !$request->wasPosted() &&
+ } else if ( ( $action == 'view' ) && !$request->wasPosted() &&
(!isset( $this->GET['title'] ) || $title->getPrefixedDBKey() != $this->GET['title'] ) &&
!count( array_diff( array_keys( $this->GET ), array( 'action', 'title' ) ) ) )
{
/**
* Cleaning up by doing deferred updates, calling LBFactory and doing the output
*
- * @param Array $deferredUpdates array of updates to do
+ * @param Array $deferredUpdates array of updates to do
* @param OutputPage $output
*/
function finalCleanup ( &$deferredUpdates, &$output ) {
wfProfileOut( __METHOD__ );
return;
}
-
+
$dbw = wfGetDB( DB_MASTER );
foreach( $updates as $up ) {
$up->doUpdate();
}
}; /* End of class MediaWiki */
-
global $wgContLang;
$namespaces = $wgContLang->getFormattedNamespaces();
$options = array();
-
+
// Godawful hack... we'll be frequently passed selected namespaces
// as strings since PHP is such a shithole.
// But we also don't want blanks and nulls and "all"s matching 0,
if( preg_match( '/^\d+$/', $selected ) ) {
$selected = intval( $selected );
}
-
+
if( !is_null( $all ) )
$namespaces = array( $all => wfMsg( 'namespacesall' ) ) + $namespaces;
foreach( $namespaces as $index => $name ) {
$name = wfMsg( 'blanknamespace' );
$options[] = self::option( $name, $index, $index === $selected );
}
-
+
return Xml::openElement( 'select', array( 'id' => 'namespace', 'name' => $element_name,
'class' => 'namespaceselector' ) )
. "\n"
. "\n"
. Xml::closeElement( 'select' );
}
-
+
/**
- * Create a date selector
- *
- * @param $selected Mixed: the month which should be selected, default ''
- * @param $allmonths String: value of a special item denoting all month. Null to not include (default)
- * @param string $id Element identifier
- * @return String: Html string containing the month selector
- */
- public static function monthSelector( $selected = '', $allmonths = null, $id = 'month' ) {
- global $wgLang;
- $options = array();
- if( is_null( $selected ) )
- $selected = '';
- if( !is_null( $allmonths ) )
- $options[] = self::option( wfMsg( 'monthsall' ), $allmonths, $selected === $allmonths );
- for( $i = 1; $i < 13; $i++ )
- $options[] = self::option( $wgLang->getMonthName( $i ), $i, $selected === $i );
- return self::openElement( 'select', array( 'id' => $id, 'name' => 'month', 'class' => 'mw-month-selector' ) )
- . implode( "\n", $options )
- . self::closeElement( 'select' );
+ * Create a date selector
+ *
+ * @param $selected Mixed: the month which should be selected, default ''
+ * @param $allmonths String: value of a special item denoting all month. Null to not include (default)
+ * @param string $id Element identifier
+ * @return String: Html string containing the month selector
+ */
+ public static function monthSelector( $selected = '', $allmonths = null, $id = 'month' ) {
+ global $wgLang;
+ $options = array();
+ if( is_null( $selected ) )
+ $selected = '';
+ if( !is_null( $allmonths ) )
+ $options[] = self::option( wfMsg( 'monthsall' ), $allmonths, $selected === $allmonths );
+ for( $i = 1; $i < 13; $i++ )
+ $options[] = self::option( $wgLang->getMonthName( $i ), $i, $selected === $i );
+ return self::openElement( 'select', array( 'id' => $id, 'name' => 'month', 'class' => 'mw-month-selector' ) )
+ . implode( "\n", $options )
+ . self::closeElement( 'select' );
}
/**
/**
* Build a drop-down box from a textual list.
- *
+ *
* @param mixed $name Name and id for the drop-down
* @param mixed $class CSS classes for the drop-down
* @param mixed $other Text for the "Other reasons" option
public static function listDropDown( $name= '', $list = '', $other = '', $selected = '', $class = '', $tabindex = Null ) {
$options = '';
$optgroup = false;
-
+
$options = self::option( $other, 'other', $selected === 'other' );
-
+
foreach ( explode( "\n", $list ) as $option) {
$value = trim( $option );
if ( $value == '' ) {
}
}
if( $optgroup ) $options .= self::closeElement('optgroup');
-
+
$attribs = array();
if( $name ) {
$attribs['id'] = $name;
"<" => "\\x3c",
">" => "\\x3e",
- # To avoid any complaints about bad entity refs
+ # To avoid any complaints about bad entity refs
"&" => "\\x26",
-
+
# Work around https://bugzilla.mozilla.org/show_bug.cgi?id=274152
# Encode certain Unicode formatting chars so affected
# versions of Gecko don't misinterpret our strings;
/**
* Encode a variable of unknown type to JavaScript.
- * Arrays are converted to JS arrays, objects are converted to JS associative
- * arrays (objects). So cast your PHP associative arrays to objects before
+ * Arrays are converted to JS arrays, objects are converted to JS associative
+ * arrays (objects). So cast your PHP associative arrays to objects before
* passing them to here.
*/
public static function encodeJsVar( $value ) {
if ( $s != '{' ) {
$s .= ', ';
}
- $s .= '"' . self::escapeJsString( $name ) . '": ' .
+ $s .= '"' . self::escapeJsString( $name ) . '": ' .
self::encodeJsVar( $elt );
}
$s .= '}';
}
return $s;
}
-
+
/**
* Check if a string is well-formed XML.
$in );
}
}
-
}
function wfIsWellFormedXmlFragment( $text ) {
return Xml::isWellFormedXmlFragment( $text );
-}
\ No newline at end of file
+}
* well-formed XML. Note that this doesn't check schema validity.
*/
public $wellFormed = false;
-
+
/**
* Name of the document's root element, including any namespace
* as an expanded URL.
*/
public $rootElement = '';
-
+
private $softNamespaces;
private $namespaces = array();
-
+
/**
* @param $file string filename
* @param $softNamespaces bool
$this->softNamespaces = $softNamespaces;
$this->run( $file );
}
-
+
private function run( $fname ) {
if( $this->softNamespaces ) {
$parser = xml_parser_create( 'UTF-8' );
} else {
$parser = xml_parser_create_ns( 'UTF-8' );
}
-
+
// case folding violates XML standard, turn it off
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-
+
xml_set_element_handler( $parser, array( $this, 'elementOpen' ), false );
$file = fopen( $fname, "rb" );
return;
}
} while( !feof( $file ) );
-
+
$this->wellFormed = true;
-
+
fclose( $file );
xml_parser_free( $parser );
}
$this->namespaces[substr( $attrib, strlen( 'xmlns:' ) )] = $val;
}
}
-
+
if( strpos( $name, ':' ) === false ) {
$ns = '';
$subname = $name;
} else {
list( $ns, $subname ) = explode( ':', $name, 2 );
}
-
+
if( isset( $this->namespaces[$ns] ) ) {
$name = $this->namespaces[$ns] . ':' . $subname;
} else {
// But..... we'll just let it slide in soft mode.
}
}
-
+
// We only need the first open element
$this->rootElement = $name;
xml_set_element_handler( $parser, false, false );
/**
* This abstract class implements many basic API functions, and is the base of all API classes.
* The class functions are divided into several areas of functionality:
- *
+ *
* Module parameters: Derived classes can define getAllowedParams() to specify which parameters to expect,
* how to parse and validate them.
- *
+ *
* Profiling: various methods to allow keeping tabs on various tasks and their time costs
- *
+ *
* Self-documentation: code to allow api to document its own state.
- *
+ *
* @addtogroup API
*/
abstract class ApiBase {
*****************************************************************************/
/**
- * Evaluates the parameters, performs the requested query, and sets up the
- * result. Concrete implementations of ApiBase must override this method to
+ * Evaluates the parameters, performs the requested query, and sets up the
+ * result. Concrete implementations of ApiBase must override this method to
* provide whatever functionality their module offers. Implementations must
* not produce any output on their own and are not expected to handle any
- * errors.
+ * errors.
*
* The execute method will be invoked directly by ApiMain immediately before
* the result of the module is output. Aside from the constructor, implementations
* should assume that no other methods will be called externally on the module
* before the result is processed.
*
- * The result data should be stored in the result object referred to by
+ * The result data should be stored in the result object referred to by
* "getResult()". Refer to ApiResult.php for details on populating a result
* object.
*/
public abstract function getVersion();
/**
- * Get the name of the module being executed by this instance
+ * Get the name of the module being executed by this instance
*/
public function getModuleName() {
return $this->mModuleName;
}
/**
- * Get parameter prefix (usually two letters or an empty string).
+ * Get parameter prefix (usually two letters or an empty string).
*/
public function getModulePrefix() {
return $this->mModulePrefix;
- }
+ }
/**
- * Get the name of the module as shown in the profiler log
+ * Get the name of the module as shown in the profiler log
*/
public function getModuleProfileName($db = false) {
if ($db)
}
/**
- * Returns true if this module is the main module ($this === $this->mMainModule),
+ * Returns true if this module is the main module ($this === $this->mMainModule),
* false otherwise.
*/
public function isMain() {
}
/**
- * Set warning section for this module. Users should monitor this section to
+ * Set warning section for this module. Users should monitor this section to
* notice any changes in API.
*/
public function setWarning($warning) {
/**
* If the module may only be used with a certain format module,
* it should override this method to return an instance of that formatter.
- * A value of null means the default format will be used.
+ * A value of null means the default format will be used.
*/
public function getCustomPrinter() {
return null;
$versions = $this->getVersion();
$pattern = '(\$.*) ([0-9a-z_]+\.php) (.*\$)';
$replacement = '\\0' . "\n " . 'http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/api/\\2';
-
+
if (is_array($versions)) {
foreach ($versions as &$v)
$v = eregi_replace($pattern, $replacement, $v);
return $msg;
}
- /**
+ /**
* Generates the parameter descriptions for this module, to be displayed in the
* module's help.
*/
$intRangeStr = "The value must be no more than {$paramSettings[self :: PARAM_MAX]}";
else
$intRangeStr = "The value must be between {$paramSettings[self :: PARAM_MIN]} and {$paramSettings[self :: PARAM_MAX]}";
-
+
$desc .= $paramPrefix . $intRangeStr;
}
break;
/**
* This method mangles parameter name based on the prefix supplied to the constructor.
- * Override this method to change parameter name during runtime
+ * Override this method to change parameter name during runtime
*/
public function encodeParamName($paramName) {
return $this->mModulePrefix . $paramName;
}
/**
- * Get a value for the given parameter
+ * Get a value for the given parameter
*/
protected function getParameter($paramName, $parseMaxLimit = true) {
$params = $this->getAllowedParams();
$value = is_array($value) ? array_map('intval', $value) : intval($value);
$min = isset ($paramSettings[self :: PARAM_MIN]) ? $paramSettings[self :: PARAM_MIN] : null;
$max = isset ($paramSettings[self :: PARAM_MAX]) ? $paramSettings[self :: PARAM_MAX] : null;
-
+
if (!is_null($min) || !is_null($max)) {
$values = is_array($value) ? $value : array($value);
foreach ($values as $v) {
/**
* Return an array of values that were given in a 'a|b|c' notation,
* after it optionally validates them against the list allowed values.
- *
+ *
* @param valueName - The name of the parameter (for error reporting)
* @param value - The value being parsed
* @param allowMultiple - Can $value contain more than one value separated by '|'?
* @param allowedValues - An array of values to check against. If null, all values are accepted.
- * @return (allowMultiple ? an_array_of_values : a_single_value)
+ * @return (allowMultiple ? an_array_of_values : a_single_value)
*/
protected function parseMultiValue($valueName, $value, $allowMultiple, $allowedValues) {
if( trim($value) === "" )
}
/**
- * Call main module's error handler
+ * Call main module's error handler
*/
public function dieUsage($description, $errorCode, $httpRespCode = 0) {
throw new UsageException($description, $this->encodeParamName($errorCode), $httpRespCode);
}
-
+
/**
* Array that maps message keys to error messages. $1 and friends are replaced.
*/
// This one MUST be present, or dieUsageMsg() will recurse infinitely
'unknownerror' => array('code' => 'unknownerror', 'info' => "Unknown error: ``\$1''"),
'unknownerror-nocode' => array('code' => 'unknownerror', 'info' => 'Unknown error'),
-
+
// Messages from Title::getUserPermissionsErrors()
'ns-specialprotected' => array('code' => 'unsupportednamespace', 'info' => "Pages in the Special namespace can't be edited"),
'protectedinterface' => array('code' => 'protectednamespace-interface', 'info' => "You're not allowed to edit interface messages"),
'confirmedittext' => array('code' => 'confirmemail', 'info' => "You must confirm your e-mail address before you can edit"),
'blockedtext' => array('code' => 'blocked', 'info' => "You have been blocked from editing"),
'autoblockedtext' => array('code' => 'autoblocked', 'info' => "Your IP address has been blocked automatically, because it was used by a blocked user"),
-
+
// Miscellaneous interface messages
'actionthrottledtext' => array('code' => 'ratelimited', 'info' => "You've exceeded your rate limit. Please wait some time and try again"),
'alreadyrolled' => array('code' => 'alreadyrolled', 'info' => "The page you tried to rollback was already rolled back"),
- 'cantrollback' => array('code' => 'onlyauthor', 'info' => "The page you tried to rollback only has one author"),
+ 'cantrollback' => array('code' => 'onlyauthor', 'info' => "The page you tried to rollback only has one author"),
'readonlytext' => array('code' => 'readonly', 'info' => "The wiki is currently in read-only mode"),
'sessionfailure' => array('code' => 'badtoken', 'info' => "Invalid token"),
'cannotdelete' => array('code' => 'cantdelete', 'info' => "Couldn't delete ``\$1''. Maybe it was deleted already by someone else"),
'ipb_already_blocked' => array('code' => 'alreadyblocked', 'info' => "The user you tried to block was already blocked"),
'ipb_blocked_as_range' => array('code' => 'blockedasrange', 'info' => "IP address ``\$1'' was blocked as part of range ``\$2''. You can't unblock the IP invidually, but you can unblock the range as a whole."),
'ipb_cant_unblock' => array('code' => 'cantunblock', 'info' => "The block you specified was not found. It may have been unblocked already"),
-
+
// API-specific messages
'missingparam' => array('code' => 'no$1', 'info' => "The \$1 parameter must be set"),
'invalidtitle' => array('code' => 'invalidtitle', 'info' => "Bad title ``\$1''"),
'blankpage' => array('code' => 'emptypage', 'info' => "Creating new, empty pages is not allowed"),
'editconflict' => array('code' => 'editconflict', 'info' => "Edit conflict detected"),
);
-
+
/**
* Output the error message related to a certain array
* @param array $error Element of a getUserPermissionsErrors()
public function isEditMode() {
return false;
}
-
+
/**
* Indicates whether this module must be called with a POST request
*/
/**
* When modules crash, sometimes it is needed to do a profileOut() regardless
- * of the profiling state the module was in. This method does such cleanup.
+ * of the profiling state the module was in. This method does such cleanup.
*/
public function safeProfileOut() {
if ($this->mTimeIn !== 0) {
ApiBase :: dieDebug(__METHOD__, 'called without calling profileDBOut() first');
return $this->mDBTime;
}
-
+
public static function debugPrint($value, $name = 'unknown', $backtrace = false) {
print "\n\n<pre><b>Debuging value '$name':</b>\n\n";
var_export($value);
*/
public static function getBaseVersion() {
return __CLASS__ . ': $Id$';
- }
+ }
}
-
/**
- * API module that facilitates deleting pages. The API eqivalent of action=delete.
+ * API module that facilitates deleting pages. The API eqivalent of action=delete.
* Requires API write mode to be enabled.
*
* @addtogroup API
/**
* Extracts the title, token, and reason from the request parameters and invokes
- * the local delete() function with these as arguments. It does not make use of
- * the delete function specified by Article.php. If the deletion succeeds, the
- * details of the article deleted and the reason for deletion are added to the
+ * the local delete() function with these as arguments. It does not make use of
+ * the delete function specified by Article.php. If the deletion succeeds, the
+ * details of the article deleted and the reason for deletion are added to the
* result object.
*/
public function execute() {
global $wgUser;
$this->getMain()->requestWriteMode();
$params = $this->extractRequestParams();
-
+
$titleObj = NULL;
if(!isset($params['title']))
$this->dieUsageMsg(array('missingparam', 'title'));
$articleObj = new Article($titleObj);
$reason = (isset($params['reason']) ? $params['reason'] : NULL);
$retval = self::delete($articleObj, $params['token'], $reason);
-
+
if(!empty($retval))
// We don't care about multiple errors, just report one of them
$this->dieUsageMsg(current($retval));
-
+
if($params['watch'] || $wgUser->getOption('watchdeletion'))
$articleObj->doWatch();
else if($params['unwatch'])
return array();
return array(array('cannotdelete', $article->mTitle->getPrefixedText()));
}
-
+
public function mustBePosted() { return true; }
-
+
public function getAllowedParams() {
return array (
'title' => null,
$this->dieUsageMsg(array('missingparam', 'token'));
if(!$wgUser->matchEditToken($params['token']))
$this->dieUsageMsg(array('sessionfailure'));
-
+
$titleObj = Title::newFromText($params['title']);
if(!$titleObj)
$this->dieUsageMsg(array('invalidtitle', $params['title']));
if($params['createonly'] && $titleObj->exists())
$this->dieUsageMsg(array('createonly-exists'));
-
+
// Now let's check whether we're even allowed to do this
$errors = $titleObj->getUserPermissionsErrors('edit', $wgUser);
if(!$titleObj->exists())
$this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection");
$reqArr['wpSection'] = $params['section'];
}
-
+
if($params['watch'])
$watch = true;
else if($params['unwatch'])
{
$r['result'] = "Failure";
$this->getResult()->addValue(null, $this->getModuleName(), $r);
- return;
- }
+ return;
+ }
else
$this->dieUsageMsg(array('hookaborted'));
}
$wgRequest = $oldRequest;
-
+
# Do the actual save
$oldRevId = $articleObj->getRevIdFetched();
$result = null;
public function getAllowedParams() {
return array (
- 'title' => array(
+ 'title' => array(
ApiBase :: PARAM_DFLT => 'API',
),
'text' => null
return __CLASS__ . ': $Id$';
}
}
-
* This action allows users to get their watchlist items in RSS/Atom formats.
* When executed, it performs a nested call to the API to get the needed data,
* and formats it in a proper format.
- *
+ *
* @addtogroup API
*/
class ApiFeedWatchlist extends ApiBase {
* Wrap the result as an RSS/Atom feed.
*/
public function execute() {
-
+
global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
try {
$params = $this->extractRequestParams();
-
+
// limit to the number of hours going from now back
$endTime = wfTimestamp(TS_MW, time() - intval($params['hours'] * 60 * 60));
-
+
$dbr = wfGetDB( DB_SLAVE );
// Prepare parameters for nested request
$fauxReqArr = array (
// Create the request
$fauxReq = new FauxRequest ( $fauxReqArr );
-
+
// Execute
$module = new ApiMain($fauxReq);
$module->execute();
// Get data array
$data = $module->getResultData();
-
+
$feedItems = array ();
foreach ($data['query']['watchlist'] as $info) {
$feedItems[] = $this->createFeedItem($info);
}
-
+
$feedTitle = $wgSitename . ' - ' . wfMsgForContent('watchlist') . ' [' . $wgContLanguageCode . ']';
$feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullUrl();
-
+
$feed = new $wgFeedClasses[$params['feedformat']] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
-
+
ApiFormatFeedWrapper :: setResult($this->getResult(), $feed, $feedItems);
} catch (Exception $e) {
// Error results should not be cached
$this->getMain()->setCacheMaxAge(0);
-
+
$feedTitle = $wgSitename . ' - Error - ' . wfMsgForContent('watchlist') . ' [' . $wgContLanguageCode . ']';
$feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullUrl();
-
- $feedFormat = isset($params['feedformat']) ? $params['feedformat'] : 'rss';
+
+ $feedFormat = isset($params['feedformat']) ? $params['feedformat'] : 'rss';
$feed = new $wgFeedClasses[$feedFormat] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
return __CLASS__ . ': $Id$';
}
}
-
/**
* This is the abstract base class for API formatters.
- *
+ *
* @addtogroup API
*/
abstract class ApiFormatBase extends ApiBase {
/**
* If formatter outputs data results as is, the results must first be sanitized.
* An XML formatter on the other hand uses special tags, such as "_element" for special handling,
- * and thus needs to override this function to return true.
+ * and thus needs to override this function to return true.
*/
public function getNeedsRawData() {
return false;
/**
* Returns true when an HTML filtering printer should be used.
- * The default implementation assumes that formats ending with 'fm'
- * should be formatted in HTML.
+ * The default implementation assumes that formats ending with 'fm'
+ * should be formatted in HTML.
*/
public function getIsHtml() {
return $this->mIsHtml;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
-<?php if ($this->mUnescapeAmps) {
+<?php if ($this->mUnescapeAmps) {
?> <title>MediaWiki API</title>
<?php } else {
?> <title>MediaWiki API Result</title>
<small>
You are looking at the HTML representation of the <?php echo( $this->mFormat ); ?> format.<br/>
HTML is good for debugging, but probably is not suitable for your application.<br/>
-See <a href='http://www.mediawiki.org/wiki/API'>complete documentation</a>, or
+See <a href='http://www.mediawiki.org/wiki/API'>complete documentation</a>, or
<a href='<?php echo( $script ); ?>'>API help</a> for more information.
</small>
<?php
public function setHelp( $help = true ) {
$this->mHelp = true;
}
-
+
/**
* Prety-print various elements in HTML format, such as xml tags and URLs.
* This method also replaces any '<' with <
// make strings inside $ italic
$text = ereg_replace("\\$[^<>\n]+\\$", '<b><i>\\0</i></b>', $text);
}
-
+
/* Temporary fix for bad links in help messages. As a special case,
* XML-escaped metachars are de-escaped one level in the help message
* for legibility. Should be removed once we have completed a fully-html
}
/**
- * This printer is used to wrap an instance of the Feed class
+ * This printer is used to wrap an instance of the Feed class
* @addtogroup API
*/
class ApiFormatFeedWrapper extends ApiFormatBase {
wfHttpError(500, 'Internal Server Error', '');
}
}
-
+
public function getVersion() {
return __CLASS__ . ': $Id$';
}
return __CLASS__ . ': $Id$';
}
}
-
return __CLASS__ . ': $Id$';
}
}
-
*/
function encode2($var)
{
- if ($this->pretty) {
+ if ($this->pretty) {
$close = "\n" . str_repeat("\t", $this->indent);
$open = $close . "\t";
$mid = ',' . $open;
$this->indent++;
$elements = array_map(array($this, 'encode2'), $var);
$this->indent--;
-
+
foreach($elements as $element) {
if(Services_JSON::isError($element)) {
return $element;
// element in an associative array,
// for now
$parts = array();
-
+
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// "name":value pair
$key = $this->decode($parts[1]);
}
}
-
}
-
-
return __CLASS__ . ': $Id$';
}
}
-
return __CLASS__ . ': $Id$';
}
}
-
return __CLASS__ . ': $Id$';
}
}
-
public function getNeedsRawData() {
return true;
}
-
+
public function setRootElement($rootElemName) {
$this->mRootElemName = $rootElemName;
}
public function execute() {
$params = $this->extractRequestParams();
$this->mDoubleQuote = $params['xmldoublequote'];
-
+
$this->printText('<?xml version="1.0" encoding="utf-8"?>');
$this->recXmlPrint($this->mRootElemName, $this->getResultData(), $this->getIsHtml() ? -2 : null);
}
switch (gettype($elemValue)) {
case 'array' :
if (isset ($elemValue['*'])) {
- $subElemContent = $elemValue['*'];
+ $subElemContent = $elemValue['*'];
if ($this->mDoubleQuote)
$subElemContent = $this->doubleQuote($subElemContent);
unset ($elemValue['*']);
foreach ($elemValue as $subElemId => & $subElemValue) {
if (is_string($subElemValue) && $this->mDoubleQuote)
$subElemValue = $this->doubleQuote($subElemValue);
-
+
if (gettype($subElemId) === 'integer') {
$indElements[] = $subElemValue;
unset ($elemValue[$subElemId]);
private function doubleQuote( $text ) {
return Sanitizer::encodeAttribute( $text );
}
-
+
public function getAllowedParams() {
return array (
'xmldoublequote' => false
);
}
-
+
public function getDescription() {
return 'Output data in XML format' . parent :: getDescription();
}
return __CLASS__ . ': $Id$';
}
}
-
return __CLASS__ . ': $Id$';
}
}
-
<?php
- /**
+ /**
* Spyc -- A Simple PHP YAML Class
* @version 0.2.3 -- 2006-02-04
* @author Chris Wanstrath <chris@ozmm.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
- /**
+ /**
* A node, used by Spyc for parsing YAML.
* @addtogroup API
*/
/**#@+
* @access public
* @var string
- */
+ */
var $parent;
var $id;
/**#@-*/
- /**
+ /**
* @access public
* @var mixed
*/
var $data;
- /**
+ /**
* @access public
* @var int
*/
var $indent;
- /**
+ /**
* @access public
* @var bool
*/
* @addtogroup API
*/
class Spyc {
-
+
/**
* Load YAML into a PHP array statically
*
- * The load method, when supplied with a YAML stream (string or file),
- * will do its best to convert YAML in a file into a PHP array. Pretty
+ * The load method, when supplied with a YAML stream (string or file),
+ * will do its best to convert YAML in a file into a PHP array. Pretty
* simple.
- * Usage:
+ * Usage:
* <code>
* $array = Spyc::YAMLLoad('lucky.yml');
* print_r($array);
$spyc = new Spyc;
return $spyc->load($input);
}
-
+
/**
* Dump YAML from PHP array statically
*
* save the returned string as nothing.yml and pass it around.
*
* Oh, and you can decide how big the indent is and what the wordwrap
- * for folding is. Pretty cool -- just pass in 'false' for either if
+ * for folding is. Pretty cool -- just pass in 'false' for either if
* you want to use the default.
*
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
* @static
* @return string
* @param array $array PHP array
- * @param int $indent Pass in false to use the default, which is 2
+ * @param int $indent Pass in false to use the default, which is 2
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
*/
public static function YAMLDump($array,$indent = false,$wordwrap = false) {
$spyc = new Spyc;
return $spyc->dump($array,$indent,$wordwrap);
}
-
+
/**
* Load YAML into a PHP array from an instantiated object
*
- * The load method, when supplied with a YAML stream (string or file path),
+ * The load method, when supplied with a YAML stream (string or file path),
* will do its best to convert the YAML into a PHP array. Pretty simple.
- * Usage:
+ * Usage:
* <code>
* $parser = new Spyc;
* $array = $parser->load('lucky.yml');
function load($input) {
// See what type of input we're talking about
// If it's not a file, assume it's a string
- if (!empty($input) && (strpos($input, "\n") === false)
+ if (!empty($input) && (strpos($input, "\n") === false)
&& file_exists($input)) {
$yaml = file($input);
} else {
$this->_lastNode = $base->id;
$this->_inBlock = false;
$this->_isInline = false;
-
+
foreach ($yaml as $linenum => $line) {
$ifchk = trim($line);
' with a tab. YAML only recognizes spaces. Please reformat.';
die($err);
}
-
+
if ($this->_inBlock === false && empty($ifchk)) {
continue;
} elseif ($this->_inBlock == true && empty($ifchk)) {
// Create a new node and get its indent
$node = new YAMLNode;
$node->indent = $this->_getIndent($line);
-
+
// Check where the node lies in the hierarchy
if ($this->_lastIndent == $node->indent) {
// If we're in a block, add the text to the parent's data
$node->parent = $this->_allNodes[$this->_lastNode]->parent;
}
}
- } elseif ($this->_lastIndent < $node->indent) {
+ } elseif ($this->_lastIndent < $node->indent) {
if ($this->_inBlock === true) {
$parent =& $this->_allNodes[$this->_lastNode];
$parent->data[key($parent->data)] .= trim($line).$this->_blockEnd;
} elseif ($this->_inBlock === false) {
// The current node's parent is the previous node
$node->parent = $this->_lastNode;
-
- // If the value of the last node's data was > or | we need to
- // start blocking i.e. taking in all lines as a text value until
+
+ // If the value of the last node's data was > or | we need to
+ // start blocking i.e. taking in all lines as a text value until
// we drop our indent.
$parent =& $this->_allNodes[$node->parent];
$this->_allNodes[$node->parent]->children = true;
if ($chk === '>') {
$this->_inBlock = true;
$this->_blockEnd = ' ';
- $parent->data[key($parent->data)] =
+ $parent->data[key($parent->data)] =
str_replace('>','',$parent->data[key($parent->data)]);
$parent->data[key($parent->data)] .= trim($line).' ';
$this->_allNodes[$node->parent]->children = false;
} elseif ($chk === '|') {
$this->_inBlock = true;
$this->_blockEnd = "\n";
- $parent->data[key($parent->data)] =
+ $parent->data[key($parent->data)] =
str_replace('|','',$parent->data[key($parent->data)]);
$parent->data[key($parent->data)] .= trim($line)."\n";
$this->_allNodes[$node->parent]->children = false;
$this->_inBlock = false;
if ($this->_blockEnd = "\n") {
$last =& $this->_allNodes[$this->_lastNode];
- $last->data[key($last->data)] =
+ $last->data[key($last->data)] =
trim($last->data[key($last->data)]);
}
}
-
+
// We don't know the parent of the node so we have to find it
// foreach ($this->_allNodes as $n) {
foreach ($this->_indentSort[$node->indent] as $n) {
}
}
}
-
+
if ($this->_inBlock === false) {
// Set these properties with information from our current node
$this->_lastIndent = $node->indent;
$this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id];
// Add a reference to the node in a References array if this node
// has a YAML reference in it.
- if (
+ if (
( (is_array($node->data)) &&
isset($node->data[key($node->data)]) &&
(!is_array($node->data[key($node->data)])) )
&&
- ( (preg_match('/^&([^ ]+)/',$node->data[key($node->data)]))
- ||
+ ( (preg_match('/^&([^ ]+)/',$node->data[key($node->data)]))
+ ||
(preg_match('/^\*([^ ]+)/',$node->data[key($node->data)])) )
) {
$this->_haveRefs[] =& $this->_allNodes[$node->id];
) {
// Incomplete reference making code. Ugly, needs cleaned up.
foreach ($node->data[key($node->data)] as $d) {
- if ( !is_array($d) &&
- ( (preg_match('/^&([^ ]+)/',$d))
- ||
+ if ( !is_array($d) &&
+ ( (preg_match('/^&([^ ]+)/',$d))
+ ||
(preg_match('/^\*([^ ]+)/',$d)) )
) {
$this->_haveRefs[] =& $this->_allNodes[$node->id];
}
}
unset($node);
-
+
// Here we travel through node-space and pick out references (& and *)
$this->_linkReferences();
-
+
// Build the PHP array out of node-space
$trunk = $this->_buildArray();
return $trunk;
}
-
+
/**
* Dump PHP array to YAML
*
* save the returned string as tasteful.yml and pass it around.
*
* Oh, and you can decide how big the indent is and what the wordwrap
- * for folding is. Pretty cool -- just pass in 'false' for either if
+ * for folding is. Pretty cool -- just pass in 'false' for either if
* you want to use the default.
*
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
* @access public
* @return string
* @param array $array PHP array
- * @param int $indent Pass in false to use the default, which is 2
+ * @param int $indent Pass in false to use the default, which is 2
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
*/
function dump($array,$indent = false,$wordwrap = false) {
} else {
$this->_dumpIndent = $indent;
}
-
+
if ($wordwrap === false or !is_numeric($wordwrap)) {
$this->_dumpWordWrap = 40;
} else {
$this->_dumpWordWrap = $wordwrap;
}
-
+
// New YAML document
$string = "---\n";
-
+
// Start at the base of the array and move through it.
foreach ($array as $key => $value) {
$string .= $this->_yamlize($key,$value,0);
}
return $string;
}
-
+
/**** Private Properties ****/
-
+
/**#@+
* @access private
* @var mixed
- */
+ */
var $_haveRefs;
var $_allNodes;
var $_lastIndent;
/**#@-*/
/**** Private Methods ****/
-
+
/**
* Attempts to convert a key / value array item to YAML
* @access private
* @param $key The name of the key
* @param $value The value of the item
* @param $indent The indent of the current node
- */
+ */
function _yamlize($key,$value,$indent) {
if (is_array($value)) {
// It has children. What to do?
}
return $string;
}
-
+
/**
* Attempts to convert an array to YAML
* @access private
* @return string
* @param $array The array you want to convert
* @param $indent The indent of the current level
- */
+ */
function _yamlizeArray($array,$indent) {
if (is_array($array)) {
$string = '';
# or is a number or contains newlines
return (bool)(gettype($value) == "string" &&
(is_numeric($value) ||
- strpos($value, "\n") ||
- preg_match("/[#:]/", $value) ||
+ strpos($value, "\n") ||
+ preg_match("/[#:]/", $value) ||
preg_match("/^[-?,[\]{}!*&|>'\"%@`]/", $value)));
-
+
}
-
+
/**
* Returns YAML from a key and a value
* @access private
* @param $key The name of the key
* @param $value The value of the item
* @param $indent The indent of the current node
- */
+ */
function _dumpNode($key,$value,$indent) {
// do some folding here, for blocks
if ($this->_needLiteral($value)) {
$value = $this->_doLiteralBlock($value,$indent);
- } else {
+ } else {
$value = $this->_doFolding($value,$indent);
}
-
+
$spaces = str_repeat(' ',$indent);
if (is_int($key)) {
// It's a sequence
- if ($value)
+ if ($value)
$string = $spaces.'- '.$value."\n";
else
$string = $spaces . "-\n";
* Creates a literal block for dumping
* @access private
* @return string
- * @param $value
+ * @param $value
* @param $indent int The value of the indent
- */
+ */
function _doLiteralBlock($value,$indent) {
$exploded = explode("\n",$value);
$newValue = '|';
}
return $newValue;
}
-
+
/**
* Folds a string of text, if necessary
* @access private
if ($this->_dumpWordWrap === 0) {
return $value;
}
-
+
if (strlen($value) > $this->_dumpWordWrap) {
$indent += $this->_dumpIndent;
$indent = str_repeat(' ',$indent);
}
return $value;
}
-
+
/* Methods used in loading */
-
+
/**
* Finds and returns the indentation of a YAML line
* @access private
* @param string $line A line from the YAML file
*/
function _parseLine($line) {
- $line = trim($line);
+ $line = trim($line);
$array = array();
}
return $array;
}
-
+
/**
* Finds the type of the passed value, returns the value as the new type.
* @access private
*/
function _toType($value) {
$matches = array();
- if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) {
+ if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) {
$value = (string)preg_replace('/(\'\'|\\\\\')/',"'",end($matches));
$value = preg_replace('/\\\\"/','"',$value);
} elseif (preg_match('/^\\[(.+)\\]$/',$value,$matches)) {
// Take out strings sequences and mappings
$explode = $this->_inlineEscape($matches[1]);
-
+
// Propogate value array
$value = array();
foreach ($explode as $v) {
$value = NULL;
} elseif (ctype_digit($value)) {
$value = (int)$value;
- } elseif (in_array(strtolower($value),
+ } elseif (in_array(strtolower($value),
array('true', 'on', '+', 'yes', 'y'))) {
$value = TRUE;
- } elseif (in_array(strtolower($value),
+ } elseif (in_array(strtolower($value),
array('false', 'off', '-', 'no', 'n'))) {
$value = FALSE;
} elseif (is_numeric($value)) {
// Just a normal string, right?
$value = trim(preg_replace('/#(.+)$/','',$value));
}
-
+
return $value;
}
-
+
/**
* Used in inlines to check for more inlines or quoted strings
* @access private
// While pure sequences seem to be nesting just fine,
// pure mappings and mappings with sequences inside can't go very
// deep. This needs to be fixed.
-
- // Check for strings
+
+ // Check for strings
$regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
$strings = array();
if (preg_match_all($regex,$inline,$strings)) {
$saved_strings[] = $strings[0][0];
- $inline = preg_replace($regex,'YAMLString',$inline);
+ $inline = preg_replace($regex,'YAMLString',$inline);
}
unset($regex);
$inline = preg_replace('/\[(.+)\]/U','YAMLSeq',$inline);
$seqs = $seqs[0];
}
-
+
// Check for mappings
$maps = array();
if (preg_match_all('/{(.+)}/U',$inline,$maps)) {
$inline = preg_replace('/{(.+)}/U','YAMLMap',$inline);
$maps = $maps[0];
}
-
+
$explode = explode(', ',$inline);
// Re-add the strings
}
}
}
-
+
// Re-add the mappings
if (!empty($maps)) {
$i = 0;
return $explode;
}
-
+
/**
* Builds the PHP array from all the YAML nodes we've gathered
* @access private
$trunk = $this->_array_kmerge($trunk,$n->data);
}
}
-
+
return $trunk;
}
-
+
/**
* Traverses node-space and sets references (& and *) accordingly
* @access private
if (!empty($node->data)) {
$key = key($node->data);
// If it's an array, don't check.
- if (is_array($node->data[$key])) {
+ if (is_array($node->data[$key])) {
foreach ($node->data[$key] as $k => $v) {
$this->_linkRef($node,$key,$k,$v);
}
$this->_linkRef($node,$key);
}
}
- }
+ }
}
return true;
}
-
+
function _linkRef(&$n,$key,$k = NULL,$v = NULL) {
if (empty($k) && empty($v)) {
// Look for &refs
if (preg_match('/^&([^ ]+)/',$n->data[$key],$matches)) {
// Flag the node so we know it's a reference
$this->_allNodes[$n->id]->ref = substr($matches[0],1);
- $this->_allNodes[$n->id]->data[$key] =
+ $this->_allNodes[$n->id]->data[$key] =
substr($n->data[$key],strlen($matches[0])+1);
// Look for *refs
} elseif (preg_match('/^\*([^ ]+)/',$n->data[$key],$matches)) {
if (preg_match('/^&([^ ]+)/',$v,$matches)) {
// Flag the node so we know it's a reference
$this->_allNodes[$n->id]->ref = substr($matches[0],1);
- $this->_allNodes[$n->id]->data[$key][$k] =
+ $this->_allNodes[$n->id]->data[$key][$k] =
substr($v,strlen($matches[0])+1);
// Look for *refs
} elseif (preg_match('/^\*([^ ]+)/',$v,$matches)) {
}
}
}
-
+
/**
* Finds the children of a node and aids in the building of the PHP array
* @access private
}
return $return;
}
-
+
/**
* Turns a node's data and its children's data into a PHP array
*
}
return true;
}
-
+
/**
* Merges arrays and maintains numeric keys.
* @param array $arr2
* @return array
*/
- function _array_kmerge($arr1,$arr2) {
- if(!is_array($arr1))
- $arr1 = array();
+ function _array_kmerge($arr1,$arr2) {
+ if(!is_array($arr1))
+ $arr1 = array();
if(!is_array($arr2))
- $arr2 = array();
-
- $keys1 = array_keys($arr1);
- $keys2 = array_keys($arr2);
- $keys = array_merge($keys1,$keys2);
- $vals1 = array_values($arr1);
- $vals2 = array_values($arr2);
- $vals = array_merge($vals1,$vals2);
- $ret = array();
-
- foreach($keys as $key) {
+ $arr2 = array();
+
+ $keys1 = array_keys($arr1);
+ $keys2 = array_keys($arr2);
+ $keys = array_merge($keys1,$keys2);
+ $vals1 = array_values($arr1);
+ $vals2 = array_values($arr2);
+ $vals = array_merge($vals1,$vals2);
+ $ret = array();
+
+ foreach($keys as $key) {
list( /* unused */ ,$val) = each($vals);
// This is the good part! If a key already exists, but it's part of a
// sequence (an int), just keep addin numbers until we find a fresh one.
while (array_key_exists($key, $ret)) {
$key++;
}
- }
- $ret[$key] = $val;
- }
+ }
+ $ret[$key] = $val;
+ }
- return $ret;
+ return $ret;
}
}
-
/**
* This is a simple class to handle action=help
- *
+ *
* @addtogroup API
*/
class ApiHelp extends ApiBase {
return __CLASS__ . ': $Id$';
}
}
-
* @addtogroup API
*/
class ApiLogin extends ApiBase {
-
+
/**
* Time (in seconds) a user must wait after submitting
* a bad login (will be multiplied by the THROTTLE_FACTOR for each bad attempt)
* attempts is increased every failed attempt.
*/
const THROTTLE_FACTOR = 2;
-
+
/**
- * The maximum number of failed logins after which the wait increase stops.
+ * The maximum number of failed logins after which the wait increase stops.
*/
const THOTTLE_MAX_COUNT = 10;
-
+
public function __construct($main, $action) {
parent :: __construct($main, $action, 'lg');
}
$result['details'] = "Please wait " . self::THROTTLE_TIME . " seconds before next log-in attempt";
}
// if we were allowed to try to login, memcache is fine
-
+
$this->getResult()->addValue(null, 'login', $result);
}
-
+
/**
- * Caches a bad-login attempt associated with the host and with an
- * expiry of $this->mLoginThrottle. These are cached by a key
+ * Caches a bad-login attempt associated with the host and with an
+ * expiry of $this->mLoginThrottle. These are cached by a key
* separate from that used by the captcha system--as such, logging
* in through the standard interface will get you a legal session
* and cookies to prove it, but will not remove this entry.
*
- * Returns the number of seconds until next login attempt will be allowed.
+ * Returns the number of seconds until next login attempt will be allowed.
*
* @access private
*/
private function cacheBadLogin() {
global $wgMemc;
-
+
$key = $this->getMemCacheKey();
$val = $wgMemc->get( $key );
} else {
$val['count'] = 1 + $val['count'];
}
-
+
$delay = ApiLogin::calculateDelay($val['count']);
-
+
$wgMemc->delete($key);
// Cache expiration should be the maximum timeout - to prevent a "try and wait" attack
- $wgMemc->add( $key, $val, ApiLogin::calculateDelay(ApiLogin::THOTTLE_MAX_COUNT) );
-
+ $wgMemc->add( $key, $val, ApiLogin::calculateDelay(ApiLogin::THOTTLE_MAX_COUNT) );
+
return $delay;
}
-
+
/**
- * How much time the client must wait before it will be
+ * How much time the client must wait before it will be
* allowed to try to log-in next.
* The return value is 0 if no wait is required.
*/
private function getNextLoginTimeout() {
global $wgMemc;
-
+
$val = $wgMemc->get($this->getMemCacheKey());
$elapse = (time() - $val['lastReqTime']); // in seconds
return $canRetryIn < 0 ? 0 : $canRetryIn;
}
-
+
/**
* Based on the number of previously attempted logins, returns
* the delay (in seconds) when the next login attempt will be allowed.
$count = $count > self::THOTTLE_MAX_COUNT ? self::THOTTLE_MAX_COUNT : $count;
return self::THROTTLE_TIME + self::THROTTLE_TIME * ($count - 1) * self::THROTTLE_FACTOR;
- }
+ }
/**
- * Internal cache key for badlogin checks. Robbed from the
+ * Internal cache key for badlogin checks. Robbed from the
* ConfirmEdit extension and modified to use a key unique to the
* API login.3
*
private function getMemCacheKey() {
return wfMemcKey( 'apilogin', 'badlogin', 'ip', wfGetIP() );
}
-
+
public function mustBePosted() { return true; }
public function getAllowedParams() {
'This is to prevent password guessing by automated password crackers.'
);
}
-
+
protected function getExamples() {
return array(
'api.php?action=login&lgname=user&lgpassword=password'
return __CLASS__ . ': $Id$';
}
}
-
}
/**
- * API module to allow users to log out of the wiki. API equivalent of
+ * API module to allow users to log out of the wiki. API equivalent of
* Special:Userlogout.
*
* @addtogroup API
*
* To use API from another application, run it using FauxRequest object, in which
* case any internal exceptions will not be handled but passed up to the caller.
- * After successful execution, use getResult() for the resulting data.
- *
+ * After successful execution, use getResult() for the resulting data.
+ *
* @addtogroup API
*/
class ApiMain extends ApiBase {
'help' => 'ApiHelp',
'paraminfo' => 'ApiParamInfo',
);
-
+
private static $WriteModules = array (
'rollback' => 'ApiRollback',
'delete' => 'ApiDelete',
parent :: __construct($this, $this->mInternalMode ? 'main_int' : 'main');
if (!$this->mInternalMode) {
-
+
// Impose module restrictions.
- // If the current user cannot read,
+ // If the current user cannot read,
// Remove all modules other than login
global $wgUser;
-
+
if( $request->getVal( 'callback' ) !== null ) {
// JSON callback allows cross-site reads.
// For safety, strip user credentials.
wfDebug( "API: stripping user credentials for JSON callback\n" );
$wgUser = new User();
}
-
+
if (!$wgUser->isAllowed('read')) {
self::$Modules = array(
'login' => self::$Modules['login'],
'logout' => self::$Modules['logout'],
'help' => self::$Modules['help'],
- );
+ );
}
}
public function createPrinterByName($format) {
return new $this->mFormats[$format] ($this, $format);
}
-
+
/**
* Schedule a database commit
*/
}
/**
- * Execute api request. Any errors will be handled if the API was called by the remote client.
+ * Execute api request. Any errors will be handled if the API was called by the remote client.
*/
public function execute() {
$this->profileIn();
/**
* Replace the result data with the information about an exception.
- * Returns the error code
+ * Returns the error code
*/
protected function substituteResultWithError($e) {
-
+
// Printer may not be initialized if the extractRequestParams() fails for the main module
if (!isset ($this->mPrinter)) {
// The printer has not been created yet. Try to manually get formatter value.
$errMessage = array (
'code' => $e->getCodeString(),
'info' => $e->getMessage());
-
+
// Only print the help message when this is for the developer, not runtime
if ($this->mPrinter->getIsHtml() || $this->mAction == 'help')
ApiResult :: setContent($errMessage, $this->makeHelpMsg());
// Instantiate the module requested by the user
$module = new $this->mModules[$this->mAction] ($this, $this->mAction);
-
+
if( $module->shouldCheckMaxlag() && isset( $params['maxlag'] ) ) {
// Check for maxlag
global $wgShowHostnames;
return;
}
}
-
+
if (!$this->mInternalMode) {
// Ignore mustBePosted() for internal calls
if($module->mustBePosted() && !$this->mRequest->wasPosted())
protected function printResult($isError) {
$printer = $this->mPrinter;
$printer->profileIn();
-
+
/* If the help message is requested in the default (xmlfm) format,
* tell the printer not to escape ampersands so that our links do
* not break. */
- $printer->setUnescapeAmps ( ( $this->mAction == 'help' || $isError )
+ $printer->setUnescapeAmps ( ( $this->mAction == 'help' || $isError )
&& $this->getParameter('format') == ApiMain::API_DEFAULT_FORMAT );
$printer->initPrinter($isError);
'',
);
}
-
+
/**
* Returns an array of strings with credits for the API
*/
* Override the parent to generate help messages for all available modules.
*/
public function makeHelpMsg() {
-
+
$this->mPrinter->setHelp();
// Use parent to make default message for the main module
$msg .= $msg2;
$msg .= "\n";
}
-
+
$msg .= "\n*** Credits: ***\n " . implode("\n ", $this->getCredits()) . "\n";
-
+
return $msg;
}
public static function makeHelpMsgHeader($module, $paramName) {
$modulePrefix = $module->getModulePrefix();
if (!empty($modulePrefix))
- $modulePrefix = "($modulePrefix) ";
-
+ $modulePrefix = "($modulePrefix) ";
+
return "* $paramName={$module->getModuleName()} $modulePrefix*";
- }
+ }
private $mIsBot = null;
private $mIsSysop = null;
private $mCanApiHighLimits = null;
-
+
/**
* Returns true if the currently logged in user is a bot, false otherwise
* OBSOLETE, use canApiHighLimits() instead
}
return $this->mIsBot;
}
-
+
/**
* Similar to isBot(), this method returns true if the logged in user is
* a sysop, and false if not.
return $this->mIsSysop;
}
-
+
public function canApiHighLimits() {
if (!isset($this->mCanApiHighLimits)) {
global $wgUser;
/**
* Add or overwrite a module in this ApiMain instance. Intended for use by extending
- * classes who wish to add their own modules to their lexicon or override the
+ * classes who wish to add their own modules to their lexicon or override the
* behavior of inherent ones.
*
* @access protected
protected function addFormat( $fmtName, $fmtClass ) {
$this->mFormats[$fmtName] = $fmtClass;
}
-
+
/**
* Get the array mapping module names to class names
*/
/**
* This exception will be thrown when dieUsage is called to stop module execution.
* The exception handling code will print a help screen explaining how this API may be used.
- *
+ *
* @addtogroup API
*/
class UsageException extends Exception {
return "{$this->getCodeString()}: {$this->getMessage()}";
}
}
-
-
-
public function __construct($main, $action) {
parent :: __construct($main, $action);
}
-
+
public function execute() {
global $wgUser;
$this->getMain()->requestWriteMode();
$params = $this->extractRequestParams();
if(is_null($params['reason']))
$params['reason'] = '';
-
+
$titleObj = NULL;
if(!isset($params['from']))
$this->dieUsageMsg(array('missingparam', 'from'));
// Run getUserPermissionsErrors() here so we get message arguments too,
// rather than just a message key. The latter is troublesome for messages
// that use arguments.
- // FIXME: moveTo() should really return an array, requires some
+ // FIXME: moveTo() should really return an array, requires some
// refactoring of other code, though (mainly SpecialMovepage.php)
$errors = array_merge($fromTitle->getUserPermissionsErrors('move', $wgUser),
$fromTitle->getUserPermissionsErrors('edit', $wgUser),
$r = array('from' => $fromTitle->getPrefixedText(), 'to' => $toTitle->getPrefixedText(), 'reason' => $params['reason']);
if(!$params['noredirect'] || !$wgUser->isAllowed('suppressredirect'))
$r['redirectcreated'] = '';
-
+
if($params['movetalk'] && $fromTalk->exists() && !$fromTitle->isTalkPage())
{
// We need to move the talk page as well
{
$r['talkmove-error-code'] = ApiBase::$messageMap[$retval]['code'];
$r['talkmove-error-info'] = ApiBase::$messageMap[$retval]['info'];
- }
+ }
}
-
+
# Watch pages
if($params['watch'] || $wgUser->getOption('watchmoves'))
{
$this->getMain()->scheduleCommit();
$this->getResult()->addValue(null, $this->getModuleName(), $r);
}
-
+
public function mustBePosted() { return true; }
-
+
public function getAllowedParams() {
return array (
'from' => null,
// Open search results may be stored for a very long time
$this->getMain()->setCacheMaxAge(1200);
-
+
$srchres = PrefixSearch::titleSearch( $search, $limit );
// Set top level elements
return __CLASS__ . ': $Id$';
}
}
-
* Initially, when the client passes in titles=, pageids=, or revisions= parameter,
* an instance of the ApiPageSet class will normalize titles,
* determine if the pages/revisions exist, and prefetch any additional data page data requested.
- *
+ *
* When generator is used, the result of the generator will become the input for the
* second instance of this class, and all subsequent actions will go use the second instance
- * for all their work.
- *
+ * for all their work.
+ *
* @addtogroup API
*/
class ApiPageSet extends ApiQueryBase {
$this->mResolveRedirects = $resolveRedirects;
if($resolveRedirects)
$this->mPendingRedirectIDs = array();
-
+
$this->mFakePageId = -1;
}
public function getMissingTitles() {
return $this->mMissingTitles;
}
-
+
/**
* Titles that were deemed invalid by Title::newFromText()
* The array's index will be unique and negative for each item
}
/**
- * Get a list of title normalizations - maps the title given
+ * Get a list of title normalizations - maps the title given
* with its normalized version.
- * @return array raw_prefixed_title (string) => prefixed_title (string)
+ * @return array raw_prefixed_title (string) => prefixed_title (string)
*/
public function getNormalizedTitles() {
return $this->mNormalizedTitles;
}
/**
- * Get a list of interwiki titles - maps the title given
+ * Get a list of interwiki titles - maps the title given
* with to the interwiki prefix.
- * @return array raw_prefixed_title (string) => interwiki_prefix (string)
+ * @return array raw_prefixed_title (string) => interwiki_prefix (string)
*/
public function getInterwikiTitles() {
return $this->mInterwikiTitles;
* Extract all requested fields from the row received from the database
*/
public function processDbRow($row) {
-
+
// Store Title object in various data structures
$title = Title :: makeTitle($row->page_namespace, $row->page_title);
-
- $pageId = intval($row->page_id);
+
+ $pageId = intval($row->page_id);
$this->mAllPages[$row->page_namespace][$row->page_title] = $pageId;
$this->mTitles[] = $title;
foreach ($this->mRequestedPageFields as $fieldName => & $fieldValues)
$fieldValues[$pageId] = $row-> $fieldName;
}
-
+
public function finishPageSetGeneration() {
$this->profileIn();
$this->resolvePendingRedirects();
$this->profileOut();
}
-
+
/**
* This method populates internal variables with page information
* based on the given array of title strings.
- *
+ *
* Steps:
* #1 For each title, get data from `page` table
* #2 If page was not found in the DB, store it as missing
- *
+ *
* Additionally, when resolving redirects:
* #3 If no more redirects left, stop.
* #4 For each redirect, get its links from `pagelinks` table.
* #5 Substitute the original LinkBatch object with the new list
- * #6 Repeat from step #1
+ * #6 Repeat from step #1
*/
private function initFromTitles($titles) {
$linkBatch = $this->processTitlesArray($titles);
if($linkBatch->isEmpty())
return;
-
+
$db = $this->getDB();
$set = $linkBatch->constructSet('page', $db);
$this->profileDBIn();
$res = $db->select('page', $this->getPageTableFields(), $set, __METHOD__);
$this->profileDBOut();
-
+
$this->initFromQueryResult($db, $res, array_flip($pageids), false); // process PageIDs
// Resolve any found redirects
$this->resolvePendingRedirects();
}
-
+
/**
* Iterate through the result of the query on 'page' table,
* and for each row create and store title object and save any extra fields requested.
private function initFromQueryResult($db, $res, &$remaining = null, $processTitles = null) {
if (!is_null($remaining) && is_null($processTitles))
ApiBase :: dieDebug(__METHOD__, 'Missing $processTitles parameter when $remaining is provided');
-
+
while ($row = $db->fetchObject($res)) {
$pageId = intval($row->page_id);
else
unset ($remaining[$pageId]);
}
-
+
// Store any extra fields requested by modules
$this->processDbRow($row);
}
$db->freeResult($res);
-
+
if(isset($remaining)) {
// Any items left in the $remaining list are added as missing
if($processTitles) {
if(empty($revids))
return;
-
+
$db = $this->getDB();
$pageids = array();
$remaining = array_flip($revids);
-
+
$tables = array('revision');
$fields = array('rev_id','rev_page');
$where = array('rev_deleted' => 0, 'rev_id' => $revids);
-
+
// Get pageIDs data from the `page` table
$this->profileDBIn();
$res = $db->select( $tables, $fields, $where, __METHOD__ );
if($this->mResolveRedirects) {
$db = $this->getDB();
$pageFlds = $this->getPageTableFields();
-
+
// Repeat until all redirects have been resolved
// The infinite loop is prevented by keeping all known pages in $this->mAllPages
- while (!empty ($this->mPendingRedirectIDs)) {
-
+ while (!empty ($this->mPendingRedirectIDs)) {
+
// Resolve redirects by querying the pagelinks table, and repeat the process
// Create a new linkBatch object for the next pass
$linkBatch = $this->getRedirectTargets();
-
+
if ($linkBatch->isEmpty())
break;
-
+
$set = $linkBatch->constructSet('page', $db);
if(false === $set)
break;
-
+
// Get pageIDs data from the `page` table
$this->profileDBIn();
$res = $db->select('page', $pageFlds, $set, __METHOD__);
$this->profileDBOut();
-
+
// Hack: get the ns:titles stored in array(ns => array(titles)) format
$this->initFromQueryResult($db, $res, $linkBatch->data, true);
}
/**
* Given an array of title strings, convert them into Title objects.
* Alternativelly, an array of Title objects may be given.
- * This method validates access rights for the title,
+ * This method validates access rights for the title,
* and appends normalization values to the output.
- *
+ *
* @return LinkBatch of title objects.
*/
private function processTitlesArray($titles) {
$linkBatch = new LinkBatch();
foreach ($titles as $title) {
-
+
$titleObj = is_string($title) ? Title :: newFromText($title) : $title;
if (!$titleObj)
{
if (!empty($iw)) {
// This title is an interwiki link.
$this->mInterwikiTitles[$titleObj->getPrefixedText()] = $iw;
- } else {
+ } else {
// Validation
if ($titleObj->getNamespace() < 0)
$linkBatch->addObj($titleObj);
}
-
+
// Make sure we remember the original title that was given to us
// This way the caller can correlate new titles with the originally requested,
// i.e. namespace is localized or capitalization is different
return $linkBatch;
}
-
+
protected function getAllowedParams() {
return array (
'titles' => array (
return __CLASS__ . ': $Id$';
}
}
-
-
$obj = new $modArr[$m]($this->getMain(), $m);
$a = $this->getClassInfo($obj);
$a['name'] = $m;
- $r['modules'][] = $a;
+ $r['modules'][] = $a;
}
$result->setIndexedTagName($r['modules'], 'module');
}
$retval['parameters'][] = $a;
continue;
}
-
+
if(isset($p[ApiBase::PARAM_DFLT]))
$a['default'] = $p[ApiBase::PARAM_DFLT];
if(isset($p[ApiBase::PARAM_ISMULTI]))
$result->setIndexedTagName($retval['parameters'], 'param');
return $retval;
}
-
+
public function getAllowedParams() {
return array (
'modules' => array(
return __CLASS__ . ': $Id$';
}
}
-
$this->dieUsage("The page parameter cannot be used together with the text and title parameters", 'params');
$prop = array_flip($params['prop']);
$revid = false;
-
+
global $wgParser, $wgUser;
if(!is_null($oldid) || !is_null($page))
{
$this->setIndexedTagNames( $result_array, $result_mapping );
$result->addValue( null, $this->getModuleName(), $result_array );
}
-
+
private function formatLangLinks( $links ) {
$result = array();
foreach( $links as $link ) {
}
return $result;
}
-
+
private function formatCategoryLinks( $links ) {
$result = array();
foreach( $links as $link => $sortkey ) {
}
return $result;
}
-
+
private function formatLinks( $links ) {
$result = array();
foreach( $links as $ns => $nslinks ) {
}
return $result;
}
-
+
private function setIndexedTagNames( &$array, $mapping ) {
foreach( $mapping as $key => $name ) {
if( isset( $array[$key] ) )
public function getAllowedParams() {
return array (
- 'title' => array(
+ 'title' => array(
ApiBase :: PARAM_DFLT => 'API',
),
'text' => null,
return __CLASS__ . ': $Id$';
}
}
-
global $wgUser;
$this->getMain()->requestWriteMode();
$params = $this->extractRequestParams();
-
+
$titleObj = NULL;
if(!isset($params['title']))
$this->dieUsageMsg(array('missingparam', 'title'));
$titleObj = Title::newFromText($params['title']);
if(!$titleObj)
$this->dieUsageMsg(array('invalidtitle', $params['title']));
-
+
$errors = $titleObj->getUserPermissionsErrors('protect', $wgUser);
if(!empty($errors))
// We don't care about multiple errors, just report one of them
$this->dieUsageMsg(current($errors));
-
+
if(in_array($params['expiry'], array('infinite', 'indefinite', 'never')))
$expiry = Block::infinity();
else
$expiry = strtotime($params['expiry']);
if($expiry < 0 || $expiry == false)
$this->dieUsageMsg(array('invalidexpiry'));
-
+
$expiry = wfTimestamp(TS_MW, $expiry);
if($expiry < wfTimestampNow())
$this->dieUsageMsg(array('pastexpiry'));
* it will create a list of titles to work on (an instance of the ApiPageSet object)
* instantiate and execute various property/list/meta modules,
* and assemble all resulting data into a single ApiResult object.
- *
+ *
* In the generator mode, a generator will be first executed to populate a second ApiPageSet object,
* and that object will be used for all subsequent modules.
- *
+ *
* @addtogroup API
*/
class ApiQuery extends ApiBase {
public function __construct($main, $action) {
parent :: __construct($main, $action);
- // Allow custom modules to be added in LocalSettings.php
+ // Allow custom modules to be added in LocalSettings.php
global $wgApiQueryPropModules, $wgApiQueryListModules, $wgApiQueryMetaModules;
self :: appendUserModules($this->mQueryPropModules, $wgApiQueryPropModules);
self :: appendUserModules($this->mQueryListModules, $wgApiQueryListModules);
/**
* Get the query database connection with the given name.
- * If no such connection has been requested before, it will be created.
- * Subsequent calls with the same $name will return the same connection
- * as the first, regardless of $db or $groups new values.
+ * If no such connection has been requested before, it will be created.
+ * Subsequent calls with the same $name will return the same connection
+ * as the first, regardless of $db or $groups new values.
*/
public function getNamedDB($name, $db, $groups) {
if (!array_key_exists($name, $this->mNamedDB)) {
public function getPageSet() {
return $this->mPageSet;
}
-
+
/**
* Get the array mapping module names to class names
*/
* Query execution happens in the following steps:
* #1 Create a PageSet object with any pages requested by the user
* #2 If using generator, execute it to get a new PageSet object
- * #3 Instantiate all requested modules.
+ * #3 Instantiate all requested modules.
* This way the PageSet object will know what shared data is required,
- * and minimize DB calls.
+ * and minimize DB calls.
* #4 Output all normalization and redirect resolution information
* #5 Execute all requested modules
*/
public function execute() {
-
+
$this->params = $this->extractRequestParams();
$this->redirects = $this->params['redirects'];
-
+
//
// Create PageSet
//
$this->InstantiateModules($modules, 'meta', $this->mQueryMetaModules);
//
- // If given, execute generator to substitute user supplied data with generated data.
+ // If given, execute generator to substitute user supplied data with generated data.
//
if (isset ($this->params['generator'])) {
$this->executeGeneratorModule($this->params['generator'], $modules);
$module->profileOut();
}
}
-
+
/**
* Query modules may optimize data requests through the $this->getPageSet() object
* by adding extra fields from the page table.
- * This function will gather all the extra request fields from the modules.
+ * This function will gather all the extra request fields from the modules.
*/
private function addCustomFldsToPageSet($modules, $pageSet) {
- // Query all requested modules.
+ // Query all requested modules.
foreach ($modules as $module) {
$module->requestExtraData($pageSet);
}
}
/**
- * Create instances of all modules requested by the client
+ * Create instances of all modules requested by the client
*/
private function InstantiateModules(&$modules, $param, $moduleList) {
$list = $this->params[$param];
$result->setIndexedTagName($normValues, 'n');
$result->addValue('query', 'normalized', $normValues);
}
-
+
// Interwiki titles
$intrwValues = array ();
foreach ($pageSet->getInterwikiTitles() as $rawTitleStr => $interwikiStr) {
$result->setIndexedTagName($intrwValues, 'i');
$result->addValue('query', 'interwiki', $intrwValues);
}
-
+
// Show redirect information
$redirValues = array ();
foreach ($pageSet->getRedirectTitles() as $titleStrFrom => $titleStrTo) {
}
// Report any invalid titles
foreach ($pageSet->getInvalidTitles() as $fakeId => $title)
- $pages[$fakeId] = array('title' => $title, 'invalid' => '');
+ $pages[$fakeId] = array('title' => $title, 'invalid' => '');
// Report any missing page ids
foreach ($pageSet->getMissingPageIDs() as $pageid) {
$pages[$pageid] = array (
}
if (!empty ($pages)) {
-
+
if ($this->params['indexpageids']) {
$pageIDs = array_keys($pages);
// json treats all map keys as strings - converting to match
$result->setIndexedTagName($pageIDs, 'id');
$result->addValue('query', 'pageids', $pageIDs);
}
-
+
$result->setIndexedTagName($pages, 'page');
$result->addValue('query', 'pages', $pages);
}
}
/**
- * For generator mode, execute generator, and use its output as new pageSet
+ * For generator mode, execute generator, and use its output as new pageSet
*/
protected function executeGeneratorModule($generatorName, $modules) {
ApiBase :: dieDebug(__METHOD__, "Unknown generator=$generatorName");
}
- // Generator results
+ // Generator results
$resultPageSet = new ApiPageSet($this, $this->redirects);
// Create and execute the generator
/**
* Returns the list of allowed parameters for this module.
- * Qurey module also lists all ApiPageSet parameters as its own.
+ * Qurey module also lists all ApiPageSet parameters as its own.
*/
public function getAllowedParams() {
return array (
$psModule = new ApiPageSet($this);
return $psModule->makeHelpMsgParameters() . parent :: makeHelpMsgParameters();
}
-
+
// @todo should work correctly
public function shouldCheckMaxlag() {
return true;
return $vers;
}
}
-
/**
* Query module to enumerate all categories, even the ones that don't have
* category pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryAllCategories extends ApiQueryGeneratorBase {
$this->addTables('category');
$this->addFields('cat_title');
-
+
if (!is_null($params['from']))
$this->addWhere('cat_title>=' . $db->addQuotes(ApiQueryBase :: titleToKey($params['from'])));
if (isset ($params['prefix']))
$this->addOption('LIMIT', $params['limit']+1);
$this->addOption('ORDER BY', 'cat_title' . ($params['dir'] == 'descending' ? ' DESC' : ''));
$this->addOption('DISTINCT');
-
+
$prop = array_flip($params['prop']);
$this->addFieldsIf( array( 'cat_pages', 'cat_subcats', 'cat_files' ), isset($prop['size']) );
//$this->addFieldsIf( 'cat_hidden', isset($prop['hidden']) );
$this->setContinueEnumParameter('from', ApiQueryBase :: keyToTitle($row->cl_to));
break;
}
-
+
// Normalize titles
$titleObj = Title::makeTitle(NS_CATEGORY, $row->cat_title);
if(!is_null($resultPageSet))
/**
* Query module to enumerate links from all pages together.
- *
+ *
* @addtogroup API
*/
class ApiQueryAllLinks extends ApiQueryGeneratorBase {
$this->addTables('pagelinks');
$this->addWhereFld('pl_namespace', $params['namespace']);
-
+
if (!is_null($params['from']))
$this->addWhere('pl_title>=' . $db->addQuotes(ApiQueryBase :: titleToKey($params['from'])));
if (isset ($params['prefix']))
/**
* Query module to enumerate all registered users.
- *
+ *
* @addtogroup API
*/
class ApiQueryAllUsers extends ApiQueryBase {
$limit = $params['limit'];
$tables = $db->tableName('user');
-
+
if( !is_null( $params['from'] ) )
$this->addWhere( 'user_name >= ' . $db->addQuotes( self::keyToTitle( $params['from'] ) ) );
-
+
if( isset( $params['prefix'] ) )
$this->addWhere( 'user_name LIKE "' . $db->escapeLike( self::keyToTitle( $params['prefix'] ) ) . '%"' );
} else {
$sqlLimit = $limit+1;
}
-
+
if ($fld_registration)
$this->addFields('user_registration');
$lastUserData = false;
$lastUser = false;
$result = $this->getResult();
-
+
//
// This loop keeps track of the last entry.
// For each new row, if the new row is for different user then the last, the last entry is added to results.
// to make sure all rows that belong to the same user are received.
//
while (true) {
-
+
$row = $db->fetchObject($res);
$count++;
-
+
if (!$row || $lastUser != $row->user_name) {
// Save the last pass's user data
if (is_array($lastUserData))
$data[] = $lastUserData;
-
+
// No more rows left
if (!$row)
break;
$lastUserData['editcount'] = intval($row->user_editcount);
if ($fld_registration)
$lastUserData['registration'] = wfTimestamp(TS_ISO_8601, $row->user_registration);
-
+
}
-
+
if ($sqlLimit == $count) {
// BUG! database contains group name that User::getAllGroups() does not return
// TODO: should handle this more gracefully
- ApiBase :: dieDebug(__METHOD__,
+ ApiBase :: dieDebug(__METHOD__,
'MediaWiki configuration error: the database contains more user groups than known to User::getAllGroups() function');
}
-
+
// Add user's group info
if ($fld_groups && !is_null($row->ug_group2)) {
$lastUserData['groups'][] = $row->ug_group2;
$result->setIndexedTagName($lastUserData['groups'], 'g');
}
}
-
+
$db->freeResult($res);
$result->setIndexedTagName($data, 'u');
ApiBase :: PARAM_TYPE => User::getAllGroups()
),
'prop' => array (
- ApiBase :: PARAM_ISMULTI => true,
+ ApiBase :: PARAM_ISMULTI => true,
ApiBase :: PARAM_TYPE => array (
'editcount',
'groups',
/**
* Query module to enumerate all available pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryAllimages extends ApiQueryGeneratorBase {
$db = $this->getDB();
$params = $this->extractRequestParams();
-
+
// Image filters
if (!is_null($params['from']))
$this->addWhere('img_name>=' . $db->addQuotes(ApiQueryBase :: titleToKey($params['from'])));
if (isset ($params['minsize'])) {
$this->addWhere('img_size>=' . intval($params['minsize']));
}
-
+
if (isset ($params['maxsize'])) {
$this->addWhere('img_size<=' . intval($params['maxsize']));
}
'prefix' => null,
'minsize' => array (
ApiBase :: PARAM_TYPE => 'integer',
- ),
+ ),
'maxsize' => array (
ApiBase :: PARAM_TYPE => 'integer',
),
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query action to return messages from site message cache
- *
+ *
* @addtogroup API
*/
class ApiQueryAllmessages extends ApiQueryBase {
public function execute() {
global $wgMessageCache;
$params = $this->extractRequestParams();
-
+
if(!is_null($params['lang']))
{
global $wgLang;
$wgLang = Language::factory($params['lang']);
}
-
+
//Determine which messages should we print
$messages_target = array();
} else {
$messages_target = explode( '|', $params['messages'] );
}
-
+
//Filter messages
if( isset( $params['filter'] ) ) {
$messages_filtered = array();
/**
* Query module to enumerate all available pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryAllpages extends ApiQueryGeneratorBase {
$db = $this->getDB();
$params = $this->extractRequestParams();
-
+
// Page filters
if (!$this->addWhereIf('page_is_redirect = 1', $params['filterredir'] === 'redirects'))
$this->addWhereIf('page_is_redirect = 0', $params['filterredir'] === 'nonredirects');
$this->addWhere('page_len>=' . intval($params['minsize']));
$forceNameTitleIndex = false;
}
-
+
if (isset ($params['maxsize'])) {
$this->addWhere('page_len<=' . intval($params['maxsize']));
$forceNameTitleIndex = false;
}
-
+
// Page protection filtering
if (isset ($params['prtype'])) {
$this->addTables('page_restrictions');
$prlevel = $params['prlevel'];
if (!is_null($prlevel) && $prlevel != '' && $prlevel != '*')
$this->addWhereFld('pr_level', $prlevel);
-
+
$this->addOption('DISTINCT');
$forceNameTitleIndex = false;
} else if (isset ($params['prlevel'])) {
$this->dieUsage('prlevel may not be used without prtype', 'params');
}
-
+
if($params['filterlanglinks'] == 'withoutlanglinks') {
$pageName = $this->getDB()->tableName('page');
$llName = $this->getDB()->tableName('langlinks');
} else if($params['filterlanglinks'] == 'withlanglinks') {
$this->addTables(array('page', 'langlinks'));
$this->addWhere('page_id=ll_from');
- $forceNameTitleIndex = false;
+ $forceNameTitleIndex = false;
} else {
$this->addTables('page');
}
public function getAllowedParams() {
global $wgRestrictionTypes, $wgRestrictionLevels;
-
+
return array (
'from' => null,
'prefix' => null,
),
'minsize' => array (
ApiBase :: PARAM_TYPE => 'integer',
- ),
+ ),
'maxsize' => array (
ApiBase :: PARAM_TYPE => 'integer',
- ),
+ ),
'prtype' => array (
ApiBase :: PARAM_TYPE => $wgRestrictionTypes,
ApiBase :: PARAM_ISMULTI => true
return __CLASS__ . ': $Id$';
}
}
-
* * backlinks - links pointing to the given page,
* * embeddedin - what pages transclude the given page within themselves,
* * imageusage - what pages use the given image
- *
+ *
* @addtogroup API
*/
class ApiQueryBacklinks extends ApiQueryGeneratorBase {
private $params, $rootTitle, $contRedirs, $contLevel, $contTitle, $contID, $redirID;
- // output element name, database column field prefix, database table
+ // output element name, database column field prefix, database table
private $backlinksSettings = array (
'backlinks' => array (
'code' => 'bl',
public function executeGenerator($resultPageSet) {
$this->run($resultPageSet);
}
-
+
private function prepareFirstQuery($resultPageSet = null) {
/* SELECT page_id, page_title, page_namespace, page_is_redirect
* FROM pagelinks JOIN page ON pl_from=page_id
$this->addOption('LIMIT', $this->params['limit'] + 1);
$this->addOption('ORDER BY', $this->bl_from);
}
-
+
private function prepareSecondQuery($resultPageSet = null) {
/* SELECT page_id, page_title, page_namespace, page_is_redirect, pl_title, pl_namespace
* FROM pagelinks JOIN page ON pl_from=page_id
$this->addFields($this->bl_ns);
$titleWhere = '';
foreach($this->redirTitles as $t)
- $titleWhere .= ($titleWhere != '' ? " OR " : '') .
+ $titleWhere .= ($titleWhere != '' ? " OR " : '') .
"({$this->bl_title} = '{$t->getDBKey()}'" .
($this->hasNS ? " AND {$this->bl_ns} = '{$t->getNamespace()}'" : "") .
")";
$this->redirTitles[] = Title::makeTitle($row->page_namespace, $row->page_title);
$resultPageSet->processDbRow($row);
}
- }
+ }
$db->freeResult($res);
-
+
if($this->params['redirect'] && !empty($this->redirTitles))
{
$this->resetQueryParams();
$this->continueStr = $this->getContinueRedirStr($contTitle->getArticleID(), $row->page_id);
break;
}
-
+
if(is_null($resultPageSet))
$this->extractRedirRowInfo($row);
else
}
}
}
-
+
private function extractRedirRowInfo($row)
{
$a['pageid'] = $row->page_id;
$a['redirect'] = '';
$ns = $this->hasNS ? $row->{$this->bl_ns} : NS_IMAGE;
$this->data[$ns][$row->{$this->bl_title}]['redirlinks'][] = $a;
- $this->getResult()->setIndexedTagName($this->data[$ns][$row->{$this->bl_title}]['redirlinks'], $this->bl_code);
+ $this->getResult()->setIndexedTagName($this->data[$ns][$row->{$this->bl_title}]['redirlinks'], $this->bl_code);
}
protected function processContinue() {
$pageSet = $this->getPageSet();
$count = $pageSet->getTitleCount();
-
+
if (!is_null($this->params['continue']))
$this->parseContinueParam();
else {
// ns+key: root title
// id1: first-level page ID to continue from
// id2: second-level page ID to continue from
-
+
// null stuff out now so we know what's set and what isn't
$this->rootTitle = $this->contID = $this->redirID = null;
$rootNs = intval($continueList[0]);
// This one isn't required
return;
$this->redirID = $redirID;
-
+
}
protected function getContinueStr($lastPageID) {
return __CLASS__ . ': $Id$';
}
}
-
/**
* This is a base class for all Query modules.
* It provides some common functionality such as constructing various SQL queries.
- *
+ *
* @addtogroup API
*/
abstract class ApiQueryBase extends ApiBase {
if (!is_null($end))
$this->addWhere($field . $before . $db->addQuotes($end));
-
+
$order = $field . ($isDirNewer ? '' : ' DESC');
if (!isset($this->options['ORDER BY']))
$this->addOption('ORDER BY', $order);
$this->profileDBIn();
$rowcount = $db->estimateRowCount($this->tables, $this->fields, $this->where, __METHOD__, $this->options);
$this->profileDBOut();
-
+
global $wgAPIMaxDBRows;
if($rowcount > $wgAPIMaxDBRows)
return false;
$arr[$prefix . 'ns'] = intval($title->getNamespace());
$arr[$prefix . 'title'] = $title->getPrefixedText();
}
-
+
/**
* Override this method to request extra fields from the pageSet
* using $pageSet->requestField('fieldName')
}
/**
- * Add sub-element under the page element with the given pageId.
+ * Add sub-element under the page element with the given pageId.
*/
protected function addPageSubItems($pageId, $data) {
$result = $this->getResult();
}
protected function setContinueEnumParameter($paramName, $paramValue) {
-
+
$paramName = $this->encodeParamName($paramName);
$msg = array( $paramName => $paramValue );
// This is an alternative continue format as a part of the URL string
// ApiResult :: setContent($msg, $paramName . '=' . urlencode($paramValue));
-
+
$this->getResult()->addValue('query-continue', $this->getModuleName(), $msg);
}
/**
* Selects the query database connection with the given name.
- * If no such connection has been requested before, it will be created.
- * Subsequent calls with the same $name will return the same connection
- * as the first, regardless of $db or $groups new values.
+ * If no such connection has been requested before, it will be created.
+ * Subsequent calls with the same $name will return the same connection
+ * as the first, regardless of $db or $groups new values.
*/
public function selectNamedDB($name, $db, $groups) {
- $this->mDb = $this->getQuery()->getNamedDB($name, $db, $groups);
+ $this->mDb = $this->getQuery()->getNamedDB($name, $db, $groups);
}
/**
}
return false;
}
-
+
public static function getBaseVersion() {
return __CLASS__ . ': $Id$';
}
*/
public abstract function executeGenerator($resultPageSet);
}
-
/**
* Query module to enumerate all available pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryBlocks extends ApiQueryBase {
/**
* A query module to enumerate categories the set of pages belong to.
- *
+ *
* @addtogroup API
*/
class ApiQueryCategories extends ApiQueryGeneratorBase {
'cl_from',
'cl_to'
));
-
+
$fld_sortkey = false;
if (!is_null($prop)) {
foreach($prop as $p) {
}
}
}
-
+
$this->addTables('categorylinks');
$this->addWhereFld('cl_from', array_keys($this->getPageSet()->getGoodTitles()));
$this->addOption('ORDER BY', "cl_from, cl_to");
$res = $this->select(__METHOD__);
if (is_null($resultPageSet)) {
-
+
$data = array();
- $lastId = 0; // database has no ID 0
+ $lastId = 0; // database has no ID 0
while ($row = $db->fetchObject($res)) {
if ($lastId != $row->cl_from) {
if($lastId != 0) {
}
$lastId = $row->cl_from;
}
-
+
$title = Title :: makeTitle(NS_CATEGORY, $row->cl_to);
-
+
$vals = array();
ApiQueryBase :: addTitleInfo($vals, $title);
if ($fld_sortkey)
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query module to enumerate pages that belong to a category.
- *
+ *
* @addtogroup API
*/
class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
$params = $this->extractRequestParams();
- if ( !isset($params['title']) || is_null($params['title']) )
+ if ( !isset($params['title']) || is_null($params['title']) )
$this->dieUsage("The cmtitle parameter is required", 'notitle');
$categoryTitle = Title::newFromText($params['title']);
if ( is_null( $categoryTitle ) || $categoryTitle->getNamespace() != NS_CATEGORY )
$this->dieUsage("The category name you entered is not valid", 'invalidcategory');
-
+
$prop = array_flip($params['prop']);
$fld_ids = isset($prop['ids']);
$fld_title = isset($prop['title']);
}
$this->addFieldsIf('cl_timestamp', $fld_timestamp || $params['sort'] == 'timestamp');
- $this->addTables(array('page','categorylinks')); // must be in this order for 'USE INDEX'
+ $this->addTables(array('page','categorylinks')); // must be in this order for 'USE INDEX'
// Not needed after bug 10280 is applied to servers
if($params['sort'] == 'timestamp')
{
}
$this->addWhere('cl_from=page_id');
- $this->setContinuation($params['continue']);
+ $this->setContinuation($params['continue']);
$this->addWhereFld('cl_to', $categoryTitle->getDBkey());
$this->addWhereFld('page_namespace', $params['namespace']);
$this->addWhereRange('cl_timestamp', ($params['dir'] == 'asc' ? 'newer' : 'older'), $params['start'], $params['end']);
-
+
$limit = $params['limit'];
$this->addOption('LIMIT', $limit +1);
break;
}
- $lastSortKey = $row->cl_sortkey; // detect duplicate sortkeys
-
+ $lastSortKey = $row->cl_sortkey; // detect duplicate sortkeys
+
if (is_null($resultPageSet)) {
$vals = array();
if ($fld_ids)
- $vals['pageid'] = intval($row->page_id);
+ $vals['pageid'] = intval($row->page_id);
if ($fld_title) {
$title = Title :: makeTitle($row->page_namespace, $row->page_title);
$vals['ns'] = intval($title->getNamespace());
$this->getResult()->addValue('query', $this->getModuleName(), $data);
}
}
-
+
private function getContinueStr($row, $lastSortKey) {
$ret = $row->cl_sortkey . '|';
if ($row->cl_sortkey == $lastSortKey) // duplicate sort key, add cl_from
$ret .= $row->cl_from;
return $ret;
}
-
+
/**
- * Add DB WHERE clause to continue previous query based on 'continue' parameter
+ * Add DB WHERE clause to continue previous query based on 'continue' parameter
*/
private function setContinuation($continue) {
if (is_null($continue))
return; // This is not a continuation request
-
+
$continueList = explode('|', $continue);
$hasError = count($continueList) != 2;
$from = 0;
if (!$hasError && strlen($continueList[1]) > 0) {
$from = intval($continueList[1]);
- $hasError = ($from == 0);
+ $hasError = ($from == 0);
}
-
+
if ($hasError)
$this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "badcontinue");
return __CLASS__ . ': $Id$';
}
}
-
/**
* Query module to enumerate all available pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryDeletedrevs extends ApiQueryBase {
$limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
$this->getResult()->addValue( 'limits', $this->getModuleName(), $limit );
}
-
+
$this->validateLimit('limit', $limit, 1, $userMax, $botMax);
-
+
if($fld_token)
// Undelete tokens are identical for all pages, so we cache one here
$token = $wgUser->editToken();
$protocol = $params['protocol'];
$query = $params['query'];
-
+
// Find the right prefix
global $wgUrlProtocols;
if(!is_null($protocol) && $protocol != '' && !in_array($protocol, $wgUrlProtocols))
}
}
}
-
+
$db = $this->getDb();
- $this->addTables(array('page','externallinks')); // must be in this order for 'USE INDEX'
+ $this->addTables(array('page','externallinks')); // must be in this order for 'USE INDEX'
$this->addOption('USE INDEX', 'el_index');
$this->addWhere('page_id=el_from');
$this->addWhereFld('page_namespace', $params['namespace']);
$fld_ids = isset($prop['ids']);
$fld_title = isset($prop['title']);
$fld_url = isset($prop['url']);
-
+
if (is_null($resultPageSet)) {
$this->addFields(array (
'page_id',
'page_namespace',
'page_title'
));
- $this->addFieldsIf('el_to', $fld_url);
+ $this->addFieldsIf('el_to', $fld_url);
} else {
$this->addFields($resultPageSet->getPageTableFields());
}
foreach ($wgUrlProtocols as $p) {
$protocols[] = substr($p, 0, strpos($p,':'));
}
-
+
return array (
'prop' => array (
ApiBase :: PARAM_ISMULTI => true,
/**
* A query module to list all external URLs found on a given set of pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryExternalLinks extends ApiQueryBase {
'el_from',
'el_to'
));
-
+
$this->addTables('externallinks');
$this->addWhereFld('el_from', array_keys($this->getPageSet()->getGoodTitles()));
$db = $this->getDB();
$res = $this->select(__METHOD__);
-
+
$data = array();
- $lastId = 0; // database has no ID 0
+ $lastId = 0; // database has no ID 0
while ($row = $db->fetchObject($res)) {
if ($lastId != $row->el_from) {
if($lastId != 0) {
}
$lastId = $row->el_from;
}
-
+
$entry = array();
ApiResult :: setContent($entry, $row->el_to);
$data[] = $entry;
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query action to get image information and upload history.
- *
+ *
* @addtogroup API
*/
class ApiQueryImageInfo extends ApiQueryBase {
public function execute() {
$params = $this->extractRequestParams();
- $prop = array_flip($params['prop']);
+ $prop = array_flip($params['prop']);
$this->fld_timestamp = isset($prop['timestamp']);
$this->fld_user = isset($prop['user']);
$this->fld_comment = isset($prop['comment']);
$this->fld_sha1 = isset($prop['sha1']);
$this->fld_metadata = isset($prop['metadata']);
$this->fld_archivename = isset($prop['archivename']);
-
+
if($params['urlheight'] != -1 && $params['urlwidth'] == -1)
$this->dieUsage("iiurlheight cannot be used without iiurlwidth", 'iiurlwidth');
$this->scale = ($params['urlwidth'] != -1);
$pageIds = $this->getPageSet()->getAllTitlesByNamespace();
if (!empty($pageIds[NS_IMAGE])) {
foreach ($pageIds[NS_IMAGE] as $dbKey => $pageId) {
-
+
$title = Title :: makeTitle(NS_IMAGE, $dbKey);
$img = wfFindFile($title);
} else {
$repository = $img->getRepoName();
-
+
// Get information about the current version first
// Check that the current version is within the start-end boundaries
if((is_null($params['start']) || $img->getTimestamp() <= $params['start']) &&
(is_null($params['end']) || $img->getTimestamp() >= $params['end'])) {
$data[] = $this->getInfo($img);
}
-
+
// Now get the old revisions
// Get one more to facilitate query-continue functionality
$count = count($data);
$this->setContinueEnumParameter('start', $oldie->getTimestamp());
break;
}
- $data[] = $this->getInfo($oldie);
+ $data[] = $this->getInfo($oldie);
}
}
}
$vals['url'] = $f->getURL();
}
- if($this->fld_comment)
+ if($this->fld_comment)
$vals['comment'] = $f->getDescription();
- if($this->fld_sha1)
+ if($this->fld_sha1)
$vals['sha1'] = wfBaseConvert($f->getSha1(), 36, 16, 40);
if($this->fld_metadata) {
$metadata = unserialize($f->getMetadata());
}
if($this->fld_archivename && $f->isOld())
$vals['archivename'] = $f->getArchiveName();
-
+
return $vals;
}
/**
* This query adds <images> subelement to all pages with the list of images embedded into those pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryImages extends ApiQueryGeneratorBase {
$res = $this->select(__METHOD__);
if (is_null($resultPageSet)) {
-
+
$data = array();
- $lastId = 0; // database has no ID 0
+ $lastId = 0; // database has no ID 0
while ($row = $db->fetchObject($res)) {
if ($lastId != $row->il_from) {
if($lastId != 0) {
}
$lastId = $row->il_from;
}
-
+
$vals = array();
ApiQueryBase :: addTitleInfo($vals, Title :: makeTitle(NS_IMAGE, $row->il_to));
$data[] = $vals;
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query module to show basic page information.
- *
+ *
* @addtogroup API
*/
class ApiQueryInfo extends ApiQueryBase {
else
// Fix E_NOTICEs about unset variables
$token = $tok_edit = $tok_delete = $tok_protect = $tok_move = null;
-
+
$pageSet = $this->getPageSet();
$titles = $pageSet->getGoodTitles();
$missing = $pageSet->getMissingTitles();
}
$db->freeResult($res);
}
-
+
// Run the talkid/subjectid query
if($fld_talkid || $fld_subjectid)
{
- $talktitles = $subjecttitles =
+ $talktitles = $subjecttitles =
$talkids = $subjectids = array();
$everything = array_merge($titles, $missing);
foreach($everything as $t)
if ($tok_move)
$pageInfo['movetoken'] = $wgUser->editToken();
}
-
+
if($fld_protection) {
if (isset($protections[$pageid])) {
$pageInfo['protection'] = $protections[$pageid];
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query module to list all langlinks (links to correspanding foreign language pages).
- *
+ *
* @addtogroup API
*/
class ApiQueryLangLinks extends ApiQueryBase {
public function execute() {
if ( $this->getPageSet()->getGoodTitleCount() == 0 )
return;
-
+
$this->addFields(array (
'll_from',
'll_lang',
$res = $this->select(__METHOD__);
$data = array();
- $lastId = 0; // database has no ID 0
+ $lastId = 0; // database has no ID 0
$db = $this->getDB();
while ($row = $db->fetchObject($res)) {
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query module to list all wiki links on a given set of pages.
- *
+ *
* @addtogroup API
*/
class ApiQueryLinks extends ApiQueryGeneratorBase {
private $table, $prefix, $description;
public function __construct($query, $moduleName) {
-
+
switch ($moduleName) {
case self::LINKS :
$this->table = 'pagelinks';
$res = $this->select(__METHOD__);
if (is_null($resultPageSet)) {
-
+
$data = array();
- $lastId = 0; // database has no ID 0
+ $lastId = 0; // database has no ID 0
while ($row = $db->fetchObject($res)) {
if ($lastId != $row->pl_from) {
if($lastId != 0) {
return __CLASS__ . ': $Id$';
}
}
-
/**
* Query action to List the log events, with optional filtering by various parameters.
- *
+ *
* @addtogroup API
*/
class ApiQueryLogEvents extends ApiQueryBase {
}
public function execute() {
- $params = $this->extractRequestParams();
+ $params = $this->extractRequestParams();
$db = $this->getDB();
$prop = $params['prop'];
'log_action',
'log_timestamp',
));
-
+
// FIXME: Fake out log_id for now until the column is live on Wikimedia
// $this->addFieldsIf('log_id', $this->fld_ids);
$this->addFieldsIf('page_id', $this->fld_ids);
$this->addFieldsIf('log_title', $this->fld_title);
$this->addFieldsIf('log_comment', $this->fld_comment);
$this->addFieldsIf('log_params', $this->fld_details);
-
+
$this->addWhereFld('log_deleted', 0);
$this->addWhereFld('log_type', $params['type']);
$vals['logid'] = 0;
$vals['pageid'] = intval($row->page_id);
}
-
+
if ($this->fld_title) {
$title = Title :: makeTitle($row->log_namespace, $row->log_title);
ApiQueryBase :: addTitleInfo($vals, $title);
}
-
+
if ($this->fld_type) {
$vals['type'] = $row->log_type;
$vals['action'] = $row->log_action;
}
-
+
if ($this->fld_details && $row->log_params !== '') {
$params = explode("\n", $row->log_params);
switch ($row->log_type) {
- case 'move':
+ case 'move':
if (isset ($params[0])) {
$title = Title :: newFromText($params[0]);
if ($title) {
$params = null;
break;
}
-
+
if (isset($params)) {
$this->getResult()->setIndexedTagName($params, 'param');
$vals = array_merge($vals, $params);
if ($this->fld_comment && !empty ($row->log_comment)) {
$vals['comment'] = $row->log_comment;
}
-
+
return $vals;
}
return __CLASS__ . ': $Id$';
}
}
-
/**
* Query module to get list of random pages
- *
+ *
* @addtogroup API
*/
-
+
class ApiQueryRandom extends ApiQueryGeneratorBase {
public function __construct($query, $moduleName) {
parent :: __construct($query, $moduleName, 'rn');
}
-
+
public function execute() {
$this->run();
}
-
+
public function executeGenerator($resultPageSet) {
$this->run($resultPageSet);
}
-
+
protected function prepareQuery($randstr, $limit, $namespace, &$resultPageSet) {
$this->resetQueryParams();
$this->addTables('page');
if(is_null($resultPageSet)) {
$result->setIndexedTagName($data, 'page');
$result->addValue('query', $this->getModuleName(), $data);
- }
+ }
}
private function extractRowInfo($row) {
$vals['id'] = $row->page_id;
return $vals;
}
-
+
public function getAllowedParams() {
return array (
'namespace' => array(
/**
* A query action to enumerate the recent changes that were done to the wiki.
* Various filters are supported.
- *
+ *
* @addtogroup API
*/
class ApiQueryRecentChanges extends ApiQueryBase {
private $fld_comment = false, $fld_user = false, $fld_flags = false,
$fld_timestamp = false, $fld_title = false, $fld_ids = false,
$fld_sizes = false;
-
+
/**
* Generates and outputs the result of this query based upon the provided parameters.
*/
public function execute() {
/* Initialize vars */
$limit = $prop = $namespace = $titles = $show = $type = $dir = $start = $end = null;
-
+
/* Get the parameters of the request. */
extract($this->extractRequestParams());
/* Build our basic query. Namely, something along the lines of:
- * SELECT * from recentchanges WHERE rc_timestamp > $start
- * AND rc_timestamp < $end AND rc_namespace = $namespace
+ * SELECT * from recentchanges WHERE rc_timestamp > $start
+ * AND rc_timestamp < $end AND rc_namespace = $namespace
* AND rc_deleted = '0'
*/
$db = $this->getDB();
if($where != '')
$this->addWhere($where);
}
-
+
if(!is_null($type))
$this->addWhereFld('rc_type', $this->parseRCType($type));
$show = array_flip($show);
/* Check for conflicting parameters. */
- if ((isset ($show['minor']) && isset ($show['!minor']))
- || (isset ($show['bot']) && isset ($show['!bot']))
+ if ((isset ($show['minor']) && isset ($show['!minor']))
+ || (isset ($show['bot']) && isset ($show['!bot']))
|| (isset ($show['anon']) && isset ($show['!anon']))
|| (isset ($show['redirect']) && isset ($show['!redirect']))) {
-
+
$this->dieUsage("Incorrect parameter - mutually exclusive values may not be supplied", 'show');
}
$this->fld_sizes = isset ($prop['sizes']);
$this->fld_redirect = isset($prop['redirect']);
$this->fld_patrolled = isset($prop['patrolled']);
-
+
global $wgUser;
if($this->fld_patrolled && !$wgUser->isAllowed('patrol'))
$this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied');
/* Add fields to our query if they are specified as a needed parameter. */
- $this->addFieldsIf('rc_id', $this->fld_ids);
- $this->addFieldsIf('rc_cur_id', $this->fld_ids);
- $this->addFieldsIf('rc_this_oldid', $this->fld_ids);
- $this->addFieldsIf('rc_last_oldid', $this->fld_ids);
- $this->addFieldsIf('rc_comment', $this->fld_comment);
+ $this->addFieldsIf('rc_id', $this->fld_ids);
+ $this->addFieldsIf('rc_cur_id', $this->fld_ids);
+ $this->addFieldsIf('rc_this_oldid', $this->fld_ids);
+ $this->addFieldsIf('rc_last_oldid', $this->fld_ids);
+ $this->addFieldsIf('rc_comment', $this->fld_comment);
$this->addFieldsIf('rc_user', $this->fld_user);
$this->addFieldsIf('rc_user_text', $this->fld_user);
$this->addFieldsIf('rc_minor', $this->fld_flags);
if(!isset($tables))
$tables = "$rc FORCE INDEX(rc_timestamp)";
$this->addTables($tables);
- /* Specify the limit for our query. It's $limit+1 because we (possibly) need to
+ /* Specify the limit for our query. It's $limit+1 because we (possibly) need to
* generate a "continue" parameter, to allow paging. */
$this->addOption('LIMIT', $limit +1);
/* Extract the data from a single row. */
$vals = $this->extractRowInfo($row);
-
+
/* Add that row's data to our final output. */
if($vals)
$data[] = $vals;
if ($this->fld_comment && !empty ($row->rc_comment)) {
$vals['comment'] = $row->rc_comment;
}
-
+
if ($this->fld_redirect)
if($row->page_is_redirect)
$vals['redirect'] = '';
return $vals;
}
-
+
private function parseRCType($type)
{
if(is_array($type))
case 'new': return RC_NEW;
case 'log': return RC_LOG;
}
- }
+ }
public function getAllowedParams() {
return array (
ApiBase :: PARAM_ISMULTI => true,
ApiBase :: PARAM_TYPE => array (
'edit',
- 'new',
+ 'new',
'log'
)
)
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query action to enumerate revisions of a given page, or show top revisions of multiple pages.
- * Various pieces of information may be shown - flags, comments, and the actual wiki markup of the rev.
- * In the enumeration mode, ranges of revisions may be requested and filtered.
- *
+ * Various pieces of information may be shown - flags, comments, and the actual wiki markup of the rev.
+ * In the enumeration mode, ranges of revisions may be requested and filtered.
+ *
* @addtogroup API
*/
class ApiQueryRevisions extends ApiQueryBase {
// If any of those parameters are used, work in 'enumeration' mode.
// Enum mode can only be used when exactly one page is provided.
- // Enumerating revisions on multiple pages make it extremely
- // difficult to manage continuations and require additional SQL indexes
+ // Enumerating revisions on multiple pages make it extremely
+ // difficult to manage continuations and require additional SQL indexes
$enumRevMode = (!is_null($user) || !is_null($excludeuser) || !is_null($limit) || !is_null($startid) || !is_null($endid) || $dir === 'newer' || !is_null($start) || !is_null($end));
-
+
$pageSet = $this->getPageSet();
$pageCount = $pageSet->getGoodTitleCount();
}
else if($this->tok_rollback)
$this->addFields('rev_user_text');
-
+
if (isset ($prop['content'])) {
// For each page we will request, the user must have read rights for that page
$this->addFields('old_flags');
$this->fld_content = true;
-
+
$this->expandTemplates = $expandtemplates;
if(isset($section))
$this->section = $section;
$this->dieUsage('end and endid cannot be used together', 'badparams');
if(!is_null($user) && !is_null( $excludeuser))
- $this->dieUsage('user and excludeuser cannot be used together', 'badparams');
-
+ $this->dieUsage('user and excludeuser cannot be used together', 'badparams');
+
// This code makes an assumption that sorting by rev_id and rev_timestamp produces
// the same result. This way users may request revisions starting at a given time,
// but to page through results use the rev_id returned after each page.
- // Switching to rev_id removes the potential problem of having more than
- // one row with the same timestamp for the same page.
+ // Switching to rev_id removes the potential problem of having more than
+ // one row with the same timestamp for the same page.
// The order needs to be the same as start parameter to avoid SQL filesort.
if (is_null($startid) && is_null($endid))
// There is only one ID, use it
$this->addWhereFld('rev_page', current(array_keys($pageSet->getGoodTitles())));
-
+
if(!is_null($user)) {
$this->addWhereFld('rev_user_text', $user);
} elseif (!is_null( $excludeuser)) {
$this->extractRowInfo($row));
}
$db->freeResult($res);
-
+
// Ensure that all revisions are shown as '<rev>' elements
$result = $this->getResult();
if ($result->getIsRawMode()) {
$vals['revid'] = intval($row->rev_id);
// $vals['oldid'] = intval($row->rev_text_id); // todo: should this be exposed?
}
-
+
if ($this->fld_flags && $row->rev_minor_edit)
$vals['minor'] = '';
if ($this->fld_timestamp) {
$vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rev_timestamp);
}
-
+
if ($this->fld_size && !is_null($row->rev_len)) {
$vals['size'] = intval($row->rev_len);
}
if ($this->fld_comment && !empty ($row->rev_comment)) {
$vals['comment'] = $row->rev_comment;
}
-
+
if($this->tok_rollback || ($this->fld_content && $this->expandTemplates))
$title = Title::newFromID($row->rev_page);
-
+
if($this->tok_rollback) {
global $wgUser;
$vals['rollbacktoken'] = $wgUser->editToken(array($title->getPrefixedText(), $row->rev_user_text));
}
-
-
+
+
if ($this->fld_content) {
global $wgParser;
$text = Revision :: getRevisionText($row);
$text = $wgParser->preprocess( $text, $title, new ParserOptions() );
}
ApiResult :: setContent($vals, $text);
- }
+ }
return $vals;
}
'excludeuser' => array(
ApiBase :: PARAM_TYPE => 'user'
),
-
+
'expandtemplates' => false,
'section' => array(
ApiBase :: PARAM_TYPE => 'integer'
return __CLASS__ . ': $Id$';
}
}
-
/**
* Query module to perform full text search within wiki titles and content
- *
+ *
* @addtogroup API
*/
class ApiQuerySearch extends ApiQueryGeneratorBase {
$params = $this->extractRequestParams();
$limit = $params['limit'];
- $query = $params['search'];
+ $query = $params['search'];
if (is_null($query) || empty($query))
$this->dieUsage("empty search string is not allowed", 'param-search');
$search->setLimitOffset( $limit+1, $params['offset'] );
$search->setNamespaces( $params['namespace'] );
$search->showRedirects = $params['redirects'];
-
+
if ($params['what'] == 'text')
$matches = $search->searchText( $query );
else
$matches = $search->searchTitle( $query );
if (is_null($matches))
- $this->dieUsage("{$params['what']} search is disabled",
+ $this->dieUsage("{$params['what']} search is disabled",
"search-{$params['what']}-disabled");
$data = array ();
'namespace' => array (
ApiBase :: PARAM_DFLT => 0,
ApiBase :: PARAM_TYPE => 'namespace',
- ApiBase :: PARAM_ISMULTI => true,
+ ApiBase :: PARAM_ISMULTI => true,
),
'what' => array (
ApiBase :: PARAM_DFLT => 'title',
return __CLASS__ . ': $Id$';
}
}
-
/**
* A query action to return meta information about the wiki site.
- *
+ *
* @addtogroup API
*/
class ApiQuerySiteinfo extends ApiQueryBase {
$this->appendSpecialPageAliases($p);
break;
case 'interwikimap' :
- $filteriw = isset($params['filteriw']) ? $params['filteriw'] : false;
+ $filteriw = isset($params['filteriw']) ? $params['filteriw'] : false;
$this->appendInterwikiMap($p, $filteriw);
break;
case 'dbrepllag' :
protected function appendGeneralInfo($property) {
global $wgSitename, $wgVersion, $wgCapitalLinks, $wgRightsCode, $wgRightsText, $wgLanguageCode, $IP, $wgEnableWriteAPI, $wgLang;
-
+
$data = array ();
$mainPage = Title :: newFromText(wfMsgForContent('mainpage'));
$data['mainpage'] = $mainPage->getPrefixedText();
if ( $svn ) $data['rev'] = $svn;
$data['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // 'case-insensitive' option is reserved for future
-
+
if (isset($wgRightsCode))
$data['rightscode'] = $wgRightsCode;
$data['rights'] = $wgRightsText;
if ( $wgEnableWriteAPI )
$data['writeapi'] = '';
-
+
$this->getResult()->addValue('query', $property, $data);
}
-
+
protected function appendNamespaces($property) {
global $wgContLang, $wgNamespacesWithSubpages;
-
+
$data = array ();
foreach ($wgContLang->getFormattedNamespaces() as $ns => $title) {
$data[$ns] = array (
if(@$wgNamespacesWithSubpages[$ns])
$data[$ns]['subpages'] = '';
}
-
+
$this->getResult()->setIndexedTagName($data, 'ns');
$this->getResult()->addValue('query', $property, $data);
}
-
+
protected function appendNamespaceAliases($property) {
global $wgNamespaceAliases;
-
+
$data = array ();
foreach ($wgNamespaceAliases as $title => $ns) {
$item = array (
ApiResult :: setContent($item, strtr($title, '_', ' '));
$data[] = $item;
}
-
+
$this->getResult()->setIndexedTagName($data, 'ns');
$this->getResult()->addValue('query', $property, $data);
}
-
+
protected function appendSpecialPageAliases($property)
{
global $wgLang;
}
$this->addOption('ORDER BY', 'iw_prefix');
-
+
$db = $this->getDB();
$res = $this->select(__METHOD__);
$this->getResult()->setIndexedTagName($data, 'iw');
$this->getResult()->addValue('query', $property, $data);
}
-
+
protected function appendDbReplLagInfo($property, $includeAll) {
global $wgShowHostnames;
$data = array();
-
+
if ($includeAll) {
if (!$wgShowHostnames)
$this->dieUsage('Cannot view all servers info unless $wgShowHostnames is true', 'includeAllDenied');
$data[] = array (
'host' => $wgShowHostnames ? $host : '',
'lag' => $lag);
- }
+ }
$result = $this->getResult();
$result->setIndexedTagName($data, 'db');
$result->addValue('query', $property, $data);
- }
+ }
protected function appendStatistics($property) {
$data = array ();
$data['admins'] = intval(SiteStats::admins());
$data['jobs'] = intval(SiteStats::jobs());
$this->getResult()->addValue('query', $property, $data);
- }
+ }
protected function appendUserGroups($property) {
global $wgGroupPermissions;
public function getAllowedParams() {
return array (
-
+
'prop' => array (
ApiBase :: PARAM_DFLT => 'general',
ApiBase :: PARAM_ISMULTI => true,
'local',
'!local',
)),
-
+
'showalldb' => false,
);
}
/**
* This query action adds a list of a specified user's contributions to the output.
- *
+ *
* @addtogroup API
*/
class ApiQueryContributions extends ApiQueryBase {
// Parse some parameters
$this->params = $this->extractRequestParams();
- $prop = array_flip($this->params['prop']);
+ $prop = array_flip($this->params['prop']);
$this->fld_ids = isset($prop['ids']);
$this->fld_title = isset($prop['title']);
$this->fld_comment = isset($prop['comment']);
$this->dieUsage( 'User parameter may not be empty', 'param_user' );
}
}
-
+
/**
* Prepares the query and returns the limit of rows requested
*/
//anything we retrieve.
list ($tbl_page, $tbl_revision) = $this->getDB()->tableNamesN('page', 'revision');
$this->addTables("$tbl_revision LEFT OUTER JOIN $tbl_page ON page_id=rev_page");
-
+
$this->addWhereFld('rev_deleted', 0);
// We only want pages by the specified users.
if($this->prefixMode)
$this->addWhere("rev_user_text LIKE '" . $this->getDb()->escapeLike($this->userprefix) . "%'");
- else
+ else
$this->addWhereFld( 'rev_user_text', $this->usernames );
// ... and in the specified timeframe.
// Ensure the same sort order for rev_user_text and rev_timestamp
// so our query is indexed
$this->addWhereRange('rev_user_text', $this->params['dir'], null, null);
- $this->addWhereRange('rev_timestamp',
+ $this->addWhereRange('rev_timestamp',
$this->params['dir'], $this->params['start'], $this->params['end'] );
$this->addWhereFld('page_namespace', $this->params['namespace']);
// Mandatory fields: timestamp allows request continuation
// ns+title checks if the user has access rights for this page
- // user_text is necessary if multiple users were specified
+ // user_text is necessary if multiple users were specified
$this->addFields(array(
'rev_timestamp',
'page_namespace',
'page_title',
'rev_user_text',
));
-
+
$this->addFieldsIf('rev_page', $this->fld_ids);
$this->addFieldsIf('rev_id', $this->fld_ids);
// $this->addFieldsIf('rev_text_id', $this->fld_ids); // Should this field be exposed?
$this->addFieldsIf('rev_minor_edit', $this->fld_flags);
$this->addFieldsIf('page_is_new', $this->fld_flags);
}
-
+
/**
* Extract fields from the database row and append them to a result array
*/
$vals['user'] = $row->rev_user_text;
if ($this->fld_ids) {
$vals['pageid'] = intval($row->rev_page);
- $vals['revid'] = intval($row->rev_id);
+ $vals['revid'] = intval($row->rev_id);
// $vals['textid'] = intval($row->rev_text_id); // todo: Should this field be exposed?
}
-
+
if ($this->fld_title)
- ApiQueryBase :: addTitleInfo($vals,
+ ApiQueryBase :: addTitleInfo($vals,
Title :: makeTitle($row->page_namespace, $row->page_title));
if ($this->fld_timestamp)
return __CLASS__ . ': $Id$';
}
}
-
/**
* Query module to get information about the currently logged-in user
- *
+ *
* @addtogroup API
*/
class ApiQueryUserInfo extends ApiQueryBase {
$r = $this->getCurrentUserInfo();
$result->addValue("query", $this->getModuleName(), $r);
}
-
+
protected function getCurrentUserInfo() {
global $wgUser;
$result = $this->getResult();
$vals['blockedby'] = User::whoIs($wgUser->blockedBy());
$vals['blockreason'] = $wgUser->blockedFor();
}
- }
+ }
if (isset($this->prop['hasmsg']) && $wgUser->getNewtalk()) {
$vals['messages'] = '';
}
}
return $vals;
}
-
+
protected function getRateLimits()
{
global $wgUser, $wgRateLimits;
if(!$wgUser->isPingLimitable())
return array(); // No limits
-
+
// Find out which categories we belong to
$categories = array();
if($wgUser->isAnon())
if(!$wgUser->isAnon())
$categories[] = 'newbie';
}
-
+
// Now get the actual limits
$retval = array();
foreach($wgRateLimits as $action => $limits)
$retval[$action][$cat]['seconds'] = $limits[$cat][1];
}
return $retval;
- }
+ }
public function getAllowedParams() {
return array (
/**
* Query module to get information about a list of users
- *
+ *
* @addtogroup API
*/
-
+
class ApiQueryUsers extends ApiQueryBase {
public function __construct($query, $moduleName) {
} else {
$this->prop = array();
}
-
+
if(is_array($params['users'])) {
$r = $this->getOtherUsersInfo($params['users']);
$result->setIndexedTagName($r, 'user');
// Canonicalize user names
foreach($users as $u) {
$n = User::getCanonicalName($u);
- if($n === false || $n === '')
+ if($n === false || $n === '')
$retval[] = array('name' => $u, 'invalid' => '');
else
$goodNames[] = $n;
$this->addFields('u1.user_name');
$this->addWhereFld('u1.user_name', $goodNames);
$this->addFieldsIf('u1.user_editcount', isset($this->prop['editcount']));
-
+
if(isset($this->prop['groups'])) {
$ug = $db->tableName('user_groups');
$tables = "$tables LEFT JOIN $ug ON ug_user=u1.user_id";
$this->addFields(array('ipb_reason', 'u2.user_name AS blocker_name'));
}
$this->addTables($tables);
-
+
$data = array();
$res = $this->select(__METHOD__);
while(($r = $db->fetchObject($res))) {
$data[$r->user_name]['blockreason'] = $r->ipb_reason;
}
}
-
+
// Second pass: add result data to $retval
foreach($goodNames as $u) {
if(!isset($data[$u]))
$retval[] = $data[$u];
}
}
- return $retval;
+ return $retval;
}
public function getAllowedParams() {
/**
* This query action allows clients to retrieve a list of recently modified pages
* that are part of the logged-in user's watchlist.
- *
+ *
* @addtogroup API
*/
class ApiQueryWatchlist extends ApiQueryGeneratorBase {
private $fld_ids = false, $fld_title = false, $fld_patrol = false, $fld_flags = false,
$fld_timestamp = false, $fld_user = false, $fld_comment = false, $fld_sizes = false;
-
+
private function run($resultPageSet = null) {
global $wgUser, $wgDBtype;
$this->addWhereRange('rc_timestamp', $dir, $start, $end);
$this->addWhereFld('wl_namespace', $namespace);
$this->addWhereIf('rc_this_oldid=page_latest', !$allrev);
-
+
if (!is_null($show)) {
$show = array_flip($show);
/* Check for conflicting parameters. */
- if ((isset ($show['minor']) && isset ($show['!minor']))
- || (isset ($show['bot']) && isset ($show['!bot']))
+ if ((isset ($show['minor']) && isset ($show['!minor']))
+ || (isset ($show['bot']) && isset ($show['!bot']))
|| (isset ($show['anon']) && isset ($show['!anon']))) {
-
+
$this->dieUsage("Incorrect parameter - mutually exclusive values may not be supplied", 'show');
}
$this->addWhereIf('rc_user != 0', isset ($show['!anon']));
}
-
+
# This is an index optimization for mysql, as done in the Special:Watchlist page
$this->addWhereIf("rc_timestamp > ''", !isset ($start) && !isset ($end) && $wgDBtype == 'mysql');
if ($this->fld_ids) {
$vals['pageid'] = intval($row->rc_cur_id);
- $vals['revid'] = intval($row->rc_this_oldid);
+ $vals['revid'] = intval($row->rc_this_oldid);
}
-
+
if ($this->fld_title)
ApiQueryBase :: addTitleInfo($vals, Title :: makeTitle($row->rc_namespace, $row->rc_title));
return __CLASS__ . ': $Id$';
}
}
-
* It simply wraps a nested array() structure, adding some functions to simplify array's modifications.
* As various modules execute, they add different pieces of information to this result,
* structuring it as it will be given to the client.
- *
+ *
* Each subarray may either be a dictionary - key-value pairs with unique keys,
* or lists, where the items are added using $data[] = $value notation.
- *
+ *
* There are two special key values that change how XML output is generated:
* '_element' This key sets the tag name for the rest of the elements in the current array.
* It is only inserted if the formatter returned true for getNeedsRawData()
* '*' This key has special meaning only to the XML formatter, and is outputed as is
- * for all others. In XML it becomes the content of the current element.
- *
+ * for all others. In XML it becomes the content of the current element.
+ *
* @addtogroup API
*/
class ApiResult extends ApiBase {
public function reset() {
$this->mData = array ();
}
-
+
/**
- * Call this function when special elements such as '_element'
- * are needed by the formatter, for example in XML printing.
+ * Call this function when special elements such as '_element'
+ * are needed by the formatter, for example in XML printing.
*/
public function setRawMode() {
$this->mIsRawMode = true;
}
-
+
/**
* Returns true if the result is being created for the formatter that requested raw data.
*/
// Do not use setElement() as it is ok to call this more than once
$arr['_element'] = $tag;
}
-
+
/**
* Calls setIndexedTagName() on $arr and each sub-array
*/
* Add value to the output data at the given path.
* Path is an indexed array, each element specifing the branch at which to add the new value
* Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value
- * If $name is empty, the $value is added as a next list element data[] = $value
+ * If $name is empty, the $value is added as a next list element data[] = $value
*/
public function addValue($path, $name, $value) {
if (!function_exists('array_intersect_key')) {
function array_intersect_key($isec, $keys) {
$argc = func_num_args();
-
+
if ($argc > 2) {
for ($i = 1; !empty($isec) && $i < $argc; $i++) {
$arr = func_get_arg($i);
-
+
foreach (array_keys($isec) as $key) {
- if (!isset($arr[$key]))
+ if (!isset($arr[$key]))
unset($isec[$key]);
}
}
-
+
return $isec;
} else {
$res = array();
if (isset($keys[$key]))
$res[$key] = $isec[$key];
}
-
+
return $res;
}
}
global $wgUser;
$this->getMain()->requestWriteMode();
$params = $this->extractRequestParams();
-
+
$titleObj = NULL;
if(!isset($params['title']))
$this->dieUsageMsg(array('missingparam', 'title'));
$this->getResult()->addValue(null, $this->getModuleName(), $info);
}
-
+
public function mustBePosted() { return true; }
-
+
public function getAllowedParams() {
return array (
'title' => null,
/**
* Unblocks the specified user or provides the reason the unblock failed.
- */
+ */
public function execute() {
global $wgUser;
$this->getMain()->requestWriteMode();
$res['reason'] = $reason;
$this->getResult()->addValue(null, $this->getModuleName(), $res);
}
-
+
public function mustBePosted() { return true; }
public function getAllowedParams() {
global $wgUser;
$this->getMain()->requestWriteMode();
$params = $this->extractRequestParams();
-
+
$titleObj = NULL;
if(!isset($params['title']))
$this->dieUsageMsg(array('missingparam', 'title'));
$info['reason'] = $retval[2];
$this->getResult()->addValue(null, $this->getModuleName(), $info);
}
-
+
public function mustBePosted() { return true; }
-
+
public function getAllowedParams() {
return array (
'title' => null,
require_once( dirname( __FILE__ ) . '/CBTProcessor.php' );
-/**
- * Push a value onto the stack
+/**
+ * Push a value onto the stack
* Argument 1: value
*/
define( 'CBT_PUSH', 1 );
}
function name() {
- $opcodeNames = array(
+ $opcodeNames = array(
CBT_PUSH => 'PUSH',
CBT_CAT => 'CAT',
CBT_CATS => 'CATS',
} else {
$text = true;
}
-
+
return $text;
}
/**
* Recursive workhorse for text mode.
- *
- * Processes text mode starting from offset $p, until either $end is
- * reached or a closing brace is found. If $needClosing is false, a
+ *
+ * Processes text mode starting from offset $p, until either $end is
+ * reached or a closing brace is found. If $needClosing is false, a
* closing brace will flag an error, if $needClosing is true, the lack
- * of a closing brace will flag an error.
+ * of a closing brace will flag an error.
*
- * The parameter $p is advanced to the position after the closing brace,
+ * The parameter $p is advanced to the position after the closing brace,
* or after the end. A CBTValue is returned.
*
* @private
$in =& $this->mText;
$start = $p;
$atStart = true;
-
+
$foundClosing = false;
while ( $p < $end ) {
$matchLength = strcspn( $in, CBT_BRACE, $p, $end - $p );
$this->mOps[] = $this->op( CBT_CAT, substr( $in, $p, $matchLength ) );
}
- // Advance the pointer
+ // Advance the pointer
$p = $pToken + 1;
-
+
// Check for closing brace
if ( $in[$pToken] == '}' ) {
$foundClosing = true;
$atStart = false;
} else {
$this->mOps[] = $this->op( CBT_CATS );
- }
+ }
}
if ( $foundClosing && !$needClosing ) {
$this->error( 'Errant closing brace', $p );
/**
* Recursive workhorse for function mode.
*
- * Processes function mode starting from offset $p, until either $end is
- * reached or a closing brace is found. If $needClosing is false, a
+ * Processes function mode starting from offset $p, until either $end is
+ * reached or a closing brace is found. If $needClosing is false, a
* closing brace will flag an error, if $needClosing is true, the lack
- * of a closing brace will flag an error.
+ * of a closing brace will flag an error.
*
- * The parameter $p is advanced to the position after the closing brace,
+ * The parameter $p is advanced to the position after the closing brace,
* or after the end. A CBTValue is returned.
*
* @private
';
}
}
-
/**
* PHP version of the callback template processor
- * This is currently used as a test rig and is likely to be used for
+ * This is currently used as a test rig and is likely to be used for
* compatibility purposes later, where the C++ extension is not available.
*/
/**
* A dependency-tracking value class
- * Callback functions should return one of these, unless they have
+ * Callback functions should return one of these, unless they have
* no dependencies in which case they can return a string.
- */
+ */
class CBTValue {
var $mText, $mDeps, $mIsTemplate;
/**
* Execute the template.
- * If $compile is true, produces an optimised template where functions with static
+ * If $compile is true, produces an optimised template where functions with static
* dependencies have been replaced by their return values.
*/
function execute( $compile = false ) {
$context = rtrim( str_replace( "\t", " ", substr( $this->mText, $startLine, $endLine - $startLine ) ) );
$text .= htmlspecialchars( $context ) . "\n" . str_repeat( ' ', $pos - $startLine ) . "^\n</pre>\n";
- }
+ }
wfProfileOut( $fname );
return $text;
}
return $this->doOpenText( $start, $end, false );
}
- /**
+ /**
* Escape text for a template if we are producing a template. Do nothing
* if we are producing plain text.
*/
/**
* Recursive workhorse for text mode.
- *
- * Processes text mode starting from offset $p, until either $end is
- * reached or a closing brace is found. If $needClosing is false, a
+ *
+ * Processes text mode starting from offset $p, until either $end is
+ * reached or a closing brace is found. If $needClosing is false, a
* closing brace will flag an error, if $needClosing is true, the lack
- * of a closing brace will flag an error.
+ * of a closing brace will flag an error.
*
- * The parameter $p is advanced to the position after the closing brace,
+ * The parameter $p is advanced to the position after the closing brace,
* or after the end. A CBTValue is returned.
*
* @private
$in =& $this->mText;
$start = $p;
$ret = new CBTValue( '', array(), $this->mCompiling );
-
+
$foundClosing = false;
while ( $p < $end ) {
$matchLength = strcspn( $in, CBT_BRACE, $p, $end - $p );
// Output the text before the brace
$ret->cat( substr( $in, $p, $matchLength ) );
- // Advance the pointer
+ // Advance the pointer
$p = $pToken + 1;
-
+
// Check for closing brace
if ( $in[$pToken] == '}' ) {
$foundClosing = true;
break;
}
-
+
// Handle the "{fn}" special case
if ( $pToken > 0 && $in[$pToken-1] == '"' ) {
wfProfileOut( $fname );
$ret->cat( $val );
} else {
// Process the function mode component
- wfProfileOut( $fname );
+ wfProfileOut( $fname );
$ret->cat( $this->doOpenFunction( $p, $end ) );
wfProfileIn( $fname );
}
} elseif ( !$foundClosing && $needClosing ) {
$this->error( 'Unclosed text section', $start );
}
- wfProfileOut( $fname );
+ wfProfileOut( $fname );
return $ret;
}
/**
* Recursive workhorse for function mode.
*
- * Processes function mode starting from offset $p, until either $end is
- * reached or a closing brace is found. If $needClosing is false, a
+ * Processes function mode starting from offset $p, until either $end is
+ * reached or a closing brace is found. If $needClosing is false, a
* closing brace will flag an error, if $needClosing is true, the lack
- * of a closing brace will flag an error.
+ * of a closing brace will flag an error.
*
- * The parameter $p is advanced to the position after the closing brace,
+ * The parameter $p is advanced to the position after the closing brace,
* or after the end. A CBTValue is returned.
*
* @private
}
}
- // The dynamic parts of the string are still represented as functions, and
- // function invocations have no dependencies. Thus the compiled result has
+ // The dynamic parts of the string are still represented as functions, and
+ // function invocations have no dependencies. Thus the compiled result has
// no dependencies.
$val = new CBTValue( "{{$compiled}}", array(), true );
}
/**
* Execute a function, caching and returning the result value.
- * $tokens is an array of CBTValue objects. $tokens[0] is the function
+ * $tokens is an array of CBTValue objects. $tokens[0] is the function
* name, the others are arguments. $p is the string position, and is used
* for error messages only.
*/
}
$fname = 'CBTProcessor::doFunction';
wfProfileIn( $fname );
-
+
$ret = new CBTValue;
-
+
// All functions implicitly depend on their arguments, and the function name
- // While this is not strictly necessary for all functions, it's true almost
- // all the time and so convenient to do automatically.
+ // While this is not strictly necessary for all functions, it's true almost
+ // all the time and so convenient to do automatically.
$ret->addDeps( $tokens );
$this->mCurrentPos = $p;
// If the output was a template, execute it
$val->execute( $this );
-
+
if ( $this->mCompiling ) {
// Escape any braces so that the output will be a valid template
$val->templateEscape();
- }
+ }
$val->removeDeps( $this->mIgnorableDeps );
$ret->addDeps( $val );
$ret->setText( $val->getText() );
if ( CBT_DEBUG ) {
- wfDebug( "doFunction $func args = "
- . var_export( $tokens, true )
- . "unexpanded return = "
+ wfDebug( "doFunction $func args = "
+ . var_export( $tokens, true )
+ . "unexpanded return = "
. var_export( $unexpanded, true )
- . "expanded return = "
- . var_export( $ret, true )
+ . "expanded return = "
+ . var_export( $ret, true )
);
}
-
+
wfProfileOut( $fname );
return $ret;
}
}
if ( $condition->getText() != '' ) {
- return new CBTValue( $trueBlock->getText(),
+ return new CBTValue( $trueBlock->getText(),
array_merge( $condition->getDeps(), $trueBlock->getDeps() ),
$trueBlock->mIsTemplate );
} else {
if ( !is_null( $falseBlock ) ) {
- return new CBTValue( $falseBlock->getText(),
+ return new CBTValue( $falseBlock->getText(),
array_merge( $condition->getDeps(), $falseBlock->getDeps() ),
$falseBlock->mIsTemplate );
} else {
return '}';
}
- /**
+ /**
* escape built-in.
- * Escape text for inclusion in an HTML attribute
+ * Escape text for inclusion in an HTML attribute
*/
function bi_escape( $val ) {
return new CBTValue( htmlspecialchars( $val->getText() ), $val->getDeps() );
}
}
-
Overview
--------
-CBT (callback-based templates) is an experimental system for improving skin
+CBT (callback-based templates) is an experimental system for improving skin
rendering time in MediaWiki and similar applications. The fundamental concept is
a template language which contains tags which pull text from PHP callbacks.
These PHP callbacks do not simply return text, they also return a description of
experiment. It is a class written in PHP which parses a template, and produces
either an optimised template with dependencies removed, or the output text
itself. I found that even with a heavily optimised template, this processor was
-not fast enough to match the speed of the original MonoBook.
+not fast enough to match the speed of the original MonoBook.
To improve the efficiency, I wrote TemplateCompiler, which takes a template,
preferably pre-optimised by TemplateProcessor, and generates PHP code from it.
The generated code is a single expression, concatenating static text and
-callback results. This approach turned out to be very efficient, making
-significant time savings compared to the original MonoBook.
+callback results. This approach turned out to be very efficient, making
+significant time savings compared to the original MonoBook.
-Despite this success, the code has been shelved for the time being. There were
+Despite this success, the code has been shelved for the time being. There were
a number of unresolved implementation problems, and I felt that there were more
pressing priorities for MediaWiki development than solving them and bringing
-this module to completion. I also believe that more research is needed into
+this module to completion. I also believe that more research is needed into
other possible template architectures. There is nothing fundamentally wrong with
the CBT concept, and I would encourage others to continue its development.
The problems I saw were:
-* Extensibility. Can non-Wikimedia installations easily extend and modify CBT
+* Extensibility. Can non-Wikimedia installations easily extend and modify CBT
skins? Patching seems to be necessary, is this acceptable? MediaWiki
extensions are another problem. Unless the interfaces allow them to return
dependencies, any hooks will have to be marked dynamic and thus inefficient.
Template syntax
---------------
-There are two modes: text mode and function mode. The brace characters "{"
+There are two modes: text mode and function mode. The brace characters "{"
and "}" are the only reserved characters. Either one of them will switch from
-text mode to function mode wherever they appear, no exceptions.
+text mode to function mode wherever they appear, no exceptions.
In text mode, all characters are passed through to the output. In function
-mode, text is split into tokens, delimited either by whitespace or by
+mode, text is split into tokens, delimited either by whitespace or by
matching pairs of braces. The first token is taken to be a function name. The
-other tokens are first processed in function mode themselves, then they are
+other tokens are first processed in function mode themselves, then they are
passed to the named function as parameters. The return value of the function
is passed through to the output.
First brace switches to function mode. The function name is escape, the first
and only parameter is {"hello"}. This parameter is executed. The braces around
the parameter cause the parser to switch to text mode, thus the string "hello",
-including the quotes, is passed back and used as an argument to the escape
-function.
+including the quotes, is passed back and used as an argument to the escape
+function.
Example:
{if title {<h1>{title}</h1>}}
-The function name is "if". The first parameter is the result of calling the
+The function name is "if". The first parameter is the result of calling the
function "title". The second parameter is a level 1 HTML heading containing
-the result of the function "title". "if" is a built-in function which will
+the result of the function "title". "if" is a built-in function which will
return the second parameter only if the first is non-blank, so the effect of
this is to return a heading element only if a title exists.
As a shortcut for generation of HTML attributes, if a function mode segment is
-surrounded by double quotes, quote characters in the return value will be
-escaped. This only applies if the quote character immediately precedes the
+surrounded by double quotes, quote characters in the return value will be
+escaped. This only applies if the quote character immediately precedes the
opening brace, and immediately follows the closing brace, with no whitespace.
-User callback functions are defined by passing a function object to the
+User callback functions are defined by passing a function object to the
template processor. Function names appearing in the text are first checked
against built-in function names, then against the method names in the function
-object. The function object forms a sandbox for execution of the template, so
+object. The function object forms a sandbox for execution of the template, so
security-conscious users may wish to avoid including functions that allow
arbitrary filesystem access or code execution.
-The callback function will receive its parameters as strings. If the
-result of the function depends only on the arguments, and certain things
+The callback function will receive its parameters as strings. If the
+result of the function depends only on the arguments, and certain things
understood to be "static", such as the source code, then the callback function
should return a string. If the result depends on other things, then the function
should call cbt_value() to get a return value:
return cbt_value( $text, $deps );
-where $deps is an array of string tokens, each one naming a dependency. As a
+where $deps is an array of string tokens, each one naming a dependency. As a
shortcut, if there is only one dependency, $deps may be a string.
$timestamp, # time of upload
$dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx)
$deleted; # Bitfield akin to rev_deleted
-
- /**#@-*/
-
+
+ /**#@-*/
+
function ArchivedFile( $title, $id=0, $key='' ) {
if( !is_object($title) ) {
throw new MWException( 'ArchivedFile constructor given bogus title.' );
'fa_user_text',
'fa_timestamp',
'fa_deleted' ),
- array(
+ array(
'fa_name' => $this->title->getDBkey(),
$conds ),
__METHOD__,
array( 'ORDER BY' => 'fa_timestamp DESC' ) );
-
+
if ( $dbr->numRows( $res ) == 0 ) {
// this revision does not exist?
return;
}
$ret = $dbr->resultObject( $res );
$row = $ret->fetchObject();
-
+
// initialize fields for filestore image object
$this->id = intval($row->fa_id);
$this->name = $row->fa_name;
return;
}
$this->dataLoaded = true;
-
+
return true;
}
/**
* Loads a file object from the filearchive table
* @return ResultWrapper
- */
- public static function newFromRow( $row ) {
+ */
+ public static function newFromRow( $row ) {
$file = new ArchivedFile( Title::makeTitle( NS_IMAGE, $row->fa_name ) );
-
+
$file->id = intval($row->fa_id);
$file->name = $row->fa_name;
$file->archive_name = $row->fa_archive_name;
$file->user_text = $row->fa_user_text;
$file->timestamp = $row->fa_timestamp;
$file->deleted = $row->fa_deleted;
-
+
return $file;
}
-
+
/**
* Return the associated title object
* @public
*/
- public function getTitle() {
+ public function getTitle() {
return $this->title;
}
/**
* Return the file name
- */
- public function getName() {
+ */
+ public function getName() {
return $this->name;
}
- public function getID() {
+ public function getID() {
$this->load();
return $this->id;
}
-
+
/**
* Return the FileStore key
- */
- public function getKey() {
+ */
+ public function getKey() {
$this->load();
return $this->key;
}
-
+
/**
* Return the FileStore storage group
- */
+ */
public function getGroup() {
return $file->group;
}
*/
public function getWidth() {
$this->load();
- return $this->width;
+ return $this->width;
}
/**
*/
public function getHeight() {
$this->load();
- return $this->height;
+ return $this->height;
}
-
+
/**
* Get handler-specific metadata
*/
$this->load();
return $this->size;
}
-
+
/**
* Return the bits of the image file, in bytes
* @public
$this->load();
return $this->bits;
}
-
+
/**
* Returns the mime type of the file.
*/
$this->load();
return $this->mime;
}
-
+
/**
* Return the type of the media in the file.
* Use the value returned by this function with the MEDIATYPE_xxx constants.
return $this->user;
}
}
-
+
/**
* Return the user name of the uploader.
*/
return $this->user_text;
}
}
-
+
/**
* Return upload description.
*/
return $this->description;
}
}
-
+
/**
* Return the user ID of the uploader.
*/
$this->load();
return $this->user;
}
-
+
/**
* Return the user name of the uploader.
*/
$this->load();
return $this->user_text;
}
-
+
/**
* Return upload description.
*/
public function isDeleted( $field ) {
return ($this->deleted & $field) == $field;
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this FileStore image file, if it's marked as deleted.
- * @param int $field
+ * @param int $field
* @return bool
*/
public function userCan( $field ) {
// Optional settings
$this->hashLevels = isset( $info['hashLevels'] ) ? $info['hashLevels'] : 2;
- $this->deletedHashLevels = isset( $info['deletedHashLevels'] ) ?
+ $this->deletedHashLevels = isset( $info['deletedHashLevels'] ) ?
$info['deletedHashLevels'] : $this->hashLevels;
$this->deletedDir = isset( $info['deletedDir'] ) ? $info['deletedDir'] : false;
}
/**
* Get a URL referring to this repository, with the private mwrepo protocol.
- * The suffix, if supplied, is considered to be unencoded, and will be
+ * The suffix, if supplied, is considered to be unencoded, and will be
* URL-encoded before being returned.
*/
function getVirtualUrl( $suffix = false ) {
* @param integer $flags Bitwise combination of the following flags:
* self::DELETE_SOURCE Delete the source file after upload
* self::OVERWRITE Overwrite an existing destination file instead of failing
- * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
+ * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
* same contents as the source
*/
function storeBatch( $triplets, $flags = 0 ) {
if ( !wfMkdirParents( $dstDir ) ) {
return $this->newFatal( 'directorycreateerror', $dstDir );
}
- // In the deleted zone, seed new directories with a blank
+ // In the deleted zone, seed new directories with a blank
// index.html, to prevent crawling
if ( $dstZone == 'deleted' ) {
file_put_contents( "$dstDir/index.html", '' );
}
}
-
+
if ( self::isVirtualUrl( $srcPath ) ) {
$srcPath = $triplets[$i][0] = $this->resolveVirtualUrl( $srcPath );
}
/**
* Pick a random name in the temp zone and store a file to it.
- * @param string $originalName The base name of the file as specified
+ * @param string $originalName The base name of the file as specified
* by the user. The file extension will be maintained.
* @param string $srcPath The current location of the file.
* @return FileRepoStatus object with the URL in the value.
}
$dstPath = "{$this->directory}/$dstRel";
$archivePath = "{$this->directory}/$archiveRel";
-
+
$dstDir = dirname( $dstPath );
$archiveDir = dirname( $archivePath );
// Abort immediately on directory creation errors since they're likely to be repetitive
if ( !$status->ok ) {
return $status;
}
-
+
foreach ( $triplets as $i => $triplet ) {
list( $srcPath, $dstRel, $archiveRel ) = $triplet;
$dstPath = "{$this->directory}/$dstRel";
if( is_file( $dstPath ) ) {
// Check if the archive file exists
// This is a sanity check to avoid data loss. In UNIX, the rename primitive
- // unlinks the destination file if it exists. DB-based synchronisation in
- // publishBatch's caller should prevent races. In Windows there's no
+ // unlinks the destination file if it exists. DB-based synchronisation in
+ // publishBatch's caller should prevent races. In Windows there's no
// problem because the rename primitive fails if the destination exists.
if ( is_file( $archivePath ) ) {
$success = false;
/**
* Move a group of files to the deletion archive.
- * If no valid deletion archive is configured, this may either delete the
+ * If no valid deletion archive is configured, this may either delete the
* file or throw an exception, depending on the preference of the repository.
*
- * @param array $sourceDestPairs Array of source/destination pairs. Each element
+ * @param array $sourceDestPairs Array of source/destination pairs. Each element
* is a two-element array containing the source file path relative to the
- * public root in the first element, and the archive file path relative
+ * public root in the first element, and the archive file path relative
* to the deleted zone root in the second element.
* @return FileRepoStatus
*/
/**
* Move the files
- * We're now committed to returning an OK result, which will lead to
+ * We're now committed to returning an OK result, which will lead to
* the files being moved in the DB also.
*/
foreach ( $sourceDestPairs as $pair ) {
}
return $status;
}
-
+
/**
* Get a relative path including trailing slash, e.g. f/fa/
* If the repo is not hashed, returns an empty string
}
/**
- * Get a relative path for a deletion archive key,
+ * Get a relative path for a deletion archive key,
* e.g. s/z/a/ for sza251lrxrc1jad41h5mgilp8nysje52.jpg
*/
function getDeletedHashPath( $key ) {
}
return $path;
}
-
+
/**
* Call a callback function for every file in the repository.
* Uses the filesystem even in child classes.
}
}
-
-
<?php
/**
- * Implements some public methods and some protected utility functions which
- * are required by multiple child classes. Contains stub functionality for
+ * Implements some public methods and some protected utility functions which
+ * are required by multiple child classes. Contains stub functionality for
* unimplemented public methods.
*
- * Stub functions which should be overridden are marked with STUB. Some more
+ * Stub functions which should be overridden are marked with STUB. Some more
* concrete functions are also typically overridden by child classes.
*
* Note that only the repo object knows what its file class is called. You should
- * never name a file class explictly outside of the repo class. Instead use the
+ * never name a file class explictly outside of the repo class. Instead use the
* repo's factory functions to generate file objects, for example:
*
* RepoGroup::singleton()->getLocalRepo()->newFile($title);
const DELETE_SOURCE = 1;
- /**
- * Some member variables can be lazy-initialised using __get(). The
+ /**
+ * Some member variables can be lazy-initialised using __get(). The
* initialisation function for these variables is always a function named
- * like getVar(), where Var is the variable name with upper-case first
+ * like getVar(), where Var is the variable name with upper-case first
* letter.
*
* The following variables are initialised in this way in this base class:
- * name, extension, handler, path, canRender, isSafeFile,
+ * name, extension, handler, path, canRender, isSafeFile,
* transformScript, hashPath, pageCount, url
*
- * Code within this class should generally use the accessor function
+ * Code within this class should generally use the accessor function
* directly, since __get() isn't re-entrant and therefore causes bugs that
* depend on initialisation order.
*/
return array( $mime, 'unknown' );
}
}
-
+
/**
* Return the name of this file
*/
if ( !isset( $this->name ) ) {
$this->name = $this->repo->getNameFromTitle( $this->title );
}
- return $this->name;
+ return $this->name;
}
/**
function getExtension() {
if ( !isset( $this->extension ) ) {
$n = strrpos( $this->getName(), '.' );
- $this->extension = self::normalizeExtension(
+ $this->extension = self::normalizeExtension(
$n ? substr( $this->getName(), $n + 1 ) : '' );
}
return $this->extension;
/**
* Return the URL of the file
*/
- public function getUrl() {
+ public function getUrl() {
if ( !isset( $this->url ) ) {
$this->url = $this->repo->getZoneUrl( 'public' ) . '/' . $this->getUrlRel();
}
- return $this->url;
+ return $this->url;
}
-
+
/**
* Return a fully-qualified URL to the file.
* Upload URL paths _may or may not_ be fully qualified, so
}
/**
- * Return the width of the image. Returns false if the width is unknown
+ * Return the width of the image. Returns false if the width is unknown
* or undefined.
*
* STUB
public function getWidth( $page = 1 ) { return false; }
/**
- * Return the height of the image. Returns false if the height is unknown
+ * Return the height of the image. Returns false if the height is unknown
* or undefined
*
* STUB
function getMediaType() { return MEDIATYPE_UNKNOWN; }
/**
- * Checks if the output of transform() for this file is likely
- * to be valid. If this is false, various user elements will
+ * Checks if the output of transform() for this file is likely
+ * to be valid. If this is false, various user elements will
* display a placeholder instead.
*
* Currently, this checks if the file is an image format
}
return $this->isSafeFile;
}
-
+
/** Accessor for __get() */
protected function getIsSafeFile() {
return $this->isSafeFile();
* Returns true if file exists in the repository.
*
* Overridden by LocalFile to avoid unnecessary stat calls.
- *
+ *
* @return boolean Whether file exists in the repository.
*/
public function exists() {
* @return boolean Whether file exists in the repository and is includable.
* @public
*/
- function isVisible() {
+ function isVisible() {
return $this->exists();
}
/**
* Transform a media file
*
- * @param array $params An associative array of handler-specific parameters. Typical
+ * @param array $params An associative array of handler-specific parameters. Typical
* keys are width, height and page.
* @param integer $flags A bitfield, may contain self::RENDER_NOW to force rendering
* @return MediaTransformOutput
$normalisedParams = $params;
$this->handler->normaliseParams( $this, $normalisedParams );
- $thumbName = $this->thumbName( $normalisedParams );
+ $thumbName = $this->thumbName( $normalisedParams );
$thumbPath = $this->getThumbPath( $thumbName );
$thumbUrl = $this->getThumbUrl( $thumbName );
-
+
if ( $this->repo->canTransformVia404() && !($flags & self::RENDER_NOW ) ) {
$thumb = $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
break;
$thumb = $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
}
}
-
+
if ( $wgUseSquid ) {
SquidUpdate::purge( array( $thumbUrl ) );
}
return $thumb;
}
- /**
+ /**
* Hook into transform() to allow migration of thumbnail files
* STUB
* Overridden by LocalFile
/**
* Get a MediaHandler instance for this file
*/
- function getHandler() {
+ function getHandler() {
if ( !isset( $this->handler ) ) {
$this->handler = MediaHandler::getHandler( $this->getMimeType() );
}
$title->purgeSquid();
}
}
-
+
/**
* Purge metadata and all affected pages when the file is created,
* deleted, or majorly updated.
}
/**
- * Return the history of this file, line by line. Starts with current version,
- * then old versions. Should return an object similar to an image/oldimage
+ * Return the history of this file, line by line. Starts with current version,
+ * then old versions. Should return an object similar to an image/oldimage
* database row.
*
* STUB
$path .= '/' . rawurlencode( $suffix );
}
return $path;
- }
+ }
/**
* @return bool
* STUB
* Overridden by LocalFile
*/
- function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false ) {
- $this->readOnlyError();
+ function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false ) {
+ $this->readOnlyError();
}
/**
- * Move or copy a file to its public location. If a file exists at the
- * destination, move it to an archive. Returns the archive name on success
- * or an empty string if it was a new file, and a wikitext-formatted
- * WikiError object on failure.
+ * Move or copy a file to its public location. If a file exists at the
+ * destination, move it to an archive. Returns the archive name on success
+ * or an empty string if it was a new file, and a wikitext-formatted
+ * WikiError object on failure.
*
* The archive name should be passed through to recordUpload for database
* registration.
*
* @param string $sourcePath Local filesystem path to the source image
* @param integer $flags A bitwise combination of:
- * File::DELETE_SOURCE Delete the source file, i.e. move
+ * File::DELETE_SOURCE Delete the source file, i.e. move
* rather than copy
- * @return The archive name on success or an empty string if it was a new
- * file, and a wikitext-formatted WikiError object on failure.
+ * @return The archive name on success or an empty string if it was a new
+ * file, and a wikitext-formatted WikiError object on failure.
*
* STUB
* Overridden by LocalFile
list( $page, $imagelinks ) = $db->tableNamesN( 'page', 'imagelinks' );
$encName = $db->addQuotes( $this->getName() );
- $sql = "SELECT page_namespace,page_title,page_id,page_len,page_is_redirect,
+ $sql = "SELECT page_namespace,page_title,page_id,page_len,page_is_redirect,
FROM $page,$imagelinks WHERE page_id=il_from AND il_to=$encName $options";
$res = $db->query( $sql, __METHOD__ );
*
* @return bool
*/
- function isLocal() {
- return $this->getRepoName() == 'local';
+ function isLocal() {
+ return $this->getRepoName() == 'local';
}
/**
*
* @return string
*/
- function getRepoName() {
- return $this->repo ? $this->repo->getName() : 'unknown';
+ function getRepoName() {
+ return $this->repo ? $this->repo->getName() : 'unknown';
}
/**
return round( $srcHeight * $dstWidth / $srcWidth );
}
}
-
+
/**
- * Get an image size array like that returned by getimagesize(), or false if it
+ * Get an image size array like that returned by getimagesize(), or false if it
* can't be determined.
*
* @param string $fileName The filename
/**
* Get the 14-character timestamp of the file upload, or false if
- * it doesn't exist
+ * it doesn't exist
*/
function getTimestamp() {
$path = $this->getPath();
function getSha1() {
return self::sha1Base36( $this->getPath() );
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this file, if it's marked as deleted.
* STUB
- * @param int $field
+ * @param int $field
* @return bool
*/
function userCan( $field ) {
* Get an associative array containing information about a file in the local filesystem.
*
* @param string $path Absolute local filesystem path
- * @param mixed $ext The file extension, or true to extract it from the filename.
+ * @param mixed $ext The file extension, or true to extract it from the filename.
* Set it to false to ignore the extension.
*/
static function getPropsFromPath( $path, $ext = true ) {
wfProfileIn( __METHOD__ );
wfDebug( __METHOD__.": Getting file info for $path\n" );
- $info = array(
+ $info = array(
'fileExists' => file_exists( $path ) && !is_dir( $path )
);
$gis = false;
}
/**
- * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case
- * encoding, zero padded to 31 digits.
+ * Get a SHA-1 hash of a file in the local filesystem, in base-36 lower case
+ * encoding, zero padded to 31 digits.
*
* 160 log 2 / log 36 = 30.95, so the 160-bit hash fills 31 digits in base 36
* fairly neatly.
define( 'MW_IMG_DELETED_COMMENT', File::DELETED_COMMENT );
define( 'MW_IMG_DELETED_USER', File::DELETED_USER );
define( 'MW_IMG_DELETED_RESTRICTED', File::DELETED_RESTRICTED );
-
-
var $descBaseUrl, $scriptDirUrl, $articleUrl, $fetchDescription, $initialCapital;
var $pathDisclosureProtection = 'paranoid';
- /**
+ /**
* Factory functions for creating new files
* Override these in the base class
*/
function __construct( $info ) {
// Required settings
$this->name = $info['name'];
-
+
// Optional settings
$this->initialCapital = true; // by default
- foreach ( array( 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
- 'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection' ) as $var )
+ foreach ( array( 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
+ 'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection' ) as $var )
{
if ( isset( $info[$var] ) ) {
$this->$var = $info[$var];
/**
* Create a new File object from the local repository
* @param mixed $title Title object or string
- * @param mixed $time Time at which the image was uploaded.
- * If this is specified, the returned object will be an
+ * @param mixed $time Time at which the image was uploaded.
+ * If this is specified, the returned object will be an
* instance of the repository's old file class instead of
- * a current file. Repositories not supporting version
+ * a current file. Repositories not supporting version
* control should return false if this parameter is set.
*/
function newFile( $title, $time = false ) {
/**
* Find an instance of the named file created at the specified time
- * Returns false if the file does not exist. Repositories not supporting
+ * Returns false if the file does not exist. Repositories not supporting
* version control should return false if the time is specified.
*
* @param mixed $title Title object or string
function getDescBaseUrl() {
if ( is_null( $this->descBaseUrl ) ) {
if ( !is_null( $this->articleUrl ) ) {
- $this->descBaseUrl = str_replace( '$1',
+ $this->descBaseUrl = str_replace( '$1',
wfUrlencode( MWNamespace::getCanonicalName( NS_IMAGE ) ) . ':', $this->articleUrl );
} elseif ( !is_null( $this->scriptDirUrl ) ) {
- $this->descBaseUrl = $this->scriptDirUrl . '/index.php?title=' .
+ $this->descBaseUrl = $this->scriptDirUrl . '/index.php?title=' .
wfUrlencode( MWNamespace::getCanonicalName( NS_IMAGE ) ) . ':';
} else {
$this->descBaseUrl = false;
/**
* Get the URL of an image description page. May return false if it is
- * unknown or not applicable. In general this should only be called by the
- * File class, since it may return invalid results for certain kinds of
+ * unknown or not applicable. In general this should only be called by the
+ * File class, since it may return invalid results for certain kinds of
* repositories. Use File::getDescriptionUrl() in user code.
*
* In particular, it uses the article paths as specified to the repository
}
/**
- * Get the URL of the content-only fragment of the description page. For
- * MediaWiki this means action=render. This should only be called by the
- * repository's file class, since it may return invalid results. User code
+ * Get the URL of the content-only fragment of the description page. For
+ * MediaWiki this means action=render. This should only be called by the
+ * repository's file class, since it may return invalid results. User code
* should use File::getDescriptionText().
*/
function getDescriptionRenderUrl( $name ) {
if ( isset( $this->scriptDirUrl ) ) {
- return $this->scriptDirUrl . '/index.php?title=' .
+ return $this->scriptDirUrl . '/index.php?title=' .
wfUrlencode( MWNamespace::getCanonicalName( NS_IMAGE ) . ':' . $name ) .
'&action=render';
} else {
* @param integer $flags Bitwise combination of the following flags:
* self::DELETE_SOURCE Delete the source file after upload
* self::OVERWRITE Overwrite an existing destination file instead of failing
- * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
+ * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
* same contents as the source
* @return FileRepoStatus
*/
* Pick a random name in the temp zone and store a file to it.
* Returns a FileRepoStatus object with the URL in the value.
*
- * @param string $originalName The base name of the file as specified
+ * @param string $originalName The base name of the file as specified
* by the user. The file extension will be maintained.
* @param string $srcPath The current location of the file.
*/
* virtual URL, into this repository at the specified destination location.
*
* Returns a FileRepoStatus object. On success, the value contains "new" or
- * "archived", to indicate whether the file was new with that name.
+ * "archived", to indicate whether the file was new with that name.
*
* @param string $srcPath The source path or URL
* @param string $dstRel The destination relative path
/**
* Move a group of files to the deletion archive.
*
- * If no valid deletion archive is configured, this may either delete the
+ * If no valid deletion archive is configured, this may either delete the
* file or throw an exception, depending on the preference of the repository.
*
* The overwrite policy is determined by the repository -- currently FSRepo
- * assumes a naming scheme in the deleted zone based on content hash, as
+ * assumes a naming scheme in the deleted zone based on content hash, as
* opposed to the public zone which is assumed to be unique.
*
- * @param array $sourceDestPairs Array of source/destination pairs. Each element
+ * @param array $sourceDestPairs Array of source/destination pairs. Each element
* is a two-element array containing the source file path relative to the
- * public root in the first element, and the archive file path relative
+ * public root in the first element, and the archive file path relative
* to the deleted zone root in the second element.
* @return FileRepoStatus
*/
/**
* Move a file to the deletion archive.
- * If no valid deletion archive exists, this may either delete the file
+ * If no valid deletion archive exists, this may either delete the file
* or throw an exception, depending on the preference of the repository
* @param mixed $srcRel Relative path for the file to be deleted
- * @param mixed $archiveRel Relative path for the archive location.
+ * @param mixed $archiveRel Relative path for the archive location.
* Relative to a private archive directory.
* @return WikiError object (wikitext-formatted), or true for success
*/
function invalidateImageRedirect( $title ) {
}
}
-
$result->value = $value;
return $result;
}
-
+
function __construct( $repo = false ) {
if ( $repo ) {
$this->cleanCallback = $repo->getErrorCleanupFunction();
function getCacheKey() {
if ( $this->repo->hasSharedCache ) {
$hashedName = md5($this->name);
- return wfForeignMemcKey( $this->repo->dbName, $this->repo->tablePrefix,
+ return wfForeignMemcKey( $this->repo->dbName, $this->repo->tablePrefix,
'file', $hashedName );
} else {
return false;
return File::getDescriptionText();
}
}
-
class ForeignDBRepo extends LocalRepo {
# Settings
- var $dbType, $dbServer, $dbUser, $dbPassword, $dbName, $dbFlags,
+ var $dbType, $dbServer, $dbUser, $dbPassword, $dbName, $dbFlags,
$tablePrefix, $hasSharedCache;
-
+
# Other stuff
var $dbConn;
var $fileFactory = array( 'ForeignDBFile', 'newFromTitle' );
function getMasterDB() {
if ( !isset( $this->dbConn ) ) {
$class = 'Database' . ucfirst( $this->dbType );
- $this->dbConn = new $class( $this->dbServer, $this->dbUser,
- $this->dbPassword, $this->dbName, false, $this->dbFlags,
+ $this->dbConn = new $class( $this->dbServer, $this->dbUser,
+ $this->dbPassword, $this->dbName, false, $this->dbFlags,
$this->tablePrefix );
}
return $this->dbConn;
throw new MWException( get_class($this) . ': write operations are not supported' );
}
}
-
-
}
return $img;
}
-
+
/**
* Wrapper for wfFindFile(), for backwards-compatibility only.
* Do not use in core code.
return NULL;
}
}
-
+
/**
* Return the URL of an image, provided its name.
*
}
return $image->getUrl();
}
-}
\ No newline at end of file
+}
* to generate image thumbnails or for uploading.
*
* Note that only the repo object knows what its file class is called. You should
- * never name a file class explictly outside of the repo class. Instead use the
+ * never name a file class explictly outside of the repo class. Instead use the
* repo's factory functions to generate file objects, for example:
*
* RepoGroup::singleton()->getLocalRepo()->newFile($title);
}
function getCacheFields( $prefix = 'img_' ) {
- static $fields = array( 'size', 'width', 'height', 'bits', 'media_type',
+ static $fields = array( 'size', 'width', 'height', 'bits', 'media_type',
'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user', 'user_text', 'description' );
static $results = array();
if ( $prefix == '' ) {
}
/**
- * Decode a row from the database (either object or array) to an array
+ * Decode a row from the database (either object or array) to an array
* with timestamps and MIME types decoded, and the field prefix removed.
*/
function decodeRow( $row, $prefix = 'img_' ) {
if ( wfReadOnly() ) {
return;
}
- if ( is_null($this->media_type) ||
+ if ( is_null($this->media_type) ||
$this->mime == 'image/svg'
) {
$this->upgradeRow();
}
/**
- * Set properties in this object to be equal to those given in the
+ * Set properties in this object to be equal to those given in the
* associative array $info. Only cacheable fields can be set.
- *
- * If 'mime' is given, it will be split into major_mime/minor_mime.
+ *
+ * If 'mime' is given, it will be split into major_mime/minor_mime.
* If major_mime/minor_mime are given, $this->mime will also be set.
*/
function setProps( $info ) {
/** createThumb inherited */
/** getThumbnail inherited */
/** transform inherited */
-
+
/**
* Fix thumbnail files from 1.4 or before, with extreme prejudice
*/
}
return $r;
}
-
+
/**
* Return the history of this file, line by line.
* starts with current version, then old versions.
$dbr = $this->repo->getSlaveDB();
if ( $this->historyLine == 0 ) {// called for the first time, return line from cur
- $this->historyRes = $dbr->select( 'image',
+ $this->historyRes = $dbr->select( 'image',
array(
'*',
"'' AS oi_archive_name",
}
} else if ( $this->historyLine == 1 ) {
$dbr->freeResult($this->historyRes);
- $this->historyRes = $dbr->select( 'oldimage', '*',
+ $this->historyRes = $dbr->select( 'oldimage', '*',
array( 'oi_name' => $this->title->getDBkey() ),
$fname,
array( 'ORDER BY' => 'oi_timestamp DESC' )
* @param string $timestamp Timestamp for img_timestamp, or false to use the current time
*
* @return FileRepoStatus object. On success, the value member contains the
- * archive name, or an empty string if it was a new file.
+ * archive name, or an empty string if it was a new file.
*/
function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false ) {
$this->lock();
$status = $this->publish( $srcPath, $flags );
- if ( $status->ok ) {
+ if ( $status->ok ) {
if ( !$this->recordUpload2( $status->value, $comment, $pageText, $props, $timestamp ) ) {
$status->fatal( 'filenotfound', $srcPath );
}
* Record a file upload in the upload log and the image table
* @deprecated use upload()
*/
- function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
- $watch = false, $timestamp = false )
+ function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
+ $watch = false, $timestamp = false )
{
$pageText = UploadForm::getInitialPageText( $desc, $license, $copyStatus, $source );
if ( !$this->recordUpload2( $oldver, $desc, $pageText ) ) {
/**
* Record a file upload in the upload log and the image table
*/
- function recordUpload2( $oldver, $comment, $pageText, $props = false, $timestamp = false )
+ function recordUpload2( $oldver, $comment, $pageText, $props = false, $timestamp = false )
{
global $wgUser;
if( $dbw->affectedRows() == 0 ) {
$reupload = true;
-
+
# Collision, this is an update of a file
# Insert previous contents into oldimage
$dbw->insertSelect( 'oldimage', 'image',
}
/**
- * Move or copy a file to its public location. If a file exists at the
- * destination, move it to an archive. Returns the archive name on success
- * or an empty string if it was a new file, and a wikitext-formatted
- * WikiError object on failure.
+ * Move or copy a file to its public location. If a file exists at the
+ * destination, move it to an archive. Returns the archive name on success
+ * or an empty string if it was a new file, and a wikitext-formatted
+ * WikiError object on failure.
*
* The archive name should be passed through to recordUpload for database
* registration.
*
* @param string $sourcePath Local filesystem path to the source image
* @param integer $flags A bitwise combination of:
- * File::DELETE_SOURCE Delete the source file, i.e. move
+ * File::DELETE_SOURCE Delete the source file, i.e. move
* rather than copy
* @return FileRepoStatus object. On success, the value member contains the
- * archive name, or an empty string if it was a new file.
+ * archive name, or an empty string if it was a new file.
*/
function publish( $srcPath, $flags = 0 ) {
$this->lock();
/** getExifData inherited */
/** isLocal inherited */
/** wasDeleted inherited */
-
+
/**
* Delete all versions of the file.
*
/** pageCount inherited */
/** scaleHeight inherited */
/** getImageSize inherited */
-
+
/**
- * Get the URL of the file description page.
+ * Get the URL of the file description page.
*/
function getDescriptionUrl() {
return $this->title->getLocalUrl();
$this->sha1 = File::sha1Base36( $this->getPath() );
if ( strval( $this->sha1 ) != '' ) {
$dbw = $this->repo->getMasterDB();
- $dbw->update( 'image',
+ $dbw->update( 'image',
array( 'img_sha1' => $this->sha1 ),
array( 'img_name' => $this->getName() ),
__METHOD__ );
}
/**
- * Decrement the lock reference count. If the reference count is reduced to zero, commits
+ * Decrement the lock reference count. If the reference count is reduced to zero, commits
* the transaction and thereby releases the image lock.
*/
function unlock() {
$props = $this->file->repo->getFileProps( $oldUrl );
if ( $props['fileExists'] ) {
// Upgrade the oldimage row
- $dbw->update( 'oldimage',
+ $dbw->update( 'oldimage',
array( 'oi_sha1' => $props['sha1'] ),
array( 'oi_name' => $this->file->getName(), 'oi_archive_name' => $row->oi_archive_name ),
__METHOD__ );
$dotExt = $ext === '' ? '' : ".$ext";
$encExt = $dbw->addQuotes( $dotExt );
list( $oldRels, $deleteCurrent ) = $this->getOldRels();
-
+
// Bitfields to further suppress the content
if ( $this->suppress ) {
$bitfield = 0;
$where = array(
'oi_name' => $this->file->getName(),
'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')' );
- $dbw->insertSelect( 'filearchive', 'oldimage',
+ $dbw->insertSelect( 'filearchive', 'oldimage',
array(
'fa_storage_group' => $encGroup,
'fa_storage_key' => "CASE WHEN oi_sha1='' THEN '' ELSE $concat END",
$dbw = $this->file->repo->getMasterDB();
list( $oldRels, $deleteCurrent ) = $this->getOldRels();
if ( count( $oldRels ) ) {
- $dbw->delete( 'oldimage',
+ $dbw->delete( 'oldimage',
array(
'oi_name' => $this->file->getName(),
- 'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')'
+ 'oi_archive_name IN (' . $dbw->makeList( array_keys( $oldRels ) ) . ')'
), __METHOD__ );
}
if ( $deleteCurrent ) {
list( $oldRels, $deleteCurrent ) = $this->getOldRels();
$dbw = $this->file->repo->getMasterDB();
if( !empty( $oldRels ) ) {
- $res = $dbw->select( 'oldimage',
+ $res = $dbw->select( 'oldimage',
array( 'oi_archive_name' ),
array( 'oi_name' => $this->file->getName(),
'oi_archive_name IN (' . $dbw->makeList( array_keys($oldRels) ) . ')',
// Lock the filearchive rows so that the files don't get deleted by a cleanup operation
// We acquire this lock by running the inserts now, before the file operations.
//
- // This potentially has poor lock contention characteristics -- an alternative
+ // This potentially has poor lock contention characteristics -- an alternative
// scheme would be to insert stub filearchive entries with no fa_name and commit
// them in a separate transaction, then run the file ops, then update the fa_name fields.
$this->doDBInserts();
function addAll() {
$this->all = true;
}
-
+
/**
- * Run the transaction, except the cleanup batch.
+ * Run the transaction, except the cleanup batch.
* The cleanup batch should be run in a separate transaction, because it locks different
* rows and there's no need to keep the image row locked while it's acquiring those locks
* The caller may have its own transaction open.
$exists = $this->file->lock();
$dbw = $this->file->repo->getMasterDB();
$status = $this->file->repo->newGood();
-
+
// Fetch all or selected archived revisions for the file,
// sorted from the most recent to the oldest.
$conditions = array( 'fa_name' => $this->file->getName() );
if ( strlen( $sha1 ) == 32 && $sha1[0] == '0' ) {
$sha1 = substr( $sha1, 1 );
}
-
+
if( is_null( $row->fa_major_mime ) || $row->fa_major_mime == 'unknown'
|| is_null( $row->fa_minor_mime ) || $row->fa_minor_mime == 'unknown'
|| is_null( $row->fa_media_type ) || $row->fa_media_type == 'UNKNOWN'
// Run the DB updates
// Because we have locked the image row, key conflicts should be rare.
- // If they do occur, we can roll back the transaction at this time with
- // no data loss, but leaving unregistered files scattered throughout the
+ // If they do occur, we can roll back the transaction at this time with
+ // no data loss, but leaving unregistered files scattered throughout the
// public zone.
// This is not ideal, which is why it's important to lock the image row.
if ( $insertCurrent ) {
$dbw->insert( 'oldimage', $insertBatch, __METHOD__ );
}
if ( $deleteIds ) {
- $dbw->delete( 'filearchive',
- array( 'fa_id IN (' . $dbw->makeList( $deleteIds ) . ')' ),
+ $dbw->delete( 'filearchive',
+ array( 'fa_id IN (' . $dbw->makeList( $deleteIds ) . ')' ),
__METHOD__ );
}
throw new MWException( __METHOD__.': invalid row' );
}
}
-
+
function newFromArchiveName( $title, $archiveName ) {
return OldLocalFile::newFromArchiveName( $title, $this, $archiveName );
}
/**
- * Delete files in the deleted directory if they are not referenced in the
- * filearchive table. This needs to be done in the repo because it needs to
- * interleave database locks with file operations, which is potentially a
+ * Delete files in the deleted directory if they are not referenced in the
+ * filearchive table. This needs to be done in the repo because it needs to
+ * interleave database locks with file operations, which is potentially a
* remote operation.
* @return FileRepoStatus
*/
$hashPath = $this->getDeletedHashPath( $key );
$path = "$root/$hashPath$key";
$dbw->begin();
- $inuse = $dbw->selectField( 'filearchive', '1',
+ $inuse = $dbw->selectField( 'filearchive', '1',
array( 'fa_storage_group' => 'deleted', 'fa_storage_key' => $key ),
__METHOD__, array( 'FOR UPDATE' ) );
if( !$inuse ) {
$ext = substr( $key, strcspn($key,'.') + 1 );
$ext = File::normalizeExtension($ext);
$inuse = $dbw->selectField( 'oldimage', '1',
- array( 'oi_sha1' => $sha1,
+ array( 'oi_sha1' => $sha1,
"oi_archive_name LIKE '%.{$ext}'",
'oi_deleted & '.File::DELETED_FILE => File::DELETED_FILE ),
__METHOD__, array( 'FOR UPDATE' ) );
class NullRepo extends FileRepo {
function __construct( $info ) {}
-
+
function storeBatch( $triplets, $flags = 0 ) {
return false;
}
-
+
function storeTemp( $originalName, $srcPath ) {
return false;
}
return false;
}
}
-
-?>
function isOld() {
return true;
}
-
- function isVisible() {
+
+ function isVisible() {
return $this->exists() && !$this->isDeleted(File::DELETED_FILE);
}
function getUrlRel() {
return 'archive/' . $this->getHashPath() . urlencode( $this->getArchiveName() );
}
-
+
function upgradeRow() {
wfProfileIn( __METHOD__ );
$this->loadFromFile();
-
+
# Don't destroy file info of missing files
if ( !$this->fileExists ) {
wfDebug( __METHOD__.": file does not exist, aborting\n" );
'oi_minor_mime' => $minor,
'oi_metadata' => $this->metadata,
'oi_sha1' => $this->sha1,
- ), array(
- 'oi_name' => $this->getName(),
+ ), array(
+ 'oi_name' => $this->getName(),
'oi_archive_name' => $this->archive_name ),
__METHOD__
);
wfProfileOut( __METHOD__ );
}
-
+
/**
* int $field one of DELETED_* bitfield constants
* for file or revision rows
function isDeleted( $field ) {
return ($this->deleted & $field) == $field;
}
-
+
/**
* Determine if the current user is allowed to view a particular
* field of this FileStore image file, if it's marked as deleted.
- * @param int $field
+ * @param int $field
* @return bool
*/
function userCan( $field ) {
return true;
}
}
-
}
-
-
Some quick notes on the file/repository architecture.
-Functionality is, as always, driven by data model.
+Functionality is, as always, driven by data model.
-* The repository object stores configuration information about a file storage
+* The repository object stores configuration information about a file storage
method.
* The file object is a process-local cache of information about a particular
These rules alone still do lead to some ambiguity -- it may not be clear whether
to implement some functionality in a repository function with a filename
-parameter, or in the file object itself.
+parameter, or in the file object itself.
-So we introduce the following rule: the file subclass is smarter than the
+So we introduce the following rule: the file subclass is smarter than the
repository subclass. The repository should in general provide a minimal API
-needed to access the storage backend efficiently.
+needed to access the storage backend efficiently.
-In particular, note that I have not implemented any database access in
-LocalRepo.php. LocalRepo provides only file access, and LocalFile provides
+In particular, note that I have not implemented any database access in
+LocalRepo.php. LocalRepo provides only file access, and LocalFile provides
database access and higher-level functions such as cache management.
Tim Starling, June 2007
}
/**
- * Construct a group of file repositories.
- * @param array $data Array of repository info arrays.
- * Each info array is an associative array with the 'class' member
+ * Construct a group of file repositories.
+ * @param array $data Array of repository info arrays.
+ * Each info array is an associative array with the 'class' member
* giving the class name. The entire array is passed to the repository
* constructor as the first parameter.
*/
* Search repositories for an image.
* You can also use wfGetFile() to do this.
* @param mixed $title Title object or string
- * @param mixed $time The 14-char timestamp the file should have
+ * @param mixed $time The 14-char timestamp the file should have
* been uploaded, or false for the current version
* @return File object or false if it is not found
*/
}
}
}
-
-
<?php
/**
- * A file object referring to either a standalone local file, or a file in a
+ * A file object referring to either a standalone local file, or a file in a
* local repository with no database, for example an FSRepo repository.
*
* Read-only.
*
- * TODO: Currently it doesn't really work in the repository role, there are
- * lots of functions missing. It is used by the WebStore extension in the
+ * TODO: Currently it doesn't really work in the repository role, there are
+ * lots of functions missing. It is used by the WebStore extension in the
* standalone role.
*/
class UnregisteredLocalFile extends File {
}
}
}
-
$h = unpack( 'V' , $h );
return array( $w[1], $h[1] );
}
-}
\ No newline at end of file
+}
# Don't make an image bigger than the source
$params['physicalWidth'] = $params['width'];
$params['physicalHeight'] = $params['height'];
-
+
if ( $params['physicalWidth'] >= $srcWidth ) {
$params['physicalWidth'] = $srcWidth;
$params['physicalHeight'] = $srcHeight;
return true;
}
-
+
function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
global $wgUseImageMagick, $wgImageMagickConvertCommand;
global $wgCustomConvertCommand;
$src_image = call_user_func( $loader, $srcPath );
$dst_image = imagecreatetruecolor( $physicalWidth, $physicalHeight );
-
+
// Initialise the destination image to transparent instead of
// the default solid black, to support PNG and GIF transparency nicely
$background = imagecolorallocate( $dst_image, 0, 0, 0 );
imagecolortransparent( $dst_image, $background );
- imagealphablending( $dst_image, false );
+ imagealphablending( $dst_image, false );
if( $colorStyle == 'palette' ) {
// Don't resample for paletted GIF images.
}
imagesavealpha( $dst_image, true );
-
+
call_user_func( $saveType, $dst_image, $dstPath );
imagedestroy( $dst_image );
imagedestroy( $src_image );
return $result;
}
}
-
-
function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
global $wgDjvuRenderer, $wgDjvuPostProcessor;
- // Fetch XML and check it, to give a more informative error message than the one which
+ // Fetch XML and check it, to give a more informative error message than the one which
// normaliseParams will inevitably give.
$xml = $image->getMetadata();
if ( !$xml ) {
- return new MediaTransformError( 'thumbnail_error', @$params['width'], @$params['height'],
+ return new MediaTransformError( 'thumbnail_error', @$params['width'], @$params['height'],
wfMsg( 'djvu_no_xml' ) );
}
-
+
if ( !$this->normaliseParams( $image, $params ) ) {
return new TransformParameterError( $params );
}
if ( $page > $this->pageCount( $image ) ) {
return new MediaTransformError( 'thumbnail_error', $width, $height, wfMsg( 'djvu_page_error' ) );
}
-
+
if ( $flags & self::TRANSFORM_LATER ) {
return new ThumbnailImage( $image, $dstUrl, $width, $height, $dstPath, $page );
}
return new MediaTransformError( 'thumbnail_error', $width, $height, wfMsg( 'thumbnail_dest_directory' ) );
}
- # Use a subshell (brackets) to aggregate stderr from both pipeline commands
+ # Use a subshell (brackets) to aggregate stderr from both pipeline commands
# before redirecting it to the overall stdout. This works in both Linux and Windows XP.
$cmd = '(' . wfEscapeShellArg( $wgDjvuRenderer ) . " -format=ppm -page={$page} -size={$width}x{$height} " .
wfEscapeShellArg( $srcPath );
}
}
}
-
-
abstract function getParamMap();
/*
- * Validate a thumbnail parameter at parse time.
+ * Validate a thumbnail parameter at parse time.
* Return true to accept the parameter, and false to reject it.
* If you return false, the parser will do something quiet and forgiving.
*/
abstract function parseParamString( $str );
/**
- * Changes the parameter array as necessary, ready for transformation.
+ * Changes the parameter array as necessary, ready for transformation.
* Should be idempotent.
* Returns false if the parameters are unacceptable and the transform should fail
*/
abstract function normaliseParams( $image, &$params );
/**
- * Get an image size array like that returned by getimagesize(), or false if it
+ * Get an image size array like that returned by getimagesize(), or false if it
* can't be determined.
*
* @param Image $image The image object, or false if there isn't one
}
/**
- * Get a MediaTransformOutput object representing the transformed output. Does not
+ * Get a MediaTransformOutput object representing the transformed output. Does not
* actually do the transform.
*
* @param Image $image The image object
}
/**
- * Get a MediaTransformOutput object representing the transformed output. Does the
+ * Get a MediaTransformOutput object representing the transformed output. Does the
* transform unless $flags contains self::TRANSFORM_LATER.
*
* @param Image $image The image object
*/
function getThumbType( $ext, $mime ) {
return array( $ext, $mime );
- }
+ }
/**
* True if the handled types can be transformed
*/
function canRender( $file ) { return true; }
/**
- * True if handled types cannot be displayed directly in a browser
+ * True if handled types cannot be displayed directly in a browser
* but can be rendered
*/
function mustRender( $file ) { return false; }
/**
* Get an associative array of page dimensions
- * Currently "width" and "height" are understood, but this might be
+ * Currently "width" and "height" are understood, but this might be
* expanded in the future.
* Returns false if unknown or if the document is not multi-page.
*/
* ...
* )
* )
- * The UI will format this into a table where the visible fields are always
+ * The UI will format this into a table where the visible fields are always
* visible, and the collapsed fields are optionally visible.
*
* The function should return false if there is no metadata to display.
/**
* FIXME: I don't really like this interface, it's not very flexible
- * I think the media handler should generate HTML instead. It can do
+ * I think the media handler should generate HTML instead. It can do
* all the formatting according to some standard. That makes it possible
* to do things like visual indication of grouped and chained streams
* in ogg container files.
function getTransform( $image, $dstPath, $dstUrl, $params ) {
return $this->doTransform( $image, $dstPath, $dstUrl, $params, self::TRANSFORM_LATER );
}
-
+
/**
* Validate thumbnail parameters and fill in the correct height
*
* @param integer &$width Specified width (input/output)
* @param integer &$height Height (output only)
- * @return false to indicate that an error should be returned to the user.
+ * @return false to indicate that an error should be returned to the user.
*/
function validateThumbParams( &$width, &$height, $srcWidth, $srcHeight, $mimeType ) {
$width = intval( $width );
}
$url = $script . '&' . wfArrayToCGI( $this->getScriptParams( $params ) );
$page = isset( $params['page'] ) ? $params['page'] : false;
-
+
if( $image->mustRender() || $params['width'] < $image->getWidth() ) {
return new ThumbnailImage( $image, $url, $params['width'], $params['height'], $page );
}
function getLongDesc( $file ) {
global $wgLang;
- return wfMsgHtml('file-info-size', $wgLang->formatNum( $file->getWidth() ), $wgLang->formatNum( $file->getHeight() ),
+ return wfMsgHtml('file-info-size', $wgLang->formatNum( $file->getWidth() ), $wgLang->formatNum( $file->getHeight() ),
$wgLang->formatSize( $file->getSize() ), $file->getMimeType() );
}
}
return true;
}
-
+
function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath;
-
+
if ( !$this->normaliseParams( $image, $params ) ) {
return new TransformParameterError( $params );
}
}
if ( !wfMkdirParents( dirname( $dstPath ) ) ) {
- return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
+ return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
wfMsg( 'thumbnail_dest_directory' ) );
}
function getLongDesc( $file ) {
global $wgLang;
- return wfMsg( 'svg-long-desc', $file->getWidth(), $file->getHeight(),
+ return wfMsg( 'svg-long-desc', $file->getWidth(), $file->getHeight(),
$wgLang->formatSize( $file->getSize() ) );
}
}
-
-
/**
* At how many bytes should we compress?
*
- * @var integer
+ * @var integer
* @access private
*/
var $_compress_threshold;
/**
* Total # of bit buckets we have
*
- * @var integer
+ * @var integer
* @access private
*/
var $_bucketcount;
/**
* # of total servers we have
*
- * @var integer
+ * @var integer
* @access private
*/
var $_active;
$this->stats['get_multi']++;
$sock_keys = array();
-
+
foreach ($keys as $key)
{
$sock = $this->get_sock($key);
// vim: sts=3 sw=3 et
// }}}
-
#Mime type info file.
#the first mime type in each line is the "main" mime type,
#the others are aliases for this type
-#the media type is given in upper case and square brackets,
+#the media type is given in upper case and square brackets,
#like [BITMAP], and must indicate a media type as defined by
#the MEDIATYPE_xxx constants in Defines.php
image/x-bmp image/bmp application/x-bmp application/bmp [BITMAP]
image/x-photoshop image/psd image/x-psd image/photoshop [BITMAP]
image/vnd.djvu image/x.djvu image/x-djvu [BITMAP]
-
+
image/svg+xml application/svg+xml application/svg image/svg [DRAWING]
application/postscript [DRAWING]
application/x-latex [DRAWING]
application/xslt+xml xslt
application/xml xml xsl xsd
application/xml-dtd dtd
-application/zip zip jar xpi sxc stc sxd std sxi sti sxm stm sxw stw
+application/zip zip jar xpi sxc stc sxd std sxi sti sxm stm sxw stw
audio/basic au snd
audio/midi mid midi kar
audio/mpeg mpga mp2 mp3
-audio/ogg ogg
+audio/ogg ogg
audio/x-aiff aif aiff aifc
audio/x-mpegurl m3u
-audio/x-ogg ogg
+audio/x-ogg ogg
audio/x-pn-realaudio ram rm
audio/x-pn-realaudio-plugin rpm
audio/x-realaudio ra
exit( -1 );
}
exit( 0 );
-
$clean = '';
$norm = '';
}
-
-
print str_replace( "\n", "$len\n", $stripped );
}
}
-
-
($same ? 'no change' : 'changed' ) );
return $out;
}
-
-
}
return $matches[1];
}
-
-
$output = escapeshellarg( $output );
#`echo $output >> /home/tstarling/open/proxy.log`;
-
-
show-body-only: yes
force-output: yes
-tidy-mark: no
+tidy-mark: no
wrap: 0
wrap-attributes: no
literal-attributes: yes
-output-xhtml: yes
+output-xhtml: yes
numeric-entities: yes
enclose-text: yes
enclose-block-text: yes
-quiet: yes
+quiet: yes
quote-nbsp: yes
fix-backslash: no
fix-uri: no