/** */
require_once( 'Sanitizer.php' );
require_once( 'HttpFunctions.php' );
-require_once( 'ImageGallery.php' );
/**
* Update this version number when the ParserOutput format
define( 'HTTP_PROTOCOLS', 'http:\/\/|https:\/\/' );
# Everything except bracket, space, or control characters
define( 'EXT_LINK_URL_CLASS', '[^][<>"\\x00-\\x20\\x7F]' );
-# Including space
-define( 'EXT_LINK_TEXT_CLASS', '[^\]\\x00-\\x1F\\x7F]' );
+# Including space, but excluding newlines
+define( 'EXT_LINK_TEXT_CLASS', '[^\]\\x0a\\x0d]' );
define( 'EXT_IMAGE_FNAME_CLASS', '[A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]' );
define( 'EXT_IMAGE_EXTENSIONS', 'gif|png|jpg|jpeg' );
-define( 'EXT_LINK_BRACKETED', '/\[(\b(' . wfUrlProtocols() . ')'.EXT_LINK_URL_CLASS.'+) *('.EXT_LINK_TEXT_CLASS.'*?)\]/S' );
+define( 'EXT_LINK_BRACKETED', '/\[(\b(' . wfUrlProtocols() . ')'.
+ EXT_LINK_URL_CLASS.'+) *('.EXT_LINK_TEXT_CLASS.'*?)\]/S' );
define( 'EXT_IMAGE_REGEX',
'/^('.HTTP_PROTOCOLS.')'. # Protocol
'('.EXT_LINK_URL_CLASS.'+)\\/'. # Hostname and path
$this->mTagHooks = array();
$this->mFunctionHooks = array();
$this->clearState();
+ $this->setHook( 'pre', array( $this, 'renderPreTag' ) );
}
/**
'/(.) (?=\\?|:|;|!|\\302\\273)/' => '\\1 \\2',
# french spaces, Guillemet-right
'/(\\302\\253) /' => '\\1 ',
- '/<center *>(.*)<\\/center *>/i' => '<div class="center">\\1</div>',
);
$text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );
$inside = $p[4];
}
- $marker = "$uniq_prefix-$element-$rand" . sprintf('%08X', $n++);
+ $marker = "$uniq_prefix-$element-$rand" . sprintf('%08X', $n++) . '-QINU';
$stripped .= $marker;
if ( $close === '/>' ) {
* will be stripped in addition to other tags. This is important
* for section editing, where these comments cause confusion when
* counting the sections in the wikisource
+ *
+ * @param array dontstrip contains tags which should not be stripped;
+ * used to prevent stipping of <gallery> when saving (fixes bug 2700)
*
* @private
*/
- function strip( $text, &$state, $stripcomments = false ) {
+ function strip( $text, &$state, $stripcomments = false , $dontstrip = array () ) {
$render = ($this->mOutputType == OT_HTML);
# Replace any instances of the placeholders
$commentState = array();
$elements = array_merge(
- array( 'nowiki', 'pre', 'gallery' ),
+ array( 'nowiki', 'gallery' ),
array_keys( $this->mTagHooks ) );
global $wgRawHtml;
if( $wgRawHtml ) {
$elements[] = 'math';
}
-
+ # Removing $dontstrip tags from $elements list (currently only 'gallery', fixing bug 2700)
+ foreach ( $elements AS $k => $v ) {
+ if ( !in_array ( $v , $dontstrip ) ) continue;
+ unset ( $elements[$k] );
+ }
+
$matches = array();
$text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
-
+
foreach( $matches as $marker => $data ) {
list( $element, $content, $params, $tag ) = $data;
if( $render ) {
$output = wfEscapeHTMLTagsOnly( $content );
break;
case 'math':
- $output = renderMath( $content );
- break;
- case 'pre':
- // Backwards-compatibility hack
- $content = preg_replace( '!<nowiki>(.*?)</nowiki>!is', '\\1', $content );
- $output = '<pre>' . wfEscapeHTMLTagsOnly( $content ) . '</pre>';
+ $output = MathRenderer::renderMath( $content );
break;
case 'gallery':
- $output = $this->renderImageGallery( $content );
+ $output = $this->renderImageGallery( $content, $params );
break;
default:
if( isset( $this->mTagHooks[$tagName] ) ) {
$output = call_user_func_array( $this->mTagHooks[$tagName],
array( $content, $params, $this ) );
} else {
- wfDebugDieBacktrace( "Invalid call hook $element" );
+ throw new MWException( "Invalid call hook $element" );
}
}
} else {
$state[$element][$marker] = $output;
}
}
-
+
# Unstrip comments unless explicitly told otherwise.
# (The comments are always stripped prior to this point, so as to
# not invoke any extension tags / parser hooks contained within
$text = preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text );
$text = $this->stripToc( $text );
+ $this->stripNoGallery( $text );
$text = $this->doHeadings( $text );
if($this->mOptions->getUseDynamicDates()) {
$df =& DateFormatter::getInstance();
wfProfileIn( $fname );
for ( $i = 6; $i >= 1; --$i ) {
$h = str_repeat( '=', $i );
- $text = preg_replace( "/^{$h}(.+){$h}(\\s|$)/m",
+ $text = preg_replace( "/^{$h}(.+){$h}\\s*$/m",
"<h{$i}>\\1</h{$i}>\\2", $text );
}
wfProfileOut( $fname );
# Normalize any HTML entities in input. They will be
# re-escaped by makeExternalLink().
$url = Sanitizer::decodeCharReferences( $url );
+
+ # Escape any control characters introduced by the above step
+ $url = preg_replace( '/[\][<>"\\x00-\\x20\\x7F]/e', "urlencode('\\0')", $url );
# Process the trail (i.e. everything after this link up until start of the next link),
# replacing any non-bracketed links
# Normalize any HTML entities in input. They will be
# re-escaped by makeExternalLink() or maybeMakeExternalImage()
$url = Sanitizer::decodeCharReferences( $url );
+
+ # Escape any control characters introduced by the above step
+ $url = preg_replace( '/[\][<>"\\x00-\\x20\\x7F]/e', "urlencode('\\0')", $url );
# Is this an external image?
$text = $this->maybeMakeExternalImage( $url );
$useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
if( is_null( $this->mTitle ) ) {
- wfDebugDieBacktrace( 'nooo' );
+ throw new MWException( 'nooo' );
}
$nottalk = !$this->mTitle->isTalkPage();
$sortkey = $text;
}
$sortkey = Sanitizer::decodeCharReferences( $sortkey );
+ $sortkey = str_replace( "\n", '', $sortkey );
$sortkey = $wgContLang->convertCategoryKey( $sortkey );
$this->mOutput->addCategory( $nt->getDBkey(), $sortkey );
wfProfileIn( "$fname-paragraph" );
# No prefix (not in list)--go to paragraph mode
// XXX: use a stack for nestable elements like span, table and div
- $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
+ $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/center|<\\/tr|<\\/td|<\\/th)/iS', $t );
$closematch = preg_match(
'/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
- '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul)/iS', $t );
+ '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<center)/iS', $t );
if ( $openmatch or $closematch ) {
$paragraphStack = false;
# TODO bug 5718: paragraph closed
}
break;
default:
- wfDebugDieBacktrace( "State machine error in $fname" );
+ throw new MWException( "State machine error in $fname" );
}
}
if( $stack > 0 ) {
return $varCache[$index] = $wgContLang->formatNum( wfNumberOfUsers() );
case MAG_NUMBEROFPAGES:
return $varCache[$index] = $wgContLang->formatNum( wfNumberOfPages() );
+ case MAG_NUMBEROFADMINS:
+ return $varCache[$index] = $wgContLang->formatNum( wfNumberOfAdmins() );
case MAG_CURRENTTIMESTAMP:
return $varCache[$index] = wfTimestampNow();
case MAG_CURRENTVERSION:
return $wgScriptPath;
case MAG_DIRECTIONMARK:
return $wgContLang->getDirMark();
+ case MAG_CONTENTLANGUAGE:
+ global $wgContLanguageCode;
+ return $wgContLanguageCode;
default:
$ret = null;
if ( wfRunHooks( 'ParserGetVariableValueSwitch', array( &$this, &$varCache, &$index, &$ret ) ) )
'text' => substr($text, $pieceStart, $pieceEnd - $pieceStart),
'title' => trim($openingBraceStack[$lastOpeningBrace]['title']),
'parts' => $openingBraceStack[$lastOpeningBrace]['parts'],
- 'lineStart' => (($pieceStart > 0) && ($text[$pieceStart-1] == '\n')),
+ 'lineStart' => (($pieceStart > 0) && ($text[$pieceStart-1] == "\n")),
);
# finally we can call a user callback and replace piece of text
$replaceWith = call_user_func( $matchingCallback, $cbArgs );
$text = $linestart . $wgContLang->getNsText( intval( $part1 ) );
$found = true;
} else {
- $index = Namespace::getCanonicalIndex( strtolower( $part1 ) );
+ $param = str_replace( ' ', '_', strtolower( $part1 ) );
+ $index = Namespace::getCanonicalIndex( strtolower( $param ) );
if ( !is_null( $index ) ) {
$text = $linestart . $wgContLang->getNsText( $index );
$found = true;
if ( !$found && $argc >= 2 ) {
$mwPluralForm =& MagicWord::get( MAG_PLURAL );
if ( $mwPluralForm->matchStartAndRemove( $part1 ) ) {
- if ($argc==2) {$args[2]=$args[1];}
- $text = $linestart . $lang->convertPlural( $part1, $args[0], $args[1], $args[2]);
+ while ( count($args) < 5 ) { $args[] = $args[count($args)-1]; }
+ $text = $linestart . $lang->convertPlural( $part1, $args[0], $args[1],
+ $args[2], $args[3], $args[4]);
$found = true;
}
}
$mwWordsToCheck = array( MAG_NUMBEROFPAGES => 'wfNumberOfPages',
MAG_NUMBEROFUSERS => 'wfNumberOfUsers',
MAG_NUMBEROFARTICLES => 'wfNumberOfArticles',
- MAG_NUMBEROFFILES => 'wfNumberOfFiles' );
+ MAG_NUMBEROFFILES => 'wfNumberOfFiles',
+ MAG_NUMBEROFADMINS => 'wfNumberOfAdmins' );
foreach( $mwWordsToCheck as $word => $func ) {
$mwCurrentWord =& MagicWord::get( $word );
if( $mwCurrentWord->matchStartAndRemove( $part1 ) ) {
$mwRawSuffix =& MagicWord::get( MAG_RAWSUFFIX );
- if( $mwRawSuffix->match( $args[0] ) ) {
+ if( isset( $args[0] ) && $mwRawSuffix->match( $args[0] ) ) {
# Raw and unformatted
$text = $linestart . call_user_func( $func );
} else {
}
}
}
+
+ # PAGESINNAMESPACE
+ if( !$found ) {
+ $mwPagesInNs =& MagicWord::get( MAG_PAGESINNAMESPACE );
+ if( $mwPagesInNs->matchStartAndRemove( $part1 ) ) {
+ $found = true;
+ $count = wfPagesInNs( intval( $part1 ) );
+ $mwRawSuffix =& MagicWord::get( MAG_RAWSUFFIX );
+ if( isset( $args[0] ) && $mwRawSuffix->match( $args[0] ) ) {
+ $text = $linestart . $count;
+ } else {
+ $text = $linestart . $wgContLang->formatNum( $count );
+ }
+ }
+ }
# #LANGUAGE:
if( !$found ) {
$colonPos = strpos( $part1, ':' );
if ( $colonPos !== false ) {
$function = strtolower( substr( $part1, 1, $colonPos - 1 ) );
+ if ( !isset( $this->mFunctionHooks[$function] ) ) {
+ foreach ($this->mFunctionHooks as $key => $value) {
+ if( is_int( $key ) ) {
+ $mwExtension =& MagicWord::get( $key );
+ if( $mwExtension->matchVariableStartToEnd( $function ) ) {
+ $function = $key;
+ break;
+ }
+ }
+ }
+ }
if ( isset( $this->mFunctionHooks[$function] ) ) {
$funcArgs = array_map( 'trim', $args );
$funcArgs = array_merge( array( &$this, trim( substr( $part1, $colonPos + 1 ) ) ), $funcArgs );
}
$title = Title::newFromText( $part1, $ns );
+
if ( !is_null( $title ) ) {
+ $checkVariantLink = sizeof($wgContLang->getVariants())>1;
+ # Check for language variants if the template is not found
+ if($checkVariantLink && $title->getArticleID() == 0){
+ $wgContLang->findVariantLink($part1, $title);
+ }
+
if ( !$title->isExternal() ) {
# Check for excessive inclusion
$dbk = $title->getPrefixedDBkey();
# Use the original $piece['title'] not the mangled $part1, so that
# modifiers such as RAW: produce separate cache entries
if( $found ) {
- $this->mTemplates[$piece['title']] = $text;
+ if( $isHTML ) {
+ // A special page; don't store it in the template cache.
+ } else {
+ $this->mTemplates[$piece['title']] = $text;
+ }
$text = $linestart . $text;
}
}
}
}
+ /**
+ * Detect __NOGALLERY__ magic word and set a placeholder
+ */
+ function stripNoGallery( &$text ) {
+ # if the string __NOGALLERY__ (not case-sensitive) occurs in the HTML,
+ # do not add TOC
+ $mw = MagicWord::get( MAG_NOGALLERY );
+ $this->mOutput->mNoGallery = $mw->matchAndRemove( $text ) ;
+ }
+
/**
* Detect __TOC__ magic word and set a placeholder
*/
$url = wfMsg( $urlmsg, $id);
$sk =& $this->mOptions->getSkin();
$la = $sk->getExternalLinkAttributes( $url, $keyword.$id );
- $text .= "<a href='{$url}'{$la}>{$keyword}{$id}</a>{$x}";
+ $text .= "<a href=\"{$url}\"{$la}>{$keyword}{$id}</a>{$x}";
}
/* Check if the next RFC keyword is preceed by [[ */
"\r\n" => "\n",
);
$text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text );
- $text = $this->strip( $text, $stripState, true );
+ $text = $this->strip( $text, $stripState, true, array( 'gallery' ) );
$text = $this->pstPass2( $text, $stripState, $user );
$text = $this->unstrip( $text, $stripState );
$text = $this->unstripNoWiki( $text, $stripState );
$text = $this->replaceVariables( $text );
# Strip out <nowiki> etc. added via replaceVariables
- $text = $this->strip( $text, $stripState );
+ $text = $this->strip( $text, $stripState, false, array( 'gallery' ) );
# Signatures
$sigText = $this->getUserSig( $user );
}
}
+ // Make sure nickname doesnt get a sig in a sig
+ $nickname = $this->cleanSigInSig( $nickname );
+
# If we're still here, make it a link to the user page
$userpage = $user->getUserPage();
return( '[[' . $userpage->getPrefixedText() . '|' . wfEscapeWikiText( $nickname ) . ']]' );
/**
* Clean up signature text
*
- * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
+ * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures @see cleanSigInSig
* 2) Substitute all transclusions
*
* @param string $text
$substText = '{{' . $substWord->getSynonym( 0 );
$text = preg_replace( $substRegex, $substText, $text );
- $text = preg_replace( '/~{3,5}/', '', $text );
+ $text = $this->cleanSigInSig( $text );
$text = $this->replaceVariables( $text );
$this->clearState();
return $text;
}
+
+ /**
+ * Strip ~~~, ~~~~ and ~~~~~ out of signatures
+ * @param string $text
+ * @return string Signature text with /~{3,5}/ removed
+ */
+ function cleanSigInSig( $text ) {
+ $text = preg_replace( '/~{3,5}/', '', $text );
+ return $text;
+ }
/**
* Set up some variables which are usually set up in parse()
*
* @public
*
- * @param string $name The function name. Function names are case-insensitive.
+ * @param mixed $id The magic word ID, or (deprecated) the function name. Function names are case-insensitive.
* @param mixed $callback The callback function (and object) to use
*
* @return The old callback function for this name, if any
*/
- function setFunctionHook( $name, $callback ) {
- $name = strtolower( $name );
- $oldVal = @$this->mFunctionHooks[$name];
- $this->mFunctionHooks[$name] = $callback;
+ function setFunctionHook( $id, $callback ) {
+ if( is_string( $id ) ) {
+ $id = strtolower( $id );
+ }
+ $oldVal = @$this->mFunctionHooks[$id];
+ $this->mFunctionHooks[$id] = $callback;
return $oldVal;
}
return $matches[0];
}
+ /**
+ * Tag hook handler for 'pre'.
+ */
+ function renderPreTag( $text, $attribs, $parser ) {
+ // Backwards-compatibility hack
+ $content = preg_replace( '!<nowiki>(.*?)</nowiki>!is', '\\1', $text );
+
+ $attribs = Sanitizer::validateTagAttributes( $attribs, 'pre' );
+ return wfOpenElement( 'pre', $attribs ) .
+ wfEscapeHTMLTagsOnly( $content ) .
+ '</pre>';
+ }
+
/**
* Renders an image gallery from a text with one line per image.
* text labels may be given by using |-style alternative text. E.g.
* labeled 'The number "1"' and
* 'A tree'.
*/
- function renderImageGallery( $text ) {
+ function renderImageGallery( $text, $params ) {
$ig = new ImageGallery();
$ig->setShowBytes( false );
$ig->setShowFilename( false );
$ig->setParsing();
- $lines = explode( "\n", $text );
+ $ig->useSkin( $this->mOptions->getSkin() );
+ if( isset( $params['caption'] ) )
+ $ig->setCaption( $params['caption'] );
+
+ $lines = explode( "\n", $text );
foreach ( $lines as $line ) {
# match lines like these:
# Image:someimage.jpg|This is some image
*/
function getTags() { return array_keys( $this->mTagHooks ); }
/**#@-*/
+
+
+ /**
+ * Break wikitext input into sections, and either pull or replace
+ * some particular section's text.
+ *
+ * External callers should use the getSection and replaceSection methods.
+ *
+ * @param $text Page wikitext
+ * @param $section Numbered section. 0 pulls the text before the first
+ * heading; other numbers will pull the given section
+ * along with its lower-level subsections.
+ * @param $mode One of "get" or "replace"
+ * @param $newtext Replacement text for section data.
+ * @return string for "get", the extracted section text.
+ * for "replace", the whole page with the section replaced.
+ */
+ private function extractSections( $text, $section, $mode, $newtext='' ) {
+ # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
+ # comments to be stripped as well)
+ $striparray = array();
+
+ $oldOutputType = $this->mOutputType;
+ $oldOptions = $this->mOptions;
+ $this->mOptions = new ParserOptions();
+ $this->mOutputType = OT_WIKI;
+
+ $striptext = $this->strip( $text, $striparray, true );
+
+ $this->mOutputType = $oldOutputType;
+ $this->mOptions = $oldOptions;
+
+ # now that we can be sure that no pseudo-sections are in the source,
+ # split it up by section
+ $uniq = preg_quote( $this->uniqPrefix(), '/' );
+ $comment = "(?:$uniq-!--.*?QINU)";
+ $secs = preg_split(
+ /*
+ "/
+ ^(
+ (?:$comment|<\/?noinclude>)* # Initial comments will be stripped
+ (?:
+ (=+) # Should this be limited to 6?
+ .+? # Section title...
+ \\2 # Ending = count must match start
+ |
+ ^
+ <h([1-6])\b.*?>
+ .*?
+ <\/h\\3\s*>
+ )
+ (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok
+ )$
+ /mix",
+ */
+ "/
+ (
+ ^
+ (?:$comment|<\/?noinclude>)* # Initial comments will be stripped
+ (=+) # Should this be limited to 6?
+ .+? # Section title...
+ \\2 # Ending = count must match start
+ (?:$comment|<\/?noinclude>|[ \\t]+)* # Trailing whitespace ok
+ $
+ |
+ <h([1-6])\b.*?>
+ .*?
+ <\/h\\3\s*>
+ )
+ /mix",
+ $striptext, -1,
+ PREG_SPLIT_DELIM_CAPTURE);
+
+ if( $mode == "get" ) {
+ if( $section == 0 ) {
+ // "Section 0" returns the content before any other section.
+ $rv = $secs[0];
+ } else {
+ $rv = "";
+ }
+ } elseif( $mode == "replace" ) {
+ if( $section == 0 ) {
+ $rv = $newtext . "\n\n";
+ $remainder = true;
+ } else {
+ $rv = $secs[0];
+ $remainder = false;
+ }
+ }
+ $count = 0;
+ $sectionLevel = 0;
+ for( $index = 1; $index < count( $secs ); ) {
+ $headerLine = $secs[$index++];
+ if( $secs[$index] ) {
+ // A wiki header
+ $headerLevel = strlen( $secs[$index++] );
+ } else {
+ // An HTML header
+ $index++;
+ $headerLevel = intval( $secs[$index++] );
+ }
+ $content = $secs[$index++];
+
+ $count++;
+ if( $mode == "get" ) {
+ if( $count == $section ) {
+ $rv = $headerLine . $content;
+ $sectionLevel = $headerLevel;
+ } elseif( $count > $section ) {
+ if( $sectionLevel && $headerLevel > $sectionLevel ) {
+ $rv .= $headerLine . $content;
+ } else {
+ // Broke out to a higher-level section
+ break;
+ }
+ }
+ } elseif( $mode == "replace" ) {
+ if( $count < $section ) {
+ $rv .= $headerLine . $content;
+ } elseif( $count == $section ) {
+ $rv .= $newtext . "\n\n";
+ $sectionLevel = $headerLevel;
+ } elseif( $count > $section ) {
+ if( $headerLevel <= $sectionLevel ) {
+ // Passed the section's sub-parts.
+ $remainder = true;
+ }
+ if( $remainder ) {
+ $rv .= $headerLine . $content;
+ }
+ }
+ }
+ }
+ # reinsert stripped tags
+ $rv = $this->unstrip( $rv, $striparray );
+ $rv = $this->unstripNoWiki( $rv, $striparray );
+ $rv = trim( $rv );
+ return $rv;
+ }
+
+ /**
+ * This function returns the text of a section, specified by a number ($section).
+ * A section is text under a heading like == Heading == or \<h1\>Heading\</h1\>, or
+ * the first section before any such heading (section 0).
+ *
+ * If a section contains subsections, these are also returned.
+ *
+ * @param $text String: text to look in
+ * @param $section Integer: section number
+ * @return string text of the requested section
+ */
+ function getSection( $text, $section ) {
+ return $this->extractSections( $text, $section, "get" );
+ }
+
+ function replaceSection( $oldtext, $section, $text ) {
+ return $this->extractSections( $oldtext, $section, "replace", $text );
+ }
+
}
/**
$mExternalLinks, # External link URLs, in the key only
$mHTMLtitle, # Display HTML title
$mSubtitle, # Additional subtitle
- $mNewSection; # Show a new section link?
+ $mNewSection, # Show a new section link?
+ $mNoGallery; # No gallery on category page? (__NOGALLERY__)
function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(),
$containsOldMagic = false, $titletext = '' )
$this->mHTMLtitle = "" ;
$this->mSubtitle = "" ;
$this->mNewSection = false;
+ $this->mNoGallery = false;
}
function getText() { return $this->mText; }
function &getTemplates() { return $this->mTemplates; }
function &getImages() { return $this->mImages; }
function &getExternalLinks() { return $this->mExternalLinks; }
+ function getNoGallery() { return $this->mNoGallery; }
function containsOldMagic() { return $this->mContainsOldMagic; }
function setText( $text ) { return wfSetVar( $this->mText, $text ); }
return (int)$count;
}
+/**
+ * Return the total number of admins
+ *
+ * @return integer
+ */
+function wfNumberOfAdmins() {
+ static $admins = -1;
+ wfProfileIn( 'wfNumberOfAdmins' );
+ if( $admins == -1 ) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), 'wfNumberOfAdmins' );
+ }
+ wfProfileOut( 'wfNumberOfAdmins' );
+ return (int)$admins;
+}
+
+/**
+ * Count the number of pages in a particular namespace
+ *
+ * @param $ns Namespace
+ * @return integer
+ */
+function wfPagesInNs( $ns ) {
+ static $pageCount = array();
+ wfProfileIn( 'wfPagesInNs' );
+ if( !isset( $pageCount[$ns] ) ) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ $pageCount[$ns] = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), 'wfPagesInNs' );
+ }
+ wfProfileOut( 'wfPagesInNs' );
+ return (int)$pageCount[$ns];
+}
+
/**
* Get various statistics from the database
* @private