7619e615823da5c5ca606e7b679560dfc8a1eeb3
[catagits/Catalyst-Runtime.git] / lib / Catalyst / ScriptRunner.pm
1 package Catalyst::ScriptRunner;
2 use Moose;
3 use FindBin;
4 use lib;
5 use File::Spec;
6 use Class::Load qw/ load_first_existing_class load_optional_class /;
7 use namespace::autoclean -also => 'subclass_with_traits';
8 use Try::Tiny;
9
10 sub find_script_class {
11     my ($self, $app, $script) = @_;
12     return load_first_existing_class("${app}::Script::${script}", "Catalyst::Script::$script");
13 }
14
15 sub find_script_traits {
16     my ($self, @try) = @_;
17
18     return grep { load_optional_class($_) } @try;
19 }
20
21 sub subclass_with_traits {
22     my ($base, @traits) = @_;
23
24     my $meta = Class::MOP::class_of($base)->create_anon_class(
25         superclasses => [ $base   ],
26         roles        => [ @traits ],
27         cache        => 1,
28     );
29     $meta->add_method(meta => sub { $meta });
30
31     return $meta->name;
32 }
33
34 sub run {
35     my ($self, $appclass, $scriptclass) = @_;
36
37     lib->import(File::Spec->catdir($FindBin::Bin, '..', 'lib'));
38
39     my $class = $self->find_script_class($appclass, $scriptclass);
40
41     my @possible_traits = ("${appclass}::TraitFor::Script::${scriptclass}", "${appclass}::TraitFor::Script");
42     my @traits = $self->find_script_traits(@possible_traits);
43
44     $class = subclass_with_traits($class, @traits)
45         if @traits;
46
47     $class->new_with_options( application_name => $appclass )->run;
48 }
49
50 __PACKAGE__->meta->make_immutable;
51 1;
52
53 =head1 NAME
54
55 Catalyst::ScriptRunner - The Catalyst Framework script runner
56
57 =head1 SYNOPSIS
58
59     # Will run MyApp::Script::Server if it exists, otherwise
60     # will run Catalyst::Script::Server.
61     Catalyst::ScriptRunner->run('MyApp', 'Server');
62
63 =head1 DESCRIPTION
64
65 This class is responsible for loading and running scripts, either in the
66 application specific namespace
67 (e.g. C<MyApp::Script::Server>), or the Catalyst namespace (e.g. C<Catalyst::Script::Server>).
68
69 If your application contains a custom script, then it will be used in preference to the generic
70 script, and is expected to sub-class the standard script.
71
72 =head1 TRAIT LOADING
73
74 Catalyst will automatically load and apply roles to the scripts in your
75 application.
76
77 C<MyApp::TraitFor::Script> will be loaded if present, and will be applied to B<ALL>
78 scripts.
79
80 C<MyApp::TraitFor::Script::XXXX> will be loaded (if present) and for script
81 individually.
82
83 =head1 METHODS
84
85 =head2 run ($application_class, $scriptclass)
86
87 Called with two parameters, the application class (e.g. MyApp)
88 and the script class, (i.e. one of Server/FastCGI/CGI/Create/Test)
89
90 =head2 find_script_class ($appname, $script_name)
91
92 Finds and loads the class for the script, trying the application specific
93 script first, and falling back to the generic script. Returns the script
94 which was loaded.
95
96 =head2 find_script_traits ($appname, @try)
97
98 Finds and loads a set of traits. Returns the list of traits which were loaded.
99
100 =head1 AUTHORS
101
102 Catalyst Contributors, see Catalyst.pm
103
104 =head1 COPYRIGHT
105
106 This library is free software. You can redistribute it and/or modify it under
107 the same terms as Perl itself.
108
109 =cut