# Note: edit user interface and cache support functions have been
# moved to separate EditPage and CacheManager classes.
-include_once( "CacheManager.php" );
+require_once( "CacheManager.php" );
class Article {
/* private */ var $mContent, $mContentLoaded;
# strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
# comments to be stripped as well)
- $striparray=array();
- $parser=new Parser();
- $parser->mOutputType=OT_WIKI;
- $striptext=$parser->strip($this->mContent, $striparray, true);
-
- # now that we can be sure that no pseudo-sections are in the source,
- # split it up by section
- $secs =
- preg_split(
- "/(^=+.*?=+|^<h[1-6].*?" . ">.*?<\/h[1-6].*?" . ">)/mi",
- $striptext, -1,
- PREG_SPLIT_DELIM_CAPTURE);
-
- if($section==0) {
- $rv=$secs[0];
- } else {
- $rv=$secs[$section*2-1] . $secs[$section*2];
- }
-
- # reinsert stripped tags
- $rv=$parser->unstrip($rv,$striparray);
- $rv=trim($rv);
+ $rv=$this->getSection($this->mContent,$section);
wfProfileOut( $fname );
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.
+ #
+ function getSection($text,$section) {
+
+ # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
+ # comments to be stripped as well)
+ $striparray=array();
+ $parser=new Parser();
+ $parser->mOutputType=OT_WIKI;
+ $striptext=$parser->strip($text, $striparray, true);
+
+ # now that we can be sure that no pseudo-sections are in the source,
+ # split it up by section
+ $secs =
+ preg_split(
+ "/(^=+.*?=+|^<h[1-6].*?" . ">.*?<\/h[1-6].*?" . ">)/mi",
+ $striptext, -1,
+ PREG_SPLIT_DELIM_CAPTURE);
+ if($section==0) {
+ $rv=$secs[0];
+ } else {
+ $headline=$secs[$section*2-1];
+ preg_match( "/^(=+).*?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>/mi",$headline,$matches);
+ $hlevel=$matches[1];
+
+ # translate wiki heading into level
+ if(strpos($hlevel,"=")!==false) {
+ $hlevel=strlen($hlevel);
+ }
+
+ $rv=$headline. $secs[$section*2];
+ $count=$section+1;
+
+ $break=false;
+ while(!empty($secs[$count*2-1]) && !$break) {
+
+ $subheadline=$secs[$count*2-1];
+ preg_match( "/^(=+).*?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>/mi",$subheadline,$matches);
+ $subhlevel=$matches[1];
+ if(strpos($subhlevel,"=")!==false) {
+ $subhlevel=strlen($subhlevel);
+ }
+ if($subhlevel > $hlevel) {
+ $rv.=$subheadline.$secs[$count*2];
+ }
+ if($subhlevel <= $hlevel) {
+ $break=true;
+ }
+ $count++;
+
+ }
+ }
+ # reinsert stripped tags
+ $rv=$parser->unstrip($rv,$striparray);
+ $rv=trim($rv);
+ return $rv;
+
+ }
+
# Load the revision (including cur_text) into this object
function loadContent( $noredir = false )
$this->mTitle->mRestrictionsLoaded = true;
wfFreeResult( $res );
} else { # oldid set, retrieve historical version
- $sql = "SELECT old_text,old_timestamp,old_user,old_flags FROM old " .
+ $sql = "SELECT old_namespace,old_title,old_text,old_timestamp,old_user,old_flags FROM old " .
"WHERE old_id={$oldid}";
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) { return; }
+ if ( 0 == wfNumRows( $res ) ) {
+ return;
+ }
$s = wfFetchObject( $res );
+ if( $this->mTitle->getNamespace() != $s->old_namespace ||
+ $this->mTitle->getDBkey() != $s->old_title ) {
+ $oldTitle = Title::makeTitle( $s->old_namesapce, $s->old_title );
+ $this->mTitle = $oldTitle;
+ $wgTitle = $oldTitle;
+ }
$this->mContent = Article::getRevisionText( $s );
$this->mUser = $s->old_user;
$this->mCounter = 0;
" FROM old, user " .
" WHERE old.old_user = user.user_id " .
" AND old.old_namespace = " . $title->getNamespace() .
- " AND old.old_title = '" . $title->getDBkey() . "'" .
+ " AND old.old_title = \"" . $title->getDBkey() . "\"" .
" AND old.old_user != 0 " .
" AND old.old_user != " . $this->getUser() .
" GROUP BY old.old_user " .
}
$text = $this->getContent( false ); # May change mTitle by following a redirect
+
+ # Another whitelist check in case oldid or redirects are altering the title
+ if ( !$this->mTitle->userCanRead() ) {
+ $wgOut->loginToUse();
+ $wgOut->output();
+ exit;
+ }
+
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
# We're looking at an old revision
$wgLinkCache->preFill( $this->mTitle );
# wrap user css and user js in pre and don't parse
+ # XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found
if (
$this->mTitle->getNamespace() == Namespace::getUser() &&
preg_match("/\\/[\\w]+\\.(css|js)$/", $this->mTitle->getDBkey())
) {
$wgOut->addWikiText( wfMsg('usercssjs'));
$wgOut->addHTML( '<pre>'.htmlspecialchars($this->mContent)."\n</pre>" );
- } else if( $wgEnableParserCache && intval($wgUser->getOption( "stubthreshold" )) == 0 ){
+ } else if( $wgEnableParserCache && intval($wgUser->getOption( "stubthreshold" )) == 0 && empty( $oldid ) ){
$wgOut->addWikiText( $text, true, $this );
} else {
$wgOut->addWikiText( $text );
/* Side effects: loads last edit */
function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary = ""){
$this->loadLastEdit();
- $oldtext = $this->getContent( true );
+ $oldtext = $this->getContent( true );
if ($section != "") {
if($section=="new") {
if($summary) $subject="== {$summary} ==\n\n";
# now that we can be sure that no pseudo-sections are in the source,
# split it up
+ # Unfortunately we can't simply do a preg_replace because that might
+ # replace the wrong section, so we have to use the section counter instead
$secs=preg_split("/(^=+.*?=+|^<h[1-6].*?" . ">.*?<\/h[1-6].*?" . ">)/mi",
$oldtext,-1,PREG_SPLIT_DELIM_CAPTURE);
$secs[$section*2]=$text."\n\n"; // replace with edited
- if($section) { $secs[$section*2-1]=""; } // erase old headline
+
+ # section 0 is top (intro) section
+ if($section!=0) {
+
+ # headline of old section - we need to go through this section
+ # to determine if there are any subsections that now need to
+ # be erased, as the mother section has been replaced with
+ # the text of all subsections.
+ $headline=$secs[$section*2-1];
+ preg_match( "/^(=+).*?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>/mi",$headline,$matches);
+ $hlevel=$matches[1];
+
+ # determine headline level for wikimarkup headings
+ if(strpos($hlevel,"=")!==false) {
+ $hlevel=strlen($hlevel);
+ }
+
+ $secs[$section*2-1]=""; // erase old headline
+ $count=$section+1;
+ $break=false;
+ while(!empty($secs[$count*2-1]) && !$break) {
+
+ $subheadline=$secs[$count*2-1];
+ preg_match(
+ "/^(=+).*?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>/mi",$subheadline,$matches);
+ $subhlevel=$matches[1];
+ if(strpos($subhlevel,"=")!==false) {
+ $subhlevel=strlen($subhlevel);
+ }
+ if($subhlevel > $hlevel) {
+ // erase old subsections
+ $secs[$count*2-1]="";
+ $secs[$count*2]="";
+ }
+ if($subhlevel <= $hlevel) {
+ $break=true;
+ }
+ $count++;
+
+ }
+
+ }
$text=join("",$secs);
-
# reinsert the stuff that we stripped out earlier
- $text=$parser->unstrip($text,$striparray,true);
+ $text=$parser->unstrip($text,$striparray);
}
+
}
return $text;
}
- function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false )
+ function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = "" )
{
global $wgOut, $wgUser, $wgLinkCache;
global $wgDBtransactions, $wgMwRedir;
$u->doUpdate();
}
- $this->showArticle( $text, wfMsg( "updated" ) );
+ $this->showArticle( $text, wfMsg( "updated" ), $sectionanchor );
return true;
}
# After we've either updated or inserted the article, update
# the link tables and redirect to the new page.
- function showArticle( $text, $subtitle )
+ function showArticle( $text, $subtitle , $sectionanchor = '' )
{
global $wgOut, $wgUser, $wgLinkCache;
global $wgMwRedir;
$r = "redirect=no";
else
$r = "";
- $wgOut->redirect( $this->mTitle->getFullURL( $r ) );
+ $wgOut->redirect( $this->mTitle->getFullURL( $r ).$sectionanchor );
}
# Add this page to my watchlist
$sql = "DELETE FROM brokenlinks WHERE bl_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
+ $sql = "DELETE FROM categorylinks WHERE cl_from={$id}";
+ wfQuery( $sql, DB_WRITE, $fname );
+
$log = new LogPage( wfMsg( "dellogpage" ), wfMsg( "dellogpagetext" ) );
$art = $this->mTitle->getPrefixedText();
$log->addEntry( wfMsg( "deletedarticle", $art ), $reason );
return false;
}
}
+
+ function getTouched() {
+ return $this->mTouched;
+ }
/* static */ function incViewCount( $id )
{
# This is called on page move and undelete, as well as edit
/* static */ function onArticleCreate($title_obj){
- global $wgEnablePersistentLC, $wgEnableParserCache, $wgUseSquid, $wgDeferredUpdateList;
+ global $wgEnablePersistentLC, $wgUseSquid, $wgDeferredUpdateList;
$titles = $title_obj->getBrokenLinksTo();
if ( $wgEnablePersistentLC ) {
LinkCache::linksccClearBrokenLinksTo( $title_obj->getPrefixedDBkey() );
}
-
- # Clear parser cache (not really used)
- if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearBrokenLinksTo( $title_obj->getPrefixedDBkey() );
- }
}
/* static */ function onArticleDelete($title_obj){
- global $wgEnablePersistentLC, $wgEnableParserCache;
+ global $wgEnablePersistentLC;
if ( $wgEnablePersistentLC ) {
LinkCache::linksccClearLinksTo( $title_obj->getArticleID() );
}
- if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearLinksTo( $title_obj->getArticleID() );
- }
}
/* static */ function onArticleEdit($title_obj){
- global $wgEnablePersistentLC, $wgEnableParserCache;
+ global $wgEnablePersistentLC;
if ( $wgEnablePersistentLC ) {
LinkCache::linksccClearPage( $title_obj->getArticleID() );
}
- if ( $wgEnableParserCache ) {
- OutputPage::parsercacheClearPage( $title_obj->getArticleID(), $title_obj->getNamespace() );
- }
}
}