X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FPlugin%2FConfigLoader.pm;h=753b76f1bfddc41c699ef7fea8c0dcf9fe13d7c6;hb=cbccabac232b50f90e74b93d680daf213e9c0927;hp=cd8a556659c2975eba168d5306d37af46f64a2b0;hpb=92e263ac7deb34499acc614a12f3c9ecd9875dab;p=catagits%2FCatalyst-Plugin-ConfigLoader.git diff --git a/lib/Catalyst/Plugin/ConfigLoader.pm b/lib/Catalyst/Plugin/ConfigLoader.pm index cd8a556..753b76f 100644 --- a/lib/Catalyst/Plugin/ConfigLoader.pm +++ b/lib/Catalyst/Plugin/ConfigLoader.pm @@ -4,11 +4,11 @@ use strict; use warnings; use Config::Any; -use NEXT; +use MRO::Compat; use Data::Visitor::Callback; use Catalyst::Utils (); -our $VERSION = '0.18'; +our $VERSION = '0.34'; =head1 NAME @@ -17,14 +17,23 @@ Catalyst::Plugin::ConfigLoader - Load config files of various types =head1 SYNOPSIS package MyApp; - + # ConfigLoader should be first in your list so # other plugins can get the config information use Catalyst qw( ConfigLoader ... ); - + # by default myapp.* will be loaded # you can specify a file if you'd like - __PACKAGE__->config( 'Plugin::ConfigLoader' => { file => 'config.yaml' } ); + __PACKAGE__->config( 'Plugin::ConfigLoader' => { file => 'config.yaml' } ); + + In the file, assuming it's in YAML format: + + foo: bar + + Accessible through the context object, or the class itself + + $c->config->{foo} # bar + MyApp->config->{foo} # bar =head1 DESCRIPTION @@ -32,10 +41,21 @@ This module will attempt to load find and load a configuration file of various types. Currently it supports YAML, JSON, XML, INI and Perl formats. Special configuration for a particular driver format can be stored in Cconfig-E{ 'Plugin::ConfigLoader' }-E{ driver }>. +For example, to pass arguments to L, use the following: + + __PACKAGE__->config( 'Plugin::ConfigLoader' => { + driver => { + 'General' => { -LowerCaseNames => 1 } + } + } ); + +See L's C parameter for more information. To support the distinction between development and production environments, this module will also attemp to load a local config (e.g. myapp_local.yaml) -which will override any duplicate settings. +which will override any duplicate settings. See +L +for details on how this is configured. =head1 METHODS @@ -43,37 +63,42 @@ which will override any duplicate settings. This method is automatically called by Catalyst's setup routine. It will attempt to use each plugin and, once a file has been successfully -loaded, set the C section. +loaded, set the C section. =cut sub setup { my $c = shift; my @files = $c->find_files; - my $cfg = Config::Any->load_files( { - files => \@files, - filter => \&_fix_syntax, - use_ext => 1, - driver_args => $c->config->{'Plugin::ConfigLoader'}->{driver} || {}, - } ); + my $cfg = Config::Any->load_files( + { files => \@files, + filter => \&_fix_syntax, + use_ext => 1, + driver_args => $c->config->{ 'Plugin::ConfigLoader' }->{ driver } + || {}, + } + ); + # map the array of hashrefs to a simple hash + my %configs = map { %$_ } @$cfg; # split the responses into normal and local cfg my $local_suffix = $c->get_config_local_suffix; - my( @cfg, @localcfg ); - for( @$cfg ) { - if( ( keys %$_ )[ 0 ] =~ m{ $local_suffix \. }xms ) { - push @localcfg, $_; - } else { - push @cfg, $_; + my ( @main, @locals ); + for ( sort keys %configs ) { + if ( m{$local_suffix\.}ms ) { + push @locals, $_; + } + else { + push @main, $_; } } - + # load all the normal cfgs, then the local cfgs last so they can override # normal cfgs - $c->load_config( $_ ) for @cfg, @localcfg; + $c->load_config( { $_ => $configs{ $_ } } ) for @main, @locals; $c->finalize_config; - $c->NEXT::setup( @_ ); + $c->next::method( @_ ); } =head2 load_config @@ -86,9 +111,9 @@ context object. It does not return a value. sub load_config { my $c = shift; my $ref = shift; - - my( $file, $config ) = each %$ref; - + + my ( $file, $config ) = %$ref; + $c->config( $config ); $c->log->debug( qq(Loaded Config "$file") ) if $c->debug; @@ -106,18 +131,20 @@ L for loading. sub find_files { my $c = shift; - my( $path, $extension ) = $c->get_config_path; + my ( $path, $extension ) = $c->get_config_path; my $suffix = $c->get_config_local_suffix; my @extensions = @{ Config::Any->extensions }; - + my @files; - if ($extension) { - next unless grep { $_ eq $extension } @extensions; - push @files, $path, "${path}_${suffix}"; - } else { + if ( $extension ) { + die "Unable to handle files with the extension '${extension}'" + unless grep { $_ eq $extension } @extensions; + ( my $local = $path ) =~ s{\.$extension}{_$suffix.$extension}; + push @files, $path, $local; + } + else { @files = map { ( "$path.$_", "${path}_${suffix}.$_" ) } @extensions; } - @files; } @@ -135,7 +162,7 @@ The order of preference is specified as: =item * C<$ENV{ CATALYST_CONFIG }> -=item * C<$c-Econfig-E{ 'Plugin::ConfigLoader' }-E>gt>{ file }> +=item * C<$c-Econfig-E{ 'Plugin::ConfigLoader' }-E{ file }> =item * C<$c-Epath_to( $application_prefix )> @@ -144,40 +171,34 @@ The order of preference is specified as: If either of the first two user-specified options are directories, the application prefix will be added on to the end of the path. -DEPRECATION NOTICE: C<$c-Econfig-E{ file }> is deprecated -and will be removed in the next release. - =cut sub get_config_path { - my $c = shift; + my $c = shift; - # deprecation notice - if( exists $c->config->{ file } ) { - $c->log->warn( q("file" config parameter has been deprecated in favor of "$c->config->{ 'Plugin::ConfigLoader' }->{ file }") ); - } my $appname = ref $c || $c; my $prefix = Catalyst::Utils::appprefix( $appname ); - my $path = Catalyst::Utils::env_value( $c, 'CONFIG' ) + my $path = Catalyst::Utils::env_value( $appname, 'CONFIG' ) || $c->config->{ 'Plugin::ConfigLoader' }->{ file } - || $c->config->{ file } # to be removed next release || $c->path_to( $prefix ); - my( $extension ) = ( $path =~ m{\.(.{1,4})$} ); - - if( -d $path ) { - $path =~ s{[\/\\]$}{}; + ## don't look for extension if this is a dir + my ( $extension ) = !-d $path ? ( $path =~ m{\.([^\/\\.]{1,4})$} ) : () ; + + if ( -d $path ) { + $path =~ s{[\/\\]$}{}; $path .= "/$prefix"; } - - return( $path, $extension ); + + return ( $path, $extension ); } =head2 get_config_local_suffix Determines the suffix of files used to override the main config. By default -this value is C, but it can be specified in the following order of preference: +this value is C, which will load C. The suffix can +be specified in the following order of preference: =over 4 @@ -189,23 +210,21 @@ this value is C, but it can be specified in the following order of prefer =back -DEPRECATION NOTICE: C<$c-Econfig-E{ config_local_suffix }> is deprecated -and will be removed in the next release. +The first one of these values found replaces the default of C in the +name of the local config file to be loaded. + +For example, if C< $ENV{ MYAPP_CONFIG_LOCAL_SUFFIX }> is set to C, +ConfigLoader will try and load C instead of +C. =cut sub get_config_local_suffix { - my $c = shift; - - # deprecation notice - if( exists $c->config->{ config_local_suffix } ) { - $c->log->warn( q("config_local_suffix" config parameter has been deprecated in favor of "$c->config->{ 'Plugin::ConfigLoader' }->{ config_local_suffix }") ); - } + my $c = shift; my $appname = ref $c || $c; - my $suffix = Catalyst::Utils::env_value( $c, 'CONFIG_LOCAL_SUFFIX' ) + my $suffix = Catalyst::Utils::env_value( $appname, 'CONFIG_LOCAL_SUFFIX' ) || $c->config->{ 'Plugin::ConfigLoader' }->{ config_local_suffix } - || $c->config->{ config_local_suffix } # to be remove in the next release || 'local'; return $suffix; @@ -218,10 +237,8 @@ sub _fix_syntax { prefix => $_ eq 'Component' ? '' : $_ . '::', values => delete $config->{ lc $_ } || delete $config->{ $_ } }, - grep { - ref $config->{ lc $_ } || ref $config->{ $_ } - } - qw( Component Model M View V Controller C ) + grep { ref $config->{ lc $_ } || ref $config->{ $_ } } + qw( Component Model M View V Controller C Plugin ) ); foreach my $comp ( @components ) { @@ -257,13 +274,15 @@ sub finalize_config { =head2 config_substitutions( $value ) -This method substitutes macros found with calls to a function. There are three -default macros: +This method substitutes macros found with calls to a function. There are a +number of default macros: =over 4 =item * C<__HOME__> - replaced with C<$c-Epath_to('')> +=item * C<__ENV(foo)__> - replaced with the value of C<$ENV{foo}> + =item * C<__path_to(foo/bar)__> - replaced with C<$c-Epath_to('foo/bar')> =item * C<__literal(__FOO__)__> - leaves __FOO__ alone (allows you to use @@ -285,9 +304,21 @@ The above will respond to C<__baz(x,y)__> in config strings. =cut sub config_substitutions { - my $c = shift; - my $subs = $c->config->{ 'Plugin::ConfigLoader' }->{ substitutions } || {}; - $subs->{ HOME } ||= sub { shift->path_to( '' ); }; + my $c = shift; + my $subs = $c->config->{ 'Plugin::ConfigLoader' }->{ substitutions } + || {}; + $subs->{ HOME } ||= sub { shift->path_to( '' ); }; + $subs->{ ENV } ||= + sub { + my ( $c, $v ) = @_; + if (! defined($ENV{$v})) { + Catalyst::Exception->throw( message => + "Missing environment variable: $v" ); + return ""; + } else { + return $ENV{ $v }; + } + }; $subs->{ path_to } ||= sub { shift->path_to( @_ ); }; $subs->{ literal } ||= sub { return $_[ 1 ]; }; my $subsre = join( '|', keys %$subs ); @@ -297,7 +328,6 @@ sub config_substitutions { } } - =head1 AUTHOR Brian Cassidy Ebricas@cpan.orgE @@ -313,9 +343,11 @@ development of this module: =item * David Kamholz Edkamholz@cpan.orgE - L integration +=item * Stuart Watt - Addition of ENV macro. + =back -Work to this module has been generously sponsored by: +Work to this module has been generously sponsored by: =over 4 @@ -325,14 +357,14 @@ Work to this module has been generously sponsored by: =head1 COPYRIGHT AND LICENSE -Copyright 2007 by Brian Cassidy +Copyright 2006-2010 by Brian Cassidy This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. +it under the same terms as Perl itself. =head1 SEE ALSO -=over 4 +=over 4 =item * L