Config-Abstraction
view release on metacpan or search on metacpan
lib/Config/Abstraction.pm view on Meta::CPAN
File::Spec->catdir($ENV{'DOCUMENT_ROOT'}, 'config');
}
if(my $dir = $ENV{'CONFIG_DIR'}) {
push @{$params->{'config_dirs'}}, $dir;
} else {
push @{$params->{'config_dirs'}}, 'conf', 'config';
}
}
}
my $self = bless {
sep_char => '.',
%{$params->{defaults} ? $params->{defaults} : $params},
env_prefix => $params->{env_prefix} || 'APP_',
config => {},
}, $class;
if(my $logger = $self->{'logger'}) {
if(!Scalar::Util::blessed($logger)) {
# Don't call $self->_load_driver('Log::Abstraction') as it can make a call to logger, which is yet to be set up
eval "require Log::Abstraction";
if($@) {
carp(ref($self), ": Log::Abstraction failed to load: $@");
} else {
Log::Abstraction->import();
$self->{'logger'} = Log::Abstraction->new($logger);
if($params->{'level'} && $self->{'logger'}->can('level')) {
$self->{'logger'}->level($params->{'level'});
}
}
}
}
$self->_load_config();
if(my $schema = $params->{'schema'}) {
$self->{'config'} = Params::Validate::Strict::validate_strict(schema => $schema, input => $self->{'config'});
}
if(defined($self->{'config'}) && scalar(keys %{$self->{'config'}})) {
return $self;
}
return undef;
}
# Determine if a value is a plain, unblessed, non-reference scalar
# safe to use in regex/string operations.
# Args: value to test
# Returns: 1 if plain scalar, 0 otherwise
sub _is_plain_scalar
{
my $val = $_[0];
return 0 if !defined($val);
return 0 if Scalar::Util::blessed($val);
return 0 if ref($val);
return 1;
}
sub _load_config
{
if(!UNIVERSAL::isa((caller)[0], __PACKAGE__)) {
Carp::croak('Illegal Operation: This method can only be called by a subclass');
}
my $self = shift;
my %merged;
if($self->{'data'}) {
# The data argument given to 'new' contains defaults that this routine will override
%merged = %{$self->{'data'}};
}
my $logger = $self->{'logger'};
if($logger) {
$logger->trace(ref($self), ' ', __LINE__, ': Entered _load_config');
}
my @dirs = @{$self->{'config_dirs'}};
if($self->{'config_file'} && (scalar(@dirs) > 1)) {
if(File::Spec->file_name_is_absolute($self->{'config_file'})) {
# Handle absolute paths
@dirs = ('');
} else {
# Look in the current directory
push @dirs, File::Spec->curdir();
}
}
for my $dir (@dirs) {
next if(!defined($dir));
if(length($dir) && !-d $dir) {
next;
}
for my $file (qw/base.yaml base.yml base.json base.xml base.ini local.yaml local.yml local.json local.xml local.ini/) {
my $path = File::Spec->catfile($dir, $file);
if($logger) {
$logger->debug(ref($self), ' ', __LINE__, ": Looking for configuration $path");
}
next unless -f $path;
next unless -r $path;
if($logger) {
$logger->debug(ref($self), ' ', __LINE__, ": Loading data from $path");
}
my $data;
# Only load config modules when they are needed
if ($file =~ /\.ya?ml$/) {
$self->_load_driver('YAML::XS', ['LoadFile']);
$data = eval { LoadFile($path) };
if($@) {
if($logger) {
$logger->notice("Failed to load YAML from $path: $@");
} else {
Carp::carp("Failed to load YAML from $path: $@");
}
next;
}
} elsif ($file =~ /\.json$/) {
$data = eval { decode_json(read_file($path)) };
if($@) {
( run in 2.201 seconds using v1.01-cache-2.11-cpan-13bb782fe5a )