[Home]WikiPatches/BackLinks

UseModWiki | WikiPatches | RecentChanges | Preferences

C2-style MeatBall:BackLinking a la Wiki:ReverseLink.

Two important points:

That being said, it works for me. I much prefer the title to do backlinking. Maybe because I grew up on C2's wiki. I added another patch /DefaultSearch to partially compensate for replacing the title full-search. /DefaultSearch puts the title into the search text so all you have to do is click in it and hit enter, like in Wiki:FindPage (when clicked from an existing page, such as Wiki:FindPage&value=FrontPage).

This patch does two things.

  1. It defines a new parameter for the search action called 'back'. Setting back=1 does a backlink search instead of a full text and title search.
  2. It defines a new configuration variable $BackLinks?, which changes the title search to use the back parameter. If $BackLinks? = 1, the title will use back=1. If $BackLinks? = 0, the title does the standard search.

-- Wiki:RobHarwood


Going from top to bottom...

We need a new configuration variable. Instead of adding to the huge list, I just added a new line right after the list.

 # Configuration/constant variables:
 use vars qw(@RcDays? @HtmlPairs @HtmlSingle?
   $TempDir? $LockDir? $DataDir $HtmlDir? $UserDir $KeepDir? $PageDir
   ...
   $UserGotoBar);
 # PATCH: Backlinks
 use vars qw($BackLinks?);
 # /PATCH: Backlinks

Add the default value to the configuration section:
 $FreeUpper   = 1;       # 1 = force upper case,   0 = do not force case
 $FastGlob?    = 1;       # 1 = new faster code,    0 = old compatible code
 # PATCH: Backlinks
 $BackLinks?   = 1;       # 1 = back-links only,    0 = full search for title
 # /PATCH: Backlinks

Possible suggestion: Set the default value in wiki.pl to 0 and override that with the configuration file. Since full-search is traditional, this might make more sense, even though backlinks are better ;-)


We need to change the URL for the title, so we do that by replacing GetSearchLink:

Old version:

 sub GetSearchLink {
   my ($id) = @_;
   my $name = $id;
   $id =~ s|.+/|/|;   # Subpage match: search for just /SubName?
   if ($FreeLinks) {
     $name =~ s/_/ /g;  # Display with spaces
     $id =~ s/_/+/g;    # Search for url-escaped spaces
   }
   return &ScriptLink("search=$id", $name);
 }

Becomes:

 # PATCH: Backlinks
 sub GetTitleLink? {
   my ($id) = @_;
   my $name = $id;
   $id =~ s|.+/|/|;   # Subpage match: search for just /SubName?
   if ($FreeLinks) {
     $name =~ s/_/ /g;  # Display with spaces
     $id =~ s/_/+/g;    # Search for url-escaped spaces
   }
   if ($BackLinks?) {
     return &GetBackLink?($id, $name);
   }else{
     return &GetSearchLink($id, $name);
   }
 }

 sub GetSearchLink {
   my ($id, $name) = @_;
   return &ScriptLink("search=$id", $name);
 }

 sub GetBackLink? {
   my ($id, $name) = @_;
   return &ScriptLink("search=$id&back=1", $name);
 }
 # /PATCH: Backlinks

In GetHeader, change the call to GetSearchLink to a call to GetTitleLink?:
  if ($id ne '') {
    $result .= $q->h1($header . &GetSearchLink ($id));
  } else {
    $result .= $q->h1($header . $title);
  }
Becomes:
  if ($id ne '') {
    # PATCH: Backlinks
    $result .= $q->h1($header . &GetTitleLink?($id));
    # /PATCH: Backlinks
  } else {
    $result .= $q->h1($header . $title);
  }

In DoOtherRequest, we need to respond to the new 'back' parameter. Near the end of the sub:
  if (($search ne "") || (&GetParam("dosearch", "") ne "")) {
    &DoSearch?($search);
    return;
  }
Becomes:
  if (($search ne "") || (&GetParam("dosearch", "") ne "")) {
    # PATCH: Backlinks
    if (&GetParam("back", 0)) {
      &DoBackLinks($search)
    }else{
      &DoSearch?($search);
    }
    # /PATCH: Backlinks
    return;
  }

