Config-Extend-MySQL
view release on metacpan or search on metacpan
lib/Config/Extend/MySQL.pm view on Meta::CPAN
B<Examples>
# read MySQL config using Config::IniFiles
my $config = Config::Extend::MySQL->new({ from => $file, using => "Config::IniFiles" });
# $config ISA Config::Extend::MySQL, ISA Config::IniFiles
# read MySQL config using Config::Tiny
my $config = Config::Extend::MySQL->new({ from => $file, using => "Config::Tiny" });
# $config ISA Config::Extend::MySQL, ISA Config::Tiny
=cut
sub new {
my ($class, $args) = @_;
croak "error: Arguments must be given as a hash reference"
unless ref $args eq "HASH";
croak "error: Missing required argument 'from'"
unless exists $args->{from};
croak "error: Empty argument 'from'"
unless defined $args->{from} and length $args->{from};
# check that the file exists and contains something
my $file = $args->{from};
croak "fatal: No such file '$file'" unless -f $file;
carp "warning: File '$file' is empty" and return if -s _ == 0;
# read the file and resolve the MySQL-isms
my $content = __read_config(file => $file);
my $fh = undef;
if (USE_IO_STRING) {
require IO::String;
$fh = IO::String->new(\$content);
}
else {
open($fh, "<", \$content)
or croak "fatal: Can't read in-memory buffer: $!";
}
# create the object using the given Config:: module
my $backend = defined $args->{using} ? $args->{using} : "Config::Tiny";
$backend->require or croak "fatal: Can't load module $args->{using}: $@";
@Config::Extend::MySQL::ISA = ($backend);
my $self = __new_from($backend, $fh, \$content)
or croak "fatal: Backend module failed to parse '$file'";
bless $self, $class;
# store the names to skip when reading directories
my @skip_names = qw(. .. CVS);
@skip{@skip_names} = (1) x @skip_names;
return $self
}
sub __new_from {
my ($backend, $fh, $content_r) = @_;
if ($backend eq "Config::IniFiles") {
local $SIG{__WARN__} = sub {}; # avoid a warning from stat() on this $fh
local *IO::String::FILENO = sub { -1 };
return Config::IniFiles->new(-file => $fh)
}
elsif ($backend eq "Config::Format::Ini") {
local $SIG{__WARN__} = sub {}; # avoid "slurp redefined" warning
local *Config::Format::Ini::slurp = sub { return ${$_[0]} };
return Config::Format::Ini::read_ini($content_r)
}
elsif ($backend eq "Config::Simple") {
# can't get Config::Simple to play nicely because it want to
# seek() and flock() the filehandle. seek() works on in-memory
# filehandles, but flock() doesn't, and can't be faked/replaced
#my $obj = Config::Simple->new(syntax => "ini");
#$obj->{_DATA} = $obj->parse_ini_file($fh);
#return $obj
return Config::Simple->new($fh)
}
elsif ($backend eq "Config::Tiny" or $backend eq "Config::INI::Reader") {
return $backend->read_string($$content_r)
}
}
sub __read_config {
my ($what, $path) = @_;
my $content = "";
my $opts = {}; #{ err_mode => "quiet" };
if ($what eq "file") {
my $base_dir = dirname($path);
$content = read_file($opts, $path);
# handle single param (without value)
$content =~ s{^ \s* (\w+ (?:-\w+)* ) \s* $}{$1 = yes}xgm;
# handle includes
$content =~ s{^ \s* !include(dir)? \s+ (.+) \s* $}
{ __read_config($1 || "file", rel2abs($2, $base_dir)) }xgme;
}
elsif ($what eq "dir") {
opendir(my $dirh, $path) or return "";
while (my $file = readdir($dirh)) {
# skip invisible files and directories we shouldn't
# recurse into, like ../ or CVS/
next if $skip{$file} or index($file, ".") == 0;
my $filepath = catfile($path, $file);
if (-f $filepath) {
$content .= __read_config(file => $filepath)
}
elsif (-d _) {
$content .= __read_config(dir => $filepath)
}
}
closedir($dirh);
( run in 0.787 second using v1.01-cache-2.11-cpan-99c4e6809bf )