282 lines
10 KiB
Perl
282 lines
10 KiB
Perl
## @file
|
|
# This file contains the implementation of the Module loading class.
|
|
#
|
|
# @author Chris Page <chris@starforge.co.uk>
|
|
# @version 0.3
|
|
# @date 13 Sept 2011
|
|
# @copy 2011, Chris Page <chris@starforge.co.uk>
|
|
#
|
|
# 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/>.
|
|
|
|
## @class
|
|
# A class to simplify runtime loading of plugin modules. This class provides
|
|
# methods to allow the various block plugin modules to be loaded on demand
|
|
# during script execution.
|
|
package Modules;
|
|
|
|
#use lib qw(/home/webperl); # modules needed for utils, blocks needed for plugins
|
|
use DBI;
|
|
use Logging qw(die_log);
|
|
use strict;
|
|
|
|
use vars qw{$VERSION $errstr};
|
|
|
|
BEGIN {
|
|
$VERSION = 0.1;
|
|
$errstr = '';
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Creation
|
|
|
|
## @cmethod $ new(%args)
|
|
# Create a new Modules object. This will create an object that provides functions
|
|
# to create block modules on the fly.
|
|
# cgi - The CGI object to access parameters and cookies through.
|
|
# dbh - The database handle to use for queries.
|
|
# settings - The system settings object
|
|
# template - The system template object
|
|
# session - The session object
|
|
# blockdir - The directory containing blocks.
|
|
# @param args A hash of key, value pairs to initialise the object with.
|
|
# @return A new Modules object, or undef if a problem occured.
|
|
sub new {
|
|
my $invocant = shift;
|
|
my $class = ref($invocant) || $invocant;
|
|
my $self = {
|
|
cgi => undef,
|
|
dbh => undef,
|
|
phpbb => undef,
|
|
settings => undef,
|
|
template => undef,
|
|
session => undef,
|
|
blockdir => undef,
|
|
@_,
|
|
};
|
|
|
|
# If we get here and still don't have a database connection, we need to fall over
|
|
return set_error("No database connection available.") if(!$self -> {"dbh"});
|
|
|
|
# Check we also have a cgi object to play with
|
|
return set_error("No CGI object available.") if(!$self -> {"cgi"});
|
|
|
|
# Aaand settings....
|
|
return set_error("No settings object available.") if(!$self -> {"settings"});
|
|
|
|
# ... finally, template
|
|
return set_error("No template object available.") if(!$self -> {"template"});
|
|
|
|
# update @INC if needed
|
|
unshift(@INC, $self -> {"blockdir"}) if($self -> {"blockdir"});
|
|
|
|
my $obj = bless $self, $class;
|
|
|
|
# Set the template object's module reference
|
|
$obj -> {"template"} -> set_module_obj($obj);
|
|
|
|
# and we're done
|
|
return $obj
|
|
}
|
|
|
|
|
|
# ============================================================================
|
|
# Loading support
|
|
#
|
|
|
|
## @method $ new_module_byblockid($blockid)
|
|
# Given a block id, create an instance of the module that implements that block. This
|
|
# will look in the blocks table to obtain the module id that implements the block, and
|
|
# then create an instance of that module.
|
|
#
|
|
# @param blockid The id of the block to generate an instance for.
|
|
# @return An instance of the module, or undef on error.
|
|
sub new_module_byblockid {
|
|
my $self = shift;
|
|
my $blockid = shift;
|
|
|
|
my $sth = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"settings"} -> {"database"} -> {"blocks"}."
|
|
WHERE id = ?");
|
|
$sth -> execute($blockid) or
|
|
die_log($self -> {"cgi"} -> remote_host(), "new_module_byblockid: Unable to execute query: ". $self -> {"dbh"} -> errstr);
|
|
|
|
my $modrow = $sth -> fetchrow_hashref();
|
|
|
|
# If we have a block row, return an instance of the module for it
|
|
return $self -> new_module_byid($modrow -> {"module_id"},
|
|
$modrow -> {"args"})
|
|
if($modrow);
|
|
|
|
return undef;
|
|
}
|
|
|
|
|
|
## @method $ new_module_byname($modname, $argument)
|
|
# Load a module based on its name, checking against the database to obtain the real
|
|
# module name, and whether the module is active. Returns a new object of the module
|
|
# on success, undef if the module is disabled or if there's a problem.
|
|
#
|
|
# @param modname The name of the module to load.
|
|
# @param argument Argument to pass to the module constructor.
|
|
# @return An instance of the module, or undef on error.
|
|
sub new_module_byname {
|
|
my $self = shift;
|
|
my $modname = shift;
|
|
my $argument = shift;
|
|
|
|
return $self -> _new_module_internal("WHERE name LIKE ?",
|
|
$modname,
|
|
$argument);
|
|
}
|
|
|
|
|
|
## @method $ new_module_byid($modid, $argument)
|
|
# Load a module based on its id, checking against the database to obtain the real
|
|
# module name, and whether the module is active. Returns a new object of the module
|
|
# on success, undef if the module is disabled or if there's a problem.
|
|
#
|
|
# @param modid The id of the module to load.
|
|
# @param argument Argument to pass to the module constructor.
|
|
# @return An instance of the module, or undef on error.
|
|
sub new_module_byid {
|
|
my $self = shift;
|
|
my $modid = shift;
|
|
my $argument = shift;
|
|
|
|
return $self -> _new_module_internal("WHERE module_id = ?",
|
|
$modid,
|
|
$argument);
|
|
}
|
|
|
|
|
|
## @method $ _new_module_internal($where, $argument, $modargs)
|
|
# Create an instance of a module. This uses the where and argument parameters as part of a database
|
|
# query to determine what the actual name of the module is, and then load and instantiate it.
|
|
#
|
|
# @param where The WHERE clause to add to the module select query.
|
|
# @param argument The argument for the select query.
|
|
# @param modargs The argument to pass to the module.
|
|
# @return A new object, or undef if a problem occured or the module is disabled.
|
|
sub _new_module_internal {
|
|
my $self = shift;
|
|
my $where = shift;
|
|
my $argument = shift;
|
|
my $modarg = shift;
|
|
|
|
my $modh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"settings"} -> {"database"} -> {"modules"}." $where");
|
|
$modh -> execute($argument)
|
|
or die_log($self -> {"cgi"} -> remote_host(), "Unable to execute module resolve query: ".$self -> {"dbh"} -> errstr);
|
|
|
|
my $modrow = $modh -> fetchrow_hashref();
|
|
|
|
# bomb if the mofule record is not found, or the module is inactive
|
|
return set_error("Unable to locate module $argument using $where, or module is inactive.") if(!$modrow || !$modrow -> {"active"});
|
|
|
|
my $name = $modrow -> {"perl_module"};
|
|
no strict "refs"; # must disable strict references to allow named module loading.
|
|
eval "require $name";
|
|
|
|
# Set up the module argument hash...
|
|
my %args = ( "modid" => $modrow -> {"id"},
|
|
"args" => $modarg,
|
|
"module" => $self,
|
|
);
|
|
foreach my $key (keys(%{$self})) {
|
|
$args{$key} = $self -> {$key} if!(defined($args{$key}));
|
|
}
|
|
|
|
my $modobj = $name -> new(%args)
|
|
or set_error("Unable to load module: ".$Block::errstr);
|
|
use strict;
|
|
|
|
return $modobj;
|
|
}
|
|
|
|
|
|
## @method $ build_sidebar($side, $page)
|
|
# Generate the contents of a sidebar. This will load the modules listed as appearing on the specified
|
|
# side of the page, and call on their block_display() functions, concatenating the results into one
|
|
# large string.
|
|
#
|
|
# @param side The side to generate the blocks for. Must be 'left' or 'right'.
|
|
# @param page An optional page ID (corresponding to the module currently shown on in the core of the
|
|
# page) that can be used to filter the blocks shown in the sidebar.
|
|
# @return A string containing the sidebar HTML, or undef if there was an error.
|
|
sub build_sidebar {
|
|
my $self = shift;
|
|
my $side = shift;
|
|
my $page = shift || 0;
|
|
|
|
# Bomb with an error is side is not valid
|
|
return set_error("build_sidebar called with an illegal value for side: $side")
|
|
unless($side eq "left" || $side eq "right");
|
|
|
|
# If a page is specified, we need to filter on it, or zero. OTherwise we'll be filtering on just 0
|
|
my $filter = $page ? "(filter = ? OR filter = 0)" : "filter = ?";
|
|
|
|
# Pull out blocks that match the specified side type, filtering them so that only 'always show' or blocks
|
|
# that show on the current page are shown.
|
|
my $sth = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"settings"} -> {"database"} -> {"blocks"}."
|
|
WHERE TYPE = ? AND $filter
|
|
ORDER BY position");
|
|
$sth -> execute($side, $page) or
|
|
die_log($self -> {"cgi"} -> remote_host(), "build_sidebar: Unable to execute query: ". $self -> {"dbh"} -> errstr);
|
|
|
|
my $result = "";
|
|
while(my $row = $sth -> fetchrow_hashref()) {
|
|
# Load the block module
|
|
my $headerobj = $self -> new_module_byid($row -> {"module_id"},
|
|
$row -> {"args"});
|
|
|
|
# If we have an object, ask it do generate its block display.
|
|
$result .= $headerobj -> block_display() if($headerobj);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
# ============================================================================
|
|
# Block identification support
|
|
|
|
## @method $ get_block_id($blockname)
|
|
# Obtain the id of a block given its unique name. This will, hopefully, allow templates
|
|
# to include references to modules without hard-coding IDs (ironically, hard coding
|
|
# the module names seems so much less nasty... weird...)
|
|
#
|
|
# @param blockname The name of the block to obtain the id for.
|
|
# @return The block id, or undef if the name can not be located.
|
|
sub get_block_id {
|
|
my $self = shift;
|
|
my $blockname = shift;
|
|
|
|
my $blockh = $self -> {"dbh"} -> prepare("SELECT id FROM ".$self -> {"settings"} -> {"database"} -> {"blocks"}."
|
|
WHERE name LIKE ?");
|
|
$blockh -> execute($blockname)
|
|
or die_log($self -> {"cgi"} -> remote_host(), "get_block_id: Unable to execute query: ". $self -> {"dbh"} -> errstr);
|
|
|
|
# Do we have the block?
|
|
my $blockr = $blockh -> fetchrow_arrayref();
|
|
|
|
# If we have the block id return it, otherwise return undef.
|
|
return $blockr -> [0] if($blockr);
|
|
return undef;
|
|
}
|
|
|
|
# ============================================================================
|
|
# Error functions
|
|
|
|
sub set_error { $errstr = shift; return undef; }
|
|
|
|
1;
|