forked from github/kensanata.oddmuse
There were some modules that did not offer "or (at your option) any later version" in their license and these had to be left alone. This should solve the incorrect FSF address issue #4 on GitHub.
159 lines
5.3 KiB
Perl
159 lines
5.3 KiB
Perl
# Copyright (C) 2006 Charles Mauch <cmauch@gmail.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Grab MLDBM at http://search.cpan.org/dist/MLDBM/lib/MLDBM.pm
|
|
# ie: http://search.cpan.org/CPAN/authors/id/C/CH/CHAMAS/MLDBM-2.01.tar.gz
|
|
|
|
use strict;
|
|
use v5.10;
|
|
|
|
use Fcntl;
|
|
use MLDBM qw( DB_File Storable );
|
|
AddModuleDescription('backlinkage.pl', 'Inline Backlinks');
|
|
|
|
our ($q, %Action, %Page, @MyAdminCode, $DataDir, $LinkPattern);
|
|
|
|
my $debug=1; # Set Text Output Verbosity when compiling
|
|
my $backfile = $DataDir . '/backlinks.db'; # Where data lives
|
|
|
|
# Stuff buildback action into admin menu.
|
|
push(@MyAdminCode, \&BacklinksMenu);
|
|
sub BacklinksMenu {
|
|
my ($id, $menuref, $restref) = @_;
|
|
push(@$menuref,
|
|
ScriptLink('action=buildback', T('Rebuild BackLink database'))
|
|
);
|
|
}
|
|
|
|
# Build Database, called my oddmuse uri action
|
|
$Action{buildback} = \&BuildBacklinkDatabase;
|
|
sub BuildBacklinkDatabase {
|
|
print GetHttpHeader('text/plain');
|
|
Unlink($backfile); # Remove old database
|
|
tie my %backhash, 'MLDBM', encode_utf8($backfile) or die "Cannot open file $backfile $!\n";
|
|
log1("Starting Database Store Process ... please wait\n\n");
|
|
|
|
foreach my $name (AllPagesList()) {
|
|
log3("Opening $name ... \n");
|
|
OpenPage($name);
|
|
my @backlinks = BacklinkProcess($name,$Page{text});
|
|
|
|
my $hash = $backhash{$name}; # Declare Hash Ref
|
|
my $backlinkcount = 0; # Used to create link key
|
|
foreach my $link (@backlinks) {
|
|
$backlinkcount++;
|
|
$hash->{'link' . $backlinkcount} = $link;
|
|
}
|
|
log2("$backlinkcount Links found in $name\n") if $backlinkcount;
|
|
$backhash{$name} = $hash; # Store Hash data in HoH
|
|
}
|
|
|
|
if ($debug >= 3) {
|
|
log4("Printing dump of USABLE Data we stored, sorted and neat\n");
|
|
for my $source (sort keys %backhash) {
|
|
for my $role (sort keys %{ $backhash{$source} }) {
|
|
log4("\n\$HoH\{\'$source\'\}\{\'$role\'\} = \"$backhash{$source}{$role}\"");
|
|
}
|
|
}
|
|
}
|
|
untie %backhash;
|
|
log1("Done. \n");
|
|
|
|
}
|
|
|
|
# Used to filter though page text to find links, ensure there is only 1 link per destination
|
|
# per page, and then return an array of backlinks.
|
|
sub BacklinkProcess {
|
|
my $name = $_[0];
|
|
my $text = $_[1];
|
|
my %seen = ();
|
|
my @backlinks;
|
|
my @wikilinks = ($text =~ m/$LinkPattern/g);
|
|
|
|
foreach my $links (@wikilinks) {
|
|
my ($class, $resolved, $title, $exists) = ResolveId($links);
|
|
if ($exists) {
|
|
push (@backlinks,$resolved) unless (($seen{$resolved}++) or ($resolved eq $name));
|
|
}
|
|
}
|
|
return @backlinks;
|
|
}
|
|
|
|
# Function used by user to display backlinks in proper html.
|
|
sub GetBackLink {
|
|
my (@backlinks, @unpopped, @alldone);
|
|
my $id = $_[0];
|
|
|
|
our ($BacklinkBanned);
|
|
$BacklinkBanned = "HomePage|ScratchPad" if !$BacklinkBanned;
|
|
tie my %backhash, 'MLDBM', encode_utf8($backfile), O_CREAT|O_RDWR, oct(644) or die "Cannot open file $backfile $!\n";
|
|
|
|
# Search database for matches
|
|
while ( my ($source, $hashes) = each %backhash ) {
|
|
while ( my ($key, $value) = each %$hashes ) {
|
|
if ($id =~ /$value/) {
|
|
push (@backlinks, $source);
|
|
}
|
|
}
|
|
}
|
|
untie %backhash;
|
|
|
|
# Render backlinks into html links
|
|
foreach my $backlink (@backlinks) {
|
|
my ($class, $resolved, $title, $exists) = ResolveId($backlink);
|
|
if (($resolved ne $id) && ($resolved !~ /^($BacklinkBanned)$/)) {
|
|
push(@unpopped, ScriptLink(UrlEncode($resolved), $resolved, $class . ' backlink', undef, Ts('Internal Page: %s', $resolved)));
|
|
}
|
|
}
|
|
|
|
my $arraycount = @unpopped;
|
|
return if !$arraycount; # Dont bother with the rest if empty results
|
|
|
|
# Pop and Push data to make it look good (no trailing commas)
|
|
my $temp = pop(@unpopped);
|
|
foreach my $backlink (@unpopped) {
|
|
push(@alldone, $backlink . ", ");
|
|
}
|
|
push(@alldone, $temp); # And push last entry back in
|
|
print $q->div({-class=>'docmeta'}, $q->h2(T('Pages that link to this page')), @alldone);
|
|
}
|
|
|
|
# Debug functions, all expect a string as input, and print it if the debug level is high enough.
|
|
# This allows for increasing levels of verbosity for runtime commenting.
|
|
|
|
sub log1 { # Very little info (only outputs if error - great for scripts)
|
|
return if (($debug < 1) or ($debug == 4));
|
|
my $msg = shift;
|
|
print "$msg";
|
|
}
|
|
|
|
sub log2 { # Info Messages
|
|
return if (($debug < 2) or ($debug == 4));
|
|
my $msg = shift;
|
|
print "$msg";
|
|
}
|
|
|
|
sub log3 { # More Info for the curious
|
|
return if (($debug < 3) or ($debug == 4));
|
|
my $msg = shift;
|
|
print "$msg";
|
|
}
|
|
|
|
sub log4 { # Dump all sorts of garbage (usally data structures)
|
|
return if ($debug < 4);
|
|
my $msg = shift;
|
|
print "$msg";
|
|
}
|