File Coverage

blib/lib/Mojolicious/Plugin/AttributeMaker.pm
Criterion Covered Total %
statement 27 81 33.3
branch 0 26 0.0
condition 0 8 0.0
subroutine 9 17 52.9
pod 1 3 33.3
total 37 135 27.4


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::AttributeMaker;
2 1     1   30969 use Mojo::Base 'Mojolicious::Plugin';
  1         11969  
  1         8  
3 1     1   2540 use attributes;
  1         1745  
  1         9  
4 1     1   182555 use Module::Load;
  1         2386  
  1         12  
5 1     1   1790 use Module::Find qw/findsubmod/;
  1         1636  
  1         70  
6 1     1   8 use feature qw/state/;
  1         2  
  1         44  
7 1     1   6 use B qw/svref_2object/;
  1         2  
  1         52  
8 1     1   6 use Scalar::Util qw/blessed/;
  1         2  
  1         1108  
9              
10             =head1 NAME
11              
12             Mojolicious::Plugin::AttributeMaker - Make attributes for Mojolicious? - easily!
13              
14             =head1 VERSION
15              
16             Version 0.03
17              
18             =cut
19              
20             our $VERSION = 0.03;
21              
22             =head1 SYNOPSIS
23              
24             =head2 Step 1 - Connect plugin to your app
25              
26             =head3 NOTE: Don`t use with lite-app!!!
27            
28             package TestApp;
29              
30             use Mojo::Base 'Mojolicious';
31            
32             # This method will run once at server start
33             sub startup {
34             my $self = shift;
35             $self->plugin('AttributeMaker',{
36             controllers => 'TestApp::Controller'
37             });
38             }
39            
40             =head2 Step 2 - Add your own custom attribute or use attribute from extensions
41            
42             =head3 Step 2.1 - Create custom attribute in your controller
43            
44             BEGIN{
45             __PACKAGE__->make_attribute(
46             Local => sub {
47             my ( $package, $method, $plugin, $mojo_app, $attrname, $attrdata ) = @_;
48             # $package - Store the name of controller
49             # $method - Store the name of action
50             # $plugin - Object of Mojolicious::Plugin::AttributeMaker
51             # $mojo_app - Object of your app
52             # $attrname - Name of attribute . In current expaple is Local
53             # $attrdata - Stores the parameters passed from the attribute
54             }
55             );
56             }
57            
58             But if you create extension,you can write upper code without 'BEGIN' section;
59            
60             sub my_custom_action :Local('param1','param2',...,paramN){ ... }
61            
62              
63             =head3 Step 2.2 - Using attribute from extensions
64              
65             =over 3
66              
67             =item * Catalyst-like routing
68              
69             Provides attributes like a Local,Path,Global
70              
71             L
72              
73             =back
74            
75             =cut
76              
77             sub MODIFY_CODE_ATTRIBUTES {
78 0     0     my ( $package, $cv, @attrs ) = @_;
79 0           my $config = config();
80             my $cleaner = sub {
81 0 0   0     $_[0] =~ m/^'/ ? $_[0] =~ s/^'// : ();
82 0 0         $_[0] =~ m/'$/ ? $_[0] =~ s/'$// : ();
83 0 0         $_[0] =~ m/^\s+/ ? $_[0] =~ s/^\s+// : ();
84 0 0         $_[0] =~ m/\s+$/ ? $_[0] =~ s/\s+$// : ();
85 0           };
86 0           foreach my $attr (@attrs) {
87 0           my $attrdata;
88 0           my $cleanattr = $attr;
89 0 0         if ( $cleanattr =~ m/(\w+)\((\N*)\)$/ ) { # Attr with params Local(blablabla)
90 0           $cleanattr = $1;
91 0           foreach ( split ',', $2 ) { # Parsing and deleting escape characters in params
92 0           $cleaner->($_);
93 0           push @$attrdata, $_;
94             }
95             }
96 0 0         if ( exists $config->{attrs}->{$cleanattr} ) {
97 0           print "Attribute ${cleanattr} called!\n";
98 0           $config->{attrs}->{$cleanattr}
99             ->( $package, svref_2object($cv)->GV->NAME, $config->{self}, $config->{app}, $cleanattr, $attrdata );
100             }
101             else {
102 0           print "Attribute ${cleanattr} not found!\n";
103             }
104             }
105 0           ();
106             }
107              
108             sub config {
109 0 0 0 0 0   shift if @_ > 0 and blessed( $_[0] );
110 0           state $conf;
111 0 0         $conf = $_[0] if $_[0];
112 0           $conf;
113             }
114              
115             sub _load_extensions {
116 0     0     foreach ( findsubmod 'Mojolicious::Plugin::AttributeMaker::Extension' ) {
117 0           load($_);
118             }
119             }
120              
121             sub _load_controllers {
122 0     0     foreach ( findsubmod config()->{controllers} ) {
123 0           load($_); #Magic start here :)
124             }
125             }
126              
127             sub _is_loaded($) {
128 0     0     my ($pkg) = @_;
129 0           ( my $file = $pkg ) =~ s/::/\//g;
130 0           $file .= '.pm';
131 0           my @loaded = grep { $_ eq $file } keys %INC;
  0            
132 0 0         if (@loaded) {
133 0           return 1;
134             }
135 0           return;
136             }
137              
138             sub make_attribute {
139 0     0 0   my ( $package, $name, $cv ) = @_;
140 0           my $config = config();
141 0 0         if ( !exists $config->{attrs}->{$name} ) {
142 0           print "Attribute ${name} registered!\n";
143 0           $config->{attrs}->{$name} = $cv;
144             }
145             else {
146 0           die("Attribute ${name} already registered!");
147             }
148             }
149              
150             sub register {
151 0     0 1   my ( $self, $app, $conf ) = @_;
152 0   0       $conf ||= {};
153 0           my $config = {
154             base_controller => _is_loaded('Mojolicious::Lite')
155             ? 'main'
156             : 'Mojolicious::Controller',
157             controllers => delete $conf->{controllers}
158             || _is_loaded('Mojolicious::Lite') ? '' : die( __PACKAGE__ . " please set controller class" ),
159             self => $self,
160             app => $app,
161             attrs => {},
162 0 0 0       %{$conf}
    0          
163             };
164 0           config($config);
165              
166             #Start infect
167 1     1   7 no strict 'refs';
  1         2  
  1         96  
168 0           *{ $config->{base_controller} . "::MODIFY_CODE_ATTRIBUTES" } = *MODIFY_CODE_ATTRIBUTES;
  0            
169 0           *{ $config->{base_controller} . "::make_attribute" } = *make_attribute;
  0            
170 0           *Mojolicious::Plugin::AttributeMaker::Extension::make_attribute = *make_attribute;
171 1     1   8 use strict 'refs';
  1         1  
  1         128  
172 0           _load_extensions();
173 0 0         _load_controllers() unless _is_loaded('Mojolicious::Lite');
174             }
175              
176             =head1 AUTHOR
177              
178             "Evgeniy Vansevich", C<< <"hammer at cpan.org"> >>
179              
180             =head1 BUGS
181              
182             Please report any bugs or feature requests to C, or through
183             the web interface at L. I will be notified, and then you'll
184             automatically be notified of progress on your bug as I make changes.
185              
186              
187              
188              
189             =head1 SUPPORT
190              
191             You can find documentation for this module with the perldoc command.
192              
193             perldoc Mojolicious::Plugin::AttributeMaker
194              
195              
196             You can also look for information at:
197              
198             =over 4
199              
200             =item * RT: CPAN's request tracker (report bugs here)
201              
202             L
203              
204             =item * AnnoCPAN: Annotated CPAN documentation
205              
206             L
207              
208             =item * CPAN Ratings
209              
210             L
211              
212             =item * Search CPAN
213              
214             L
215              
216             =back
217              
218              
219             =head1 ACKNOWLEDGEMENTS
220              
221              
222             =head1 LICENSE AND COPYRIGHT
223              
224             Copyright 2014 "Evgeniy Vansevich".
225              
226             This program is free software; you can redistribute it and/or modify it
227             under the terms of the the Artistic License (2.0). You may obtain a
228             copy of the full license at:
229              
230             L
231              
232             Any use, modification, and distribution of the Standard or Modified
233             Versions is governed by this Artistic License. By using, modifying or
234             distributing the Package, you accept this license. Do not use, modify,
235             or distribute the Package, if you do not accept this license.
236              
237             If your Modified Version has been derived from a Modified Version made
238             by someone other than you, you are nevertheless required to ensure that
239             your Modified Version complies with the requirements of this license.
240              
241             This license does not grant you the right to use any trademark, service
242             mark, tradename, or logo of the Copyright Holder.
243              
244             This license includes the non-exclusive, worldwide, free-of-charge
245             patent license to make, have made, use, offer to sell, sell, import and
246             otherwise transfer the Package with respect to any patent claims
247             licensable by the Copyright Holder that are necessarily infringed by the
248             Package. If you institute patent litigation (including a cross-claim or
249             counterclaim) against any party alleging that the Package constitutes
250             direct or contributory patent infringement, then this Artistic License
251             to you shall terminate on the date that such litigation is filed.
252              
253             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
254             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
255             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
256             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
257             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
258             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
259             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
260             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261              
262              
263             =cut
264              
265             1;