Do not fail pod coverage
[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
52 =head1 NAME
53
54 Catalyst::ScriptRunner - The Catalyst Framework script runner
55
56 =head1 SYNOPSIS
57
58     # Will run MyApp::Script::Server if it exists, otherwise
59     # will run Catalyst::Script::Server.
60     Catalyst::ScriptRunner->run('MyApp', 'Server');
61
62 =head1 DESCRIPTION
63
64 This class is responsible for loading and running scripts, either in the
65 application specific namespace
66 (e.g. C<MyApp::Script::Server>), or the Catalyst namespace (e.g. C<Catalyst::Script::Server>).
67
68 If your application contains a custom script, then it will be used in preference to the generic
69 script, and is expected to sub-class the standard script.
70
71 =head1 TRAIT LOADING
72
73 Catalyst will automatically load and apply roles to the scripts in your
74 application.
75
76 C<MyApp::TraitFor::Script> will be loaded if present, and will be applied to B<ALL>
77 scripts.
78
79 C<MyApp::TraitFor::Script::XXXX> will be loaded (if present) and for script
80 individually.
81
82 =head1 METHODS
83
84 =head2 run ($application_class, $scriptclass)
85
86 Called with two parameters, the application class (e.g. MyApp)
87 and the script class, (i.e. one of Server/FastCGI/CGI/Create/Test)
88
89 =head2 find_script_class ($appname, $script_name)
90
91 Finds and loads the class for the script, trying the application specific
92 script first, and falling back to the generic script. Returns the script
93 which was loaded.
94
95 =head2 find_script_traits ($appname, @try)
96
97 Finds and loads a set of traits. Returns the list of traits which were loaded.
98
99 =head1 AUTHORS
100
101 Catalyst Contributors, see Catalyst.pm
102
103 =head1 COPYRIGHT
104
105 This library is free software. You can redistribute it and/or modify it under
106 the same terms as Perl itself.
107
108 =cut