File Coverage

blib/lib/Prophet/App.pm
Criterion Covered Total %
statement 21 97 21.6
branch 0 26 0.0
condition 0 10 0.0
subroutine 7 21 33.3
pod 8 13 61.5
total 36 167 21.5


line stmt bran cond sub pod time code
1             package Prophet::App;
2 40     40   170 use Any::Moose;
  40         58  
  40         271  
3 40     40   17040 use File::Spec ();
  40         66  
  40         904  
4 40     40   15759 use Prophet::Config;
  40         121  
  40         1472  
5 40     40   20493 use Prophet::UUIDGenerator;
  40         122  
  40         1667  
6 40     40   268 use Params::Validate qw/validate validate_pos/;
  40         52  
  40         12943  
7              
8             has handle => (
9             is => 'rw',
10             isa => 'Prophet::Replica',
11             lazy => 1,
12             default => sub {
13             my $self = shift;
14              
15             if ( defined $self->local_replica_url
16             && $self->local_replica_url !~ /^[\w\+]{2,}\:/ ) {
17             # the reason why we need {2,} is to not match name on windows, e.g. C:\foo
18             my $path = $self->local_replica_url;
19             $path = File::Spec->rel2abs(glob($path)) unless File::Spec->file_name_is_absolute($path);
20             $self->local_replica_url("file://$path");
21             }
22              
23             return Prophet::Replica->get_handle( url => $self->local_replica_url, app_handle => $self, );
24             },
25             );
26              
27             has config => (
28             is => 'rw',
29             isa => 'Prophet::Config',
30             default => sub {
31             my $self = shift;
32             return Prophet::Config->new(
33             app_handle => $self,
34             confname => 'prophetrc',
35             );
36             },
37             documentation => "This is the config instance for the running application",
38             );
39              
40              
41              
42 40     40   236 use constant DEFAULT_REPLICA_TYPE => 'prophet';
  40         48  
  40         45673  
