Files
oddmuse/modules/backlinkage.pl

159 lines
5.3 KiB
Perl
Raw Normal View History

2006-09-12 17:25:30 +00:00
# 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
2006-09-12 17:25:30 +00:00
# (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/>.
2006-09-12 17:25:30 +00:00
# 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;
2006-09-12 17:25:30 +00:00
use MLDBM qw( DB_File Storable );
AddModuleDescription('backlinkage.pl', 'Inline Backlinks');
2006-09-12 17:25:30 +00:00
2015-04-10 13:31:28 +03:00
our ($q, %Action, %Page, @MyAdminCode, $DataDir, $LinkPattern);
my $debug=1; # Set Text Output Verbosity when compiling
my $backfile = $DataDir . '/backlinks.db'; # Where data lives
2006-09-12 17:25:30 +00:00
# Stuff buildback action into admin menu.
2006-09-12 17:25:30 +00:00
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
2006-09-12 17:25:30 +00:00
$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");
2006-09-12 17:25:30 +00:00
foreach my $name (AllPagesList()) {
log3("Opening $name ... \n");
2006-09-12 17:25:30 +00:00
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}\"");
}
2006-09-12 17:25:30 +00:00
}
}
untie %backhash;
log1("Done. \n");
2006-09-12 17:25:30 +00:00
}
# 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.
2006-09-12 17:25:30 +00:00
sub GetBackLink {
my (@backlinks, @unpopped, @alldone);
2006-09-12 17:25:30 +00:00
my $id = $_[0];
2015-04-10 13:31:28 +03:00
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";
2006-09-12 17:25:30 +00:00
# Search database for matches
while ( my ($source, $hashes) = each %backhash ) {
while ( my ($key, $value) = each %$hashes ) {
2006-09-12 17:25:30 +00:00
if ($id =~ /$value/) {
push (@backlinks, $source);
}
}
}
untie %backhash;
# Render backlinks into html links
foreach my $backlink (@backlinks) {
2006-09-12 17:25:30 +00:00
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)));
2006-09-12 17:25:30 +00:00
}
}
2006-09-12 17:25:30 +00:00
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)
2006-09-12 17:25:30 +00:00
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";
}