File Coverage

blib/lib/CGI/Application/Plugin/BREAD.pm
Criterion Covered Total %
statement 21 174 12.0
branch 0 26 0.0
condition 0 3 0.0
subroutine 7 22 31.8
pod 5 5 100.0
total 33 230 14.3


%; %;
line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::BREAD;
2              
3 3     3   100097 use 5.006;
  3         12  
  3         112  
4 3     3   19 use strict;
  3         5  
  3         87  
5 3     3   14 use warnings;
  3         12  
  3         127  
6              
7 3     3   16 use vars qw( @ISA @EXPORT @EXPORT_OK $VERSION );
  3         7  
  3         268  
8              
9 3     3   5496 use HTML::Template;
  3         50592  
  3         162  
10 3     3   3358 use HTML::FillInForm;
  3         10835  
  3         7618  
11              
12             @ISA = qw( Exporter AutoLoader );
13              
14             our @EXPORT_OK = qw(
15             bread_db
16             browse_page_size
17             template_path
18             template_type
19             log_directive
20             );
21              
22             our $VERSION = '0.12_2';
23              
24             sub import
25             {
26 3     3   41 my $caller = scalar( caller );
27 3         41 $caller->add_callback( 'prerun' => \&_register_runmodes );
28 3         279 goto &Exporter::import;
29             }
30              
31             sub _register_runmodes
32             {
33 0     0     my ( $self, %runmodes, $tables, $uri );
34 0           $self = shift;
35            
36             #warn "CGI::Application::Plugin::BREAD::register_runmodes() called!";
37 0           %runmodes = ( 'start' => \&_start );
38 0           $tables = {};
39 0 0         if ( $self->{'BREAD'}->{'classes'} ) {
40 0           foreach my $cdbi_class ( @{$self->{'BREAD'}->{'classes'}} ) {
  0            
41 0           my $table = $cdbi_class->table;
42 0           $runmodes{ "browse_$table" } = \&_browse;
43 0           $runmodes{ "read_$table" } = \&_read;
44 0           $runmodes{ "edit_$table" } = \&_edit;
45 0           $runmodes{ "add_$table" } = \&_add;
46 0           $runmodes{ "delete_$table" } = \&_delete;
47 0           $runmodes{ 'add_'.$table.'_submit' } = \&_submit;
48 0           $runmodes{ 'edit_'.$table.'_submit' } = \&_submit;
49 0           $tables->{$table} = $cdbi_class;
50             }
51             } else {
52 0           die "We don't have any db classes! Did you set any up with the bread_db() method?";
53             }
54 0           $self->{'BREAD'}->{'tables'} = $tables;
55 0           $uri = $ENV{'SCRIPT_URI'};
56             # take off any tailing parameters...
57             #$uri =~ s/\?.+//;
58 0           $self->{'BREAD'}->{'uri'} = $uri;
59            
60 0           $self->run_modes( %runmodes );
61             }
62              
63             sub bread_db
64             {
65 0     0 1   my ( $self, $parameter, $classes );
66            
67 0           ( $self, $parameter ) = @_;
68             #warn "CGI::Application::Plugin::BREAD::bread_db() called!";
69            
70             # check parameter type ... it's either an arrayref or a ::Loader ref
71 0           $classes = [];
72 0 0         if ( ref( $parameter ) eq 'ARRAY' ) {
    0          
73 0           $self->{'BREAD'}->{'cdbi_type'} = 'classes';
74 0           foreach my $cdbi_class ( @$parameter ) {
75             # check to see if it's loaded already
76 0 0         unless ( $cdbi_class:: ) {
77 0           my ( $file );
78 0           $file = $cdbi_class;
79 0           $file =~ s-::-/-g;
80 0           eval {
81 0           require "$file.pm";
82 0           $cdbi_class->import();
83             };
84 0 0         die "CGI::Application::Plugin::BREAD::bread_db(): Couldn't use $cdbi_class class: $@" if ( $@ );
85             }
86 0           push @$classes, $cdbi_class;
87             }
88             } elsif ( ref( $parameter ) =~ /^Class::DBI::Loader/ ) {
89 0           $self->{'BREAD'}->{'cdbi_type'} = 'loader';
90 0           foreach my $class ( $parameter->classes ) {
91 0           push @$classes, $class;
92             }
93             } else {
94 0           my $ref = ref( $parameter );
95 0           die "CGI::Application::Plugin::BREAD::bread_db(): Invalid parameter\nParameter must either be an array reference of Class::DBI classes or a Class::DBI::Loader object\nYou gave me a $ref object.";
96             }
97 0           $self->{'BREAD'}->{'classes'} = $classes;
98             }
99              
100             sub browse_page_size
101             {
102 0     0 1   my ( $self, $size ) = @_;
103 0 0 0       if ( $size =~ /^\d+$/ && $size > 0 ) {
104 0           $self->{'BREAD'}->{'page_size'} = $size;
105             } else {
106 0           warn "CGI::Application::Plugin::BREAD::browse_page_size(): Invalid page_size ($size) - must be a positive decimal.";
107             }
108             }
109              
110             sub template_path
111             {
112 0     0 1   warn "Sorry - this feature (CAP::Bread::template_path()) hasn't been implemented yet!";
113             }
114              
115             sub template_type
116             {
117 0     0 1   warn "Sorry - this feature (CAP::Bread::template_type()) hasn't been implemented yet!";
118             }
119              
120             sub log_directive
121             {
122 0     0 1   warn "Sorry - this feature (CAP::Bread::log_directive()) hasn't been implemented yet!";
123             }
124              
125             sub _start
126             {
127 0     0     my ( $self, $table_ar, $table_hr, $uri, $template_html, $template );
128 0           $self = shift;
129            
130 0           $table_ar = [];
131 0           $table_hr = $self->{'BREAD'}->{'tables'};
132 0           while( my ( $table, undef ) = each %$table_hr ) {
133 0           push @$table_ar, {
134             'table' => $table,
135             };
136             }
137 0           $uri = $self->{'BREAD'}->{'uri'};
138            
139 0           $template_html = <<_EOF_;
140            
141            
142             Database Administration
143            
144            
145             This application is setup to manage the following tables:
146            
147            
148            
  • : ">Browse or ">Add
  • 149            
    150            
    151            
    152            
    153             _EOF_
    154            
    155 0           $template = HTML::Template->new( 'scalarref' => \$template_html );
    156 0           $template->param( 'tables' => $table_ar );
    157 0           $template->output;
    158             }
    159              
    160             sub _browse
    161             {
    162 0     0     my ( $self, $runmode, $table, $class, @columns, $colspan, @other_columns, $objects_iterator, $headers, $records, $subtemplate, $uri, $template_html, $template, $get_data_sub, $pager );
    163            
    164 0           $self = shift;
    165 0           $runmode = $self->get_current_runmode();
    166 0           ( $table ) = $runmode =~ /^browse_(.+)$/;
    167            
    168 0           $class = $self->{'BREAD'}->{'tables'}->{$table};
    169 0 0         $self->{'BREAD'}->{'page_size'} = 20 if ! $self->{'BREAD'}->{'page_size'};
    170            
    171 0           @columns = $class->columns;
    172 0           $colspan = scalar( @columns );
    173 0           $objects_iterator = $class->retrieve_all;
    174 0           $headers = [];
    175 0           $subtemplate = '';
    176 0           $uri = $self->{'BREAD'}->{'uri'};
    177             # pull out primary column (if we have it) first...
    178 0 0         if ( my $primary = $class->primary_column ) {
    179 0           push @$headers, { 'header' => $primary };
    180 0           $subtemplate .= qq%"> &$primary=" onClick="javascript: if (confirm('Are You Sure?')){return true;}else{return false;}">Delete
    181             # now need to take it out of @columns
    182 0           @other_columns = grep( !/^$primary$/, @columns );
    183             } else {
    184 0           @other_columns = @columns;
    185             }
    186 0           foreach my $header ( sort @other_columns ) {
    187 0           push @$headers, { 'header' => $header };
    188 0           $subtemplate .= qq%
    189             }
    190            
    191 0           $template_html = <<_EOF_;
    192            
    193            
    194             Database Administration :: Browsing <TMPL_VAR NAME="table" ESCAPE=HTML> Table
    195            
    196            
    197              
    198            

    199             The table has the following records, broken up into pages of each:
    200            

    201              
    202            
    203            
    204            
    205            
    206            
    207            
    208            
    209            
    210            
    211            
    212            
    213             $subtemplate
    214            
    215            
    216            
    217            
    218            
    219            
    220            
    221            
    222            
    223            
    224            
    225              
    226            
    227            
    228             _EOF_
    229            
    230 0           $template = HTML::Template->new( 'scalarref' => \$template_html, 'global_vars' => 1 );
    231 0           $template->param(
    232             'table' => $table,
    233             'headers' => $headers,
    234             'count' => $objects_iterator->count,
    235             'pagesize' => $self->{'BREAD'}->{'page_size'},
    236             'num_pages' => sprintf( "%d", ($objects_iterator->count/$self->{'BREAD'}->{'page_size'})+1 )
    237             );
    238            
    239             $get_data_sub = sub
    240             {
    241 0     0     my ( $offset, $rows, @objects, $records );
    242 0           ( $offset, $rows ) = @_;
    243 0           @objects = $objects_iterator->slice( $offset, $rows+$offset-1 );
    244 0           $records = [];
    245            
    246 0           foreach my $obj ( @objects ) {
    247 0           my %data = ();
    248 0           foreach my $column ( @columns ) {
    249 0           my $subdata = $obj->get( $column );
    250 0 0         $subdata = ref( $subdata ) if ref( $subdata );
    251 0           $data{$column} = $subdata;
    252             }
    253 0           push @$records, \%data;
    254             }
    255              
    256 0           return $records;
    257 0           };
    258            
    259 0           require HTML::Pager;
    260 0           $pager = HTML::Pager->new(
    261             'template' => $template,
    262             'query' => $self->query,
    263             'rows' => $objects_iterator->count,
    264             'page_size' => $self->{'BREAD'}->{'page_size'},
    265             'get_data_callback' => $get_data_sub,
    266             'persist_vars' => [ 'rm' ],
    267             );
    268 0           return $pager->output();
    269             }
    270              
    271             sub _read
    272 0     0     {
    273             # not sure if this is needed...
    274             }
    275              
    276             sub _edit
    277             {
    278 0     0     my ( $self, $runmode, $table, $html, $class, $obj, %data, $fif );
    279            
    280 0           $self = shift;
    281 0           $runmode = $self->get_current_runmode();
    282 0           ( $table ) = $runmode =~ /^edit_(.+)$/;
    283              
    284 0           $html = _get_add_or_edit_form( $self );
    285              
    286 0           $class = $self->{'BREAD'}->{'tables'}->{$table};
    287 0           $obj = $class->retrieve( $self->query->param( 'id' ) );
    288 0           %data = ();
    289 0           foreach my $column ( sort $class->columns ) {
    290 0           $data{ $column } = $obj->get( $column );
    291             }
    292            
    293 0           $fif = HTML::FillInForm->new();
    294 0           $fif->fill(
    295             'scalarref' => \$html,
    296             'fdat' => \%data
    297             );
    298             }
    299              
    300             sub _add
    301             {
    302 0     0     my ( $self );
    303            
    304 0           $self = shift;
    305            
    306 0           _get_add_or_edit_form( $self );
    307             }
    308              
    309             sub _delete
    310             {
    311 0     0     my ( $self, $runmode, $table, $class, $obj );
    312            
    313 0           $self = shift;
    314 0           $runmode = $self->get_current_runmode();
    315 0           ( $table ) = $runmode =~ /^delete_(.+)$/;
    316 0           $class = $self->{'BREAD'}->{'tables'}->{$table};
    317 0           $obj = $class->retrieve( $self->query->param( 'id' ) );
    318            
    319 0           $obj->delete;
    320            
    321 0           $self->header_type( 'redirect' );
    322 0           $self->header_props( -url => $self->{'BREAD'}->{'uri'} );
    323             }
    324              
    325             sub _submit
    326             {
    327 0     0     my ( $self, $runmode, $mode, $table, $class, $form );
    328              
    329 0           $self = shift;
    330 0           $runmode = $self->get_current_runmode();
    331 0           ( $mode, $table ) = $runmode =~ /^(add|edit)_(.+)_submit$/;
    332 0           $class = $self->{'BREAD'}->{'tables'}->{$table};
    333            
    334 0           $form = $class->as_form( params => $self->query );
    335 0 0         if ( $form->submitted ) {
    336 0 0         if ( $mode eq 'add' ) {
        0          
    337 0           my $obj = $class->create_from_form( $form );
    338             } elsif ( $mode eq 'edit' ) {
    339 0           my $obj = $class->update_from_form( $form );
    340             } else {
    341 0           warn "CGI::Application::Plugin::BREAD::_submit(): Unknown mode ($mode) - Expecting add or edit.";
    342             }
    343             }
    344            
    345             # redirecting user back to main page
    346 0           $self->header_type( 'redirect' );
    347 0           $self->header_props( -url => $self->{'BREAD'}->{'uri'} );
    348             }
    349              
    350             sub _get_add_or_edit_form
    351             {
    352 0     0     my ( $self, $subtitle, $form, $rm_hidden, $runmode, $mode, $table, $class, $template_html, $template );
    353            
    354 0           $self = shift;
    355            
    356 0 0         if ( $self->query->param( 'id' ) ) {
    357 0           $subtitle = q%Editing Entry # %;
    358             } else {
    359 0           $subtitle = 'Adding an Entry';
    360             }
    361              
    362 0           $runmode = $self->get_current_runmode();
    363 0           ( $mode, $table ) = $runmode =~ /^(add|edit)_(.+)$/;
    364 0           $class = $self->{'BREAD'}->{'tables'}->{$table};
    365 0           $class->form_builder_defaults( { method => 'post' } );
    366              
    367 0           $form = $class->as_form( params => $self->query )->render;
    368 0           $rm_hidden = '';
    369 0           $form =~ s/
    370              
    371 0           $template_html = <<_EOF_;
    372            
    373            
    374             Database Administration :: $subtitle to the <TMPL_VAR NAME="table" ESCAPE=HTML> Table
    375            
    376            
    377              
    378             $form
    379              
    380            
    381            
    382             _EOF_
    383            
    384 0           $template = HTML::Template->new( 'scalarref' => \$template_html, 'associate' => $self->query );
    385 0           $template->param(
    386             'table' => $table,
    387             );
    388 0           $template->output;
    389             }
    390              
    391             1;
    392             __END__