rename test test
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Utils.pm
CommitLineData
f05af9ba 1package Catalyst::Utils;
2
3use strict;
a2f2cde9 4use Catalyst::Exception;
37a3ac5c 5use File::Spec;
d837e1a7 6use HTTP::Request;
812a28c9 7use Path::Class;
d837e1a7 8use URI;
d9183506 9use Class::Inspector;
5e5bd6df 10use Carp qw/croak/;
2f381252 11use Cwd;
f05af9ba 12
13=head1 NAME
14
15Catalyst::Utils - The Catalyst Utils
16
17=head1 SYNOPSIS
18
19See L<Catalyst>.
20
21=head1 DESCRIPTION
22
23=head1 METHODS
24
b5ecfcf0 25=head2 appprefix($class)
41ca9ba7 26
85d9fce6 27 MyApp::Foo becomes myapp_foo
41ca9ba7 28
29=cut
30
31sub appprefix {
32 my $class = shift;
0ef447d8 33 $class =~ s/::/_/g;
41ca9ba7 34 $class = lc($class);
35 return $class;
36}
37
b5ecfcf0 38=head2 class2appclass($class);
84cf74e7 39
0ef447d8 40 MyApp::Controller::Foo::Bar becomes MyApp
41 My::App::Controller::Foo::Bar becomes My::App
2d90477f 42
84cf74e7 43=cut
44
45sub class2appclass {
46 my $class = shift || '';
47 my $appname = '';
0ef447d8 48 if ( $class =~ /^(.+?)::([MVC]|Model|View|Controller)::.+$/ ) {
84cf74e7 49 $appname = $1;
50 }
51 return $appname;
52}
53
b5ecfcf0 54=head2 class2classprefix($class);
2930d610 55
0ef447d8 56 MyApp::Controller::Foo::Bar becomes MyApp::Controller
57 My::App::Controller::Foo::Bar becomes My::App::Controller
2d90477f 58
2930d610 59=cut
60
61sub class2classprefix {
62 my $class = shift || '';
63 my $prefix;
0ef447d8 64 if ( $class =~ /^(.+?::([MVC]|Model|View|Controller))::.+$/ ) {
2930d610 65 $prefix = $1;
66 }
67 return $prefix;
68}
69
b5ecfcf0 70=head2 class2classsuffix($class);
84cf74e7 71
0ef447d8 72 MyApp::Controller::Foo::Bar becomes Controller::Foo::Bar
2d90477f 73
84cf74e7 74=cut
75
76sub class2classsuffix {
77 my $class = shift || '';
78 my $prefix = class2appclass($class) || '';
0ef447d8 79 $class =~ s/$prefix\:://;
84cf74e7 80 return $class;
81}
82
b5ecfcf0 83=head2 class2env($class);
3ad654e0 84
26e73131 85Returns the environment name for class.
3ad654e0 86
87 MyApp becomes MYAPP
88 My::App becomes MY_APP
89
90=cut
91
92sub class2env {
93 my $class = shift || '';
0ef447d8 94 $class =~ s/::/_/g;
3ad654e0 95 return uc($class);
96}
97
b5ecfcf0 98=head2 class2prefix( $class, $case );
f05af9ba 99
e2cc89a9 100Returns the uri prefix for a class. If case is false the prefix is converted to lowercase.
f05af9ba 101
0ef447d8 102 My::App::Controller::Foo::Bar becomes foo/bar
2d90477f 103
f05af9ba 104=cut
105
106sub class2prefix {
107 my $class = shift || '';
e494bd6b 108 my $case = shift || 0;
f05af9ba 109 my $prefix;
0ef447d8 110 if ( $class =~ /^.+?::([MVC]|Model|View|Controller)::(.+)$/ ) {
e494bd6b 111 $prefix = $case ? $2 : lc $2;
0ef447d8 112 $prefix =~ s{::}{/}g;
f05af9ba 113 }
114 return $prefix;
115}
116
b5ecfcf0 117=head2 class2tempdir( $class [, $create ] );
37a3ac5c 118
e2cc89a9 119Returns a tempdir for a class. If create is true it will try to create the path.
37a3ac5c 120
121 My::App becomes /tmp/my/app
122 My::App::C::Foo::Bar becomes /tmp/my/app/c/foo/bar
123
124=cut
125
126sub class2tempdir {
127 my $class = shift || '';
128 my $create = shift || 0;
4be535b1 129 my @parts = split '::', lc $class;
37a3ac5c 130
131 my $tmpdir = dir( File::Spec->tmpdir, @parts )->cleanup;
132
4be535b1 133 if ( $create && !-e $tmpdir ) {
37a3ac5c 134
135 eval { $tmpdir->mkpath };
136
4be535b1 137 if ($@) {
37a3ac5c 138 Catalyst::Exception->throw(
4be535b1 139 message => qq/Couldn't create tmpdir '$tmpdir', "$@"/ );
37a3ac5c 140 }
141 }
142
143 return $tmpdir->stringify;
144}
145
b5ecfcf0 146=head2 home($class)
812a28c9 147
148Returns home directory for given class.
149
150=cut
151
152sub home {
51f412bd 153 my $class = shift;
154
155 # make an $INC{ $key } style string from the class name
156 (my $file = "$class.pm") =~ s{::}{/}g;
157
158 if ( my $inc_entry = $INC{$file} ) {
51452916 159 {
51f412bd 160 # look for an uninstalled Catalyst app
161
162 # find the @INC entry in which $file was found
163 (my $path = $inc_entry) =~ s/$file$//;
2f381252 164 $path ||= cwd() if !defined $path || !length $path;
51f412bd 165 my $home = dir($path)->absolute->cleanup;
166
167 # pop off /lib and /blib if they're there
168 $home = $home->parent while $home =~ /b?lib$/;
169
170 # only return the dir if it has a Makefile.PL or Build.PL
c09c6cd7 171 if (-f $home->file("Makefile.PL") or -f $home->file("Build.PL")) {
172
173 # clean up relative path:
174 # MyApp/script/.. -> MyApp
175
059c085b 176 my $dir;
177 my @dir_list = $home->dir_list();
178 while (($dir = pop(@dir_list)) && $dir eq '..') {
c09c6cd7 179 $home = dir($home)->parent->parent;
180 }
181
182 return $home->stringify;
183 }
51452916 184 }
4be535b1 185
51f412bd 186 {
187 # look for an installed Catalyst app
188
189 # trim the .pm off the thing ( Foo/Bar.pm -> Foo/Bar/ )
190 ( my $path = $inc_entry) =~ s/\.pm$//;
191 my $home = dir($path)->absolute->cleanup;
192
193 # return if if it's a valid directory
194 return $home->stringify if -d $home;
62459712 195 }
812a28c9 196 }
51f412bd 197
198 # we found nothing
199 return 0;
812a28c9 200}
201
b5ecfcf0 202=head2 prefix($class, $name);
812a28c9 203
204Returns a prefixed action.
205
0ef447d8 206 MyApp::Controller::Foo::Bar, yada becomes foo/bar/yada
812a28c9 207
208=cut
209
210sub prefix {
211 my ( $class, $name ) = @_;
212 my $prefix = &class2prefix($class);
213 $name = "$prefix/$name" if $prefix;
214 return $name;
215}
216
b5ecfcf0 217=head2 request($uri)
4d60aa90 218
e2cc89a9 219Returns an L<HTTP::Request> object for a uri.
4d60aa90 220
221=cut
222
223sub request {
224 my $request = shift;
225 unless ( ref $request ) {
a88c7ec8 226 if ( $request =~ m/^http/i ) {
f4c0f6f7 227 $request = URI->new($request);
4d60aa90 228 }
229 else {
f4c0f6f7 230 $request = URI->new( 'http://localhost' . $request );
4d60aa90 231 }
232 }
233 unless ( ref $request eq 'HTTP::Request' ) {
234 $request = HTTP::Request->new( 'GET', $request );
235 }
4d60aa90 236 return $request;
237}
238
dd91afb5 239=head2 ensure_class_loaded($class_name, \%opts)
d9183506 240
241Loads the class unless it already has been loaded.
242
dd91afb5 243If $opts{ignore_loaded} is true always tries the require whether the package
244already exists or not. Only pass this if you're either (a) sure you know the
245file exists on disk or (b) have code to catch the file not found exception
246that will result if it doesn't.
247
d9183506 248=cut
249
250sub ensure_class_loaded {
251 my $class = shift;
d06051f7 252 my $opts = shift;
d9183506 253
5e5bd6df 254 croak "Malformed class Name $class"
255 if $class =~ m/(?:\b\:\b|\:{3,})/;
256
59ede84e 257 croak "Malformed class Name $class"
258 if $class =~ m/[^\w:]/;
259
260 croak "ensure_class_loaded should be given a classname, not a filename ($class)"
261 if $class =~ m/\.pm$/;
262
d06051f7 263 return if !$opts->{ ignore_loaded }
264 && Class::Inspector->loaded( $class ); # if a symbol entry exists we don't load again
d9183506 265
266 # this hack is so we don't overwrite $@ if the load did not generate an error
267 my $error;
268 {
269 local $@;
7a1958eb 270 my $file = $class . '.pm';
271 $file =~ s{::}{/}g;
272 eval { CORE::require($file) };
d9183506 273 $error = $@;
274 }
6bfff75e 275
d9183506 276 die $error if $error;
6bfff75e 277 die "require $class was successful but the package is not defined"
278 unless Class::Inspector->loaded($class);
279
280 return 1;
d9183506 281}
282
358e1592 283=head2 merge_hashes($hashref, $hashref)
284
285Base code to recursively merge two hashes together with right-hand precedence.
286
287=cut
288
289sub merge_hashes {
290 my ( $lefthash, $righthash ) = @_;
291
292 return $lefthash unless defined $righthash;
293
294 my %merged = %$lefthash;
0ef447d8 295 for my $key ( keys %$righthash ) {
296 my $right_ref = ( ref $righthash->{ $key } || '' ) eq 'HASH';
297 my $left_ref = ( ( exists $lefthash->{ $key } && ref $lefthash->{ $key } ) || '' ) eq 'HASH';
298 if( $right_ref and $left_ref ) {
358e1592 299 $merged{ $key } = merge_hashes(
300 $lefthash->{ $key }, $righthash->{ $key }
0ef447d8 301 );
358e1592 302 }
303 else {
304 $merged{ $key } = $righthash->{ $key };
0ef447d8 305 }
358e1592 306 }
307
308 return \%merged;
309}
310
cb69249e 311=head2 env_value($class, $key)
312
313Checks for and returns an environment value. For instance, if $key is
314'home', then this method will check for and return the first value it finds,
315looking at $ENV{MYAPP_HOME} and $ENV{CATALYST_HOME}.
316
317=cut
318
319sub env_value {
320 my ( $class, $key ) = @_;
321
322 $key = uc($key);
323 my @prefixes = ( class2env($class), 'CATALYST' );
324
325 for my $prefix (@prefixes) {
326 if ( defined( my $value = $ENV{"${prefix}_${key}"} ) ) {
327 return $value;
328 }
329 }
330
331 return;
332}
d9183506 333
2f381252 334=head1 AUTHORS
f05af9ba 335
2f381252 336Catalyst Contributors, see Catalyst.pm
f05af9ba 337
338=head1 COPYRIGHT
339
340This program is free software, you can redistribute it and/or modify it under
341the same terms as Perl itself.
342
343=cut
344
3451;