* "Edit this section" feature that allows loading just part of an article
authorErik Moeller <erik@users.mediawiki.org>
Mon, 30 Jun 2003 00:19:35 +0000 (00:19 +0000)
committerErik Moeller <erik@users.mediawiki.org>
Mon, 30 Jun 2003 00:19:35 +0000 (00:19 +0000)
instead of the whole one
* "Table of contents" feature that is displayed above the article if that
preference is enabled and there are more than three headings
* Rewrote auto-numbering code
* Automatic insertion of anchors into every page
* minor fixes to update.php

includes/Article.php
includes/OutputPage.php
includes/Skin.php
languages/Language.php
update.php

index 85617c3..ea9e958 100644 (file)
@@ -50,7 +50,7 @@ class Article {
 
        function getContent( $noredir = false )
        {
-               global $action,$wgTitle; # From query string
+               global $action,$section,$count,$wgTitle; # From query string
                wfProfileIn( "Article::getContent" );
 
                if ( 0 == $this->getID() ) {
@@ -75,7 +75,20 @@ class Article {
                                ) 
                                {
                                return $this->mContent . "\n" .wfMsg("anontalkpagetext"); }
-                       else {
+                       else {                          
+                               if($action=="edit") {
+                                       if($section!="") {
+
+                                               $secs=preg_split("/(^=+.*?=+)/m",
+                                                $this->mContent, -1,
+                                                PREG_SPLIT_DELIM_CAPTURE);
+                                               if($section==0) {
+                                                       return trim($secs[0]);
+                                               } else {
+                                                       return trim($secs[$section*2-1] . $secs[$section*2]);
+                                               }
+                                       }
+                               }
                                return $this->mContent;
                        }
                }
@@ -367,10 +380,12 @@ class Article {
                global $wgOut, $wgUser, $wgTitle;
                global $wpTextbox1, $wpSummary, $wpWatchthis;
                global $wpSave, $wpPreview;
-               global $wpMinoredit, $wpEdittime, $wpTextbox2;
-               global $oldid, $redirect;
+               global $wpMinoredit, $wpEdittime, $wpTextbox2, $wpSection;
+               global $oldid, $redirect, $section;
                global $wgLang;
 
+               if($wpSection) { $section=$wpSection; }
+
                $sk = $wgUser->getSkin();
                $isConflict = false;
                $wpTextbox1 = rtrim ( $wpTextbox1 ) ; # To avoid text getting longer on each preview
@@ -424,7 +439,7 @@ class Article {
                        }
                        if ( ! $isConflict ) {
                                # All's well: update the article here
-                               $this->updateArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis );
+                               $this->updateArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis, $wpSection );
                                return;
                        }
                }
@@ -553,6 +568,7 @@ name=\"wpSummary\" maxlength=200 size=60><br>
 <input tabindex=6 type=submit value=\"{$prev}\" name=\"wpPreview\">
 <em>{$cancel}</em> | <em>{$edithelp}</em>
 <br><br>{$copywarn}
+<input type=hidden value=\"{$section}\" name=\"wpSection\">
 <input type=hidden value=\"{$wpEdittime}\" name=\"wpEdittime\">\n" );
 
                if ( $isConflict ) {
@@ -628,12 +644,21 @@ name=\"wpSummary\" maxlength=200 size=60><br>
                $this->showArticle( $text, wfMsg( "newarticle" ) );
        }
 