43              
44             =head1 NAME
45              
46             Prophet::App
47              
48             =head1 SYNOPSIS
49              
50             =head1 METHODS
51              
52             =head2 BUILD
53              
54             =cut
55              
56             =head2 default_replica_type
57              
58             Returns a string of the the default replica type for this application.
59              
60             =cut
61              
62             sub default_replica_type {
63 0     0 1   my $self = shift;
64 0   0       return $ENV{'PROPHET_REPLICA_TYPE'} || DEFAULT_REPLICA_TYPE;
65             }
66              
67              
68             =head2 local_replica_url
69              
70             Returns the URL of the current local replica. If no URL has been
71             provided (usually via C<$ENV{PROPHET_REPO}>), returns undef.
72              
73             =cut
74              
75             sub local_replica_url {
76 0     0 1   my $self = shift;
77 0 0         if (@_) {
78 0           $ENV{'PROPHET_REPO'} = shift;
79             }
80              
81 0   0       return $ENV{'PROPHET_REPO'} || undef;
82             }
83              
84             =head2 require
85              
86             =cut
87              
88             sub require {
89 0     0 1   my $self = shift;
90 0           my $class = shift;
91 0           $self->_require(module => $class);
92             }
93              
94             =head2 try_to_require
95              
96             =cut
97              
98             sub try_to_require {
99 0     0 1   my $self = shift;
100 0           my $class = shift;
101 0           $self->_require(module => $class, quiet => 1);
102             }
103              
104             =head2 _require
105              
106             =cut
107              
108             sub _require {
109 0     0     my $self = shift;
110 0           my %args = ( module => undef, quiet => undef, @_);
111 0           my $class = $args{'module'};
112              
113             # Quick hack to silence warnings.
114             # Maybe some dependencies were lost.
115 0 0         unless ($class) {
116 0           warn sprintf("no class was given at %s line %d\n", (caller)[1,2]);
117 0           return 0;
118             }
119              
120 0 0         return 1 if $self->already_required($class);
121              
122             # .pm might already be there in a weird interaction in Module::Pluggable
123 0           my $file = $class;
124 0 0         $file .= ".pm"
125             unless $file =~ /\.pm$/;
126              
127 0           $file =~ s/::/\//g;
128              
129 0           my $retval = eval {
130 0           local $SIG{__DIE__} = 'DEFAULT';
131 0           CORE::require "$file"
132             };
133              
134 0           my $error = $@;
135 0 0         if (my $message = $error) {
136 0           $message =~ s/ at .*?\n$//;
137 0 0 0       if ($args{'quiet'} and $message =~ /^Can't locate \Q$file\E/) {
    0          
138 0           return 0;
139             }
140             elsif ( $error !~ /^Can't locate $file/) {
141 0           die $error;
142             } else {
143 0           warn sprintf("$message at %s line %d\n", (caller(1))[1,2]);
144 0           return 0;
145             }
146             }
147              
148 0           return 1;
149             }
150              
151             =head2 already_required class
152              
153             Helper function to test whether a given class has already been require'd.
154              
155             =cut
156              
157             sub already_required {
158 0     0 1   my ($self, $class) = @_;
159              
160 0 0         return 0 if $class =~ /::$/; # malformed class
161              
162 0           my $path = join('/', split(/::/,$class)).".pm";
163 0 0         return ( $INC{$path} ? 1 : 0);
164             }
165              
166             sub set_db_defaults {
167 0     0 0   my $self = shift;
168 0           my $settings = $self->database_settings;
169 0           for my $name ( keys %$settings ) {
170 0           my ($uuid, @metadata) = @{$settings->{$name}};
  0            
171              
172 0           my $s = $self->setting(
173             label => $name,
174             uuid => $uuid,
175             default => \@metadata,
176             );
177              
178 0           $s->initialize;
179             }
180             }
181              
182             sub setting {
183 0     0 0   my $self = shift;
184 0           my %args = validate( @_, { uuid => 0, default => 0, label => 0 } );
185 0           require Prophet::DatabaseSetting;
186              
187 0           my ($uuid, $default);
188              
189 0 0         if ( $args{uuid} ) {
    0          
190 0           $uuid = $args{'uuid'};
191 0           $default = $args{'default'};
192             } elsif ( $args{'label'} ) {
193 0           ($uuid, $default) = @{ $self->database_settings->{ $args{'label'} }};
  0            
194             }
195             return Prophet::DatabaseSetting->new(
196             handle => $self->handle,
197             uuid => $uuid,
198             default => $default,
199             label => $args{label}
200 0           );
201              
202             }
203              
204       0 0   sub database_settings {} # XXX wants a better name
205              
206              
207             =head3 log $MSG
208              
209             Logs the given message to C (but only if the C
210             environmental variable is set).
211              
212             =cut
213              
214             sub log_debug {
215 0     0 0   my $self = shift;
216 0 0         return unless ($ENV{'PROPHET_DEBUG'});
217 0           $self->log(@_);
218             }
219              
220             sub log {
221 0     0 1   my $self = shift;
222 0           my ($msg) = validate_pos(@_, 1);
223 0           print STDERR $msg."\n";# if ($ENV{'PROPHET_DEBUG'});
224             }
225              
226             =head2 log_fatal $MSG
227              
228             Logs the given message and dies with a stack trace.
229              
230             =cut
231              
232             sub log_fatal {
233 0     0 1   my $self = shift;
234              
235             # always skip this fatal_error function when generating a stack trace
236 0           local $Carp::CarpLevel = $Carp::CarpLevel + 1;
237              
238 0           $self->log(@_);
239 0           Carp::confess(@_);
240             }
241              
242              
243             sub current_user_email {
244 0     0 0   my $self = shift;
245 0   0       return $self->config->get( key => 'user.email-address' ) || $ENV{'PROPHET_EMAIL'} || $ENV{'EMAIL'};
246              
247             }
248              
249             =head2 display_name_for_replica UUID
250              
251             Returns a "friendly" id for the replica with the given uuid. UUIDs are for
252             computers, friendly names are for people. If no name is found, the friendly
253             name is just the UUID.
254              
255             =cut
256              
257             # friendly names are replica subsections in the config file
258             sub display_name_for_replica {
259 0     0 1   my $self = shift;
260 0           my $uuid = shift;
261              
262 0           my %possibilities = $self->config->get_regexp( key => '^replica\..*\.uuid$' );
263             # form a hash of uuid -> name
264             my %sources_by_uuid = map {
265 0           my $uuid = $possibilities{$_};
  0            
266 0           $_ =~ /^replica\.(.*)\.uuid$/;
267 0           my $name = $1;
268 0           ( $uuid => $name );
269             } keys %possibilities;
270 0 0         return exists $sources_by_uuid{$uuid} ? $sources_by_uuid{$uuid} : $uuid;
271             }
272              
273             __PACKAGE__->meta->make_immutable;
274 40     40   246 no Any::Moose;
  40         59  
  40         239  
275              
276             1;