BEGIN {
eval "require CGI::Simple; CGI::Simple->import;"
if ($@) {
eval "require CGI; CGI->import";
die ($@) if $@;
$main::q = CGI->new;
}
else {
$main::q = CGI::Simple->new;
}
}
####
use Module::prefer 'prefer';
# use CGI::Simple if possible, CGI otherwise
my $CGI = prefer(
[
'CGI::Simple' => [1],
'CGI' => [1],
],
);
####
$chosen = prefer( \@modspec, @default_args );
####
[ 'Module::Name' => [ $use_default_args, @special_args ], ... ]
####
# 'bar' in default, special args for Module::A
$chosen = prefer (
[
'Module::A' => [1,'foo'], # use Module::A ('bar','foo');
'Module::B' => [1], # use Module::B ('bar');
],
'bar',
);
####
# 'foo' and 'bar' in default, Module::B does it's own thing
$chosen = prefer (
[
'Module::A' => [1], # use Module::A ('bar','foo');
'Module::B' => [0,'bar'], # use Module::B ('bar') - ignore defaults!
],
'foo', 'bar',
);
####
package Module::Prefer;
use strict;
use warnings;
use base 'Exporter';
our @EXPORT_OK = qw'prefer';
sub prefer {
# prefer ([ module_name => [ $use_defaults, @param ], ... ], @default_args);
my $modspec = shift;
my $caller = caller;
my $module;
my @err;
if (@$modspec % 2 != 0) { die "need a hash-like ARRAYref in first argument" }
for (my $i = 0; $i <= @$modspec/2; $i+=2) {
eval 'require '.$modspec->[$i].';';
if ($@) { push @err, [ $modspec->[$i], $@ ]; next; }
$module = $i;
last;
}
if (defined $module && $$modspec[$module]->can('import')) {
# Required one of the modules!
my $call = "package $caller; ".$$modspec[$module]."->import";
my $param = $modspec->[$module+1];
# mod_name => undef same as mod_name => [0]
unless (defined $param && @$param) { $param = [0] }
my $use_defaults = shift @$param;
if ($use_defaults) {
# we should use defaults, if there are any
if (@_ || @$param) {
# only add things if we either have some defaults, or some specials
$call .= '('.(@_ ? "\@_," : '').(@$param ? "\@\$param" : '');
$call =~ s/,$//;
$call .= ')';
}
}
elsif (@$param) {
# only use the specials, if any exist
$call .= "(\@\$param)";
}
$call .= ';';
eval "$call";
die ($@) if $@;
}
else {
# couldn't require any module;
die "Failed to require any of the modules:\n\t"
.join("\n\t",map { sprintf('%20s => %s', @$_) } @err)
."\n";
}
return $modspec->[$module]; #return name of module used
}
1;
__END__
=head1 NAME
This document describes Module::Prefer
=head1 SYNOPSIS
Allows a package to effectively C