-       function updateArticle( $text, $summary, $minor, $watchthis )
+       function updateArticle( $text, $summary, $minor, $watchthis, $section )
        {
                global $wgOut, $wgUser, $wgTitle, $wgLinkCache;
                global $wgDBtransactions;
                $fname = "Article::updateArticle";
 
+               // insert updated section into old text if we have only edited part 
+               // of the article
+               if ($section != "") {
+                       $oldtext=$this->getContent();
+                       $secs=preg_split("/(^=+.*?=+)/m",$oldtext,-1,PREG_SPLIT_DELIM_CAPTURE);
+                       $secs[$section*2]=$text."\n\n"; // replace with edited
+                       if($section) { $secs[$section*2-1]=""; } // erase old headline
+                       $text=join("",$secs);           
+               }
                if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
                if ( $minor ) { $me2 = 1; } else { $me2 = 0; }          
                if ( preg_match( "/^(#redirect[^\\n]+)/i", $text, $m ) ) {
index 21019c3..8aaf592 100644 (file)
@@ -664,7 +664,7 @@ class OutputPage {
 
                $text = $this->magicISBN( $text );
                $text = $this->magicRFC( $text );
-               $text = $this->autoNumberHeadings( $text );
+               $text = $this->formatHeadings( $text );
 
                $sk = $wgUser->getSkin();
                $text = $sk->transformContent( $text );
@@ -1190,41 +1190,119 @@ class OutputPage {
                return $text;
        }
 
-       /* private */ function autoNumberHeadings( $text )
+
+/* 
+ * 
+ * This function accomplishes several tasks:
+ * 1) Auto-number headings if that option is enabled
+ * 2) Add an [edit] link to sections for logged in users who have enabled the option
+ * 3) Add a Table of contents on the top for users who have enabled the option
+ * 4) Auto-anchor headings
+ *
+ * It loops through all headlines, collects the necessary data, then splits up the
+ * string and re-inserts the newly formatted headlines.
+ *
+ * */
+       /* private */ function formatHeadings( $text )
        {
-               global $wgUser;
-               if ( 1 != $wgUser->getOption( "numberheadings" ) ) {
-                       return $text;
-               }
-               $j = 0;
-               $n = -1;
-               for ( $i = 0; $i < 9; ++$i ) {
-                       if ( stristr( $text, "<h$i>" ) != false ) {
-                               ++$j;
-                               if ( $n == -1 ) $n = $i;
+               global $wgUser,$wgArticle,$wgTitle,$wpPreview;
+               $nh=$wgUser->getOption( "numberheadings" );
+               $st=$wgUser->getOption( "showtoc" );
+               $es=$wgUser->getID() && $wgUser->getOption( "editsection" );
+
+               $sk=$wgUser->getSkin();
+               preg_match_all("/<H([1-6])(.*?>)(.*?)<\/H[1-6]>/i",$text,$matches);
+
+               $c=0;
+
+               foreach($matches[3] as $headline) {
+                       if($level) { $prevlevel=$level;}
+                       $level=$matches[1][$c];
+                       if(($nh||$st) && $level>$prevlevel) { 
+                                                       
+                               $h[$level]=0; // reset when we enter a new level                                
+                               if($toclevel) {
+                                       $toc.=$sk->tocIndent($level-$prevlevel);
+                               }
+                               $toclevel++;
+                       
+                       } 
+                       if(($nh||$st) && $level<$prevlevel) {
+                               $h[$level+1]=0; // reset when we step back a level
+                               if($toclevel) {
+                                       $toc.=$sk->tocUnindent($prevlevel-$level);
+                               }
+                               $toclevel--;
+
+                       }
+                       $h[$level]++; // count number of headlines for each level
+                       
+                       if($nh||$st) {
+                               for($i=1;$i<=$level;$i++) {
+                                       if($h[$i]) {
+                                               if($dot) {$numbering.=".";}
+                                               $numbering.=$h[$i];
+                                               $dot=1;                                 
+                                       }
+                               }
                        }
+
+                       
+                       $canonized_headline=preg_replace("/<.*?>/","",$headline); // strip out HTML
+                       $tocline=$canonized_headline;
+                       $canonized_headline=str_replace(" ","_",trim($canonized_headline));                     
+                       $refer[$c]=$canonized_headline;
+                       $refers[$canonized_headline]++;  // count how many in assoc. array so we can track dupes in anchors
+                       $refcount[$c]=$refers[$canonized_headline];
+                       if($nh||$st) {
+                               $tocline=$numbering ." ". $tocline;
+                               if($nh) {
+                                       $headline=$numbering . " " . $headline; // the two are different if the line contains a link
+                               }                               
+                       }
+                       $anchor=$canonized_headline;
+                       if($refcount[$c]>1) {$anchor.="_".$refcount[$c];}
+                       if($st) {
+                               $toc.=$sk->tocLine($anchor,$tocline);
+                       }
+                       $head[$c].="<H".$level.$matches[2][$c]
+                        ."<a name=\"".$anchor."\">"
+                        .$headline
+                        ."</a>"
+                        ."</H".$level.">";
+                       $numbering="";
+                       $c++;
+                       $dot=0;
+               }               
+
+               if($st) {
+                       $toclines=$c;
+                       while($toclevel>0) {
+                               $toc.="</ul>";
+                               $toclevel--;
+                       }
+
+                       $toc=$sk->tocTable($toc);
                }
-               if ( $j < 2 ) return $text;
-               $i = $n;
-               $v = array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
-               $t = "";
-               while ( count( spliti( "<h", $text, 2 ) ) == 2 ) {
-                       $a = spliti( "<h", $text, 2 );
-                       $j = substr( $a[1], 0, 1 );
-                       if ( strtolower( $j ) != "r" ) {
-                               $t .= $a[0] . "<h" . $j . ">";
-                               ++$v[$j];
-                               $b = array();
-                               for ( $k = $i; $k <= $j; $k++ ) array_push( $b, $v[$k] );
-                               for ( $k = $j+1; $k < 9; $k++ ) $v[$k] = 0;
-                               $t .= implode( ".", $b ) . " ";
-                $text = substr( $a[1] , 2 ) ;
-                       } else { # <HR> tag, not a heading!
-                               $t .= $a[0] . "<hr>";
-                               $text = substr( $a[1], 2 );
+
+
+               // split up and insert constructed headlines
+               
+               $blocks=preg_split("/<H[1-6].*?>.*?<\/H[1-6]>/i",$text);
+               $i=0;
+               foreach($blocks as $block) {                    
+                       $full.=$block;
+                       if($es && $c>0 && !isset($wpPreview)) {
+                               $full.=$sk->editSectionLink($i);
                        }
+
+                       $full.=$head[$i];
+                       $i++;
+               }
+               if($st && $toclines>3) {
+                       $full=$toc."<a name=\"top\"></a>".$full;
                }
-        return $t . $text;
+               return $full;
        }
 
        /* private */ function magicISBN( $text )
index d00a192..2525476 100644 (file)
@@ -1655,6 +1655,42 @@ class Skin {
                $s .= "</li>\n";
                return $s;
        }
+
+       function tocIndent($level) {
+
+               while($level--) $rv.="<ul style=\"list-style-type:none;margin:0px;\">";
+               return $rv;
+
+       }
+
+       function tocUnindent($level) {
+               while($level--) $rv.="</ul>";
+               return $rv;
+       }
+
+       function tocLine($anchor,$tocline) {
+
+               return "<li><A CLASS=\"internal\" HREF=\"#".$anchor."\">".$tocline."</A></li>";
+
+       }
+
+       function tocTable($toc) {
+
+       return
+       "<table border=\"0\" bgcolor=\"#8888aa\" cellpadding=\"0\" cellspacing=\"1\"><tr><td>" .
+       "<table border=\"0\" bgcolor=\"#f3f3ff\" CELLPADDING=5><tr><td>".
+       "<b>".wfMsg("toc")."</b><p>".
+       $toc."</td></tr></table></td></tr></table><P>";
+       }
+
+       function editSectionLink($section) {
+
+               global $wgTitle;
+               $editurl="&section={$section}";
+               $url=$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
+               return "<p style=\"text-align:left;\"><small>[".$url."]</small></p>";
+
+       }
 }
 
 include_once( "SkinStandard.php" );
index 42579d6..b857533 100644 (file)
@@ -25,7 +25,7 @@
        "contextlines" => 5, "contextchars" => 50,
        "skin" => 0, "math" => 1, "rcdays" => 7, "rclimit" => 50,
        "highlightbroken" => 1, "stubthreshold" => 0,
-       "previewontop" => 1
+       "previewontop" => 1, "editsection"=>1, "showtoc"=>1
 );
 
 /* private */ $wgQuickbarSettingsEn = array(
@@ -53,6 +53,8 @@ this</a> (alternative: like this<a href=\"\" class=\"internal\">?</a>).",
        "hideminor" => "Hide minor edits in recent changes",
        "usenewrc" => "Enhanced recent changes (not for all browsers)",
        "numberheadings" => "Auto-number headings",
+       "editsection"=>"Show links for editing individual sections",
+       "showtoc"=>"Show table of contents for articles with more than 3 headings",
        "rememberpassword" => "Remember password across sessions",
        "editwidth" => "Edit box has full width",
        "editondblclick" => "Edit pages on double click (JavaScript)",
@@ -351,6 +353,8 @@ See $1.",
 "retrievedfrom" => "Retrieved from \"$1\"",
 "newmessages" => "You have $1.",
 "newmessageslink" => "new messages",
+"editsection"=>"edit",
+"toc" => "Table of contents",
 
 # Main script and global functions
 #
index e93fb1e..66ae6f0 100644 (file)
@@ -10,7 +10,7 @@ if ( ! ( is_readable( "./LocalSettings.php" )
        exit();
 }
 
-$DP = "./includes";
+$IP = "./includes";
 include_once( "./LocalSettings.php" );
 include_once( "./AdminSettings.php" );
 
@@ -23,7 +23,7 @@ if ( $wgUseTeX && ( ! is_executable( "./math/texvc" ) ) ) {
 umask( 000 );
 set_time_limit( 0 );
 
-include_once( "{$IP}/Version.php" );
+include_once( "Version.php" );
 include_once( "{$IP}/Setup.php" );
 $wgTitle = Title::newFromText( "Update script" );
 $wgCommandLineMode = true;