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 )