-<?
+<?php
# Class representing a Wikipedia article and history.
# See design.doc for an overview.
# Note: edit user interface and cache support functions have been
# moved to separate EditPage and CacheManager classes.
-/* CHECK MERGE @@@
- TEST THIS @@@
-
- * s/\$wgTitle/\$this->mTitle/ performed, many replacements
- * mTitle variable added to class
-*/
-
include_once( "CacheManager.php" );
class Article {
return;
}
if ( $rt->getNamespace() == Namespace::getSpecial() ) {
- $wgOut->redirect( wfLocalUrl(
- $rt->getPrefixedURL() ) );
+ $wgOut->redirect( $rt->getFullURL() );
return;
}
$rid = $rt->getArticleID();
function view()
{
global $wgUser, $wgOut, $wgLang;
- global $oldid, $diff; # From query
- global $wgLinkCache, $IP;
+ global $oldid, $diff, $printable; # From query
+ global $wgLinkCache, $IP, $wgEnableParserCache;
+
$fname = "Article::view";
wfProfileIn( $fname );
}
$wgLinkCache->preFill( $this->mTitle );
- $wgOut->addWikiText( $text );
+
+ if ( $printable == "yes" ) {
+ $wgOut->mParserOptions->setPrintable( true );
+ }
+
+ if( $wgEnableParserCache && intval($wgUser->getOption( "stubthreshold" )) == 0 ){
+ $wgOut->addWikiText( $text, true, $this );
+ } else {
+ $wgOut->addWikiText( $text );
+ }
+
+ # Add link titles as META keywords
+ $wgOut->addMetaTags() ;
$this->viewUpdates();
wfProfileOut( $fname );
/* private */ function insertNewArticle( $text, $summary, $isminor, $watchthis )
{
global $wgOut, $wgUser, $wgLinkCache, $wgMwRedir;
+ global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
$fname = "Article::insertNewArticle";
$newid = wfInsertId();
$this->mTitle->resetArticleID( $newid );
- Article::onArticleCreate( $this->mTitle, $text );
+ Article::onArticleCreate( $this->mTitle );
RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary );
if ($watchthis) {
$sql = "UPDATE cur set cur_touched='$now' WHERE cur_namespace=$talkns AND cur_title='" . wfStrencode( $ttl ) . "'";
wfQuery( $sql, DB_WRITE );
+ # standard deferred updates
+ $this->editUpdates( $text );
+
+ # Squid purging
+ if ( $wgUseSquid ) {
+ $urlArr = Array(
+ $this->mTitle->getInternalURL(),
+ $this->mTitle->getInternalURL('action=history')
+ );
+ wfPurgeSquidServers($urlArr);
+ /* this needs to be done after LinksUpdate */
+ $u = new SquidUpdate($this->mTitle);
+ array_push( $wgDeferredUpdateList, $u );
+ }
+
$this->showArticle( $text, wfMsg( "newarticle" ) );
}
- function updateArticle( $text, $summary, $minor, $watchthis, $section = "", $forceBot = false )
- {
- global $wgOut, $wgUser, $wgLinkCache;
- global $wgDBtransactions, $wgMwRedir;
- $fname = "Article::updateArticle";
+ /* Side effects: loads last edit */
+ function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary = ""){
$this->loadLastEdit();
-
- // insert updated section into old text if we have only edited part
- // of the article
- if ($section != "") {
- $oldtext=$this->getContent();
+ $oldtext = $this->getContent();
+ if ($section != "") {
if($section=="new") {
if($summary) $subject="== {$summary} ==\n\n";
$text=$oldtext."\n\n".$subject.$text;
$text=join("",$secs);
}
}
+ return $text;
+ }
+
+ function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false )
+ {
+ global $wgOut, $wgUser, $wgLinkCache;
+ global $wgDBtransactions, $wgMwRedir;
+ global $wgUseSquid, $wgInternalServer;
+ $fname = "Article::updateArticle";
+
if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() . ")[^\\n]+)/i", $text, $m ) ) {
$bot = (int)($wgUser->isBot() || $forceBot);
RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
- $oldid, $this->getTimestamp() );
+ $oldid, $this->getTimestamp(), $bot );
Article::onArticleEdit( $this->mTitle );
}
$this->unwatch();
}
}
+ # standard deferred updates
+ $this->editUpdates( $text );
+
+ # Squid updates
+
+ if ( $wgUseSquid ) {
+ $urlArr = Array(
+ $this->mTitle->getInternalURL(),
+ $this->mTitle->getInternalURL('action=history')
+ );
+ wfPurgeSquidServers($urlArr);
+ }
$this->showArticle( $text, wfMsg( "updated" ) );
return true;
$wgOut = new OutputPage();
$wgOut->addWikiText( $text );
- # Every 1000th edit, prune the recent changes table.
- wfSeedRandom();
- if ( 0 == mt_rand( 0, 999 ) ) {
- $cutoff = wfUnix2Timestamp( time() - ( 7 * 86400 ) );
- $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$cutoff}'";
- wfQuery( $sql, DB_WRITE );
- }
-
if( $wgMwRedir->matchStart( $text ) )
$r = "redirect=no";
else
$r = "";
- $wgOut->redirect( wfLocalUrl( $this->mTitle->getPrefixedURL(), $r ) );
+ $wgOut->redirect( $this->mTitle->getFullURL( $r ) );
}
# Add this page to my watchlist
} else {
$log->addEntry( wfMsg( "protectedarticle", $this->mTitle->getPrefixedText() ), "" );
}
- $wgOut->redirect( wfLocalUrl( $this->mTitle->getPrefixedURL() ) );
+ $wgOut->redirect( $this->mTitle->getFullURL() );
}
function unprotect()
$wgOut->setRobotpolicy( "noindex,nofollow" );
$wgOut->addWikiText( wfMsg( "confirmdeletetext" ) );
- $t = $this->mTitle->getPrefixedURL();
-
- $formaction = wfEscapeHTML( wfLocalUrl( $t, "action=delete" . $par ) );
+ $formaction = $this->mTitle->escapeLocalURL( "action=delete" . $par );
+
$confirm = wfMsg( "confirm" );
$check = wfMsg( "confirmcheck" );
$delcom = wfMsg( "deletecomment" );
function doDeleteArticle( $title )
{
- global $wgUser, $wgOut, $wgLang, $wpReason, $wgDeferredUpdateList;
+ global $wgUser, $wgOut, $wgLang, $wgRequest;
+ global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
$fname = "Article::doDeleteArticle";
wfDebug( "$fname\n" );
$u = new SiteStatsUpdate( 0, 1, -$this->isCountable( $this->getContent( true ) ) );
array_push( $wgDeferredUpdateList, $u );
+
+ # Squid purging
+ if ( $wgUseSquid ) {
+ $urlArr = Array(
+ $this->mTitle->getInternalURL(),
+ $this->mTitle->getInternalURL('action=history')
+ );
+ wfPurgeSquidServers($urlArr);
+
+ /* prepare the list of urls to purge */
+ $sql = "SELECT cur_namespace,cur_title FROM links,cur WHERE l_to={$id} and l_from=cur_id" ;
+ $res = wfQuery ( $sql, DB_READ ) ;
+ while ( $BL = wfFetchObject ( $res ) )
+ {
+ $tobj = Title::MakeTitle( $BL->cur_namespace, $BL->cur_title ) ;
+ $blurlArr[] = $tobj->getInternalURL();
+ }
+ wfFreeResult ( $res ) ;
+ $u = new SquidUpdate( $this->mTitle, $blurlArr );
+ array_push( $wgDeferredUpdateList, $u );
+
+ }
+
+
# Move article and history to the "archive" table
$sql = "INSERT INTO archive (ar_namespace,ar_title,ar_text," .
$res = wfQuery( $sql, DB_READ, $fname );
$sql = "INSERT INTO brokenlinks (bl_from,bl_to) VALUES ";
- $now = wfTimestampNow();
+ $now = wfTimestampNow();
$sql2 = "UPDATE cur SET cur_touched='{$now}' WHERE cur_id IN (";
$first = true;
while ( $s = wfFetchObject( $res ) ) {
- $nt = Title::newFromDBkey( $s->l_from );
- $lid = $nt->getArticleID();
-
if ( ! $first ) { $sql .= ","; $sql2 .= ","; }
$first = false;
- $sql .= "({$lid},'{$t}')";
- $sql2 .= "{$lid}";
+ $sql .= "({$s->l_from},'{$t}')";
+ $sql2 .= "{$s->l_from}";
}
$sql2 .= ")";
if ( ! $first ) {
$sql = "DELETE FROM links WHERE l_to={$id}";
wfQuery( $sql, DB_WRITE, $fname );
- $sql = "DELETE FROM links WHERE l_from='{$t}'";
+ $sql = "DELETE FROM links WHERE l_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
- $sql = "DELETE FROM imagelinks WHERE il_from='{$t}'";
+ $sql = "DELETE FROM imagelinks WHERE il_from={$d}";
wfQuery( $sql, DB_WRITE, $fname );
$sql = "DELETE FROM brokenlinks WHERE bl_from={$id}";
$log = new LogPage( wfMsg( "dellogpage" ), wfMsg( "dellogpagetext" ) );
$art = $title->getPrefixedText();
- $wpReason = wfCleanQueryVar( $wpReason );
+ $wpReason = $wgRequest->getText( "wpReason" );
$log->addEntry( wfMsg( "deletedarticle", $art ), $wpReason );
# Clear the cached article id so the interface doesn't act like we exist
function rollback()
{
- global $wgUser, $wgLang, $wgOut, $from;
+ global $wgUser, $wgLang, $wgOut, $wgRequest;
if ( ! $wgUser->isSysop() ) {
$wgOut->sysopRequired();
}
# Enhanced rollback, marks edits rc_bot=1
- $bot = !!$_REQUEST['bot'];
+ $bot = $wgRequest->getBool( 'bot' );
# Replace all this user's current edits with the next one down
$tt = wfStrencode( $this->mTitle->getDBKey() );
$uid = $s->cur_user;
$pid = $s->cur_id;
- $from = str_replace( '_', ' ', wfCleanQueryVar( $from ) );
+ $from = str_replace( '_', ' ', $wgRequest->getVal( "from" ) );
if( $from != $s->cur_user_text ) {
$wgOut->setPageTitle(wfmsg("rollbackfailed"));
$wgOut->addWikiText( wfMsg( "alreadyrolled",
$wgOut->setPagetitle( wfMsg( "actioncomplete" ) );
$wgOut->setRobotpolicy( "noindex,nofollow" );
$wgOut->addHTML( "<h2>" . $newcomment . "</h2>\n<hr>\n" );
- $this->updateArticle( Article::getRevisionText( $s ), $newcomment, 1, $this->mTitle->userIsWatching(), "", $bot );
-
+ $this->updateArticle( Article::getRevisionText( $s ), $newcomment, 1, $this->mTitle->userIsWatching(), $bot );
Article::onArticleEdit( $this->mTitle );
$wgOut->returnToMain( false );
}
}
}
+ # Do standard deferred updates after page edit.
+ # Every 1000th edit, prune the recent changes table.
+ /* private */ function editUpdates( $text )
+ {
+ global $wgDeferredUpdateList, $wgDBname, $wgMemc;
+ global $wgMessageCache;
+
+ wfSeedRandom();
+ if ( 0 == mt_rand( 0, 999 ) ) {
+ $cutoff = wfUnix2Timestamp( time() - ( 7 * 86400 ) );
+ $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$cutoff}'";
+ wfQuery( $sql, DB_WRITE );
+ }
+ $id = $this->getID();
+ $title = $this->mTitle->getPrefixedDBkey();
+ $shortTitle = $this->mTitle->getDBkey();
+
+ $adj = $this->mCountAdjustment;
+
+ if ( 0 != $id ) {
+ $u = new LinksUpdate( $id, $title );
+ array_push( $wgDeferredUpdateList, $u );
+ $u = new SiteStatsUpdate( 0, 1, $adj );
+ array_push( $wgDeferredUpdateList, $u );
+ $u = new SearchUpdate( $id, $title, $text );
+ array_push( $wgDeferredUpdateList, $u );
+
+ $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle );
+ array_push( $wgDeferredUpdateList, $u );
+
+ if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+ $wgMessageCache->replace( $shortTitle, $text );
+ }
+ }
+ }
/* private */ function setOldSubtitle()
{
function preSaveTransform( $text )
{
- $s = "";
- while ( "" != $text ) {
- $p = preg_split( "/<\\s*nowiki\\s*>/i", $text, 2 );
- $s .= $this->pstPass2( $p[0] );
-
- if ( ( count( $p ) < 2 ) || ( "" == $p[1] ) ) { $text = ""; }
- else {
- $q = preg_split( "/<\\/\\s*nowiki\\s*>/i", $p[1], 2 );
- $s .= "<nowiki>{$q[0]}</nowiki>";
- $text = $q[1];
- }
- }
- return rtrim( $s );
+ global $wgParser, $wgUser;
+ return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) );
}
-
- /* private */ function pstPass2( $text )
- {
- global $wgUser, $wgLang, $wgLocaltimezone;
-
- # Signatures
- #
- $n = $wgUser->getName();
- $k = $wgUser->getOption( "nickname" );
- if ( "" == $k ) { $k = $n; }
- if(isset($wgLocaltimezone)) {
- $oldtz = getenv("TZ"); putenv("TZ=$wgLocaltimezone");
- }
- /* Note: this is an ugly timezone hack for the European wikis */
- $d = $wgLang->timeanddate( date( "YmdHis" ), false ) .
- " (" . date( "T" ) . ")";
- if(isset($wgLocaltimezone)) putenv("TZ=$oldtz");
-
- $text = preg_replace( "/~~~~/", "[[" . $wgLang->getNsText(
- Namespace::getUser() ) . ":$n|$k]] $d", $text );
- $text = preg_replace( "/~~~/", "[[" . $wgLang->getNsText(
- Namespace::getUser() ) . ":$n|$k]]", $text );
-
- # Context links: [[|name]] and [[name (context)|]]
- #
- $tc = "[&;%\\-,.\\(\\)' _0-9A-Za-z\\/:\\x80-\\xff]";
- $np = "[&;%\\-,.' _0-9A-Za-z\\/:\\x80-\\xff]"; # No parens
- $namespacechar = '[ _0-9A-Za-z\x80-\xff]'; # Namespaces can use non-ascii!
- $conpat = "/^({$np}+) \\(({$tc}+)\\)$/";
-
- $p1 = "/\[\[({$np}+) \\(({$np}+)\\)\\|]]/"; # [[page (context)|]]
- $p2 = "/\[\[\\|({$tc}+)]]/"; # [[|page]]
- $p3 = "/\[\[($namespacechar+):({$np}+)\\|]]/"; # [[namespace:page|]]
- $p4 = "/\[\[($namespacechar+):({$np}+) \\(({$np}+)\\)\\|]]/";
- # [[ns:page (cont)|]]
- $context = "";
- $t = $this->mTitle->getText();
- if ( preg_match( $conpat, $t, $m ) ) {
- $context = $m[2];
- }
- $text = preg_replace( $p4, "[[\\1:\\2 (\\3)|\\2]]", $text );
- $text = preg_replace( $p1, "[[\\1 (\\2)|\\1]]", $text );
- $text = preg_replace( $p3, "[[\\1:\\2|\\2]]", $text );
-
- if ( "" == $context ) {
- $text = preg_replace( $p2, "[[\\1]]", $text );
- } else {
- $text = preg_replace( $p2, "[[\\1 ({$context})|\\1]]", $text );
- }
-
- # {{SUBST:xxx}} variables
- #
- $mw =& MagicWord::get( MAG_SUBST );
- $text = $mw->substituteCallback( $text, "wfReplaceSubstVar" );
-
-/* Experimental:
- # Trim trailing whitespace
- # MAG_END (__END__) tag allows for trailing
- # whitespace to be deliberately included
- $text = rtrim( $text );
- $mw =& MagicWord::get( MAG_END );
- $mw->matchAndRemove( $text );
-*/
- return $text;
- }
-
+
/* Caching functions */
# checkLastModified returns true iff it has taken care of all
#
# This is a good place to put code to clear caches, for instance.
- /* static */ function onArticleCreate($title_obj,$text=''){
- global $wgEnablePersistentLC, $wgEnableParserCache, $wgUseSquid;
- global $wgDeferredUpdateList, $wgDBname, $wgMemc;
- global $wgMessageCache, $wgInternalServer;
- # Do standard deferred updates after page edit.
- $id = $title_obj->getArticleID();
- $title = $title_obj->getPrefixedDBkey();
- $shortTitle = $title_obj->getDBkey();
-
- $adj = $this->mCountAdjustment;
-
- if ( 0 != $id ) {
- $u = new LinksUpdate( $id, $title );
- array_push( $wgDeferredUpdateList, $u );
- $u = new SiteStatsUpdate( 0, 1, $adj );
- array_push( $wgDeferredUpdateList, $u );
- $u = new SearchUpdate( $id, $title, $text );
- array_push( $wgDeferredUpdateList, $u );
-
- $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle );
- array_push( $wgDeferredUpdateList, $u );
-
- if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
- $wgMessageCache->replace( $shortTitle, $text );
- }
- }
+ /* static */ function onArticleCreate($title_obj){
+ global $wgEnablePersistentLC, $wgEnableParserCache;
if ( $wgEnablePersistentLC ) {
- LinkCache::linksccClearBrokenLinksTo( $title );
+ LinkCache::linksccClearBrokenLinksTo( $title_obj->getPrefixedDBkey() );
}
if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearBrokenLinksTo( $title );
- }
- if ( $wgUseSquid ) {
- $urlArr = Array(
- $wgInternalServer.wfLocalUrl( $title_obj->getPrefixedURL())
- );
- wfPurgeSquidServers($urlArr);
- /* this needs to be done after LinksUpdate */
- $u = new SquidUpdate($title_obj);
- array_push( $wgDeferredUpdateList, $u );
+ OutputPage::parsercacheClearBrokenLinksTo( $title_obj->getPrefixedDBkey() );
}
}
- /* static */ function onArticleDelete($title_obj,$text=''){
- global $wgEnablePersistentLC, $wgEnableParserCache, $wgUseSquid, $wgDeferredUpdateList;
- global $wgDeferredUpdateList, $wgDBname, $wgMemc;
- global $wgMessageCache, $wgInternalServer;
-
- $id = $title_obj->getArticleID();
- $title = $title_obj->getPrefixedDBkey();
- $shortTitle = $title_obj->getDBkey();
-
+ /* static */ function onArticleDelete($title_obj){
+ global $wgEnablePersistentLC, $wgEnableParserCache;
if ( $wgEnablePersistentLC ) {
- LinkCache::linksccClearLinksTo( $id );
+ LinkCache::linksccClearLinksTo( $title_obj->getArticleID() );
}
if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearLinksTo( $id );
- }
- if ( $wgUseSquid ) {
- $urlArr = Array(
- $wgInternalServer.wfLocalUrl( $title_obj->getPrefixedURL())
- );
- wfPurgeSquidServers($urlArr);
-
- /* prepare the list of urls to purge */
- $sql = "SELECT l_from FROM links WHERE l_to={$id}" ;
- $res = wfQuery ( $sql, DB_READ ) ;
- while ( $BL = wfFetchObject ( $res ) )
- {
- $t = Title::newFromDBkey( $BL->l_from) ;
- $blurlArr[] = $wgInternalServer.wfLocalUrl( $t->getPrefixedURL() );
- }
- wfFreeResult ( $res ) ;
- $u = new SquidUpdate( $title_obj, $blurlArr );
- array_push( $wgDeferredUpdateList, $u );
-
+ OutputPage::parsercacheClearLinksTo( $title_obj->getArticleID() );
}
}
- /* static */ function onArticleEdit($title_obj,$text=''){
- global $wgEnablePersistentLC, $wgEnableParserCache, $wgUseSquid;
- global $wgDeferredUpdateList, $wgDBname, $wgMemc;
- global $wgMessageCache, $wgInternalServer;
-
- $id = $title_obj->getArticleID();
- $title = $title_obj->getPrefixedDBkey();
- $shortTitle = $title_obj->getDBkey();
-
- $adj = $this->mCountAdjustment;
-
- if ( 0 != $id ) {
- $u = new LinksUpdate( $id, $title );
- array_push( $wgDeferredUpdateList, $u );
- $u = new SiteStatsUpdate( 0, 1, $adj );
- array_push( $wgDeferredUpdateList, $u );
- $u = new SearchUpdate( $id, $title, $text );
- array_push( $wgDeferredUpdateList, $u );
-
- $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle );
- array_push( $wgDeferredUpdateList, $u );
-
- if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
- $wgMessageCache->replace( $shortTitle, $text );
- }
- }
+ /* static */ function onArticleEdit($title_obj){
+ global $wgEnablePersistentLC, $wgEnableParserCache;
if ( $wgEnablePersistentLC ) {
- LinkCache::linksccClearPage( $id );
+ LinkCache::linksccClearPage( $title_obj->getArticleID() );
}
if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearPage( $id );
- }
- if ( $wgUseSquid ) {
- $urlArr = Array(
- $wgInternalServer.wfLocalUrl( $title_obj->getPrefixedURL()),
- );
- wfPurgeSquidServers($urlArr);
+ OutputPage::parsercacheClearPage( $title_obj->getArticleID(), $title_obj->getNamespace() );
}
}
}