Finally, we need to add the meat. Two new subs are added. DoBackLinks is based on DoSearch?, and GetBackLinkList? is based on GetFullLinkList. This was the tricky part. The link action had almost what I wanted, but back links feel like a search, so the idea was to merge the two features. It doesn't really matter where these go, but I put them just before DoSearch?.
 # PATCH: Backlinks
 sub DoBackLinks {
   my ($string) = @_;

   if ($string eq '') {
     &DoIndex?();
     return;
   }
   print &GetHeader(, &QuoteHtml?(Ts('BackLinks? for: %s', $string)), );
   print '
'; &PrintPageList?(&GetBackLinkList?($string)); print &GetCommonFooter(); }

 sub GetBackLinkList? {
   my ($name, $link, $search);
   my (@found, @links, @pglist); 

   $search = &GetParam("search", "");
   $search =~ s/ /_/g;

   @pglist = &AllPagesList();
   PAGE: foreach $name (@pglist) {
     @links = &GetPageLinks($name, 1, 0, 0);
     foreach $link (@links) {
       $link =~ s/\.//;
       if ($link eq $search) {
         push(@found, $name);
         next PAGE;
       }
     }
   }
   @found = sort(@found);
   return @found;
 }
 # /PATCH: Backlinks



Easier patch

Consider UseMod:search=ModWiki vs. UseMod:search=\bModWiki\b vs. UseMod:search=\b(?-i)ModWiki\b. This gives us a smaller patch that will be as fast as searching.

 sub GetBackLinksSearchLink {
   my ($id) = @_;
   my $name = $id;

   $id =~ s|.+/|/|;   # Subpage match: search for just /SubName
   if ($FreeLinks) {
     $name =~ s/_/ /g;  # Display with spaces
     $id =~ s/_/+/g;    # Search for url-escaped spaces
   }
   return &ScriptLink("back=$id", $name);
 }

 sub GetHeader {
    ...
    if ($id ne '') {
     $result .= $q->h1($header . &GetBackLinksSearchLink($id));
    } else {
      $result .= $q->h1($header . $title);
    }
    ...
 }

 sub DoOtherRequest {
   ...
   $search = &GetParam("search", "");
   if (($search ne "") || (&GetParam("dosearch", "") ne "")) {
     &DoSearch($search);
     return;
   } else {
     $search = &GetParam("back","");
     if( $search ne "" ) {
       &DoBackLinks($search);
       return;
     }
   }
   ...
 }

Place directly after sub DoSearch?...

 sub DoBackLinks {
   my ($string) = @_;
 
   if (&ValidId($string) ne '') {
     &DoIndex();
     return;
   }
   print &GetHeader('', &QuoteHtml(Ts('Backlinks for: %s', $string)), '');
   print '<br>';
   &PrintPageList(&SearchTitleAndBody("\\b(?-i)$string\\b"));
   print &GetCommonFooter();
 }

-- SunirShah

Moving discussion to MeatBall:BackLink...

For 1.0, I'm going to go with the easier patch for now simply due to computation overhead concerns. Note that false positives for links like [[the]] are resolvable by just upgrading the easy patch to be sensitive to the FreeLinkPattern?. e.g. /\[\[the\]\]/gs However, I encourage people to apply the better patch to their own scripts. If we can optimize this search without consuming a very large amount of disk space, we should definitely do it. -- SunirShah


## modify it.
sub DoOtherRequest {
....
	$search = &GetParam("reverse", "");
	if ($search ne "") {
#		&DoReverse($search);
		&DoGetBackSearchLink($search);
		return;
	}
}

## add new codes.
sub DoGetBackSearchLink {
	my ($id) = @_;
	my @x;
	my @split_text;
	my ($name, $mainid, $subid);
	my $result;

	$name = $id;
	if ($FreeLinks) {
		$name =~ s/_/ /g;  # Display with spaces
		$id =~ s/_/+/g;    # Search for url-escaped spaces
	}
	($mainid, $subid) = split(/\//,$name);
	if ($id eq '') {
		&DoIndex();
		return;
	}
	print &GetHeader('', &QuoteHtml(Ts('Search for: %s', $name)), '');
	print '<br>';
	@x = &SearchBack($mainid, $subid);
	@x = sort @x;

	&PrintPageList(@x);
	print &GetCommonFooter();
}

sub SearchBack {
	my ($mainid, $subid) = @_;
	my ($name, $temp_name, $temp_sub, @found);
	foreach $name (&AllPagesList()) {
		($temp_name, $temp_sub) = split (/\//, $name);
		if (($name ne $mainid) && ($mainid ne $temp_name)) {
			&OpenPage($name);
			&OpenDefaultText();

			$Text{'text'} =~ s/((.|\n)*?\<\/nowiki>)|($UrlPattern)|(<html>(.|\n)*?\<\/html>)|(<pre>(.|\n)*?\<\/pre>)//gi;

			if ($subid ne "") {
				if ($mainid =~ /$LinkPattern/) {
					if (($subid =~ /$LinkPattern/)
						&& ($Text{'text'} =~ /$mainid\/$subid[^\/]/)) {
						push(@found, $name);
					} elsif ($Text{'text'} =~ /\[\[$mainid\/$subid\]\]/) {
						push(@found, $name);
					}
				} else {
					if ($Text{'text'} =~ /\[\[$mainid\/$subid\]\]/) {
						push(@found, $name);
					}
				}
			} else {
				if ($mainid =~ /$LinkPattern/) {
					if ($Text{'text'} =~ /$mainid[^\/]/) {
						push(@found, $name);
					}
				} else {
					if ($Text{'text'} =~ /\[\[$mainid\]\]/) {
						push(@found, $name);
					}
				}
			}
		} elsif (($name eq $mainid) || ($mainid eq $temp_name)) {
			&OpenPage($name);
			&OpenDefaultText();
			if ($subid ne "") {
				if ($temp_name =~ /$LinkPattern/) {
					if (($subid =~ /$LinkPattern/)
						&& (($Text{'text'} =~ /$mainid\/$subid[^\/]/)
						|| ($Text{'text'} =~ /\/$subid[^\/]/))) {
						push(@found, $name);
					} else {
						if (($Text{'text'} =~ /\[\[$mainid\/$subid\]\]/)
						|| ($Text{'text'} =~ /\[\[\/$subid\]\]/)) {
							push(@found, $name);
						}
					}
				} else {
					if ($subid =~ /$LinkPattern/) {
						if ($Text{'text'} =~ /\/$subid[^\/]/) {
							push (@found, $name);
						}
					} else {
						if (($Text{'text'} =~ /\[\[$mainid\/$subid\]\]/)
							|| ($Text{'text'} =~ /\[\[\/$subid\]\]/)) {
							push(@found, $name);
						}
					}
				}
			} else {
				if ($mainid =~ /$LinkPattern/) {
					if ($Text{'text'} =~ /$mainid/) {
						push(@found, $name);
					}
				} else {
					if ($Text{'text'} =~ /\[\[$mainid\]\]/) {
						push(@found, $name);
					}
				}
			}

		}
	}
	return @found;
}
</pre>

Im not a Perl programmer, I cannot resolve like <nowiki>[http://bla.bla "anywikilink"].

and, maybe "regular backlink patch" has same problem too.

please modify it. - anonymous

----
I remodified. If you decide to use below regular-expression routine, you can get more correct result but too slow nor you can get very fast but correctless result.(maybe include that such as WikiLinks)
<pre>
sub SearchBack {
....
## rate vs quality
$Text{'text'} =~ s/(<nowiki>(.|\n)*?\<\/nowiki>)|($UrlPattern)|(<html>(.|\n)*?\<\/html>)|(<pre>(.|\n)*?\<\/pre>)//gi;
}
....
- same anonymous

UseModWiki | WikiPatches | RecentChanges | Preferences
Edit text of this page | View other revisions | Search MetaWiki
Last edited February 6, 2003 5:54 pm by 218.145.25.107 (diff)
Search: