File Coverage

blib/lib/Bigtop/Backend/Control/Gantry.pm
Criterion Covered Total %
statement 99 1057 9.3
branch 0 302 0.0
condition 0 85 0.0
subroutine 33 99 33.3
pod 6 6 100.0
total 138 1549 8.9


line stmt bran cond sub pod time code
1             package Bigtop::Backend::Control::Gantry;
2 1     1   1556 use strict; use warnings;
  1     1   2  
  1         28  
  1         5  
  1         1  
  1         96  
3              
4             # I apologize to all developers for littering the top of this file with POD.
5             # If I don't the first POD that perldoc shows is the POD template for generated
6             # code. Try vim folding.
7              
8             =head1 NAME
9              
10             Bigtop::Backend::Control::Gantry - controller generator for the Gantry framework
11              
12             =head1 SYNOPSIS
13              
14             Build a file like this called my.bigtop:
15              
16             config {
17             base_dir `/home/username`;
18             Control Gantry {}
19             }
20             app App::Name {
21             controller SomeController {}
22             }
23              
24             Then run this command:
25              
26             bigtop my.bigtop Control
27              
28             =head1 DESCRIPTION
29              
30             When your bigtop config includes Control Gantry, this module will be
31             loaded by Bigtop::Parser when bigtop is run with all or Control
32             in its build list.
33              
34             This module builds files in the lib subdirectory of base_dir/App-Name.
35             (But you can change name by supplying app_dir, as explained in
36             Bigtop::Parser's pod.)
37              
38             There will generally be two files for each controller you define. One
39             will have the name you give it with the app name in front. For the SYNOPSIS
40             example, that file will be called
41              
42             /home/username/App-Name/lib/App/Name/SomeController.pm
43              
44             I call this file the stub. It won't have much useful code in it, though
45             it might have method stubs depending on what's in its controller block.
46              
47             The other file will have generated code in it. As such it will go in the
48             GEN subdirectory of the directory where the stub lives. In the example,
49             the name will be:
50              
51             /home/username/App-Name/lib/App/Name/GEN/SomeController.pm
52              
53             During the intial build, both of these files will be made. Subsequently,
54             the stub will not be regenerated (unless you delete it), but the GEN file
55             will be. To prevent regeneration you may either put no_gen in the
56             Control Gantry block of the config, like this:
57              
58             config {
59             ...
60             Control Gantry { no_gen 1; }
61             }
62              
63             or you may mark the controller itself:
64              
65             controller SomeController {
66             no_gen 1;
67             }
68              
69             =head2 controller KEYWORDS
70              
71             Each controller has the form
72              
73             controller name is type {
74             keyword arg, list;
75             method name is type {
76             keyword arg, list;
77             }
78             }
79              
80             For a list of the keywords you can include in the controller block see the pod
81             for Bigtop::Control. For a list of the keywords you can include in the
82             method block, see below (and note that most of these vary by the method's
83             type).
84              
85             The controller phrase 'is type' is optional and defaults to 'is stub' which
86             has no effect. The supported types are:
87              
88             =over 4
89              
90             =item AutoCRUD
91              
92             This simply adds Gantry::Plugins::AutoCRUD to your uses list (it
93             will create the list if you don't have one). Do not manually put
94             Gantry::Plugins::AutoCRUD in the uses list if you use type AutoCRUD, or
95             it will have two use statements.
96              
97             =item CRUD
98              
99             This adds Gantry::Plugins::CRUD to your uses list (it will create the list
100             if you don't have one). As with AutoCRUD, don't manually put
101             Gantry::Plugins::CRUD in your uses list if you set the type to CRUD.
102              
103             In addition to modifying your uses list, this type will make extra code.
104             Each time it sees a method of type AutoCRUD_form, it will make the following
105             things (suppose the AutoCRUD_form method is called my_crud_form):
106              
107             =over 4
108              
109             =item form method
110              
111             This method will be suitable for use as the form named parameter to the
112             Gantry::Plugins::CRUD constructor.
113              
114             You get this whether you set the controller type to CRUD or not.
115              
116             =item constructed crud object
117              
118             my $my_crud = Gantry::Plugins::CRUD->new(
119             add_action => \&my_crud_add,
120             edit_action => \&my_crud_edit,
121             delete_action => \&my_crud_delete,
122             form => \&my_crud_form,
123             redirect => \&my_crud_redirect,
124             text_descr => 'your text_description here',
125             );
126              
127             =item redirect method
128              
129             Replicates the default behavior of always sending the user back to
130             $self->location on successful save or cancel.
131              
132             =item do_* methods
133              
134             A set of methods for add, edit, and delete which Gantry's handler will call.
135             These are stubs. Example:
136              
137             #-------------------------------------------------
138             # $self->do_add( )
139             #-------------------------------------------------
140             sub do_add {
141             my $self = shift;
142              
143             $crud->add( $self, { data => \@_ } );
144             }
145              
146             Note that you should do something better with the data. This method
147             leaves you having to fish through an array in the action method, and
148             therefore makes it harder for code readers to find out what is in the data.
149              
150             =item action methods
151              
152             A set of methods corresponding to do_add, do_edit, and do_delete which
153             are specified during the construction of the crud object. Example:
154              
155             #-------------------------------------------------
156             # $self->my_crud_add( $id )
157             #-------------------------------------------------
158             sub my_crud_add {
159             my ( $self, $params, $data ) = @_;
160              
161             my $row = $YOUR_CONTROLLED_TABLE->create( $param );
162             $row->dbi_commit();
163             }
164              
165             Note that the new object creation code a Class::DBI style API can be
166             called against the model alias of the table this controller controls.
167             That won't work if you are controlling multiple tables. The same
168             holds for the edit and delete methods.
169              
170             =back
171              
172             Note that all generated names are based on the name of the form method.
173             The name is made with a brain dead regex which simply strips _form from
174             that name.
175              
176             =back
177              
178             =head2 method KEYWORDS
179              
180             Most of the method keywords depend on the method's type. This one doesn't:
181              
182             =over 4
183              
184             =item extra_args
185              
186             Make this a comma separated list of arguments your method should expect.
187             Example:
188              
189             extra_args `$cust_id`, `@params`;
190              
191             Note that there is almost no magic here. These will simply be added
192             to the method's opening comment and argument capturing code. So
193             if the above example appeared in a handler method, the stub would look
194             roughly like this:
195              
196             #--------------------------------------------------
197             # $self->method_name( $cust_id, @params )
198             #--------------------------------------------------
199             sub method_name {
200             my ( $self, $cust_id, @params ) = @_;
201             }
202              
203             =back
204              
205             =head1 SUPPORTED METHOD TYPES
206              
207             Note Well: Gantry's handlers must be called do_*. The leading do_
208             will not be magically supplied. Type it yourself.
209              
210             Each method must have a type. This backend supports the following types
211             (where support may vary depending on the type):
212              
213             =over 4
214              
215             =item stub
216              
217             Generates an empty method body. (But it handles arguments, see
218             extra_args above.)
219              
220             =item main_listing
221              
222             Generates a method, which you should probably name do_main, which produces
223             a listing of all the items in a table sorted by the columns in the table's
224             foreign_display.
225              
226             You may include the following keys in the method block:
227              
228             =over 4
229              
230             =item rows
231              
232             An integer number of rows to display on each page of main listing output.
233             There is no default. If you omit this, you get all the rows, which is
234             painful if there are very many.
235              
236             You must be using DBIx::Class for this to be effective.
237              
238             =item cols
239              
240             This is the list of columns that should appear in the listing.
241             More than 5 or 6 will likely look funny. Use the field names from
242             the table you are controlling.
243              
244             =item col_labels
245              
246             This optional list allows you to specify labels for the columns instead
247             of using the label specfied in the field block of the controlled table.
248             Each list element is either a simple string which becomes the label
249             or a pair in which the key is the label and the value is a url (or code
250             which builds one) which becomes the href of an html link. Example:
251              
252             col_labels `Better Text`,
253             Label => `$self->location() . '/exotic/locaiton'`;
254              
255             Note that for pairs, you may use any valid Perl in the link text. Enclose
256             it in backquotes. It will not be modified, mind your own quotes.
257              
258             =item extra_args
259              
260             See above.
261              
262             =item header_options
263              
264             These are the options that will appear at the end of the column label
265             stripe at the top of the output table. Typically this is just:
266              
267             header_options Add;
268              
269             But you can expand on that in a couple of ways. You can have other
270             options:
271              
272             header_options AddBuyer, AddSeller;
273              
274             These will translate into href links in the html page as
275              
276             current_base_uri/addbuyer
277             current_base_uri/addseller
278              
279             (In Gantry this means you should have do_addbuyer and do_addseller
280             methods in the same .pm file where the main_listing lives.)
281              
282             You can also control the generated url:
283              
284             header_options AddUser => `$self->exotic_location() . "/strange_add"`;
285              
286             Put valid Perl inside the backquotes. It will NOT be changed in any way.
287             You must ensure that the code will work in the final app. In this case
288             that likely means that exotic_location should return a uri which is
289             mentioned in a Location block in httpd.conf. Further, the module
290             set as the handler for that location must have a method called
291             do_strange_add.
292              
293             =item html_template
294              
295             The name of the Template Toolkit file to use as the view for this page.
296             By default this is results.tt for main_listing methods and main.tt for
297             base_link methods.
298              
299             =item row_options
300              
301             These yield href links at the end of each row in the output table.
302             Typical example:
303              
304             row_options Edit, Delete;
305              
306             These work just like header_options with one exception. The url has
307             the id of the row appended at the end.
308              
309             If you say
310              
311             row_options Edit => `$url`;
312              
313             You must make sure that the url is exactly correct (including appending
314             '/$id' to it). Supplied values will be taken literally.
315              
316             =item title
317              
318             The browser window title for this page.
319              
320             =back
321              
322             =item AutoCRUD_form
323              
324             Generates a method, usually called _form, which Gantry::Plugins::AutoCRUD
325             calls from its do_add and do_edit methods.
326              
327             You may include the following keys in the method block:
328              
329             =over 4
330              
331             =item all_fields_but
332              
333             A comma separated list of fields that should not appear on the form.
334             Typical example:
335              
336             all_fields_but id;
337              
338             =item extra_args
339              
340             See above. Note that for the extra_args to be available, they must
341             be passed from the AutoCRUD calling method.
342              
343             =item extra_keys
344              
345             List key/value pairs you want to appear in the hash returned by the method.
346             Example:
347              
348             extra_keys
349             legend => `$self->path_info =~ /edit/i ? 'Edit' : 'Add'`,
350             javascript => `$self->calendar_month_js( 'customer' )`;
351              
352             The javascript entry is exactly correct for a form named customer
353             using Gantry::Plugins::Calendar.
354              
355             Note that whatever you put inside the backquotes appears EXACTLY as is
356             in the generated output. Nothing will be done to it, not even quote
357             escaping.
358              
359             =item fields
360              
361             A comma separated list of the fields to include on the form. The
362             names must match fields of table you are controlling.
363             Example:
364              
365             fields first_name, last_name, street, city, state, zip;
366              
367             Note that all_fields_but is usually easier, but directly using fields
368             allows you to change the order in which the entry widgets appear.
369              
370             =item form_name
371              
372             The name of the html form. This is important if you are using javascript
373             which needs to refer to the form (for example if you are using
374             Gantry::Plugins::Calendar).
375              
376             =back
377              
378             =item CRUD_form
379              
380             Takes the same keywords as AutoCRUD_form but makes a form method suitable
381             for use with Gantry::Plugins::CRUD. Note that due to the callback scheme
382             used in that module, the name you give the generated method is entirely up
383             to you. Note that the method is generated in the stub and therefore must
384             be included during initial building to avoid gymnastics (like renaming the
385             stub, genning, renaming the regened stub, moving the form method from that
386             file back into the real stub...).
387              
388             =back
389              
390             =head1 METHODS
391              
392             To keep podcoverage tests happy.
393              
394             =over 4
395              
396             =item backend_block_keywords
397              
398             Tells tentmaker that I understand these config section backend block keywords:
399              
400             no_gen
401             dbix
402             full_use
403             template
404              
405             =item what_do_you_make
406              
407             Tells tentmaker what this module makes. Summary: Gantry controller modules.
408              
409             =item gen_Control
410              
411             Called by Bigtop::Parser to get me to do my thing.
412              
413             =item build_config_lists
414              
415             What I call on the various AST packages to do my thing.
416              
417             =item build_init_sub
418              
419             What I call on the various AST packages to do my thing.
420              
421             =item setup_template
422              
423             Called by Bigtop::Parser so the user can substitute an alternate template
424             for the hard coded one here.
425              
426             =back
427              
428             =head1 AUTHOR
429              
430             Phil Crow
431              
432             =head1 COPYRIGHT and LICENSE
433              
434             Copyright (C) 2005 by Phil Crow
435              
436             This library is free software; you can redistribute it and/or modify
437             it under the same terms as Perl itself, either Perl version 5.8.6 or,
438             at your option, any later version of Perl 5 you may have available.
439              
440             =head1 IGNORE the REST
441              
442             After this paragraph, you will likely see other POD. It belongs to
443             the generated modules. I just couldn't figure out how to hide it.
444              
445             =cut
446              
447 1     1   464 use Bigtop::Backend::Control;
  1         2  
  1         25  
448 1     1   6 use File::Spec;
  1         1  
  1         18  
449 1     1   4 use Inline;
  1         2  
  1         6  
450 1     1   35 use Bigtop;
  1         1  
  1         116  
451              
452             #-----------------------------------------------------------------
453             # Register keywords in the grammar
454             #-----------------------------------------------------------------
455              
456             BEGIN {
457 1     1   5 Bigtop::Parser->add_valid_keywords(
458             Bigtop::Keywords->get_docs_for(
459             'controller',
460             qw(
461             plugins
462             autocrud_helper
463             )
464             )
465             );
466              
467 1         5 Bigtop::Parser->add_valid_keywords(
468             Bigtop::Keywords->get_docs_for(
469             'method',
470             qw(
471             extra_args
472             order_by
473             rows
474             paged_conf
475             cols
476             col_labels
477             pseudo_cols
478             header_options
479             header_option_perms
480             authed_methods
481             permissions
482             literal
483             livesearch
484             row_options
485             row_option_perms
486             title
487             html_template
488             limit_by
489             where_terms
490             all_fields_but
491             fields
492             extra_keys
493             form_name
494             expects
495             returns
496             )
497             )
498             );
499              
500 1         5 Bigtop::Parser->add_valid_keywords(
501             Bigtop::Keywords->get_docs_for(
502             'field',
503             qw(
504             label
505             searchable
506             pseudo_value
507             unique_name
508             html_form_type
509             html_form_optional
510             html_form_constraint
511             html_form_default_value
512             html_form_cols
513             html_form_rows
514             html_form_display_size
515             html_form_hint
516             html_form_class
517             html_form_options
518             html_form_foreign
519             html_form_onchange
520             html_form_fieldset
521             date_select_text
522             html_form_raw_html
523             )
524             )
525             );
526             }
527              
528             #-----------------------------------------------------------------
529             # The Default Template
530             #-----------------------------------------------------------------
531              
532             our $template_is_setup = 0;
533             our $default_template_text = <<'EO_TT_blocks';
534             [% BLOCK hashref %]
535             return {
536             [% IF authed_methods.keys.0 %]
537             authed_methods => [
538             [% FOREACH k IN authed_methods.keys %]
539             { action => '[% k %]', group => '[% authed_methods.$k %]' },
540             [% END %]
541             ],
542             [% END %]
543             [% IF permissions.size >= 1 %]
544             permissions => {
545             bits => '[% permissions.0 %]',
546             group => '[% permissions.1 %]'
547             },
548             [% END %]
549             [% IF literals.0 %]
550              
551             [% FOREACH literal IN literals %]
552             [% literal %],
553             [% END %]
554             [% END %]
555             };
556             [% END %]
557              
558             [% BLOCK base_module %]
559             package [% app_name %];
560              
561             use strict;
562             use warnings;
563              
564             our $VERSION = '0.01';
565              
566             use base '[% gen_package_name %]';
567              
568             [% FOREACH module IN external_modules %]
569             use [% module %];
570             [% END %]
571             [% child_output %]
572              
573              
574             [%- IF class_accessors -%]
575             [% class_accessors %]
576             [%- END -%]
577              
578             [% IF init_sub %]
579             #-----------------------------------------------------------------
580             # $self->init( $r )
581             #-----------------------------------------------------------------
582             # This method inherited from [% gen_package_name +%]
583             [% END %]
584             [% IF config_accessor_comments %]
585             [% config_accessor_comments %]
586             [% END %]
587              
588             1;
589              
590             [% pod %]
591             [% END %]
592              
593             [% BLOCK gen_base_module %]
594             # NEVER EDIT this file. It was generated and will be overwritten without
595             # notice upon regeneration of this application. You have been warned.
596             package [% gen_package_name %];
597              
598             use strict;
599             use warnings;
600              
601             [% IF full_use_statement %]
602             use Gantry qw{[% IF engine +%]
603             -Engine=[% engine %][% END %][% IF template_engine +%]
604             -TemplateEngine=[% template_engine %][% END +%]
605             [% IF plugins %] -PluginNamespace=[% app_name +%]
606             [% plugins +%]
607             [% END %]
608             };
609             [% ELSE %]
610             use Gantry[% IF template_engine %] qw{ -TemplateEngine=[% template_engine %] }[% END %];
611             [% END %]
612              
613             use JSON;
614             use Gantry::Utils::TablePerms;
615              
616             our @ISA = qw( Gantry );
617              
618             [% FOREACH module IN external_modules %]
619             use [% module %];
620             [% END %]
621              
622             [% IF dbix %]
623             use [% base_model %];
624             sub schema_base_class { return '[% base_model %]'; }
625             use Gantry::Plugins::DBIxClassConn qw( get_schema );
626             [% END %]
627              
628             #-----------------------------------------------------------------
629             # $self->namespace() or [% app_name %]->namespace()
630             #-----------------------------------------------------------------
631             sub namespace {
632             return '[% app_name %]';
633             }
634              
635             [% init_sub %]
636              
637             [% config_accessors %]
638             [% IF child_output %]
639             [% child_output %]
640             [% ELSE %]
641             #-----------------------------------------------------------------
642             # $self->do_main( )
643             #-----------------------------------------------------------------
644             sub do_main {
645             my ( $self ) = @_;
646              
647             $self->stash->view->template( 'main.tt' );
648             $self->stash->view->title( '[% dist_name %]' );
649              
650             $self->stash->view->data( { pages => $self->site_links() } );
651             } # END do_main
652              
653             #-----------------------------------------------------------------
654             # $self->site_links( )
655             #-----------------------------------------------------------------
656             sub site_links {
657             my $self = shift;
658              
659             return [
660             [% FOREACH page IN pages %]
661             [% IF page.link.match( '^/' ) %]
662             { link => '[% page.link %]', label => '[% page.label %]' },
663             [% ELSE %]
664             { link => $self->app_rootp() . '/[% page.link %]', label => '[% page.label %]' },
665             [% END %]
666             [% END %]
667             ];
668             } # END site_links
669             [% END %]
670              
671             1;
672              
673             [% gen_pod +%]
674             [% END %]
675              
676             [% BLOCK test_file %]
677             use strict;
678             use warnings;
679              
680             use Test::More tests => [% module_count %];
681              
682             [% FOREACH module IN modules %]
683             use_ok( '[% module %]' );
684             [% END %]
685             [% END %]
686              
687             [% BLOCK pod_test %]
688             use Test::More;
689              
690             eval "use Test::Pod 1.14";
691             plan skip_all => 'Test::Pod 1.14 required' if $@;
692             plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
693              
694             all_pod_files_ok();
695             [% END %]
696              
697             [% BLOCK pod_cover_test %]
698             use Test::More;
699              
700             eval "use Test::Pod::Coverage 1.04";
701             plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
702             plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
703              
704             all_pod_coverage_ok();
705             [% END %]
706              
707             [% BLOCK run_test %]
708             use strict;
709             use warnings;
710              
711             use Test::More tests => [% num_tests %];
712              
713             use [% app_name %] qw{
714             -Engine=CGI
715             -TemplateEngine=[% template_engine || TT +%]
716             [% IF plugins %] -PluginNamespace=[% app_name +%]
717             [% plugins +%]
718             [% END %]
719             };
720              
721             use Gantry::Server;
722             use Gantry::Engine::CGI;
723              
724             # these tests must contain valid template paths to the core gantry templates
725             # and any application specific templates
726              
727             my $cgi = Gantry::Engine::CGI->new( {
728             config => {
729             [% FOREACH var_pair IN configs %]
730             [% var_pair.0 %] => '[% var_pair.1 %]',
731             [% END %]
732             },
733             locations => {
734             [% FOREACH location IN locations %]
735             '[% location.0 %]' => '[% location.1 %]',
736             [% END %]
737             },
738             } );
739              
740             my @tests = qw(
741             [% FOREACH location IN locations %]
742             [% location.0 +%]
743             [% END %]
744             );
745              
746             my $server = Gantry::Server->new();
747             $server->set_engine_object( $cgi );
748              
749             SKIP: {
750              
751             eval {
752             require DBD::SQLite;
753             };
754             skip 'DBD::SQLite is required for run tests.', [% num_tests %] if ( $@ );
755              
756             unless ( -f 'app.db' ) {
757             skip 'app.db sqlite database required for run tests.', [% num_tests %];
758             }
759              
760             foreach my $location ( @tests ) {
761             my( $status, $page ) = $server->handle_request_test( $location );
762             ok( $status eq '200',
763             "expected 200, received $status for $location" );
764              
765             if ( $status ne '200' ) {
766             print STDERR $page . "\n\n";
767             }
768             }
769              
770             }
771             [% END %]
772              
773             [% BLOCK controller_block %]
774             package [% package_name %];
775              
776             use strict;
777             use warnings;
778              
779             [% IF sub_modules %]
780             our $VERSION = '0.01';
781              
782             [% END %]
783             use base '[% inherit_from %]';
784             [% FOREACH module IN sub_modules %]
785             [% IF loop.first %]
786              
787             [% END %]
788             use [% module %];
789             [% END %]
790             [% child_output %]
791              
792             [% class_accessors %]
793              
794             1;
795              
796             [% pod %]
797             [% END %]
798              
799             [% BLOCK pod %]
800             =head1 NAME
801              
802             [% IF sub_module %]
803             [% package_name %] - A controller in the [% app_name %] application
804             [% ELSE %]
805             [% package_name %] - the base module of this web app
806             [% END %]
807              
808             =head1 SYNOPSIS
809              
810             This package is meant to be used in a stand alone server/CGI script or the
811             Perl block of an httpd.conf file.
812              
813             Stand Alone Server or CGI script:
814              
815             use [% package_name %];
816              
817             my $cgi = Gantry::Engine::CGI->new( {
818             config => {
819             #...
820             },
821             locations => {
822             [% IF sub_module %]
823             '/someurl' => '[% package_name %]',
824             [% ELSE %]
825             '/' => '[% package_name %]',
826             [% END %]
827             #...
828             },
829             } );
830              
831             httpd.conf:
832              
833            
834             # ...
835             use [% package_name %];
836            
837             [% IF sub_module %]
838              
839            
840             SetHandler perl-script
841             PerlHandler [% package_name +%]
842            
843             [% END %]
844              
845             If all went well, one of these was correctly written during app generation.
846              
847             =head1 DESCRIPTION
848              
849             This module was originally generated by Bigtop. But feel free to edit it.
850             You might even want to describe the table this module controls here.
851              
852             [% IF sub_module %]
853             =head1 METHODS
854             [% ELSIF gen_package_name AND NOT sub_modules %]
855             =head1 METHODS (inherited from [% gen_package_name %])
856             [% ELSE %]
857             =head1 METHODS
858             [% END %]
859              
860             =over 4
861              
862             [% FOREACH method IN methods %]
863             =item [% method %]
864              
865              
866             [% END %]
867              
868             =back
869              
870             [% IF gen_package_name AND mixins %]
871              
872             =head1 METHODS INHERITED FROM [% gen_package_name +%]
873              
874             =over 4
875              
876             [% FOREACH mixin IN mixins %]
877             =item [% mixin %]
878              
879              
880             [% END %]
881              
882             =back
883              
884             [% END -%]
885              
886             =head1 [% other_module_text +%]
887              
888             [% FOREACH used_module IN used_modules %]
889             [% used_module +%]
890             [% END %]
891             [% FOREACH see_also IN sub_modules %]
892             [% see_also +%]
893             [% END %]
894              
895             =head1 AUTHOR
896              
897             [% FOREACH author IN authors %]
898             [% author.0 %][% IF author.1 %], E[% author.1 %]E[% END +%]
899              
900             [% END %]
901             [%- IF contact_us %]
902             =head1 CONTACT US
903              
904             [% contact_us +%]
905              
906             [% END -%]
907             =head1 COPYRIGHT AND LICENSE
908              
909             Copyright (C) [% year %] [% copyright_holder %]
910              
911              
912             [% IF license_text %]
913             [% license_text %]
914              
915             [% ELSE %]
916             This library is free software; you can redistribute it and/or modify
917             it under the same terms as Perl itself, either Perl version 5.8.6 or,
918             at your option, any later version of Perl 5 you may have available.
919             [% END %]
920              
921             =cut
922             [% END %]
923              
924             [% BLOCK gen_pod %]
925             =head1 NAME
926              
927             [% gen_package_name %] - generated support module for [% package_name +%]
928              
929             =head1 SYNOPSIS
930              
931             In [% package_name %]:
932              
933             use base '[% gen_package_name %]';
934              
935             =head1 DESCRIPTION
936              
937             This module was generated by Bigtop (and IS subject to regeneration) to
938             provide methods in support of the whole [% package_name +%]
939             application.
940              
941             [% package_name %] should inherit from this module.
942              
943             =head1 METHODS
944              
945             =over 4
946              
947             [% FOREACH method IN methods %]
948             =item [% method +%]
949              
950             [% END %]
951              
952             =back
953              
954             =head1 AUTHOR
955              
956             [% FOREACH author IN authors %]
957             [% author.0 %][% IF author.1 %], E[% author.1 %]E[% END +%]
958              
959             [% END %]
960             [%- IF contact_us %]
961             =head1 CONTACT US
962              
963             [% contact_us +%]
964              
965             [% END -%]
966             =head1 COPYRIGHT AND LICENSE
967              
968             Copyright (C) [% year %] [% copyright_holder %]
969              
970              
971             [% IF license_text %]
972             [% license_text %]
973              
974             [% ELSE %]
975             This library is free software; you can redistribute it and/or modify
976             it under the same terms as Perl itself, either Perl version 5.8.6 or,
977             at your option, any later version of Perl 5 you may have available.
978             [% END %]
979              
980             =cut
981             [% END %]
982              
983             [% BLOCK gen_controller_pod %]
984             =head1 NAME
985              
986             [% gen_package_name %] - generated support module for [% package_name +%]
987              
988             =head1 SYNOPSIS
989              
990             In [% package_name %]:
991              
992             use base '[% gen_package_name %]';
993              
994             =head1 DESCRIPTION
995              
996             This module was generated by bigtop and IS subject to regeneration.
997             Use it in [% package_name %] to provide the methods below.
998             Feel free to override them.
999              
1000             =head1 METHODS
1001              
1002             =over 4
1003              
1004             [% FOREACH method IN gen_methods %]
1005             =item [% method +%]
1006              
1007             [% END %]
1008              
1009             =back
1010              
1011             =head1 AUTHOR
1012              
1013             Generated by bigtop and subject to regeneration.
1014              
1015             =cut
1016             [% END %]
1017              
1018             [% BLOCK gen_controller_block %]
1019             # NEVER EDIT this file. It was generated and will be overwritten without
1020             # notice upon regeneration of this application. You have been warned.
1021             package [% gen_package_name %];
1022              
1023             use strict;
1024             use warnings;
1025              
1026             [% IF wsdl %]
1027             use [% app_name %] qw(
1028             -PluginNamespace=[% package_name +%]
1029             SOAP::[% soap_style +%]
1030             );
1031              
1032             our @ISA = qw( [% app_name %] );
1033             [% ELSIF plugins %]
1034             use [% app_name %] qw{
1035             -PluginNamespace=[% package_name +%]
1036             [% plugins +%]
1037             };
1038              
1039             our @ISA = qw( [% app_name %] );
1040              
1041             use JSON;
1042             use Gantry::Utils::TablePerms;
1043             [% ELSE %]
1044             use base '[% app_name %]';
1045             use JSON;
1046             use Gantry::Utils::TablePerms;
1047             [% END %]
1048              
1049             [% child_output %]
1050             [% IF wsdl %][% wsdl %][% END %]
1051             [% IF init_sub %]
1052              
1053             [% init_sub %]
1054             [% END %]
1055             [% IF config_accessors %]
1056             [% config_accessors %]
1057             [% END %]
1058             [% IF plugins %]
1059              
1060             #-----------------------------------------------------------------
1061             # $self->namespace() or Apps::Checkbook->namespace()
1062             #-----------------------------------------------------------------
1063             sub namespace {
1064             return '[% package_name %]';
1065             }
1066             [% END %]
1067              
1068             1;
1069              
1070             [% gen_pod %]
1071              
1072             [% END %]
1073              
1074             [% BLOCK use_stub %]
1075             use [% module -%]
1076             [%- IF imports -%] qw(
1077             [% imports.join("\n ") %]
1078              
1079             );
1080              
1081             [%- ELSE -%];
1082             [% END %]
1083             [% END %]
1084              
1085             [% BLOCK explicit_use_stub %]
1086             use [% module %][% IF import_list %] [% import_list %][% END %];
1087             [% END %]
1088              
1089             [% BLOCK export_array %]
1090             our @EXPORT = qw(
1091             [% FOREACH exported_sub IN exported_subs %]
1092             [% exported_sub +%]
1093             [% END %]
1094             );
1095             [% END %]
1096              
1097             [% BLOCK dbix_uses %]
1098             [% use_my_model %]
1099             use [% base_model %];
1100             sub schema_base_class { return '[% base_model %]'; }
1101             use Gantry::Plugins::DBIxClassConn qw( get_schema );
1102             [% END %]
1103              
1104             [% BLOCK get_orm_helper %]
1105             #-----------------------------------------------------------------
1106             # get_orm_helper( )
1107             #-----------------------------------------------------------------
1108             sub get_orm_helper {
1109             return '[% helper %]';
1110             }
1111              
1112             [% END %]
1113              
1114             [% BLOCK class_access %]
1115             #-----------------------------------------------------------------
1116             # get_model_name( )
1117             #-----------------------------------------------------------------
1118             sub get_model_name {
1119             return $[% model_alias %];
1120             }
1121              
1122             [% END %]
1123              
1124             [% BLOCK text_description %]
1125             #-----------------------------------------------------------------
1126             # text_descr( )
1127             #-----------------------------------------------------------------
1128             sub text_descr {
1129             return '[% description %]';
1130             }
1131             [% END %]
1132              
1133             [% BLOCK controller_method +%]
1134             #-----------------------------------------------------------------
1135             # $self->[% method_name %]( [% child_output.doc_args.join( ', ' ) %] )
1136             #-----------------------------------------------------------------
1137             # This method inherited from [% gen_package_name %]
1138              
1139             [% END %]
1140              
1141             [% BLOCK gen_controller_method +%]
1142             #-----------------------------------------------------------------
1143             # $self->[% method_name %]( [% child_output.doc_args.join( ', ' ) %] )
1144             #-----------------------------------------------------------------
1145             sub [% method_name %] {
1146             [% child_output.body %]
1147             } # END [% method_name %]
1148              
1149             [% END %]
1150              
1151             [% BLOCK init_method_body %]
1152             [% arg_capture %]
1153              
1154             # process SUPER's init code
1155             $self->SUPER::init( $r );
1156              
1157             [% FOREACH config IN configs %]
1158             $self->set_[% config %]( $self->fish_config( '[% config %]' ) || '' );
1159             [% END %]
1160             [% END %]
1161              
1162             [% BLOCK config_accessors %]
1163             [% FOREACH config IN configs %]
1164             #-----------------------------------------------------------------
1165             # $self->set_[% config %]( $new_value )
1166             #-----------------------------------------------------------------
1167             sub set_[% config %] {
1168             my ( $self, $value ) = @_;
1169              
1170             $self->{ __[% config %]__ } = $value;
1171             }
1172              
1173             #-----------------------------------------------------------------
1174             # $self->[% config %]( )
1175             #-----------------------------------------------------------------
1176             sub [% config %] {
1177             my $self = shift;
1178              
1179             return $self->{ __[% config %]__ };
1180             }
1181              
1182             [% END %]
1183             [% END %]
1184              
1185             [% BLOCK arg_capture %]
1186             [% FOREACH arg IN args %]
1187             my [% arg %] = shift;
1188             [% END %]
1189             [% END %]
1190              
1191             [% BLOCK arg_capture_st_nick_style %]
1192             my ( [% args.join( ', ' ) %] ) = @_;
1193             [% END %]
1194              
1195             [% BLOCK self_setup %]
1196             $self->stash->view->template( '[% template %]' );
1197             $self->stash->view->title( '[% title %]' );
1198             [% IF with_real_loc %]
1199              
1200             my $real_location = $self->location() || '';
1201             if ( $real_location ) {
1202             $real_location =~ s{/+$}{};
1203             $real_location .= '/';
1204             }
1205             [% END %]
1206             [% END %]
1207              
1208             [% BLOCK main_links %]
1209             $self->stash->view->data( { pages => $self->site_links() } );
1210             [% END %]
1211              
1212             [% BLOCK site_links %]
1213             return [
1214             [% FOREACH page IN pages %]
1215             { link => [% page.link %], label => '[% page.label %]' },
1216             [% END %]
1217             ];
1218             [% END %]
1219              
1220             [% BLOCK main_heading %]
1221             [% IF limit_by %]
1222             my $header_option_suffix = ( $[% limit_by %] ) ? "/$[% limit_by %]" : '';
1223              
1224             [% END %]
1225             my @header_options = (
1226             [% FOREACH option IN header_options %]
1227             {
1228             text => '[% option.text %]',
1229             link => [% option.location +%],
1230             type => '[% option.type %]',
1231             },
1232             [% END %]
1233             );
1234              
1235             my $retval = {
1236             headings => [
1237             [% FOREACH heading IN headings %]
1238             [% IF heading.simple %]
1239             [% IF heading.simple.match( "'" ) %]q[[% heading.simple %]][% ELSE %]'[% heading.simple %]'[% END %],
1240             [% ELSIF heading.href %]
1241             '[% heading.href.text %]][% ELSE %]'>[% heading.href.text %]'[% END %],
1242             [% END %]
1243             [% END %]
1244             ],
1245             };
1246             [% END %]
1247              
1248             [% BLOCK main_table %]
1249              
1250             [%- IF livesearch %]
1251             $retval->{ livesearch } = 1;
1252              
1253             [% END -%]
1254             my $params = $self->params;
1255              
1256             [% IF where_terms.size > 0 %]
1257             my $search = {
1258             [% FOREACH where_term IN where_terms %]
1259             [% where_term.col_name %] => [% where_term.value %],
1260             [% END %]
1261             };
1262             [% ELSE %]
1263             my $search = {};
1264             [% END %]
1265             if ( $params->{ search } ) {
1266             my $form = $self->form();
1267              
1268             my @searches;
1269             foreach my $field ( @{ $form->{ fields } } ) {
1270             if ( $field->{ searchable } ) {
1271             push( @searches,
1272             ( $field->{ name } => { 'like', "%$params->{ search }%" } )
1273             );
1274             }
1275             }
1276              
1277             $search = {
1278             -or => \@searches
1279             } if scalar( @searches ) > 0;
1280             }
1281              
1282             my @row_options = (
1283             [% FOREACH row_option IN row_options %]
1284             {
1285             text => '[% row_option.text %]',
1286             [% IF row_option.location %]
1287             link => [% row_option.location %],
1288             [% END %]
1289             type => '[% row_option.type %]',
1290             },
1291             [% END %]
1292             );
1293              
1294             my $perm_obj = Gantry::Utils::TablePerms->new(
1295             {
1296             site => $self,
1297             real_location => $real_location,
1298             header_options => \@header_options,
1299             row_options => \@row_options,
1300             }
1301             );
1302              
1303             $retval->{ header_options } = $perm_obj->real_header_options;
1304              
1305             my $limit_to_user_id = $perm_obj->limit_to_user_id;
1306             $search->{ user_id } = $limit_to_user_id if ( $limit_to_user_id );
1307              
1308             [% IF dbix AND rows AND limit_by -%]
1309             my $page = $params->{ page } || 1;
1310              
1311             if ( $[% limit_by %] ) {
1312             $search->{ [% limit_by %] } = $[% limit_by %];
1313             }
1314              
1315             my $schema = $self->get_schema();
1316             my $results = $[% model %]->get_listing(
1317             {
1318             [% IF pseudo_cols.size > 0 %]
1319             '+select' => [[% FOREACH pseudo_col IN pseudo_cols %][% pseudo_col.field %][% UNLESS loop.last %] [% END %][% END %]],
1320             '+as' => [[% FOREACH pseudo_col IN pseudo_cols %]'[% pseudo_col.alias %]'[% UNLESS loop.last %] [% END %][% END %]],
1321             [% END %]
1322             schema => $schema,
1323             rows => [% rows %],
1324             where => $search,[% IF order_by %][% "\n" %] order_by => '[% order_by %]',[% END +%]
1325             }
1326             );
1327              
1328             my $rows = $results->page( $page );
1329             $retval->{ page } = $rows->pager();
1330              
1331             ROW:
1332             while ( my $row = $rows->next ) {
1333             [%- ELSIF dbix AND rows -%]
1334             my $page = $params->{ page } || 1;
1335              
1336             my $schema = $self->get_schema();
1337             my $results = $[% model %]->get_listing(
1338             {
1339             [% IF pseudo_cols.size > 0 %]
1340             '+select' => [[% FOREACH pseudo_col IN pseudo_cols %][% pseudo_col.field %][% UNLESS loop.last %] [% END %][% END %]],
1341             '+as' => [[% FOREACH pseudo_col IN pseudo_cols %]'[% pseudo_col.alias %]'[% UNLESS loop.last %] [% END %][% END %]],
1342             [% END %]
1343             schema => $schema,
1344             rows => [% rows %],
1345             where => $search,[% IF order_by %][% "\n" %] order_by => '[% order_by %]',[% END +%]
1346             }
1347             );
1348              
1349             my $rows = $results->page( $page );
1350             $retval->{ page } = $rows->pager();
1351              
1352             ROW:
1353             while ( my $row = $rows->next ) {
1354             [%- ELSIF dbix AND limit_by -%]
1355             if ( $[% limit_by %] ) {
1356             $search->{ [% limit_by %] } = $[% limit_by %];
1357             }
1358              
1359             my $schema = $self->get_schema();
1360             my @rows = $[% model %]->get_listing(
1361             {
1362             [% IF pseudo_cols.size > 0 %]
1363             '+select' => [[% FOREACH pseudo_col IN pseudo_cols %][% pseudo_col.field %][% UNLESS loop.last %] [% END %][% END %]],
1364             '+as' => [[% FOREACH pseudo_col IN pseudo_cols %]'[% pseudo_col.alias %]'[% UNLESS loop.last %] [% END %][% END %]],
1365             [% END %]
1366             schema => $schema,
1367             where => $search,[% IF order_by %][% "\n" %] order_by => '[% order_by %]',[% END +%]
1368             }
1369             );
1370              
1371             ROW:
1372             foreach my $row ( @rows ) {
1373             [%- ELSIF dbix -%]
1374             my $schema = $self->get_schema();
1375             my @rows = $[% model %]->get_listing(
1376             {
1377             [% IF pseudo_cols.size > 0 %]
1378             '+select' => [[% FOREACH pseudo_col IN pseudo_cols %][% pseudo_col.field %][% UNLESS loop.last %] [% END %][% END %]],
1379             '+as' => [[% FOREACH pseudo_col IN pseudo_cols %]'[% pseudo_col.alias %]'[% UNLESS loop.last %] [% END %][% END %]],
1380             [% END %]
1381             schema => $schema,
1382             where => $search,[% IF order_by %][% "\n" %] order_by => '[% order_by %]',[% END +%]
1383             }
1384             );
1385              
1386             ROW:
1387             foreach my $row ( @rows ) {
1388             [%- ELSE -%]
1389             my @rows = $[% model %]->get_listing([% IF order_by %] { order_by => '[% order_by %]', } [% END %]);
1390              
1391             ROW:
1392             foreach my $row ( @rows ) {
1393             [%- END -%]
1394              
1395             last ROW if $perm_obj->hide_all_data;
1396              
1397             my $id = $row->id;
1398             [% FOREACH foreigner IN foreigners %]
1399             my $[% foreigner %] = ( $row->[% foreigner %] )
1400             ? $row->[% foreigner %]->foreign_display()
1401             : '';
1402             [% END %]
1403              
1404             push(
1405             @{ $retval->{rows} }, {
1406             orm_row => $row,
1407             data => [
1408             [% FOREACH data_col IN data_cols %]
1409             [% data_col %],
1410             [% END %]
1411             ],
1412             options => $perm_obj->real_row_options( $row ),
1413             }
1414             );
1415             }
1416              
1417             if ( $params->{ json } ) {
1418             $self->template_disable( 1 );
1419              
1420             my $obj = {
1421             headings => $retval->{ headings },
1422             header_options => $retval->{ header_options },
1423             rows => $retval->{ rows },
1424             };
1425              
1426             my $json = to_json( $obj, { allow_blessed => 1 } );
1427             return( $json );
1428             }
1429              
1430             $self->stash->view->data( $retval );
1431             [% END %]
1432              
1433             [% BLOCK form_body %]
1434             [% arg_capture %]
1435             [%- IF dbix -%]
1436             my $selections = $[% model %]->get_form_selections(
1437             {
1438             schema => $self->get_schema(),
1439             [% IF refers_to.size > 0 %]
1440             foreign_tables => {
1441             [% FOREACH rt_table IN refers_to %]
1442             '[% rt_table %]' => 1,
1443             [% END %]
1444             }
1445             [% END -%]
1446             }
1447             );
1448              
1449             [%- ELSE -%]
1450             my $selections = $[% model %]->get_form_selections();
1451              
1452             [%- END -%]
1453              
1454             return {
1455             [% IF form_name %] name => '[% form_name %]',
1456             [% END -%]
1457             [% IF raw_row %] row => $row,
1458             [% ELSE %] row => $data->{row},
1459             [% END -%]
1460             [% FOREACH extra_key_name IN extra_keys.keys() %]
1461             [% extra_key_name %] => [% extra_keys.$extra_key_name %],
1462             [% END %]
1463             fields => [
1464             [% FOREACH field IN fields %]
1465             {
1466             [% FOREACH key = field.keys %]
1467             [% IF key == 'options_string' %]
1468             options => [% field.$key %],
1469             [% ELSIF key == 'constraint' OR field.$key.match( '^\d+$' ) %]
1470             [% key %] => [% field.$key %],
1471             [% ELSIF key == 'options' %]
1472             options => [
1473             [% arg_list = field.$key %]
1474             [% FOREACH pair IN arg_list %]
1475             [% FOREACH pair_key IN pair.keys() %]
1476             { label => '[% pair_key %]', value => '[% pair.$pair_key %]' },
1477             [% END %]
1478             [% END %]
1479             ],
1480             [% ELSE %]
1481             [% key %] => [% IF field.$key.match( "'" ) %]q[[% field.$key %]][% ELSE %]'[% field.$key %]'[% END %],
1482             [% END %]
1483             [% END %]
1484             },
1485             [% END %]
1486             ],
1487             };
1488             [% END %]
1489              
1490             [% BLOCK crud_helpers %]
1491              
1492             my $[% crud_name %] = Gantry::Plugins::CRUD->new(
1493             add_action => \&[% crud_name %]_add,
1494             edit_action => \&[% crud_name %]_edit,
1495             delete_action => \&[% crud_name %]_delete,
1496             form => __PACKAGE__->can( '[% form_method_name %]' ),
1497             redirect => \&[% crud_name %]_redirect,
1498             text_descr => '[% text_descr %]',
1499             );
1500              
1501             #-----------------------------------------------------------------
1502             # $self->[% crud_name %]_redirect( $data )
1503             # The generated version mimics the default behavior, feel free
1504             # to delete the redirect key from the constructor call for $crud
1505             # and this sub.
1506             #-----------------------------------------------------------------
1507             sub [% crud_name %]_redirect {
1508             my ( $self, $data ) = @_;
1509             return $self->location;
1510             }
1511              
1512             #-------------------------------------------------
1513             # $self->do_add( )
1514             #-------------------------------------------------
1515             sub do_add {
1516             my $self = shift;
1517             [% IF with_perms %]
1518              
1519             Gantry::Plugins::CRUD::verify_permission( { site => $self } );
1520             [% END %]
1521              
1522             $[% crud_name %]->add( $self, { data => \@_ } );
1523             }
1524              
1525             #-------------------------------------------------
1526             # $self->[% crud_name %]_add( $params, $data )
1527             #-------------------------------------------------
1528             sub [% crud_name %]_add {
1529             my ( $self, $params, $data ) = @_;
1530              
1531             # make a new row in the $[% model_alias %] table using data from $params
1532             # remember to add commit if needed
1533              
1534             $[% model_alias %]->gupdate_or_create( $self, $params );
1535             }
1536              
1537             #-------------------------------------------------
1538             # $self->do_delete( $doomed_id, $confirm )
1539             #-------------------------------------------------
1540             sub do_delete {
1541             my ( $self, $doomed_id, $confirm ) = @_;
1542              
1543             my $row = $[% model_alias %]->gfind( $self, $doomed_id );
1544             [% IF with_perms %]
1545              
1546             Gantry::Plugins::CRUD::verify_permission( { site => $self, row => $row } );
1547             [% END %]
1548              
1549             $[% crud_name %]->delete( $self, $confirm, { row => $row } );
1550             }
1551              
1552             #-------------------------------------------------
1553             # $self->[% crud_name %]_delete( $data )
1554             #-------------------------------------------------
1555             sub [% crud_name %]_delete {
1556             my ( $self, $data ) = @_;
1557              
1558             # fish the id (or the actual row) from the data hash
1559             # delete it
1560             # remember to add commit if needed
1561              
1562             $data->{ row }->delete;
1563             }
1564              
1565             #-------------------------------------------------
1566             # $self->do_edit( $id )
1567             #-------------------------------------------------
1568             sub do_edit {
1569             my ( $self, $id ) = @_;
1570              
1571             my $row = $[% model_alias %]->gfind( $self, $id );
1572             [% IF with_perms %]
1573              
1574             Gantry::Plugins::CRUD::verify_permission( { site => $self, row => $row } );
1575             [% END %]
1576              
1577             $[% crud_name %]->edit( $self, { row => $row } );
1578             }
1579              
1580             #-------------------------------------------------
1581             # $self->[% crud_name %]_edit( $param, $data )
1582             #-------------------------------------------------
1583             sub [% crud_name %]_edit {
1584             my( $self, $params, $data ) = @_;
1585              
1586             # retrieve the row from the data hash
1587             # update the row
1588             # remember to add commit if needed
1589              
1590             $data->{row}->update( $params );
1591             }
1592             [% END %]
1593              
1594             [% BLOCK SOAP_gen_method_body %]
1595             my $self = shift;
1596             my $input = $self->soap_in;
1597             my $output_data = $self->[% internal_method %]( $input );
1598              
1599             $self->template_disable( 1 );
1600              
1601             return $self->soap_out( $output_data );
1602             [% END %]
1603              
1604             [% BLOCK SOAP_stub_method %]
1605             #-----------------------------------------------------------------
1606             # $self->[% internal_method %]( )
1607             #-----------------------------------------------------------------
1608             sub [% internal_method %] {
1609             my ( $self, $input ) = @_;
1610             } # END [% internal_method %]
1611             [% END %]
1612              
1613             [% BLOCK soap_methods %]
1614              
1615             #-----------------------------------------------------------------
1616             # $self->namespace( )
1617             #-----------------------------------------------------------------
1618             sub namespace {
1619             return '[% stub_module %]';
1620             } # END namespace
1621              
1622             #-----------------------------------------------------------------
1623             # $self->get_soap_ops
1624             #-----------------------------------------------------------------
1625             sub get_soap_ops {
1626             my $self = shift;
1627              
1628             return {
1629             soap_name => '[% soap_name %]',
1630             location => $self->location,
1631             namespace_base => '[% namespace_base %]',
1632             operations => [
1633             [% FOREACH op IN operations %]
1634             {
1635             name => '[% op.name %]',
1636             expects => [
1637             [% FOREACH param IN op.expects %]
1638             { name => '[% param.name %]', type => '[% param.type %]' },
1639             [% END %]
1640             ],
1641             returns => [
1642             [% FOREACH param IN op.returns %]
1643             { name => '[% param.name %]', type => '[% param.type %]' },
1644             [% END %]
1645             ],
1646             },
1647             [% END %]
1648             ],
1649             };
1650             } # END get_soap_ops
1651             [% END %]
1652             [% BLOCK soap_doc_advice %]
1653             #-----------------------------------------------------------------
1654             # $self->[% handler_method %]( )
1655             #-----------------------------------------------------------------
1656             sub [% handler_method %] {
1657             [% arg_capture %]
1658              
1659             my $params = $self->params(); # easy way
1660              
1661             [% FOREACH expected_param IN soap_params.expects %]
1662             my $[% expected_param.name %] = $params->{ [% expected_param.name %] };
1663             [% END %]
1664              
1665             # hard way:
1666             # my $xmlobj = XML::LibXML->new();
1667             # my $dom = $xmlobj->parse_string( $self->get_post_body() )
1668             # or return return_error( "Mal-formed XML request: $!" );
1669             #
1670             [% FOREACH expected_param IN soap_params.expects %]
1671             # my ( $[% expected_param.name %]_node ) = $dom->getElementsByLocalName( '[% expected_param.name %]' );
1672             # my $[% expected_param.name %] = $[% expected_param.name %]_node->textContent;
1673             [% END %]
1674              
1675             [% FOREACH returned_param IN soap_params.returns %]
1676             my $[% returned_param.name %];
1677             [% END %]
1678              
1679             my $time = $self->soap_current_time();
1680              
1681             my $ret_struct = [
1682             {
1683             GantrySoapServiceResponse => [
1684             [% FOREACH returned_param IN soap_params.returns %]
1685             { [% returned_param.name %] => $[% returned_param.name %] },
1686             [% END %]
1687             ]
1688             }
1689             ];
1690              
1691             $self->soap_namespace_set(
1692             'http://usegantry.org/soapservice'
1693             );
1694              
1695             return $self->soap_out( $ret_struct, 'internal', 'pretty' );
1696             } # END [% handler_method %]
1697             [% END %]
1698             EO_TT_blocks
1699              
1700             #-----------------------------------------------------------------
1701             # Methods in the B::C::Gantry package
1702             #-----------------------------------------------------------------
1703              
1704             sub what_do_you_make {
1705             return [
1706 0     0 1   [ 'lib/AppName.pm' => 'Base module stub [safe to change]' ],
1707             [ 'lib/AppName/*.pm' => 'Controller stubs [safe to change]' ],
1708             [ 'lib/AppName/GEN/*.pm' => 'Generated code [please, do not edit]' ],
1709             ];
1710             }
1711              
1712             sub backend_block_keywords {
1713             return [
1714 0     0 1   { keyword => 'no_gen',
1715             label => 'No Gen',
1716             descr => 'Skip everything for this backend',
1717             type => 'boolean' },
1718              
1719             { keyword => 'run_test',
1720             label => 'Run Tests',
1721             descr => 'Makes tests which hit pages via a simple server',
1722             type => 'boolean',
1723             default => 'true' },
1724              
1725             { keyword => 'full_use',
1726             label => 'Full Use Statement',
1727             descr => 'use Gantry qw( -Engine=... ); [defaults to false]',
1728             type => 'boolean',
1729             default => 'false' },
1730              
1731             { keyword => 'dbix',
1732             label => 'For use with DBIx::Class',
1733             descr => 'Makes controllers usable with DBIx::Class',
1734             type => 'boolean',
1735             default => 'false' },
1736              
1737             { keyword => 'template',
1738             label => 'Alternate Template',
1739             descr => 'A custom TT template.',
1740             type => 'text' },
1741             ];
1742             }
1743              
1744             sub setup_template {
1745 0     0 1   my $class = shift;
1746 0   0       my $template_text = shift || $default_template_text;
1747              
1748 0 0         return if ( $template_is_setup );
1749              
1750 0           Inline->bind(
1751             TT => $template_text,
1752             POST_CHOMP => 1,
1753             TRIM_LEADING_SPACE => 0,
1754             TRIM_TRAILING_SPACE => 0,
1755             );
1756              
1757 0           $template_is_setup = 1;
1758             }
1759              
1760             sub gen_Control {
1761 0     0 1   my $class = shift;
1762 0           my $build_dir = shift;
1763 0           my $bigtop_tree = shift;
1764              
1765 0           my $app_name = $bigtop_tree->get_appname();
1766 0           my $lookup = $bigtop_tree->{application}{lookup};
1767 0           my $app_stmnts = $lookup->{app_statements};
1768 0           my $authors = $bigtop_tree->get_authors();
1769 0           my $contact_us = $bigtop_tree->get_contact_us();
1770 0           my @external_modules;
1771 0           my $copyright_holder = $bigtop_tree->get_copyright_holder();
1772 0           my $license_text = $bigtop_tree->get_license_text();
1773 0           my $config = $bigtop_tree->get_config();
1774 0           my $config_block = $config->{Control};
1775              
1776 0           my $full_use_statement = 0;
1777 0 0 0       if ( defined $config_block->{full_use} and $config_block->{full_use} ) {
1778 0           $full_use_statement = 1;
1779             }
1780              
1781 0 0         @external_modules = @{ $app_stmnts->{uses} }
  0            
1782             if defined ( $app_stmnts->{uses} );
1783              
1784 0           my $year = ( localtime )[5];
1785 0           $year += 1900;
1786              
1787 0           my ( $module_dir, @sub_dirs )
1788             = Bigtop::make_module_path( $build_dir, $app_name );
1789              
1790             # First, make one controller for each controller block in the bigtop_file
1791             # collect the names of all the controllers and their models.
1792 0           my $sub_modules = $bigtop_tree->walk_postorder(
1793             'output_controllers',
1794             {
1795             module_dir => $module_dir,
1796             app_name => $app_name,
1797             lookup => $lookup,
1798             tree => $bigtop_tree,
1799             authors => $authors,
1800             contact_us => $contact_us,
1801             copyright_holder => $copyright_holder,
1802             license_text => $license_text,
1803             year => $year,
1804             sub_modules => undef,
1805             },
1806             );
1807              
1808             # Second, make the main modules.
1809 0           my $app_configs = $bigtop_tree->{application}{lookup}{configs};
1810 0           my $config_values = $bigtop_tree->get_app_configs;
1811 0           my $base_controller = $bigtop_tree->walk_postorder( 'base_controller' );
1812              
1813 0           my ( $all_configs, $accessor_configs )
1814             = build_config_lists( $app_configs, $config_values );
1815              
1816 0           my $config_accessors =
1817             Bigtop::Backend::Control::Gantry::config_accessors(
1818             { configs => $accessor_configs, }
1819             );
1820              
1821 0           my @pod_methods = map { $_, "set_$_" } @{ $accessor_configs };
  0            
  0            
1822              
1823 0           my $init_sub = build_init_sub( $accessor_configs );
1824              
1825             # now form nav links
1826 0           my $location = $bigtop_tree->walk_postorder( 'output_location' )->[0];
1827 0           my $nav_links = $bigtop_tree->walk_postorder(
1828             'output_nav_links', $location
1829             );
1830              
1831 0           my @pages;
1832 0           foreach my $nav_link ( @{ $nav_links } ) {
  0            
1833 0           my %nav_pair = @{ $nav_link };
  0            
1834 0           push @pages, \%nav_pair;
1835             }
1836              
1837 0           my( $base_model, $dbix ) = ( '', '' );
1838 0 0         if ( $config_block->{ dbix } ) {
1839 0           $base_model = $app_name . '::Model';
1840 0           $dbix = 1;
1841             }
1842            
1843 0 0 0       if ( defined $base_controller->[0] and $base_controller->[0] ) {
1844             # warn "skipping previously generated modules\n";
1845 0           $bigtop_tree->walk_postorder(
1846             'output_controllers',
1847             {
1848             module_dir => $module_dir,
1849             app_name => $app_name,
1850             lookup => $lookup,
1851             tree => $bigtop_tree,
1852             authors => $authors,
1853             contact_us => $contact_us,
1854             copyright_holder => $copyright_holder,
1855             license_text => $license_text,
1856             year => $year,
1857             sub_modules => $sub_modules,
1858             full_use_statement => $full_use_statement,
1859             init_sub => $init_sub,
1860             config_accessors => $config_accessors,
1861             dbix => $dbix,
1862             base_model => $base_model,
1863             methods => \@pod_methods,
1864             pages => \@pages,
1865 0           %{ $config },
1866             },
1867             );
1868             }
1869             else { # spoof up a base_controller block, if they don't provide one
1870 0           my $base_module_name = pop @sub_dirs;
1871 0           my $base_module_file = File::Spec->catfile(
1872             $build_dir, 'lib', @sub_dirs, "$base_module_name.pm"
1873             );
1874 0           my $gen_base_module_name = "GEN$base_module_name";
1875 0           my $gen_base_module_file = File::Spec->catfile(
1876             $build_dir, 'lib', @sub_dirs, "$gen_base_module_name.pm"
1877             );
1878 0           my $gen_package_name = join '::', @sub_dirs, $gen_base_module_name;
1879              
1880             # remember the pod
1881              
1882 0           unshift @pod_methods, qw( namespace init do_main site_links );
1883              
1884 0 0         if ( $config_block->{ dbix } ) {
1885 0           unshift @pod_methods, 'schema_base_class';
1886             }
1887              
1888 0           my $pod = Bigtop::Backend::Control::Gantry::pod(
1889             {
1890             package_name => $app_name,
1891             gen_package_name => $gen_package_name,
1892             methods => \@pod_methods,
1893             other_module_text=> 'SEE ALSO',
1894             used_modules => [ 'Gantry',
1895             $gen_package_name,
1896 0           @{ $sub_modules } ],
1897             authors => $authors,
1898             contact_us => $contact_us,
1899             copyright_holder => $copyright_holder,
1900             license_text => $license_text,
1901             sub_module => 0,
1902             year => $year,
1903             }
1904             );
1905              
1906 0           my $base_module_content =
1907             Bigtop::Backend::Control::Gantry::base_module(
1908             {
1909             dist_name => $base_module_name,
1910             app_name => $app_name,
1911             gen_package_name => $gen_package_name,
1912             external_modules => \@external_modules,
1913             sub_modules => $sub_modules,
1914             init_sub => $init_sub,
1915             config_accessors => $config_accessors,
1916             pod => $pod,
1917             full_use_statement => $full_use_statement,
1918             pages => \@pages,
1919 0           %{ $config }, # Go fish!
1920             }
1921             );
1922              
1923 0           eval {
1924 1     1   7 no warnings qw( Bigtop );
  1         2  
  1         184  
1925 0           Bigtop::write_file(
1926             $base_module_file, $base_module_content, 'no_overwrite'
1927             );
1928             };
1929 0 0         warn $@ if ( $@ );
1930              
1931 0           my $gen_pod = Bigtop::Backend::Control::Gantry::gen_pod(
1932             {
1933             package_name => $app_name,
1934             gen_package_name => $gen_package_name,
1935             methods => \@pod_methods,
1936             other_module_text=> 'SEE ALSO',
1937             used_modules => [ 'Gantry',
1938             $gen_package_name,
1939 0           @{ $sub_modules } ],
1940             authors => $authors,
1941             contact_us => $contact_us,
1942             copyright_holder => $copyright_holder,
1943             license_text => $license_text,
1944             sub_module => 0,
1945             year => $year,
1946             }
1947             );
1948              
1949 0           my $gen_base_content =
1950             Bigtop::Backend::Control::Gantry::gen_base_module(
1951             {
1952             dist_name => $base_module_name,
1953             app_name => $app_name,
1954             gen_package_name => $gen_package_name,
1955             external_modules => \@external_modules,
1956             sub_modules => $sub_modules,
1957             init_sub => $init_sub,
1958             config_accessors => $config_accessors,
1959             gen_pod => $gen_pod,
1960             full_use_statement => $full_use_statement,
1961             dbix => $dbix,
1962             base_model => $base_model,
1963             pages => \@pages,
1964 0           %{ $config }, # Go fish!
1965             }
1966             );
1967              
1968 0           eval {
1969 1     1   5 no warnings qw( Bigtop );
  1         2  
  1         950  
1970 0           Bigtop::write_file( $gen_base_module_file, $gen_base_content );
1971             };
1972 0 0         warn $@ if ( $@ );
1973             }
1974              
1975             # finally, make the tests
1976             # start with the use test (compile test for all controllers)
1977 0           my $test_dir = File::Spec->catdir( $build_dir, 't' );
1978 0           my $test_file = File::Spec->catfile( $test_dir, '01_use.t' );
1979              
1980 0           mkdir $test_dir;
1981              
1982 0           unshift @{ $sub_modules }, $app_name;
  0            
1983              
1984 0           my $module_count = @{ $sub_modules };
  0            
1985              
1986 0           my $test_file_content = Bigtop::Backend::Control::Gantry::test_file(
1987             {
1988             modules => $sub_modules,
1989             module_count => $module_count,
1990             }
1991             );
1992              
1993 0           eval { Bigtop::write_file( $test_file, $test_file_content ); };
  0            
1994 0 0         warn $@ if ( $@ );
1995              
1996             # now make the pod and pod coverage tests
1997 0           my $pod_test_file = File::Spec->catfile( $test_dir, '02_pod.t' );
1998 0           my $pod_cover_test_file = File::Spec->catfile(
1999             $test_dir, '03_podcover.t'
2000             );
2001              
2002 0           my $pod_test_content =
2003             Bigtop::Backend::Control::Gantry::pod_test( {} );
2004 0           my $pod_cover_test_content =
2005             Bigtop::Backend::Control::Gantry::pod_cover_test( {} );
2006              
2007 0           eval {
2008 1     1   7 no warnings qw( Bigtop );
  1         3  
  1         81  
2009 0           Bigtop::write_file(
2010             $pod_test_file, $pod_test_content, 'no overwrite'
2011             );
2012             };
2013 0 0         warn $@ if ( $@ );
2014              
2015 0           eval {
2016 1     1   6 no warnings qw( Bigtop );
  1         2  
  1         335  
2017 0           Bigtop::write_file(
2018             $pod_cover_test_file, $pod_cover_test_content, 'no overwrite'
2019             );
2020             };
2021 0 0         warn $@ if ( $@ );
2022              
2023             # finally, make the run test, unless they asked not to
2024 0 0 0       if ( not defined $config_block->{ run_test }
2025             or
2026             $config_block->{ run_test } )
2027             {
2028              
2029             # ...first, prepare the configs
2030 0           my @configs;
2031 0           my $saw_root = 0;
2032              
2033             APP_CONFIG:
2034 0           foreach my $var ( sort keys %{ $config_values->{ base } } ) {
  0            
2035              
2036 0 0         next APP_CONFIG if $var eq 'dbconn';
2037              
2038 0           my $value = $config_values->{ base }{ $var };
2039 0 0         if ( ref $value ) {
2040 0           ( $value ) = keys %{ $value };
  0            
2041             }
2042 0           push @configs, [ $var, $value ];
2043              
2044 0 0         $saw_root++ if $var eq 'root';
2045             }
2046 0           unshift @configs, [ 'dbconn', 'dbi:SQLite:dbname=app.db' ];
2047 0 0         push @configs, [ 'root', 'html:html/templates' ] unless $saw_root;
2048              
2049             # ...then, the locations
2050 0           my $locations = $bigtop_tree->walk_postorder(
2051             'output_test_locations', $lookup
2052             );
2053 0           my $num_tests = @{ $locations };
  0            
2054              
2055 0           my $run_test_file = File::Spec->catfile( $test_dir, '10_run.t' );
2056 0           my $run_test_content = Bigtop::Backend::Control::Gantry::run_test(
2057             {
2058             app_name => $app_name,
2059             configs => \@configs,
2060             locations => $locations,
2061             num_tests => $num_tests,
2062 0           %{ $config }, # fish for template engine name
2063             }
2064             );
2065              
2066 0           eval {
2067 1     1   8 no warnings qw( Bigtop );
  1         2  
  1         820  
2068 0           Bigtop::write_file(
2069             $run_test_file, $run_test_content,
2070             );
2071             };
2072 0 0         warn $@ if ( $@ );
2073              
2074             }
2075             }
2076              
2077             sub build_init_sub {
2078 0     0 1   my $configs = shift;
2079              
2080 0           my $arg_capture =
2081             Bigtop::Backend::Control::Gantry::arg_capture_st_nick_style(
2082             { args => [ qw( $self $r ) ] }
2083             );
2084              
2085 0           my $body = Bigtop::Backend::Control::Gantry::init_method_body(
2086             {
2087             arg_capture => $arg_capture,
2088             configs => $configs,
2089             }
2090             );
2091              
2092 0           my $method = Bigtop::Backend::Control::Gantry::gen_controller_method(
2093             {
2094             method_name => 'init',
2095             child_output => {
2096             body => $body,
2097             doc_args => [ '$r' ],
2098             },
2099             }
2100             );
2101              
2102 0           $method =~ s/^\s+//;
2103 0 0         $method =~ s/^/#/gm if ( @{ $configs } == 0 ); # no configs, comment it out
  0            
2104              
2105 0           return "$method\n";
2106             }
2107              
2108             sub build_config_lists {
2109 0     0 1   my $app_configs = shift;
2110 0           my $config_values = shift;
2111              
2112 0           my @accessor_configs;
2113             my @all_configs;
2114              
2115 0           SET_VAR:
2116 0           foreach my $config ( keys %{ $app_configs } ) {
2117              
2118 0 0         if ( defined $config_values ) {
2119 0 0         next SET_VAR unless defined $config_values->{ base }{ $config };
2120             }
2121              
2122 0           push @all_configs, $config;
2123              
2124 0           my $item = $app_configs->{$config}[0];
2125              
2126 0 0         if ( ref( $item ) =~ /HASH/ ) {
2127              
2128 0           my ( $value, $condition ) = %{ $item };
  0            
2129              
2130 0 0         next SET_VAR if $condition eq 'no_accessor';
2131             }
2132              
2133 0           push @accessor_configs, $config;
2134             }
2135              
2136 0           return \@all_configs, \@accessor_configs;
2137             }
2138              
2139             #-----------------------------------------------------------------
2140             # Packages named in the grammar
2141             #-----------------------------------------------------------------
2142              
2143             package # application
2144             application;
2145 1     1   8 use strict; use warnings;
  1     1   3  
  1         39  
  1         6  
  1         2  
  1         227  
2146              
2147             sub output_test_locations {
2148 0     0     my $self = shift;
2149 0           my $child_output = shift;
2150 0           my $lookup = shift;
2151              
2152 0           my $app_name = $self->get_name();
2153 0           my $base_location = '/';
2154              
2155 0           my @retval;
2156              
2157             # we only skip the test if there is an explicit, true, skip test statement
2158 0           my $skip_base_test = 0;
2159 0           my $base_controller = $lookup->{ controllers }{ base_controller };
2160              
2161 0 0         if ( defined $base_controller ) {
2162 0           my $skip_test = $base_controller->{ statements }{ skip_test };
2163 0 0         if ( defined $skip_test ) {
2164 0           $skip_base_test = $skip_test->[0];
2165             }
2166             }
2167              
2168 0 0         push @retval, [ $base_location, $app_name ] unless $skip_base_test;
2169              
2170 0           while ( @{ $child_output } ) {
  0            
2171 0           my ( $loc_type ) = shift @{ $child_output };
  0            
2172              
2173 0           my $data = shift @{ $child_output };
  0            
2174 0           my ( $location, $module ) = @{ $data };
  0            
2175              
2176 0 0         if ( $loc_type eq 'rel_location' ) {
2177 0           $location = $base_location . $location;
2178             }
2179              
2180 0           $module = $app_name . '::' . $module;
2181              
2182 0           push @retval, [ $location, $module ];
2183             }
2184              
2185 0           return \@retval;
2186             }
2187              
2188             package # join_table
2189             join_table;
2190 1     1   10 use strict; use warnings;
  1     1   6  
  1         35  
  1         6  
  1         1  
  1         72  
2191              
2192             sub output_field_names {
2193 0     0     my $self = shift;
2194 0           my $child_output = shift;
2195 0           my $data = shift;
2196              
2197 0 0         return unless $self->{__NAME__} eq $data->{table_of_interest};
2198              
2199 0           return $child_output;
2200             }
2201              
2202             package # table_block
2203             table_block;
2204 1     1   5 use strict; use warnings;
  1     1   3  
  1         20  
  1         5  
  1         1  
  1         84  
2205              
2206             sub output_field_names {
2207 0     0     my $self = shift;
2208 0           my $child_output = shift;
2209 0           my $data = shift;
2210              
2211 0 0         return unless $self->{__TYPE__} eq 'tables';
2212              
2213 0 0         return unless $self->{__NAME__} eq $data->{table_of_interest};
2214              
2215 0           return $child_output;
2216             }
2217              
2218             package # table_element_block
2219             table_element_block;
2220 1     1   5 use strict; use warnings;
  1     1   2  
  1         20  
  1         4  
  1         2  
  1         74  
2221              
2222             sub output_field_names {
2223 0     0     my $self = shift;
2224              
2225 0 0         return unless $self->{__TYPE__} eq 'field';
2226              
2227 0           return [ $self->{__NAME__} ];
2228             }
2229              
2230             package # controller_block
2231             controller_block;
2232 1     1   7 use strict; use warnings;
  1     1   2  
  1         27  
  1         5  
  1         4  
  1         33  
2233              
2234 1     1   5 use Bigtop;
  1         2  
  1         2063  
2235              
2236             my %magical_uses = (
2237             CRUD => 'Gantry::Plugins::CRUD',
2238             AutoCRUD => 'Gantry::Plugins::AutoCRUD',
2239             stub => '',
2240             );
2241             my %magical_gen_uses = (
2242             # SOAP => 'Gantry::Plugins::SOAP::RPCMP',
2243             );
2244              
2245             sub get_package_name {
2246 0     0     my $self = shift;
2247 0           my $data = shift;
2248              
2249 0           return $data->{app_name} . '::' . $self->get_name();
2250             }
2251              
2252             sub get_gen_package_name {
2253 0     0     my $self = shift;
2254 0           my $data = shift;
2255              
2256 0 0         if ( $self->is_base_controller ) {
2257 0           my @pieces = split /::/, $data->{ app_name };
2258 0           my $module_name = 'GEN' . pop @pieces;
2259 0           return join '::', @pieces, $module_name;
2260             }
2261             else {
2262 0           return $data->{app_name} . '::GEN::' . $self->get_name();
2263             }
2264             }
2265              
2266             # this on is for walk_postorder use
2267             sub base_controller {
2268 0     0     my $self = shift;
2269              
2270 0 0         return [ 1 ] if ( $self->is_base_controller );
2271             }
2272              
2273             sub skip_base_controller {
2274 0     0     my $self = shift;
2275              
2276 0 0         return unless $self->is_base_controller;
2277              
2278             #warn "I'm the base controller\n";
2279              
2280 0           return;
2281             }
2282              
2283             sub output_extra_use {
2284 0     0     my $self = shift;
2285 0           my $type = shift;
2286 0   0       my $module = $magical_uses{ $type } || return;
2287              
2288 0           my $poser = {
2289             __ARGS__ => [ $module ]
2290             };
2291 0           bless $poser, 'controller_statement';
2292              
2293 0           my %extra_use = @{ $poser->uses };
  0            
2294              
2295 0           my $output = $extra_use{ uses_output };
2296              
2297 0           return ( $output, $module );
2298             }
2299              
2300             sub output_extra_gen_use {
2301 0     0     my $self = shift;
2302 0           my $type = shift;
2303 0   0       my $module = $magical_gen_uses{ $type } || return;
2304              
2305 0           my $poser = {
2306             __ARGS__ => [ $module ]
2307             };
2308 0           bless $poser, 'controller_statement';
2309              
2310 0           my %extra_use = @{ $poser->uses };
  0            
2311              
2312 0           my $output = $extra_use{ uses_output };
2313              
2314 0           return ( $output, $module );
2315             }
2316              
2317             sub output_controllers {
2318 0     0     my $self = shift;
2319 0           shift;
2320 0           my $data = shift;
2321              
2322 0 0         if ( $self->is_base_controller ) { # if its the base, we need the subs
2323 0 0         return unless defined $data->{ sub_modules };
2324             }
2325             else { # if we have the subs, we don't need them again
2326 0 0         return if defined $data->{ sub_modules };
2327             }
2328              
2329 0           my $model_alias = $self->walk_postorder( 'get_model_alias' )->[0];
2330              
2331 0           $data->{ model_alias } = $model_alias;
2332              
2333 0           my $child_output = $self->walk_postorder( 'output_controller', $data );
2334              
2335             # generate the content of the controller and its GEN module
2336 0           my $short_name = $self->get_name();
2337 0           my $package_name = $self->get_package_name( $data );
2338 0           my $gen_package_name = $self->get_gen_package_name( $data );
2339              
2340             # skip it if we can
2341 0           my $statements = $data->{lookup}{controllers}{$short_name}{statements};
2342              
2343 0 0 0       return if ( defined $statements->{no_gen} and $statements->{no_gen}[0] );
2344              
2345             # Begin by inserting magical things based on controller type
2346 0           my $controller_type = $self->get_controller_type();
2347 0           my ( $extra_use, $extra_module )
2348             = $self->output_extra_use( $controller_type );
2349              
2350 0           my ( $gen_extra_use, $gen_extra_module )
2351             = $self->output_extra_gen_use( $controller_type );
2352              
2353             #############################################
2354             # Deal with what the children made for us. #
2355             #############################################
2356 0           my ( $output_str, $class_access, $gen_output_str, $output_hash )
2357             = _extract_output_from( $child_output );
2358              
2359 0           my $stub_method_names = $output_hash->{stub_method_name};
2360 0           my $gen_method_names = $output_hash->{gen_method_name};
2361 0           my $crud_doc_methods = $output_hash->{crud_doc_methods};
2362             my $soap_style = _extract_soap_style(
2363             $output_hash->{ soap_style }
2364 0           );
2365              
2366             # gen_method_names is an array ref of names or undef if there are none
2367              
2368             # build beginning of dependencies section (the base app and the GEN
2369             # if it has methods)
2370 0 0         my @depend_head = ( $data->{app_name} )
2371             unless ( $self->is_base_controller );
2372              
2373             push @depend_head, $gen_package_name
2374             if ( defined $gen_method_names
2375             or
2376             defined $output_hash->{ extra_stub_method_name }
2377 0 0 0       );
2378              
2379 0           unshift @{ $output_hash->{used_modules} }, \@depend_head;
  0            
2380              
2381 0           my $used_modules = _flatten( $output_hash->{used_modules} );
2382              
2383 0 0         if ( $extra_use ) {
2384 0           push @{ $used_modules }, $extra_module;
  0            
2385 0           chomp $extra_use;
2386 0           $output_str = "\n$extra_use" . $output_str;
2387             }
2388              
2389 0 0         if ( $gen_extra_use ) {
2390 0           push @{ $used_modules }, $gen_extra_module;
  0            
2391 0           chomp $gen_extra_use;
2392 0           $gen_output_str = "\n$gen_extra_use" . $gen_output_str;
2393             }
2394              
2395             # deal with SOAP rpc stubs
2396 0 0         if ( defined $output_hash->{ extra_stub_method_name } ) {
2397 0           push @{ $stub_method_names },
2398 0           @{ $output_hash->{ extra_stub_method_name } };
  0            
2399             }
2400              
2401             # ... and SOAP wsdl method
2402 0           my $wsdl;
2403 0 0         if ( defined $output_hash->{ soap_params } ) {
2404             $wsdl = Bigtop::Backend::Control::Gantry::soap_methods(
2405             {
2406             operations => $output_hash->{ soap_params },
2407             soap_name => $statements->{ soap_name }[0],
2408 0           namespace_base => $statements->{ namespace_base }[0],
2409             stub_module => $package_name,
2410             }
2411             );
2412 0 0         if ( $wsdl ) {
2413 0           push @{ $gen_method_names }, qw( namespace get_soap_ops );
  0            
2414             }
2415             }
2416              
2417             # make doc stubs for standard controller accessor methods
2418 0 0         if ( defined $statements->{controls_table} ) {
2419 0           push @{ $stub_method_names }, qw( get_model_name text_descr );
  0            
2420             }
2421              
2422 0           my $config_block = $data->{ tree }->get_config()->{ Control };
2423 0 0         if ( $config_block->{ dbix } ) {
2424              
2425 0           push @{ $stub_method_names }, qw( get_orm_helper );
  0            
2426              
2427 0 0         if ( $self->is_base_controller ) {
2428 0           push @{ $gen_method_names }, qw( schema_base_class );
  0            
2429             }
2430             }
2431              
2432             # make the gen use statement if it has methods
2433 0           my $gen_use_statement;
2434 0 0         if ( defined $gen_method_names ) {
2435 0           $gen_use_statement = Bigtop::Backend::Control::Gantry::use_stub(
2436             { module => $gen_package_name, imports => $gen_method_names }
2437             );
2438             }
2439              
2440 0           my $export_array = Bigtop::Backend::Control::Gantry::export_array(
2441             { exported_subs => $gen_method_names }
2442             );
2443              
2444 0           my $loc_configs = $data->{lookup}{controllers}{$short_name}{configs};
2445 0           my ( $all_configs, $accessor_configs ) =
2446             Bigtop::Backend::Control::Gantry::build_config_lists(
2447             $loc_configs
2448             );
2449              
2450 0           my $init_sub;
2451 0 0         if ( @{ $accessor_configs } ) {
  0            
2452 0           $init_sub = Bigtop::Backend::Control::Gantry::build_init_sub(
2453             $accessor_configs
2454             );
2455             }
2456              
2457 0           my $config_accessors;
2458 0 0         if ( @{ $accessor_configs } ) {
  0            
2459 0           $config_accessors = Bigtop::Backend::Control::Gantry::config_accessors(
2460             { configs => $accessor_configs, }
2461             );
2462             }
2463              
2464 0           my $inherit_from;
2465 0           my $other_module_text = 'DEPENDENCIES';
2466              
2467 0           my @pack_pieces;
2468             my $base_name;
2469              
2470 0 0         if ( $self->is_base_controller ) {
2471 0           @pack_pieces = split /::/, $data->{ app_name };
2472 0           $base_name = pop @pack_pieces;
2473 0           $base_name .= '.pm';
2474              
2475 0           $inherit_from = 'Gantry'; # only a default
2476 0           $other_module_text = 'SEE ALSO';
2477              
2478 0           $package_name = $data->{ app_name };
2479 0           $used_modules = [ 'Gantry' ];
2480 0 0         if ( $gen_method_names ) {
2481 0           push @{ $used_modules }, $gen_package_name;
  0            
2482             }
2483             # now push in any modules from uses statements
2484             }
2485             else {
2486 0           @pack_pieces = split /::/, $short_name;
2487 0           $base_name = pop @pack_pieces;
2488 0           $base_name .= '.pm';
2489              
2490 0           $inherit_from = $data->{ app_name };
2491             }
2492              
2493 0 0         if ( defined $gen_method_names ) { # in either case, use GEN if available
2494 0           $inherit_from = $gen_package_name;
2495             }
2496              
2497 0           my $all_gen_methods = $gen_method_names;
2498              
2499 0 0         if ( $data->{ init_sub } ) {
2500             # unshift has side effect of defining array if not defined
2501 0           unshift @{ $gen_method_names }, qw( namespace init );
  0            
2502              
2503 0           $all_gen_methods = [
2504             @{ $gen_method_names },
2505 0           @{ $data->{ methods } },
  0            
2506             ];
2507             }
2508              
2509 0 0         if ( defined $crud_doc_methods ) {
2510 0           foreach my $method_set ( @{ $crud_doc_methods } ) {
  0            
2511 0           push @{ $stub_method_names }, @{ $method_set };
  0            
  0            
2512             }
2513             }
2514              
2515 0 0 0       if ( not $self->is_base_controller()
      0        
2516             and
2517             defined $statements->{plugins} and $statements->{plugins}[0]
2518             ) {
2519 0           push @{ $all_gen_methods }, 'namespace';
  0            
2520             }
2521              
2522 0 0         my $pod = Bigtop::Backend::Control::Gantry::pod(
2523             {
2524             app_name => $data->{app_name},
2525             accessors => $accessor_configs,
2526             package_name => $package_name,
2527             methods => $stub_method_names,
2528             gen_package_name =>
2529             ( defined $all_gen_methods ) ? $gen_package_name : undef,
2530             mixins => $all_gen_methods,
2531             other_module_text=> $other_module_text,
2532             used_modules => $used_modules,
2533             authors => $data->{authors},
2534             contact_us => $data->{contact_us},
2535             copyright_holder => $data->{copyright_holder},
2536             license_text => $data->{license_text},
2537             sub_module => ( not $self->is_base_controller ),
2538             sub_modules => $data->{sub_modules},
2539             year => $data->{year},
2540             }
2541             );
2542              
2543 0           my $output;
2544             my $gen_pod;
2545 0           my $gen_output;
2546              
2547 0 0         if ( $self->is_base_controller ) {
2548 0           $output = Bigtop::Backend::Control::Gantry::base_module(
2549             {
2550             package_name => $package_name,
2551             gen_package_name => $inherit_from,
2552             gen_use_statement => $gen_use_statement,
2553             child_output => $output_str,
2554             class_accessors => $class_access,
2555             pod => $pod,
2556             config_accessors => $config_accessors,
2557 0           %{ $data },
2558             }
2559             );
2560             $gen_pod =
2561             Bigtop::Backend::Control::Gantry::gen_pod(
2562             {
2563             package_name => $data->{ app_name },
2564             gen_package_name => $gen_package_name,
2565             other_module_text=> 'SEE ALSO',
2566             used_modules => [ 'Gantry',
2567             $gen_package_name,
2568 0           @{ $data->{ sub_modules } } ],
  0            
2569             sub_module => 0,
2570 0           %{ $data },
2571             methods => $all_gen_methods,
2572             }
2573             # these are in $data: authors, contact_ud, copyright_holder,
2574             # license_text, year, and app_name
2575             );
2576 0           $gen_output = Bigtop::Backend::Control::Gantry::gen_base_module(
2577             {
2578             child_output => $gen_output_str,
2579             gen_package_name => $gen_package_name,
2580             init_sub => $init_sub,
2581             config_accessors => $config_accessors,
2582             gen_pod => $gen_pod,
2583 0           %{ $data }, # Go fish!
2584             }
2585             );
2586             }
2587             else {
2588             # deal with non-base controller plugins
2589              
2590 0           my $plugins;
2591 0 0 0       if ( defined $statements->{plugins} and $statements->{plugins}[0] ) {
2592 0           $plugins = join ', ', @{ $statements->{plugins} };
  0            
2593             }
2594              
2595 0 0         if ( $plugins ) {
2596 0           my $config = $data->{ tree }->get_config();
2597 0           my $app_level_plugins = $config->{ plugins };
2598 0 0         $plugins = "$app_level_plugins $plugins"
2599             if $app_level_plugins;
2600              
2601 0           $inherit_from = $gen_package_name;
2602             }
2603              
2604 0           $output = Bigtop::Backend::Control::Gantry::controller_block(
2605             {
2606             app_name => $data->{app_name},
2607             package_name => $package_name,
2608             inherit_from => $inherit_from,
2609             gen_use_statement => $gen_use_statement,
2610             child_output => $output_str,
2611             class_accessors => $class_access,
2612             pod => $pod,
2613             sub_modules => $data->{sub_modules},
2614             wsdl => $wsdl,
2615             soap_style => $soap_style,
2616             }
2617             );
2618              
2619 0 0         $gen_pod =
2620             Bigtop::Backend::Control::Gantry::gen_controller_pod(
2621             {
2622             package_name => $package_name,
2623             gen_package_name =>
2624             ( defined $all_gen_methods ) ? $gen_package_name : undef,
2625             gen_methods => $all_gen_methods,
2626             sub_module => 1,
2627             }
2628             );
2629              
2630 0           $gen_output = Bigtop::Backend::Control::Gantry::gen_controller_block(
2631             {
2632             app_name => $data->{app_name},
2633             gen_package_name => $gen_package_name,
2634             package_name => $package_name,
2635             child_output => $gen_output_str,
2636             export_array => $export_array,
2637             gen_pod => $gen_pod,
2638             wsdl => $wsdl,
2639             soap_style => $soap_style,
2640             plugins => $plugins,
2641             config_accessors => $config_accessors,
2642             init_sub => $init_sub,
2643             }
2644             );
2645             }
2646              
2647 0           my $pm_file;
2648             my $gen_pm_file;
2649 0           my $retval;
2650              
2651             # put the content onto the disk
2652 0 0         if ( $self->is_base_controller ) {
2653              
2654 0           my $module_dir = $data->{ module_dir };
2655              
2656             # Example: module_dir = t/gantry/play/Apps-Checkbook/lib/Apps/Checkbook
2657             # we want to strip off the last dir and put our module names there:
2658             # t/gantry/play/Apps-Checkbook/lib/Apps/Checkbook.pm
2659             # t/gantry/play/Apps-Checkbook/lib/Apps/GENCheckbook.pm
2660 0           my @module_dir_pieces = File::Spec->splitdir( $module_dir );
2661 0           pop @module_dir_pieces;
2662 0           my $base_module_dir = File::Spec->catdir( @module_dir_pieces );
2663              
2664 0           mkdir $base_module_dir;
2665              
2666 0           $pm_file = File::Spec->catfile( $base_module_dir, $base_name );
2667 0           $gen_pm_file = File::Spec->catfile(
2668             $base_module_dir, "GEN$base_name"
2669             );
2670              
2671 0           $retval = [];
2672             }
2673             else {
2674              
2675             # ... first make sure the directories exist for this piece
2676 0           my $module_home = File::Spec->catdir( $data->{module_dir} );
2677 0           foreach my $subdir ( @pack_pieces ) {
2678 0           $module_home = File::Spec->catdir( $module_home, $subdir );
2679 0           mkdir $module_home;
2680             }
2681              
2682             # ... then make sure GEN directories exist (similar plan)
2683 0           my $gen_home = File::Spec->catdir( $data->{module_dir}, 'GEN' );
2684              
2685 0 0         if ( defined $all_gen_methods ) {
2686 0           mkdir $gen_home;
2687              
2688 0           foreach my $subdir ( @pack_pieces ) {
2689 0           $gen_home = File::Spec->catdir( $gen_home, $subdir );
2690 0           mkdir $gen_home;
2691             }
2692             }
2693              
2694 0           $pm_file = File::Spec->catfile( $module_home, $base_name);
2695 0           $gen_pm_file = File::Spec->catfile( $gen_home, $base_name);
2696              
2697 0           $retval = [ $package_name ];
2698             }
2699              
2700             # ... then write them
2701 0           eval {
2702             # Is the stub already present? Then skip it.
2703 1     1   10 no warnings qw( Bigtop );
  1         2  
  1         1210  
2704 0           Bigtop::write_file( $pm_file, $output, 'no overwrite' );
2705 0 0         if ( defined $all_gen_methods ) {
2706 0           Bigtop::write_file( $gen_pm_file, $gen_output );
2707             }
2708             # else {
2709             # warn "no gen to write $gen_pm_file\n";
2710             # warn $gen_output;
2711             # }
2712             };
2713 0 0         return if ( $@ );
2714              
2715             # tell postorder walker what we just built
2716 0           return $retval;
2717             }
2718              
2719             sub _flatten {
2720 0     0     my $input = shift;
2721              
2722 0           my @output;
2723              
2724 0           foreach my $element ( @{ $input } ) {
  0            
2725 0           push @output, @{ $element };
  0            
2726             }
2727              
2728 0           return \@output;
2729             }
2730              
2731             sub _extract_output_from {
2732 0     0     my $child_output = shift;
2733              
2734 0           my %all_output;
2735              
2736             # extract from the individual child output lists
2737 0           foreach my $output_list ( @{ $child_output } ) {
  0            
2738 0           my $output_hash = { @{ $output_list } };
  0            
2739              
2740 0           foreach my $type ( keys %{ $output_hash } ) {
  0            
2741 0 0         next unless defined $output_hash->{ $type };
2742 0           push @{ $all_output{ $type } }, $output_hash->{ $type };
  0            
2743             }
2744             }
2745              
2746             # join the results
2747 0           my $empty_string = '';
2748 0           my $output = $empty_string;
2749 0           my $class_access = $empty_string;
2750 0           my $gen_output = $empty_string;
2751              
2752             # make sure uses are near the top
2753 0 0         if ( defined $all_output{uses_output} ) {
2754 0           $output .= join $empty_string, @{ $all_output{uses_output} };
  0            
2755             }
2756              
2757 0 0         if ( defined $all_output{uses_gen_output} ) {
2758 0           $gen_output .= join $empty_string, @{ $all_output{uses_gen_output} };
  0            
2759             }
2760              
2761             # then get the rest
2762 0 0         if ( defined $all_output{output} ) {
2763 0           $output .= join $empty_string, @{ $all_output{output} };
  0            
2764             }
2765              
2766 0 0         if ( defined $all_output{gen_output} ) {
2767 0           $gen_output .= join $empty_string, @{ $all_output{gen_output} };
  0            
2768             }
2769              
2770 0 0         if ( defined $all_output{class_access} ) {
2771 0           $class_access .= join $empty_string, @{ $all_output{class_access} };
  0            
2772             }
2773              
2774             return (
2775 0           $output,
2776             $class_access,
2777             $gen_output,
2778             \%all_output,
2779             );
2780             }
2781              
2782             sub _extract_soap_style {
2783 0     0     my $soap_styles = shift;
2784              
2785 0 0         return unless ref $soap_styles eq 'ARRAY';
2786              
2787 0           my %soap_styles = map { $_ => 1 } @{ $soap_styles };
  0            
  0            
2788              
2789 0 0         if ( keys %soap_styles > 1 ) {
2790 0           die "Mixing SOAP styles is not supported by Bigtop.\n";
2791             }
2792             else {
2793 0 0         return 'RPC' if defined $soap_styles{ 'SOAP' };
2794 0 0         return 'Doc' if defined $soap_styles{ 'SOAPDoc' };
2795 0           return undef;
2796             }
2797             }
2798              
2799             sub output_nav_links {
2800 0     0     my $self = shift;
2801 0           my $child_output = shift;
2802 0   0       my $base_location = shift || '';
2803              
2804 0           my %retval = @{ $child_output };
  0            
2805              
2806 0 0 0       if ( defined $retval{ label } and $retval{ label } ) {
2807              
2808 0 0         if ( $self->is_base_controller ) {
2809 0           push @{ $child_output }, 'link', $base_location;
  0            
2810             }
2811              
2812 0           return [ $child_output ];
2813             }
2814             else {
2815 0           return [];
2816             }
2817             }
2818              
2819             sub output_test_locations {
2820 0     0     my $self = shift;
2821 0           my $child_output = shift;
2822 0           my $lookup = shift;
2823              
2824 0 0         return if ( $self->is_base_controller );
2825              
2826 0           my %child_output = @{ $child_output};
  0            
2827              
2828 0           my @keys = keys %{ $self };
  0            
2829              
2830             my $controller_statements = $lookup->{ controllers }
2831             { $self->{__NAME__} }
2832 0           { statements };
2833              
2834 0 0 0       if ( defined $controller_statements->{ skip_test}
2835             and
2836             $controller_statements->{ skip_test}
2837             ) {
2838 0           return;
2839             }
2840              
2841 0           my @retval;
2842              
2843             # add my name to the data going up
2844 0           foreach my $loc_type ( keys %child_output ) {
2845             push @retval,
2846             $loc_type => [
2847             $child_output{ $loc_type } => $self->{ __NAME__ }
2848 0           ];
2849             }
2850              
2851 0           return \@retval;
2852             }
2853              
2854             # controller_statement
2855              
2856             package # controller_statement
2857             controller_statement;
2858 1     1   10 use strict; use warnings;
  1     1   2  
  1         34  
  1         7  
  1         2  
  1         336  
2859              
2860             sub output_controller {
2861 0     0     my $self = shift;
2862 0           my $child_output = shift;
2863 0           my $data = shift;
2864              
2865 0           my $keyword = $self->{__KEYWORD__};
2866              
2867 0 0         return unless Bigtop::Backend::Control->is_controller_keyword( $keyword );
2868              
2869 0           return [ $self->$keyword( $child_output, $data ) ];
2870             }
2871              
2872             sub _form_uses {
2873 0     0     my $self = shift;
2874              
2875 0           my @output;
2876             my @used_modules;
2877              
2878 0           foreach my $module ( @{ $self->{__ARGS__} } ) {
  0            
2879              
2880 0 0         if ( ref( $module ) eq 'HASH' ) {
2881 0           my ( $used, $import ) = %{ $module };
  0            
2882 0           my $use_statement =
2883             Bigtop::Backend::Control::Gantry::explicit_use_stub(
2884             {
2885             module => $used,
2886             import_list => $import,
2887             }
2888             );
2889 0           chomp $use_statement;
2890 0           push @output, $use_statement;
2891 0           $module = $used;
2892             }
2893              
2894             else {
2895 0           my @exported;
2896 0           eval {
2897 0           my $module_path = $module;
2898 0           $module_path =~ s{::}{/}g;
2899 0           require "$module_path.pm";
2900             };
2901              
2902 0 0         if ( $@ ) {
2903 0           push @output, Bigtop::Backend::Control::Gantry::use_stub(
2904             { module => $module, }
2905             );
2906             }
2907             else {
2908             {
2909 1     1   7 no strict 'refs';
  1         3  
  1         1283  
  0            
2910 0           @exported = @{"$module\::EXPORT"};
  0            
2911             }
2912 0 0         if ( @exported ) {
2913 0           push @output, Bigtop::Backend::Control::Gantry::use_stub(
2914             { module => $module, imports => \@exported }
2915             );
2916             }
2917             else {
2918 0           push @output, Bigtop::Backend::Control::Gantry::use_stub(
2919             { module => $module }
2920             );
2921             }
2922             }
2923             }
2924              
2925 0           push @used_modules, $module;
2926             }
2927              
2928 0           my $output = join "\n", @output;
2929 0           $output .= "\n\n";
2930              
2931 0           return $output, \@used_modules;
2932             }
2933              
2934             sub uses {
2935 0     0     my $self = shift;
2936              
2937 0           my ( $output, $used_modules ) = $self->_form_uses();
2938              
2939             return [
2940 0           uses_output => $output,
2941             uses_gen_output => $output,
2942             used_modules => $used_modules,
2943             ];
2944             }
2945              
2946             sub stub_uses {
2947 0     0     my $self = shift;
2948              
2949 0           my ( $output, $used_modules ) = $self->_form_uses();
2950              
2951             return [
2952 0           uses_output => $output,
2953             used_modules => $used_modules,
2954             ];
2955             }
2956              
2957             sub gen_uses {
2958 0     0     my $self = shift;
2959              
2960 0           my ( $output, $used_modules ) = $self->_form_uses();
2961              
2962             return [
2963 0           uses_gen_output => $output,
2964             used_modules => $used_modules,
2965             ];
2966             }
2967              
2968             sub is_crud {
2969 0     0     my $self = shift;
2970 0           my $data = shift;
2971              
2972 0           my $controller_name = $self->get_controller_name;
2973 0   0       my $controller_type = $data->{lookup}
2974             {controllers}
2975             {$controller_name}
2976             {type}
2977             || 'stub';
2978              
2979 0           return ( $controller_type eq 'CRUD' );
2980             }
2981              
2982             sub is_dbix_class {
2983 0     0     my $self = shift;
2984 0           my $data = shift;
2985 0           my $config_block = $data->{ tree }->get_config()->{ Control };
2986              
2987 0           return $config_block->{ dbix };
2988             }
2989              
2990             sub get_model_alias {
2991 0     0     my $self = shift;
2992              
2993 0 0         return unless $self->{ __KEYWORD__ } eq 'controls_table';
2994              
2995 0           my $alias = uc $self->{ __ARGS__ }[0];
2996 0           $alias =~ s/\./_/;
2997              
2998 0           return [ $alias ];
2999             }
3000              
3001             sub controls_table {
3002 0     0     my $self = shift;
3003 0           my $child_output = shift;
3004 0           my $data = shift;
3005 0           my $table = $self->{__ARGS__}[0];
3006              
3007 0           $table =~ s/\./_/;
3008              
3009 0           my $model = "$data->{app_name}\::Model::$table";
3010              
3011 0           my $model_alias = $data->{ model_alias };
3012              
3013 0           my $output = Bigtop::Backend::Control::Gantry::use_stub(
3014             { module => $model, imports => "\$$model_alias" }
3015             );
3016 0           my $gen_output = $output;
3017              
3018 0           my $class_access = '';
3019              
3020 0 0         unless ( $self->is_crud( $data ) ) {
3021 0           $class_access = Bigtop::Backend::Control::Gantry::class_access(
3022             { model_alias => $model_alias }
3023             );
3024              
3025 0 0         if ( $self->is_dbix_class( $data ) ) {
3026 0           my $helper = 'Gantry::Plugins::AutoCRUDHelper::DBIxClass';
3027 0           my $controller = $self->get_controller_name();
3028              
3029 0 0         if ( defined $data->{ tree }
3030             { application }
3031             { lookup }
3032             { controllers }
3033             { $controller }
3034             { statements }
3035             { autocrud_helper }
3036             ) {
3037             $helper = $data->{tree}
3038             { application }
3039             { lookup }
3040             { controllers }
3041             { $controller }
3042             { statements }
3043             { autocrud_helper }
3044 0           [ 0 ];
3045             }
3046              
3047             $class_access .=
3048 0           Bigtop::Backend::Control::Gantry::get_orm_helper(
3049             {
3050             helper => $helper,
3051             }
3052             );
3053             }
3054             }
3055              
3056             # This use statement goes in both stub and gen output.
3057             return [
3058 0           uses_output => $output,
3059             uses_gen_output => $gen_output,
3060             class_access => $class_access,
3061             used_modules => [ $model ],
3062             ];
3063             }
3064              
3065             sub text_description {
3066 0     0     my $self = shift;
3067 0           my $child_output = shift;
3068 0           my $data = shift;
3069 0           my $description = $self->{__ARGS__}[0];
3070              
3071 0 0         if ( $self->is_crud( $data ) ) {
3072 0           return;
3073             }
3074             else {
3075 0           my $output = Bigtop::Backend::Control::Gantry::text_description(
3076             { description => $description }
3077             );
3078              
3079             return [
3080 0           class_access => $output,
3081             ];
3082             }
3083             }
3084              
3085             sub output_nav_links {
3086 0     0     my $self = shift;
3087              
3088 0 0         if ( $self->{__KEYWORD__} eq 'rel_location' ) {
    0          
3089 0           return [ link => $self->{__ARGS__}->get_first_arg() ]
3090             }
3091             elsif ( $self->{__KEYWORD__} eq 'location' ) {
3092 0           return [ link => $self->{__ARGS__}->get_first_arg() ]
3093             }
3094              
3095 0 0         if ( $self->{__KEYWORD__} eq 'page_link_label' ) {
3096 0           return [ label => $self->{__ARGS__}->get_first_arg() ]
3097             }
3098              
3099 0           return [];
3100             }
3101              
3102             sub output_test_locations {
3103 0     0     my $self = shift;
3104              
3105 0 0         return unless ( $self->{ __KEYWORD__ } =~ /location/ );
3106              
3107 0           return [ $self->{ __KEYWORD__ } => $self->{ __ARGS__ }->get_first_arg, ];
3108             }
3109              
3110             package # controller_method
3111             controller_method;
3112 1     1   47 use strict; use warnings;
  1     1   9  
  1         31  
  1         7  
  1         2  
  1         906  
3113              
3114             sub output_controller {
3115 0     0     my $self = shift;
3116 0           shift; # There's no child output, we're in the recursion base.
3117 0           my $data = shift;
3118              
3119 0           my $gen_package_name
3120             = $self->{__PARENT__}->get_gen_package_name( $data );
3121              
3122 0           my $base_name = $gen_package_name;
3123 0           $base_name =~ s/.*:://;
3124              
3125 0           my $method_name = $self->{__NAME__};
3126 0           my $type = $self->{__TYPE__};
3127 0           my $method_body = $self->{__BODY__};
3128              
3129 0           my $controller_statements
3130             = $data->{lookup}
3131             {controllers}
3132             {$base_name}
3133             {statements};
3134              
3135 0           my $statements = $data->{lookup}
3136             {controllers}
3137             {$base_name}
3138             {methods}
3139             {$method_name}
3140             {statements};
3141              
3142 0 0         return if ( $statements->{no_gen} );
3143              
3144             # restart recursion based on method type
3145 0 0         unless ( $method_body->can( "output_$type" ) ) {
3146 0           die "Error: bad type '$type' for method '$method_name'\n"
3147             . "in controller '$base_name'\n";
3148             }
3149              
3150 0           my $child_output = $method_body->walk_postorder( "output_$type", $data );
3151              
3152 0 0         if ( $child_output ) {
3153 0           $child_output = { @{ $child_output } };
  0            
3154             }
3155              
3156 0           my $stub_method_name;
3157 0 0         if ( $type eq 'stub' ) {
    0          
3158 0           $stub_method_name = $self->{__NAME__};
3159             }
3160             elsif ( defined $child_output->{ stub_method_name } ) {
3161 0           $stub_method_name = $child_output->{ stub_method_name };
3162             }
3163              
3164 0           my $gen_method_name;
3165 0 0 0       if ( defined $child_output->{gen_output}
3166             and
3167             $child_output->{gen_output}{body} )
3168             {
3169 0           $gen_method_name = $self->{__NAME__};
3170             }
3171              
3172 0           my ( $output, $gen_output );
3173              
3174 0 0         if ( $child_output->{gen_output} ) {
3175 0           $gen_output = Bigtop::Backend::Control::Gantry::gen_controller_method(
3176             {
3177             method_name => $self->{__NAME__},
3178             child_output => $child_output->{gen_output},
3179             }
3180             );
3181             }
3182              
3183 0 0         if ( $child_output->{comment_output} ) {
3184 0           $output = Bigtop::Backend::Control::Gantry::controller_method(
3185             {
3186             method_name => $self->{__NAME__},
3187             child_output => $child_output->{comment_output},
3188             gen_package_name => $gen_package_name,
3189             }
3190             );
3191             }
3192              
3193 0 0         if ( $child_output->{ extra_comment_methods } ) {
3194 0           foreach my $method ( @{ $child_output->{ extra_comment_methods } } ) {
  0            
3195 0           $output .= Bigtop::Backend::Control::Gantry::controller_method(
3196             {
3197             method_name => $method,
3198             gen_package_name => $gen_package_name,
3199             }
3200             );
3201             }
3202             }
3203              
3204 0 0         if ( $child_output->{stub_output} ) {
3205 0           $output .= Bigtop::Backend::Control::Gantry::gen_controller_method(
3206             {
3207             method_name => $self->{__NAME__},
3208             child_output => $child_output->{stub_output},
3209             }
3210             );
3211             }
3212              
3213 0           my $extra_stub_method;
3214             my $crud_doc_methods;
3215              
3216 0 0         if ( $child_output->{ extra_for_stub } ) {
3217 0           $output .= "\n$child_output->{ extra_for_stub }{ full_sub }\n";
3218 0           $extra_stub_method = $child_output->{ extra_for_stub }{ name };
3219             }
3220              
3221 0 0         if ( $child_output->{crud_output} ) {
3222 0           my $crud_name = $self->{__NAME__};
3223 0           $crud_name =~ s/_form//;
3224 0   0       $crud_name ||= 'crud';
3225              
3226 0           my $text_descr = $controller_statements->{text_description}[0];
3227 0           my $model_alias = $data->{model_alias};
3228              
3229 0 0 0       unless ( defined $model_alias and $model_alias ) {
3230 0           die "Error: controller $base_name is type CRUD but is missing\n"
3231             . " it's controls table statement.\n";
3232             }
3233              
3234 0           my $with_perms = $self->{__PARENT__}->walk_postorder(
3235             'with_perms'
3236             )->[0];
3237              
3238 0   0       my $crud_helpers = Bigtop::Backend::Control::Gantry::crud_helpers(
3239             {
3240             form_method_name => $self->{__NAME__},
3241             crud_name => $crud_name,
3242             text_descr => $text_descr || 'missing text descr',
3243             model_alias => $model_alias,
3244             with_perms => $with_perms,
3245             }
3246             );
3247              
3248 0           $crud_doc_methods = _crud_doc_methods( $crud_helpers );
3249              
3250 0           my $form_method =
3251             Bigtop::Backend::Control::Gantry::gen_controller_method(
3252             {
3253             method_name => $self->{__NAME__},
3254             child_output => $child_output->{crud_output},
3255             }
3256             );
3257              
3258 0           $output = $crud_helpers;
3259 0           $gen_output .= $form_method;
3260              
3261 0           $output .= Bigtop::Backend::Control::Gantry::controller_method(
3262             {
3263             method_name => $self->{__NAME__},
3264             gen_package_name => $gen_package_name,
3265             child_output => { doc_args => '$data' },
3266             }
3267             );
3268              
3269 0           $gen_method_name = $self->{__NAME__};
3270             }
3271              
3272             return [
3273             [
3274             gen_output => $gen_output,
3275             output => $output,
3276             stub_method_name => $stub_method_name,
3277             gen_method_name => $gen_method_name,
3278             extra_stub_method_name => $extra_stub_method,
3279             soap_params => $child_output->{ soap_params },
3280             soap_style => ( $child_output->{ soap_params } )
3281 0 0         ? $type
3282             : undef,
3283             crud_doc_methods => $crud_doc_methods,
3284             ]
3285             ];
3286             }
3287              
3288             sub _crud_doc_methods {
3289 0     0     my $crud_output = shift;
3290              
3291 0           my @retval = ( $crud_output =~ /^sub\s+(\S+)/msg );
3292              
3293 0           return \@retval;
3294             }
3295              
3296             package # method_body
3297             method_body;
3298 1     1   13 use strict; use warnings;
  1     1   2  
  1         30  
  1         5  
  1         2  
  1         4040  
3299              
3300             sub get_table_name_for {
3301 0     0     my $self = shift;
3302 0           my $lookup = shift;
3303 0           my $name_of = shift;
3304              
3305 0           my $table_name = $self->get_table_name( $lookup );
3306              
3307 0 0         unless ( $table_name ) {
3308 0           die "Error: I can't generate main_listing in $name_of->{method} "
3309             . "of controller $name_of->{controller}.\n"
3310             . " The controller did not have a 'controls_table' statement.\n";
3311             }
3312              
3313 0           $name_of->{table} = $table_name;
3314             }
3315              
3316             sub get_fields_from {
3317 0     0     my $self = shift;
3318 0           my $lookup = shift;
3319 0           my $name_of = shift;
3320              
3321 0           my $fields = $lookup->{tables}{ $name_of->{table} }{fields};
3322              
3323 0 0         unless ( $fields ) {
3324 0           die "Error: I can't generate main_listing for $name_of->{method} "
3325             . "of controller $name_of->{controller}.\n"
3326             . " I can't seem to find the fields in the table for "
3327             . "this controller.\n"
3328             . " I was looking for them in the table named '$name_of->{table}'.\n"
3329             . " Maybe that name is misspelled.\n";
3330             }
3331              
3332 0           return $fields;
3333             }
3334              
3335             sub get_field_for {
3336 0     0     my $col = shift;
3337 0           my $fields = shift;
3338 0           my $name_of = shift;
3339              
3340 0           my $field = $fields->{$col};
3341              
3342             # make sure there really is a field
3343 0 0         unless ( $field ) {
3344 0           die "Error: I couldn't find a field called '$col' in "
3345             . "$name_of->{table}\'s field list.\n"
3346             . " Perhaps you misspelled '$col' in the definition of\n"
3347             . " method $name_of->{method} for controller "
3348             . "$name_of->{controller}.\n";
3349             }
3350              
3351 0           return $field;
3352             }
3353              
3354             sub output_stub {
3355 0     0     my $self = shift;
3356 0           my $child_output = shift;
3357 0           my $data = shift;
3358              
3359 0           my $choices = { @{ $child_output } };
  0            
3360              
3361             # set up args
3362 0           my ( $arg_capture, @doc_args )
3363 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3364              
3365             return [
3366 0           stub_output => {
3367             body => $arg_capture,
3368             doc_args => \@doc_args,
3369             }
3370             ];
3371             }
3372              
3373             sub output_base_links {
3374 0     0     my $self = shift;
3375 0           my $child_output = shift;
3376 0           my $data = shift;
3377              
3378 0           my $choices = { @{ $child_output } };
  0            
3379              
3380             # set up args
3381 0           my ( $arg_capture, @doc_args )
3382 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3383              
3384 0   0       my $title = $choices->{title}[0] || 'Main Listing';
3385 0   0       my $template = $choices->{html_template}[0] || 'main.tt';
3386              
3387             # set self vars for title/template etc.
3388 0           my $self_setup = Bigtop::Backend::Control::Gantry::self_setup(
3389             { title => $title, template => $template }
3390             );
3391              
3392             my $view_data = Bigtop::Backend::Control::Gantry::main_links(
3393             { pages => $data->{ pages } }
3394 0           );
3395              
3396             return [
3397 0           gen_output => {
3398             body => "$arg_capture\n$self_setup\n$view_data",
3399             doc_args => \@doc_args,
3400             },
3401             comment_output => {
3402             doc_args => \@doc_args,
3403             }
3404             ];
3405             }
3406              
3407             sub output_hashref {
3408 0     0     my $self = shift;
3409 0           my $child_output = shift;
3410 0           my $data = shift;
3411              
3412 0           my $choices = { @{ $child_output } };
  0            
3413              
3414             # set up args
3415 0           my ( $arg_capture, @doc_args )
3416 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3417              
3418            
3419 0           my @literals;
3420 0           foreach my $literal ( @{ $choices->{literal} } ) {
  0            
3421 0           push( @literals, $literal );
3422             }
3423            
3424 0           my %authed_methods;
3425 0 0         if ( $choices->{authed_methods} ) {
3426 0           foreach my $pair ( @{ $choices->{authed_methods} } ) {
  0            
3427 0           my ( $key, $value ) = %{ $pair };
  0            
3428 0           $authed_methods{ $key } = $value;
3429             }
3430             }
3431            
3432 0           my @permissions;
3433 0 0         if ( $choices->{permissions} ) {
3434 0           foreach my $pair ( @{ $choices->{permissions} } ) {
  0            
3435 0           my ( $key, $value );
3436            
3437 0 0         if ( ref( $pair ) eq 'HASH' ) { ( $key, $value ) = %{ $pair }; }
  0            
  0            
3438 0           else { $key = $pair; }
3439            
3440 0 0 0       if ( $key !~ /[crud-]+/ or length( $key ) ne 12 ) {
3441 0           die "invalid permission bits, $key ( usage: crudcrudcrud )\n"
3442             . "at " . $self->get_controller_name . "\n";
3443             }
3444              
3445 0           push( @permissions, $key );
3446 0           push( @permissions, $value );
3447             }
3448             }
3449            
3450 0           my $config_hashref = Bigtop::Backend::Control::Gantry::hashref(
3451             {
3452             authed_methods => \%authed_methods,
3453             permissions => \@permissions,
3454             literals => \@literals,
3455             }
3456             );
3457              
3458             return [
3459 0           gen_output => {
3460             body => "$arg_capture\n$config_hashref",
3461             doc_args => \@doc_args,
3462             },
3463             comment_output => {
3464             doc_args => \@doc_args,
3465             },
3466             ];
3467             }
3468              
3469             sub output_links {
3470 0     0     my $self = shift;
3471 0           my $child_output = shift;
3472 0           my $data = shift;
3473              
3474 0           my $choices = { @{ $child_output } };
  0            
3475              
3476             # set up args
3477 0           my ( $arg_capture, @doc_args )
3478 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3479              
3480 0           my @abs_pages;
3481 0           foreach my $page ( @{ $data->{ pages } } ) {
  0            
3482 0           my $abs_page;
3483              
3484 0 0         if ( $page->{ link } =~ m{^/} ) {
3485 0           $abs_page = {
3486             link => qq{'$page->{ link }'},
3487             },
3488             }
3489             else {
3490 0           $abs_page = {
3491             link => qq{\$self->app_rootp() . '/$page->{ link }'},
3492             };
3493             }
3494 0           $abs_page->{ label } = $page->{ label };
3495 0           push @abs_pages, $abs_page;
3496             }
3497              
3498 0           my $body = Bigtop::Backend::Control::Gantry::site_links(
3499             { pages => \@abs_pages }
3500             );
3501              
3502             return [
3503 0           gen_output => {
3504             body => "$arg_capture\n$body",
3505             # body => "$arg_capture\n$self_setup\n$view_data",
3506             doc_args => \@doc_args,
3507             },
3508             comment_output => {
3509             doc_args => \@doc_args,
3510             }
3511             ];
3512             }
3513              
3514             sub output_main_listing {
3515 0     0     my $self = shift;
3516 0           my $child_output = shift;
3517 0           my $data = shift;
3518              
3519 0           my $choices = { @{ $child_output } };
  0            
3520 0           my @optional_args;
3521              
3522             # see if we are paging
3523 0   0       my $rows = $choices->{ rows }[0] || undef;
3524 0 0         if ( $choices->{ paged_conf }[0] ) {
3525 0           $rows = '$self->' . $choices->{ paged_conf }[0];
3526             }
3527              
3528             # see if we are limiting output rows by foreign key
3529 0   0       my $limit_by = $choices->{ limit_by }[0] || undef;
3530 0 0         if ( defined $limit_by ) {
3531 0           push @{ $choices->{ extra_args} }, '$' . $limit_by;
  0            
3532             }
3533              
3534             # set up args
3535 0           my ( $arg_capture, @doc_args )
3536 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3537              
3538             # provide defaults
3539 0   0       my $title = $choices->{title}[0] || 'Main Listing';
3540 0   0       my $template = $choices->{html_template}[0] || 'results.tt';
3541              
3542             # set self vars for title/template etc.
3543 0           my $self_setup = Bigtop::Backend::Control::Gantry::self_setup(
3544             { title => $title, template => $template, with_real_loc => 1 }
3545             );
3546              
3547             # set up headings
3548 0           my @col_labels;
3549             my @cols;
3550 0           my @pseudo_cols;
3551 0           my @foreigners;
3552 0           my %name_of;
3553              
3554 0           $name_of{method} = $self->get_method_name();
3555 0           $name_of{controller} = $self->get_controller_name();
3556              
3557 0           $self->get_table_name_for( $data->{lookup}, \%name_of );
3558              
3559 0           my $fields = $self->get_fields_from( $data->{lookup}, \%name_of );
3560              
3561 0           foreach my $col ( @{ $choices->{cols} } ) {
  0            
3562 0           my $field = get_field_for( $col, $fields, \%name_of );
3563              
3564             # Push column onto pseudo_cols array if it's a requested pseudo column.
3565 0 0         if ($fields->{$col}{pseudo_value}) {
3566 0           push @pseudo_cols, { alias => $col, field => $fields->{$col}{pseudo_value}{args}[0] }
3567             }
3568              
3569             # get the field's label
3570 0           my $label;
3571 0 0 0       if ( defined $choices->{col_labels} and @{ $choices->{col_labels} } ) {
  0            
3572 0           my $element = shift @{ $choices->{col_labels} };
  0            
3573 0 0         if ( ref( $element ) =~ /HASH/ ) {
3574 0           my ( $text, $link ) = %{ $element };
  0            
3575 0           push @col_labels, { href => { text => $text, link => $link } };
3576             }
3577             else {
3578 0           push @col_labels, { simple => $element };
3579             }
3580             }
3581             else {
3582 0           $label = $fields->{$col}{label}{args}[0];
3583 0 0         unless ( $label ) {
3584 0           warn "Warning: I couldn't find the label for "
3585             . "'$col' in $name_of{table}\'s fields.\n"
3586             . " Using '$col' as the label in method $name_of{method}"
3587             . " of\n"
3588             . " controller $name_of{controller}.\n";
3589              
3590 0           $label = $col;
3591             }
3592 0           push @col_labels, { simple => $label };
3593             }
3594              
3595             # see if it's foreigner or has a special display method
3596 0 0         if ( defined $fields->{$col}{refers_to} ) {
    0          
3597 0           push @cols, "\$$col";
3598 0           push @foreigners, $col;
3599             }
3600             elsif ( defined $fields->{ $col }{ html_form_options } ) {
3601 0           push @cols, "\$row->${col}_display()";
3602             }
3603             else {
3604 0           push @cols, "\$row->$col";
3605             }
3606             }
3607              
3608             # Populate pseudo_cols array for any pseudo columns that weren't requested
3609             # in $choices->{cols}.
3610 0           foreach my $pseudo_col ( @{ $choices->{pseudo_cols} } ) {
  0            
3611 0           push @pseudo_cols, { alias => $pseudo_col, field => $fields->{$pseudo_col}{pseudo_value}{args}[0] }
3612             }
3613              
3614             # put options in the heading bar
3615 0           my $header_options = [];
3616 0 0         if ( $choices->{header_options} ) {
3617 0 0         my $url_suffix = ( defined $limit_by ) ? '$header_option_suffix' : '';
3618              
3619 0           my $perms;
3620 0 0         if ( $choices->{ header_option_perms } ) {
3621 0           $perms = $choices->{ header_option_perms }->one_hash();
3622             }
3623              
3624 0           $header_options = _build_options(
3625             {
3626             options => $choices->{header_options},
3627             url_suffix => $url_suffix,
3628             perms => $perms,
3629             }
3630             );
3631             }
3632              
3633 0           my $heading = Bigtop::Backend::Control::Gantry::main_heading(
3634             {
3635             headings => \@col_labels,
3636             header_options => $header_options,
3637             limit_by => $limit_by,
3638             }
3639             );
3640              
3641 0           my $order_by;
3642 0 0         if ( $choices->{order_by} ) {
3643 0           $order_by = $choices->{order_by}[0];
3644             }
3645              
3646             # generate database retrieval
3647 0           my $row_options = [];
3648 0 0         if ( $choices->{row_options} ) {
3649 0           my $perms;
3650 0 0         if ( $choices->{ row_option_perms } ) {
3651 0           $perms = $choices->{ row_option_perms }->one_hash();
3652             }
3653             $row_options = _build_options(
3654             {
3655             options => $choices->{ row_options },
3656 0           row_options => 1,
3657             perms => $perms,
3658             }
3659             );
3660             #, '/$id' );
3661             }
3662              
3663 0           my @where_terms;
3664 0 0         if ( $choices->{ where_terms } ) {
3665 0           foreach my $where_term ( @{ $choices->{ where_terms } } ) {
  0            
3666 0           my ( $col_name, $value ) = %{ $where_term };
  0            
3667 0           push @where_terms, {
3668             col_name => $col_name,
3669             value => $value,
3670             };
3671             }
3672             }
3673              
3674 0           my $main_table = Bigtop::Backend::Control::Gantry::main_table(
3675             {
3676             model => $data->{model_alias},
3677             rows => $rows,
3678             data_cols => \@cols,
3679             pseudo_cols => \@pseudo_cols,
3680             row_options => $row_options,
3681             dbix => $self->is_dbix_class( $data ),
3682             limit_by => $limit_by,
3683             foreigners => \@foreigners,
3684             livesearch => $choices->{livesearch}[0],
3685             order_by => $order_by,
3686             where_terms => \@where_terms,
3687             }
3688             );
3689              
3690             # return the result
3691             # We must call the templates separately, Inline::TT does not support
3692             # including one block inside another. (Since each block is logically
3693             # a file and you can never call a block in another file with TT.
3694             # In reality the reason is a bit more subtle. To call a block, with
3695             # Inline::TT, you need to call it as a function in the Bigtop::* class.
3696             # But inside the templates, you cannot call a Perl function without
3697             # enabling Perl code, which we don't want to do.)
3698             return [
3699 0           gen_output => {
3700             body => "$arg_capture\n$self_setup\n$heading\n$main_table",
3701             doc_args => \@doc_args,
3702             },
3703             comment_output => {
3704             doc_args => \@doc_args,
3705             }
3706             ];
3707             } # END output_main_listing
3708              
3709             sub is_dbix_class {
3710 0     0     my $self = shift;
3711 0           my $data = shift;
3712 0           my $config_block = $data->{ tree }->get_config()->{ Control };
3713              
3714 0           return $config_block->{ dbix };
3715             }
3716              
3717             sub output_SOAP {
3718 0     0     my $self = shift;
3719 0           my $child_output = shift;
3720 0           my $data = shift;
3721 0           my $choices = { @{ $child_output } };
  0            
3722              
3723 0           my $extra_comment_methods;
3724 0 0         if ( not defined $data->{ WSDL_COMMENTS } ) {
3725             $extra_comment_methods = [ qw( namespace get_soap_ops ) ],
3726              
3727 0           $data->{ WSDL_COMMENTS } = 'done';
3728             }
3729              
3730 0           my $handler_method = $self->get_method_name();
3731 0           ( my $internal_method = $handler_method ) =~ s/^do_//;
3732              
3733 0           my $extra_sub = Bigtop::Backend::Control::Gantry::SOAP_stub_method(
3734             {
3735             handler_method => $handler_method,
3736             internal_method => $internal_method,
3737             }
3738             );
3739              
3740 0           my $soap_params = _extract_soap_params( $choices, $internal_method );
3741              
3742             return [
3743 0           extra_for_stub => {
3744             name => $internal_method,
3745             full_sub => $extra_sub,
3746             },
3747             extra_comment_methods => $extra_comment_methods,
3748             soap_params => $soap_params,
3749             soap_style => 'RPC',
3750             ];
3751             }
3752              
3753             sub output_SOAPDoc {
3754 0     0     my $self = shift;
3755 0           my $child_output = shift;
3756 0           my $data = shift;
3757 0           my $choices = { @{ $child_output } };
  0            
3758              
3759 0           my $extra_comment_methods;
3760 0 0         if ( not defined $data->{ WSDL_COMMENTS } ) {
3761             $extra_comment_methods = [ qw( namespace get_soap_ops ) ],
3762              
3763 0           $data->{ WSDL_COMMENTS } = 'done';
3764             }
3765              
3766             # set up args
3767 0           my ( $arg_capture, @doc_args )
3768 0           = _build_arg_capture( @{ $choices->{extra_args} } );
3769              
3770 0           my $handler_method = $self->get_method_name();
3771 0           ( my $internal_method = $handler_method ) =~ s/^do_//;
3772              
3773 0           my $soap_params = _extract_soap_params( $choices, $internal_method );
3774              
3775 0           my $body_advice = Bigtop::Backend::Control::Gantry::soap_doc_advice(
3776             {
3777             arg_capture => $arg_capture,
3778             soap_params => $soap_params,
3779             handler_method => $handler_method,
3780             }
3781             );
3782              
3783             return [
3784 0           soap_style => 'SOAPDoc',
3785             extra_for_stub => {
3786             name => $handler_method,
3787             full_sub => $body_advice,
3788             },
3789             soap_params => $soap_params,
3790             extra_comment_methods => $extra_comment_methods,
3791             ];
3792             }
3793              
3794             sub _extract_soap_params {
3795 0     0     my $choices = shift;
3796 0           my $internal_method = shift;
3797              
3798 0           my %soap_params;
3799 0           $soap_params{ name } = $internal_method;
3800              
3801 0           foreach my $expected ( @{ $choices->{ expects } } ) {
  0            
3802 0 0         if ( ref( $expected ) eq 'HASH' ) {
3803 0           my ( $name, $type ) = %{ $expected };
  0            
3804 0           push @{ $soap_params{ expects } },
  0            
3805             { name => $name, type => $type };
3806             }
3807             else {
3808 0           push @{ $soap_params{ expects } },
  0            
3809             { name => $expected, type => 'xsd:string' };
3810             }
3811             }
3812              
3813 0           foreach my $returned ( @{ $choices->{ returns } } ) {
  0            
3814 0 0         if ( ref( $returned ) eq 'HASH' ) {
3815 0           my ( $name, $type ) = %{ $returned };
  0            
3816 0           push @{ $soap_params{ returns } },
  0            
3817             { name => $name, type => $type };
3818             }
3819             else {
3820 0           push @{ $soap_params{ returns } },
  0            
3821             { name => $returned, type => 'xsd:string' };
3822             }
3823             }
3824              
3825 0           return \%soap_params;
3826             }
3827              
3828             # Given
3829             # [ Label => url, Label2 => url2, Label_no_url; ]
3830             # Returns
3831             # [
3832             # { text => 'Label', link => 'url' },
3833             # { text => 'Label2', link => 'url2' },
3834             # { text => 'Plain_Label', link => '$$self{location}/plain_label' },
3835             # ]
3836             my %crud_type_for = (
3837             add => 'create',
3838             create => 'create',
3839             view => 'retrieve',
3840             edit => 'update',
3841             udpate => 'update',
3842             delete => 'delete',
3843             );
3844             sub _build_options {
3845 0     0     my $opts = shift;
3846 0           my $bigtop_args = $opts->{ options };
3847 0           my $url_suffix = $opts->{ url_suffix };
3848 0   0       my $row_options = $opts->{ row_options } || 0;
3849 0   0       my $perms = $opts->{ perms } || {};
3850              
3851 0           my @options;
3852 0           foreach my $option ( @{ $bigtop_args } ) {
  0            
3853 0           my $label;
3854             my $location;
3855 0           my $crud_type;
3856 0           my $action;
3857              
3858 0 0         if ( ref( $option ) =~ /HASH/ ) {
3859 0           ( $label, $location ) = %{ $option };
  0            
3860              
3861 0 0         if ( $row_options ) { # remove /$id if present
3862 0           $location =~ s{ / \$ id (.)? $ }{$1}x;
3863             }
3864 0           $action = _label_to_action( $label );
3865             }
3866             else {
3867 0           $label = $option;
3868 0           $action = _label_to_action( $label );
3869              
3870 0 0         if ( not $row_options ) {
3871 0           $location = '$real_location . "' .
3872             $action . $url_suffix . '"';
3873             }
3874              
3875             }
3876 0   0       $crud_type = $perms->{ $label } || $crud_type_for{ $action };
3877              
3878 0 0         if ( $row_options ) {
3879 0   0       $crud_type ||= 'retrieve';
3880             }
3881             else {
3882 0   0       $crud_type ||= 'create';
3883             }
3884              
3885 0           push @options, {
3886             text => $label,
3887             location => $location,
3888             type => $crud_type,
3889             };
3890             }
3891              
3892 0           return \@options;
3893             }
3894              
3895             sub _label_to_action {
3896 0     0     my $label = shift;
3897 0           my $action = lc $label;
3898              
3899 0           $action =~ s/ /_/g;
3900              
3901 0           return $action;
3902             }
3903              
3904             sub _build_arg_capture {
3905 0     0     my @extras = @_;
3906              
3907 0           my @args = ( '$self', @extras );
3908 0           my $arg_capture =
3909             Bigtop::Backend::Control::Gantry::arg_capture_st_nick_style(
3910             { args => \@args }
3911             );
3912              
3913 0           return ( $arg_capture, @extras );
3914             }
3915              
3916             sub _crud_form_outputer {
3917 0     0     my $self = shift;
3918 0           my $child_output = shift;
3919 0           my $data = shift;
3920 0           shift; # parent. not needed.
3921 0   0       my $auto_crud = shift || 0;
3922              
3923             # set up args
3924 0           my $choices = { @{ $child_output } };
  0            
3925              
3926 0 0         my $default_arg = ( $auto_crud ) ? '$row' : '$data';
3927              
3928 0           my ( $arg_capture, @doc_args )
3929 0           = _build_arg_capture( $default_arg, @{ $choices->{extra_args} } );
3930              
3931             # get the fields
3932 0           my %name_of;
3933 0           $name_of{method} = $self->get_method_name();
3934 0           $name_of{controller} = $self->get_controller_name();
3935              
3936 0 0         if ( $name_of{method} eq '_form' ) {
3937 0 0         if ( $auto_crud ) {
3938 0           warn "form methods should be called form (not _form)\n";
3939             }
3940             else {
3941 0           warn "form methods should have a name like my_form, "
3942             . "not just _form\n";
3943             }
3944             }
3945              
3946 0           $self->get_table_name_for( $data->{lookup}, \%name_of );
3947              
3948 0           my $fields = $self->get_fields_from( $data->{lookup}, \%name_of );
3949              
3950 0 0 0       unless ( defined $choices->{fields}
3951             or
3952             defined $choices->{all_fields_but} )
3953             {
3954 0           die "Error: I can't generate AutoCRUD_form for $name_of{method} "
3955             . "of controller $name_of{controller}.\n"
3956             . " No fields (or all_fields_but) were given.\n";
3957             }
3958              
3959 0           my $requested_fields;
3960              
3961 0 0         if ( defined $choices->{all_fields_but} ) {
3962 0           $requested_fields = _find_all_fields_but(
3963             $choices->{all_fields_but},
3964             $data,
3965             $name_of{table}
3966             );
3967             }
3968             else {
3969 0           $requested_fields = $choices->{fields};
3970             }
3971              
3972 0           my @field_lookups;
3973             my @refers_to;
3974 0           foreach my $field_name ( @{ $requested_fields } ) {
  0            
3975 0           my $field = get_field_for( $field_name, $fields, \%name_of );
3976              
3977 0           my %clean_field;
3978              
3979 0           $clean_field{name} = $field_name;
3980              
3981 0           FIELD_STATEMENT:
3982 0           foreach my $key ( keys %{ $field } ) {
3983 0 0         next FIELD_STATEMENT if ( $key eq '__IDENT__' );
3984              
3985 0           my $clean_key = $key;
3986 0           $clean_key =~ s/html_form_//;
3987              
3988 0           my $clean_value = $field->{$key}{args}[0];
3989              
3990             # translate foreign key into select list
3991 0 0         if ( $clean_key eq 'refers_to' ) {
    0          
3992 0           $clean_key = 'options_string';
3993              
3994 0 0         if ( ref( $clean_value ) eq 'HASH' ) {
3995 0           ( $clean_value ) = %{ $clean_value };
  0            
3996             }
3997 0           $clean_value =~ s/\./_/; # might have schema prefix
3998 0           push( @refers_to, $clean_value );
3999 0           $clean_value = '$selections->{' . $clean_value . '}';
4000             }
4001             # pull out all pairs
4002             elsif ( $clean_key eq 'options' ) {
4003 0           my @option_pairs;
4004 0           foreach my $pair ( @{ $field->{$key}{args} } ) {
  0            
4005 0           push @option_pairs, $pair;
4006             }
4007 0           $clean_value = \@option_pairs;
4008             }
4009             else {
4010 0           $clean_value = $field->{$key}{args}[0];
4011             }
4012              
4013 0           $clean_field{ $clean_key } = $clean_value;
4014             }
4015              
4016 0           push @field_lookups, \%clean_field;
4017             }
4018              
4019 0           my %extra_keys;
4020 0 0         if ( $choices->{extra_keys} ) {
4021 0           foreach my $pair ( @{ $choices->{extra_keys} } ) {
  0            
4022 0           my ( $key, $value ) = %{ $pair };
  0            
4023 0           $extra_keys{ $key } = $value;
4024             }
4025             }
4026              
4027             # build body
4028 0           my $form_body = Bigtop::Backend::Control::Gantry::form_body(
4029             {
4030             model => $data->{model_alias},
4031             form_name => $choices->{form_name}[0],
4032             fields => \@field_lookups,
4033             refers_to => \@refers_to,
4034             extra_keys => \%extra_keys,
4035             raw_row => $auto_crud,
4036             dbix => $self->is_dbix_class( $data ),
4037             }
4038             );
4039              
4040 0 0         my $output_type = ( $auto_crud ) ? 'gen_output' : 'crud_output';
4041              
4042             return [
4043 0           $output_type => {
4044             body => "$arg_capture\n$form_body",
4045             doc_args => \@doc_args,
4046             },
4047             comment_output => {
4048             doc_args => \@doc_args,
4049             }
4050             ];
4051             }
4052              
4053             sub output_AutoCRUD_form {
4054 0     0     return _crud_form_outputer( @_, 1 );
4055             }
4056              
4057             sub output_CRUD_form {
4058 0     0     my ( $self, undef, $data ) = @_;
4059              
4060 0           return _crud_form_outputer( @_, 0 );
4061             }
4062              
4063             sub _find_all_fields_but {
4064 0     0     my $excluded_fields = shift;
4065 0           my $data = shift;
4066 0           my $table_name = shift;
4067              
4068 0           my $bigtop_tree = $data->{tree};
4069              
4070             # ask the corresponding table for its fields
4071 0           my $fields = $bigtop_tree->walk_postorder(
4072             'output_field_names', { table_of_interest => $table_name }
4073             );
4074              
4075 0           my @retval;
4076              
4077             # now build the return list
4078             my %exclude_this;
4079 0           @exclude_this{ @{ $excluded_fields } } = @{ $excluded_fields };
  0            
  0            
4080              
4081 0           foreach my $field ( @{ $fields } ) {
  0            
4082 0 0         push @retval, $field unless $exclude_this{ $field };
4083             }
4084              
4085 0           return \@retval;
4086             }
4087              
4088             package # method_statement
4089             method_statement;
4090 1     1   8 use strict; use warnings;
  1     1   3  
  1         28  
  1         6  
  1         1  
  1         297  
4091              
4092             sub with_perms {
4093 0     0     my $self = shift;
4094              
4095 0 0         return unless $self->{__KEYWORD__} eq 'permissions';
4096              
4097 0           return [ $self->{__ARGS__} ];
4098             }
4099              
4100             sub walker_output {
4101 0     0     my $self = shift;
4102              
4103 0           return [ $self->{__KEYWORD__} => $self->{__ARGS__} ];
4104             }
4105              
4106 0     0     sub output_hashref { goto &walker_output; }
4107              
4108 0     0     sub output_stub { goto &walker_output; }
4109              
4110 0     0     sub output_main_listing { goto &walker_output; }
4111              
4112 0     0     sub output_AutoCRUD_form { goto &walker_output; }
4113              
4114 0     0     sub output_CRUD_form { goto &walker_output; }
4115              
4116 0     0     sub output_base_links { goto &walker_output; }
4117              
4118 0     0     sub output_links { goto &walker_output; }
4119              
4120 0     0     sub output_SOAP { goto &walker_output; }
4121              
4122 0     0     sub output_SOAPDoc { goto &walker_output; }
4123              
4124             1;