File Coverage

blib/lib/CatalystX/InjectComponent.pm
Criterion Covered Total %
statement 15 53 28.3
branch 0 22 0.0
condition 0 8 0.0
subroutine 5 9 55.5
pod 1 3 33.3
total 21 95 22.1


line stmt bran cond sub pod time code
1             package CatalystX::InjectComponent;
2             {
3             $CatalystX::InjectComponent::VERSION = '0.025';
4             }
5             # ABSTRACT: Inject components into your Catalyst application
6              
7 1     1   36503 use warnings;
  1         1  
  1         32  
8 1     1   4 use strict;
  1         2  
  1         29  
9              
10              
11 1     1   1838 use Devel::InnerPackage;
  1         4185  
  1         64  
12 1     1   3967 use Class::Inspector;
  1         6991  
  1         34  
13 1     1   10 use Carp;
  1         3  
  1         1087  
14              
15             sub put_package_into_INC ($) {
16 0     0 0   my $package = shift;
17 0           (my $file = "$package.pm") =~ s{::}{/}g;
18 0   0       $INC{$file} ||= 1;
19             }
20              
21             sub loaded ($) {
22 0     0 0   my $package = shift;
23 0 0         if ( Class::Inspector->loaded( $package ) ) {
24 0           put_package_into_INC $package; # As a courtesy
25 0           return 1;
26             }
27 0           return 0;
28             }
29              
30             sub inject {
31 0     0 1   my $self = shift;
32 0           my %given = @_;
33              
34 0           my ($into, $component, $as);
35 0 0         if ( $given{catalyst} ) { # Legacy argument parsing
36 0           ($into, $component, $as) = @given{ qw/catalyst component into/ };
37             }
38             else {
39 0           ($into, $component, $as) = @given{ qw/into component as/ };
40             }
41            
42 0 0         croak "No Catalyst (package) given" unless $into;
43 0 0         croak "No component (package) given" unless $component;
44              
45 0 0         unless ( loaded $component ) {
46 0 0         eval "require $component;" or croak "Couldn't require (component base) $component: $@";
47             }
48              
49 0   0       $as ||= $component;
50 0 0 0       unless ( $as =~ m/^(?:Controller|Model|View)::/ || $given{skip_mvc_renaming} ) {
51 0           my $category;
52 0           for (qw/ Controller Model View /) {
53 0 0         if ( $component->isa( "Catalyst::$_" ) ) {
54 0           $category = $_;
55 0           last;
56             }
57             }
58 0 0         croak "Don't know what kind of component \"$component\" is" unless $category;
59 0           $as = "${category}::$as";
60             }
61 0           my $component_package = join '::', $into, $as;
62              
63 0 0         unless ( loaded $component_package ) {
64 0 0         eval "package $component_package; use parent qw/$component/; 1;" or
65             croak "Unable to build component package for \"$component_package\": $@";
66 0           put_package_into_INC $component_package; # As a courtesy
67             }
68              
69 0           $self->_setup_component( $into => $component_package );
70 0           for my $inner_component_package ( Devel::InnerPackage::list_packages( $component_package ) ) {
71 0           $self->_setup_component( $into => $inner_component_package );
72             }
73             }
74              
75             sub _setup_component {
76 0     0     my $self = shift;
77 0           my $into = shift;
78 0           my $component_package = shift;
79 0           $into->components->{$component_package} = $into->setup_component( $component_package );
80             }
81              
82             1; # End of CatalystX::InjectComponent
83              
84             __END__
85             =pod
86              
87             =head1 NAME
88              
89             CatalystX::InjectComponent - Inject components into your Catalyst application
90              
91             =head1 VERSION
92              
93             version 0.025
94              
95             =head1 SYNOPSIS
96              
97             package My::App;
98              
99             use Catalyst::Runtime '5.80';
100              
101             use Moose;
102             BEGIN { extends qw/Catalyst/ }
103              
104             ...
105              
106             after 'setup_components' => sub {
107             my $class = shift;
108             CatalystX::InjectComponent->inject( into => $class, component => 'MyModel' );
109             if ( $class->config->{ ... ) {
110             CatalystX::InjectComponent->inject( into => $class, component => 'MyRootV2', as => 'Controller::Root' );
111             }
112             else {
113             CatalystX::InjectComponent->inject( into => $class, component => 'MyRootV1', as => 'Root' ); # Controller:: will be automatically prefixed
114             }
115             };
116              
117             =head1 DESCRIPTION
118              
119             CatalystX::InjectComponent will inject Controller, Model, and View components into your Catalyst application at setup (run)time. It does this by creating
120             a new package on-the-fly, having that package extend the given component, and then having Catalyst setup the new component (via C<< ->setup_component >>)
121              
122             =head1 So, how do I use this thing?
123              
124             You should inject your components when appropriate, typically after C<setup_compenents> runs
125              
126             If you're using the Moose version of Catalyst, then you can use the following technique:
127              
128             use Moose;
129             BEGIN { extends qw/Catalyst/ }
130              
131             after 'setup_components' => sub {
132             my $class = shift;
133              
134             CatalystX::InjectComponent->inject( into => $class, ... )
135             };
136              
137             =head1 METHODS
138              
139             =head2 CatalystX::InjectComponent->inject( ... )
140              
141             into The Catalyst package to inject into (e.g. My::App)
142             component The component package to inject
143             as An optional moniker to use as the package name for the derived component
144              
145             For example:
146              
147             ->inject( into => My::App, component => Other::App::Controller::Apple )
148            
149             The above will create 'My::App::Controller::Other::App::Controller::Apple'
150              
151             ->inject( into => My::App, component => Other::App::Controller::Apple, as => Apple )
152              
153             The above will create 'My::App::Controller::Apple'
154              
155             =head1 ACKNOWLEDGEMENTS
156              
157             Inspired by L<Catalyst::Plugin::AutoCRUD>
158              
159             =head1 AUTHOR
160              
161             Robert Krimen <robertkrimen@gmail.com>
162              
163             =head1 COPYRIGHT AND LICENSE
164              
165             This software is copyright (c) 2012 by Robert Krimen.
166              
167             This is free software; you can redistribute it and/or modify it under
168             the same terms as the Perl 5 programming language system itself.
169              
170             =cut
171