[Home]WikiPatches/PeriPerify

UseModWiki | WikiPatches | RecentChanges | Preferences

This is my first patch to UseMod and not yet thoroughly-debugged: be warned. It makes UseMod more like the PeriPeri? prototype site.

Features:

What is the benefit? Subpages were never designed to support proper namespaces; with Shatter, you can get them.

Examples:

This is a different way of thinking about subpages, so I suggest the following rules to abide by:

This patch is a spike of the MeatBall:FacetWiki project; see that page for more information.

-- KritTer


@@ -45,7 +45,7 @@

   $UrlProtocols $UrlPattern $ImageExtensions $RFCPattern $ISBNPattern
   $FS $FS1 $FS2 $FS3 $CookieName $SiteBase $StyleSheet $NotFoundPg
   $FooterNote $EditNote $MaxPost $NewText $NotifyDefault $HttpCharset
   $UserGotoBar $UseSetpage $ShatterWiki $SetDivChar $SetFSChar );
 # Note: $NotifyDefault is kept because it was a config variable in 0.90
 # Other global variables:
 use vars qw(%Page %Section %Text %InterSite %SaveUrl %SaveNumUrl
@@ -84,9 +84,12 @@
 $NewText     = "";              # New page text ("" for default message)
 $HttpCharset = "";              # Charset for pages, like "iso-8859-2"
 $UserGotoBar = "";              # HTML added to end of goto bar
 $SetDivChar  = "/";             # Set divider when $UseSetpage active
 $SetFSChar   = ",";             # Set divider to use in file storage

 # Major options:
 $UseSubpage  = 1;       # 1 = use subpages,       0 = do not use subpages
 $UseSetpage  = 1;       # 1 = use setsubpages,    0 = do not use setsubpages
 $UseCache    = 0;       # 1 = cache HTML pages,   0 = generate every page
 $EditAllowed = 1;       # 1 = editing allowed,    0 = read-only
 $RawHtml     = 0;       # 1 = allow <HTML> tag,   0 = no raw HTML in pages
@@ -119,6 +122,7 @@
 $UseLookup   = 1;       # 1 = lookup host names,  0 = skip lookup (IP only)
 $FreeUpper   = 1;       # 1 = force upper case,   0 = do not force case
 $FastGlob    = 1;       # 1 = new faster code,    0 = old compatible code
 $ShatterWiki = 1;       # 1 = use Shatter algo,   0 = no Shattering

 # HTML tag lists, enabled if $HtmlTags is set.
 # Scripting is currently possible with these tags,
@@ -161,7 +165,7 @@
 # == Common and cache-browsing code ====================================
 sub InitLinkPatterns {
   my ($UpperLetter, $LowerLetter, $AnyLetter, $LpA, $LpB, $LpX, $QDelim);

   # Field separators are used in the URL-style patterns below.
   $FS  = "\xb3";      # The FS character is a superscript "3"
@@ -185,14 +189,17 @@
   # Main link pattern: lowercase between uppercase, then anything
   $LpA = $UpperLetter . "+" . $LowerLetter . "+" . $UpperLetter
          . $AnyLetter . "*";
   # Optional loose subpage link pattern: uppercase, lowercase, then anything
   $LpB = $UpperLetter . "+" . $LowerLetter . "+" . $AnyLetter . "*";
   # Strict pattern: use main LinkPattern for subpages
   # $LpB = $LpA;
   # Optional set-subpage link pattern: subpage names separated by set divider
   my $LpX = "$LpB(?:[$SetDivChar]$LpB)*";
 
   if ($UseSubpage and $UseSetpage) {
     $LinkPattern = "((?:(?:$LpA)?\\/$LpX)|$LpA)";
   } elsif ($UseSubpage) {
     $LinkPattern = "((?:(?:$LpA)?\\/$LpB)|$LpA)";
   } else {
     $LinkPattern = "($LpA)";
   }
@@ -213,7 +220,10 @@
     }
   }
   $FreeLinkPattern = "($AnyLetter+)";
   if ($UseSetpage and $UseSubpage) {
     $FreeLinkPattern = "((?:(?:$AnyLetter+)?\\/(?:$AnyLetter+" .
                        "[$SetDivChar])*)?$AnyLetter+)";
   } elsif ($UseSubpage) {
     $FreeLinkPattern = "((?:(?:$AnyLetter+)?\\/)?$AnyLetter+)";
   }
   $FreeLinkPattern .= $QDelim;
@@ -264,7 +274,7 @@
 sub GetHtmlCacheFile {
   my ($id) = @_;

   return $HtmlDir . "/" . &GetPage($id) . ".htm";
 }

 sub GetPageDirectory {
@@ -360,6 +370,9 @@
     if ($FreeLinks && (!-f &GetPageFile($id))) {
       $id = &FreeToNormal($id);
     }
     if ($UseSetpage) {
       $id = &SetToNormal($id);
     }
     if (($NotFoundPg ne '') && (!-f &GetPageFile($id))) {
       $id = $NotFoundPg;
     }
@@ -372,6 +385,9 @@
     if ($FreeLinks && (!-f &GetPageFile($id))) {
       $id = &FreeToNormal($id);
     }
     if ($UseSetpage) {
       $id = &SetToNormal($id);
     }
     if (($NotFoundPg ne '') && (!-f &GetPageFile($id))) {
       $id = $NotFoundPg;
     }
@@ -384,6 +400,9 @@
     &DoRandom();
     return 1;
   } elsif ($action eq 'history') {
     if ($UseSetpage) {
       $id = &SetToNormal($id);
     }
     &DoHistory($id)   if &ValidIdOrDie($id);
     return 1;
   }
@@ -421,6 +440,9 @@
     } else {
       ($id) = ($Text{'text'} =~ /\#REDIRECT\s+(\S+)/);
     }
     if ($UseSetpage) {
       $id = &SetToNormal($id);
     }
     if (&ValidId($id) eq '') {
       # Later consider revision in rebrowse?
       &ReBrowsePage($id, $oldId, 0);
@@ -460,7 +482,7 @@
     &OpenKeptRevisions('text_default')  if (!$openKept);
     $fullHtml .= &GetDiffHTML($showDiff, $id, $diffRevision, $newText);
   }
   $fullHtml .= &WikiToHTML($Text{'text'}, $id);
   $fullHtml .= "<hr>\n"  if (!&GetParam('embed', $EmbedWiki));
   if (($id eq $RCName) || (T($RCName) eq $id) || (T($id) eq $RCName)) {
     print $fullHtml;
@@ -747,9 +769,9 @@
   $html = Ts('Revision %s', $rev) . ": ";
   if ($isCurrent) {
     $html .= &GetPageLinkText($id, T('View'), '') . ' ';
     if ($canEdit) {
       $html .= &GetEditLink($id, T('Edit'), '') . ' ';
     }
     if ($UseDiff) {
       $html .= T('Diff') . ' ';
@@ -793,13 +815,16 @@
 }

 sub GetPageLinkText {
   my ($id, $name, $ref) = @_;

   $id =~ s|^/|$MainPage/|;
   if ($FreeLinks) {
     $id = &FreeToNormal($id);
     $name =~ s/_/ /g;
   }
   if ($ShatterWiki and $ref) {
     $id .= ":".$ref;
   }
   return &ScriptLink($id, $name);
 }
@@ -824,7 +849,7 @@
 }

 sub GetPageOrEditLink {
   my ($id, $name, $ref) = @_;
   my (@temp, $exists);

   if ($name eq "") {
@@ -836,6 +861,11 @@
   $id =~ s|^/|$MainPage/|;
   if ($FreeLinks) {
     $id = &FreeToNormal($id);
     $ref = &FreeToNormal($ref);
   }
   if ($UseSetpage) {
     $id = &SetToNormal($id);
     $ref = &SetToNormal($ref);
   }
   $exists = 0;
   if ($UseIndex) {
@@ -847,7 +877,7 @@
     $exists = 1;
   }
   if ($exists) {
     return &GetPageLinkText($id, $name, $ref);
   }
   if ($FreeLinks) {
     if ($name =~ m| |) {  # Not a single word
@@ -1041,7 +1071,7 @@
   $result .= &GetHistoryLink($id, T('View other revisions'));
   if ($rev ne '') {
     $result .= ' | ';
     $result .= &GetPageLinkText($id, T('View current revision'), '');
   }
   if ($Section{'revision'} > 0) {
     $result .= '<br>';
@@ -1151,7 +1181,7 @@
 # ==== Common wiki markup ====
 sub WikiToHTML {
   my ($pageText, $id) = @_;

   %SaveUrl = ();
   %SaveNumUrl = ();
@@ -1163,15 +1193,15 @@
   }
   $pageText = &QuoteHtml($pageText);
   $pageText =~ s/\\ *\r?\n/ /g;          # Join lines with backslash at end
   $pageText = &CommonMarkup($pageText, 1, 0, $id);   # Multi-line markup
   $pageText = &WikiLinesToHtml($pageText, $id); # Line-oriented markup
   $pageText =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge;   # Restore saved text
   $pageText =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge;   # Restore nested saved text
   return $pageText;
 }

 sub CommonMarkup {
   my ($text, $useImage, $doLines, $id) = @_;
   local $_ = $text;

   if ($doLines < 2) { # 2 = do line-oriented only
@@ -1202,8 +1232,9 @@
     if ($FreeLinks) {
       # Consider: should local free-link descriptions be conditional?
       # Also, consider that one could write [[Bad Page|Good Page]]?
       s/\[\[$FreeLinkPattern\|([^\]]+)\]\]/&StorePageOrEditLink($1,$2,$id)
                                                                   /geo;
       s/\[\[$FreeLinkPattern\]\]/&StorePageOrEditLink($1, "", $id)/geo;
     }
     if ($BracketText) {  # Links like [URL text of link]
       s/\[$UrlPattern\s+([^\]]+?)\]/&StoreBracketUrl($1, $2)/geos;
@@ -1217,7 +1248,7 @@
     s/$UrlPattern/&StoreUrl($1, $useImage)/geo;
     s/$InterLinkPattern/&StoreInterPage($1)/geo;
     if ($WikiLinks) {
       s/$LinkPattern/&GetPageOrEditLink($1, "", $id)/geo;
     }
     s/$RFCPattern/&StoreRFC($1)/geo;
     s/$ISBNPattern/&StoreISBN($1)/geo;
@@ -1241,7 +1272,7 @@
 }

 sub WikiLinesToHtml {
   my ($pageText, $id) = @_;
   my ($pageHtml, @htmlStack, $code, $depth, $oldCode);

   @htmlStack = ();
@@ -1284,8 +1315,8 @@
       }
     }
     s/^\s*$/<p>\n/;                             # Blank lines become <p> tags
     $pageHtml .= &CommonMarkup($_, 1, 2, $id);  # Line-oriented common markup
   }
   while (@htmlStack > 0) {       # Clear stack
     $pageHtml .=  "</" . pop(@htmlStack) . ">\n";
@@ -1434,11 +1465,11 @@
 sub StoreBracketLink {
   my ($name, $text) = @_;

   return &StoreRaw(&GetPageLinkText($name, "[$text]", ''));
 }

 sub StorePageOrEditLink {
   my ($page, $name, $id) = @_;
 
   if ($FreeLinks) {
     $page =~ s/^\s+//;      # Trim extra spaces
@@ -1447,7 +1478,7 @@
   }
   $name =~ s/^\s+//;
   $name =~ s/\s+$//;
   return &StoreRaw(&GetPageOrEditLink($page, $name, $id));
 }
 
 sub StoreRFC {
@@ -1588,7 +1619,7 @@
   if ($rev ne "") {
     $html = '<b>'
             . Ts('Difference (from revision %s to current revision)', $rev)
             . "</b>\n" . "$links<br>" . &DiffToHTML($diffText,$id) . "<hr>\n";
   } else {
     if (($diffType != 2) &&
         ((!defined(&GetPageCache("old$cacheName"))) ||
@@ -1599,7 +1630,7 @@
     } else {
       $html = '<b>'
               . Ts('Difference (from prior %s revision)', $priorName)
               . "</b>\n$links<br>" . &DiffToHTML($diffText,$id) . "<hr>\n";
     }
   }
   return $html;
@@ -1652,7 +1683,7 @@
 }

 sub DiffToHTML {
   my ($html, $id) = @_;
   my ($tChanged, $tRemoved, $tAdded);
 
   $tChanged = T('Changed:');
@@ -1663,13 +1694,13 @@
   $html =~ s/(^|\n)(\d+.*c.*)/$1 <br><strong>$tChanged $2<\/strong><br>/g;
   $html =~ s/(^|\n)(\d+.*d.*)/$1 <br><strong>$tRemoved $2<\/strong><br>/g;
   $html =~ s/(^|\n)(\d+.*a.*)/$1 <br><strong>$tAdded $2<\/strong><br>/g;
   $html =~ s/\n((<.*\n)+)/&ColorDiff($1,"ffffaf",$id)/ge;
   $html =~ s/\n((>.*\n)+)/&ColorDiff($1,"cfffcf",$id)/ge;
   return $html;
 }
 
 sub ColorDiff {
   my ($diff, $color, $id) = @_;

   $diff =~ s/(^|\n)[<>]/$1/g;
   $diff = &QuoteHtml($diff);
@@ -1679,7 +1710,7 @@
   $SaveUrlIndex = 0;
   $SaveNumUrlIndex = 0;
   $diff =~ s/$FS//g;
   $diff =  &CommonMarkup($diff, 0, 1, $id); # No images, all patterns
   $diff =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge;   # Restore saved text
   $diff =~ s/$FS(\d+)$FS/$SaveUrl{$1}/ge;   # Restore nested saved text
   $diff =~ s/\r?\n/<br>/g;
@@ -1734,7 +1765,7 @@
 sub GetPageFile {
   my ($id) = @_;

   return $PageDir . "/" . &GetPage($id) . ".db";
 }

 sub OpenPage {
@@ -1841,8 +1872,7 @@
 }

 sub KeepFileName {
   return $KeepDir . "/" . &GetPage($OpenPageName) . ".kp";
 }

 sub SaveKeepSection {
@@ -1982,7 +2012,17 @@
   if ($id =~ m| |) {
     return Ts('Page name may not contain space characters: %s', $id);
   }
   if ($UseSetpage and $UseSubpage) {
     if (($SetDivChar ne "/") and ($id =~ m|.*/.*/|)) {
       return Ts('Too many / characters in page %s', $id);
     }
     if (($id =~ /^\//) or ($id =~ m/^[$SetDivChar]/)) {
       return Ts('Invalid Page %s (subpage without main page)', $id);
     }
     if (($id =~ /\/$/) or ($id =~ /[$SetDivChar]$/)) {
       return Ts('Invalid Page %s (missing subpage name)', $id);
     }
   } elsif ($UseSubpage) {
     if ($id =~ m|.*/.*/|) {
       return Ts('Too many / characters in page %s', $id);
     }
@@ -2099,7 +2139,7 @@
 sub GetLockedPageFile {
   my ($id) = @_;

   return $PageDir . "/" . &GetPage($id) . ".lck";
 }

 sub RequestLockDir {
@@ -2422,6 +2462,10 @@
     $id =~ s/__+/_/g;
     $id =~ s/^_//;
     $id =~ s/_$//;
     if ($UseSetpage and $UseSubpage) {
       $id =~ s|_\\${SetDivChar}|${SetDivChar}|g;
       $id =~ s|\\${SetDivChar}_|${SetDivChar}|g;
     }
     if ($UseSubpage) {
       $id =~ s|_/|/|g;
       $id =~ s|/_|/|g;
@@ -2435,6 +2479,59 @@
   }
   return $id;
 }
 sub SetToNormal {
   (my $id) = @_;
   return $id unless $id =~ m|[:/]|;
   if ($id =~ s(:(.*))()) {
 #### Run the Shatter algorithm ###############################################
     my $referrer = SetToNormal($1);
     OpenPage($1);
     OpenDefaultText();
     my @LINKS = ($Text{'text'} =~ m($LinkPattern)g);
     push @LINKS, (grep /^$LinkPattern$/, split "/", $referrer);
     (my $name, my $set) = split "/", $id, 2;
     my @set = sort split /$SetDivChar/, $set;
     my %set = map { $_ => undef } @set;
     my $ss = "\./" . $PageDir . "/" . &GetPageDirectory($name) ."/".$name."/";
     $ss .= "\\(.*[$SetFSChar]\\)?" . join("[$SetFSChar]",
               map { $_ . "\\([$SetFSChar].*\\)?" } @set) if (scalar @set);
     $ss .= ".*" unless (scalar @set);
     $ss .= "\.db";
     my @VALID = grep { scalar(@set) == scalar(grep { exists $set{$_} }
                                               split $SetFSChar, $_) }
                 map { m(([^/]*)\.db$); $1 } split "\n", `find . -regex "$ss"`;
     push @VALID, join $SetFSChar, @set;
     my %VALIDWORDS = map { ($_ => undef) }
                      map { split $SetFSChar, $_ } @VALID;
     my %WORDS = map { ($_ => undef) } grep { not exists $set{$_} }
                 grep { exists $VALIDWORDS{$_} } @LINKS;
     my %SHATTER;
     my @APPLICABLE = map { map { $SHATTER{$_}++ } split $SetFSChar, $_; $_ }
                      grep { scalar(keys %WORDS) == scalar
                                grep { exists $WORDS{$_} }
                                split $SetFSChar, $_ } @VALID;
     my $SHATTER = join $SetFSChar, sort grep
                   { $SHATTER{$_} == scalar @APPLICABLE } keys %SHATTER;
     if ((0 < scalar @APPLICABLE) and
         (0 < grep { $_ eq $SHATTER } @APPLICABLE)) {
         $SHATTER =~ s([$SetFSChar])($SetDivChar);
         return $name unless $SHATTER;
         return "$name/$SHATTER";
     }
     return $name if scalar @set == 0;
     return "$name/".join $SetDivChar, @set;
   }
   (my $name, my $set) = split "/", $id, 2;
   $set = join $SetDivChar, sort split /$SetDivChar/, $set;
   return "$name/$set";
 }
 sub GetPage {
   (my $id) = @_;
   return &GetPageDirectory($id)."/".$id unless $id =~ m|/|;
   (my $name, my $set) = split "/", $id, 2;
   $set = join $SetFSChar, split /$SetDivChar/, $set;
   return GetPageDirectory($id)."/$name/$set";
 }
 #END_OF_BROWSE_CODE

 # == Page-editing and other special-action code ========================
@@ -2632,7 +2729,7 @@
     }
     $MainPage = $id;
     $MainPage =~ s|/.*||;  # Only the main page name (remove subpage)
     print &WikiToHTML($oldText, $id) . "<hr>\n";
     print "<h2>", T('Preview only, not yet saved'), "</h2>\n";
   }
   print &GetHistoryLink($id, T('View other revisions')) . "<br>\n";
@@ -3806,7 +3903,7 @@
   $fname = &GetPageFile($page);
   unlink($fname)  if (-f $fname);
   $fname = $KeepDir . "/" . &GetPage($page) . ".kp";
   unlink($fname)  if (-f $fname);
   unlink($IndexFile)  if ($UseIndex);
   &EditRecentChanges(1, $page, "")  if ($doRC);  # Delete page
@@ -3887,7 +3984,7 @@
   my ($fname, $status, $data, @kplist, %tempSection, $changed);
   my ($sectName, $newText);

   $fname = $KeepDir . "/" . &GetPage($page) . ".kp";
   return  if (!(-f $fname));
   ($status, $data) = &ReadFile($fname);
   return  if (!$status);
@@ -4019,8 +4116,8 @@
   &CreatePageDir($PageDir, $new);  # It might not exist yet
   rename($oldfname, $newfname);
   &CreatePageDir($KeepDir, $new);
   $oldkeep = $KeepDir . "/" . &GetPage($old) . ".kp";
   $newkeep = $KeepDir . "/" . &GetPage($new) . ".kp";
   unlink($newkeep)  if (-f $newkeep);  # Clean up if needed.
   rename($oldkeep,  $newkeep);
   unlink($IndexFile)  if ($UseIndex);

UseModWiki | WikiPatches | RecentChanges | Preferences
Edit text of this page | View other revisions | Search MetaWiki
Last edited April 14, 2003 9:28 am by iota.wwwcache.cam.ac.uk (diff)
Search: