File Coverage

blib/lib/DBIx/Browse/CGI.pm
Criterion Covered Total %
statement 15 301 4.9
branch 0 102 0.0
condition 0 54 0.0
subroutine 5 20 25.0
pod 5 15 33.3
total 25 492 5.0


line stmt bran cond sub pod time code
1             #
2             # $Id: CGI.pm,v 0.7 2002/05/01 11:34:40 evilio Exp $
3             #
4             package DBIx::Browse::CGI;
5              
6 2     2   2356 use strict;
  2         6  
  2         81  
7 2     2   10 use diagnostics;
  2         4  
  2         25  
8 2     2   66 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  2         4  
  2         148  
9              
10 2     2   21 use CGI qw( -no_debug );
  2         4  
  2         19  
11 2     2   2106 use CGI::Carp;
  2         5410  
  2         18  
12              
13             require Exporter;
14             require DBIx::Browse;
15              
16             @ISA = qw( DBIx::Browse Exporter);
17              
18             @EXPORT = qw(
19             );
20             #
21             # Keep Revision from CVS and Perl version in paralel.
22             #
23             $VERSION = do { my @r=(q$Revision: 0.7 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
24              
25             #
26             # init
27             #
28             sub init {
29 0     0 0   my $self = shift;
30 0           my $param = shift;
31              
32 0           my ( $cgi, $maxrows, $maxflength, $default_action,
33             $styles, $form_params, $order, $noprint);
34              
35 0   0       $cgi = $param->{cgi} || new CGI;
36 0   0       $maxrows = $param->{max_rows} || 10;
37 0   0       $maxflength = $param->{max_flength} || 40;
38 0   0       $order = $param->{row_order} || '';
39 0   0       $default_action = $param->{default_action} || 'List';
40 0   0       $form_params = $param->{form_params} || {};
41 0   0       $styles = $param->{styles} || [ 'Even','Odd'];
42 0   0       $noprint = $param->{no_print} || 0;
43              
44 0           $self->{cgi} = $cgi;
45 0           $self->{max_rows} = $maxrows;
46 0           $self->{max_flength} = $maxflength;
47 0           $self->{actions} = {
48             'List' => \&DBIx::Browse::CGI::list_form,
49             'Edit' => \&DBIx::Browse::CGI::edit_form
50             };
51 0           $self->{default_action} = $default_action;
52 0           $self->{form_params} = $form_params;
53 0           $self->{row_order} = $order;
54 0           $self->{styles} = $styles;
55 0           $self->{noprint} = $noprint;
56 0           $self->{cgi_buffer} = '';
57             #
58             # This must be last
59             #
60 0           $self->SUPER::init( $param );
61             }
62              
63             #
64             # list_form
65             #
66             sub list_form {
67 0     0 1   my $self = shift;
68 0   0       my $param = shift || {};
69 0           my $q = $self->{cgi};
70 0           my $string = '';
71 0           my @columns;
72             my @fnames;
73 0           my @forder;
74 0           my @flength;
75 0           my $where ='';
76 0           my $row;
77 0   0       my $rec = $q->param('record_number') || 0;
78              
79 0 0         if ($q->param('nextrec')) {
80 0           $rec += 10;
81             }
82              
83 0 0         if ($q->param('prevrec')) {
84 0           $rec -= 10;
85             }
86              
87 0 0         if ($q->param('firstrec')) {
88 0           $rec = 0;
89             }
90            
91              
92 0           @columns = ( @{$self->{aliases}} );
  0            
93              
94 0 0 0       if ( $param->{field_names} &&
  0            
95             (scalar @{$param->{field_names}} == scalar @columns )) {
96 0           @fnames = @{$param->{field_names}};
  0            
97             } else {
98 0           @fnames = @columns;
99             }
100              
101 0           for (my $f = 0; $f < scalar( @columns ); $f++) {
102 0           my $c = $columns[$f];
103             #if ( grep( /^$c$/, @{$self->{aliases}} )) {
104             # my $i = $f - scalar(@{$self->{non_linked}});
105             # $c = $self->{table_aliases}->[$i+1].'.'.$self->{linked_values}->[$i];
106             #}
107             #else {
108             # $c = $self->{table_aliases}->[0].'.'.$c;
109             #}
110 0 0         if ( $q->param('search.'.$columns[$f]) ) {
111 0           $where .= $c;
112 0           $where .= $self->{syntax}->{ilike};
113 0           $where .= $self->{dbh}->quote(
114             $self->{syntax}->{glob}.
115             $q->param('search.'.$columns[$f]).
116             $self->{syntax}->{glob}
117             );
118 0           $where .= ' AND ';
119             }
120             }
121 0           $where =~ s/AND $//;
122              
123 0           $q->param(-name => 'where_clause', -value => "$where");
124            
125 0           my $last = $self->count( {where => "$where"})-1;
126              
127 0 0         if ($q->param('lastrec')) {
128 0           $rec = $last - $self->{max_rows} + 1;
129             }
130              
131 0           $self->debug("Rec: $rec, Last: $last, Max: $self->{max_rows}");
132              
133 0 0         $rec = ($rec <= ($last-$self->{max_rows}+1)) ? $rec : $last-$self->{max_rows}+1;
134 0 0         $rec = ($rec < 0 ) ? 0 : $rec;
135              
136 0 0         my $sth = $self->prepare({
137             where => "$where",
138             order => $self->row_order,
139             limit => $self->{max_rows},
140             offset => "$rec"
141             }) or $self->die();;
142 0 0         $sth->execute() or $self->die();;
143              
144              
145 0           $q->param(-name => 'record_number', -value => "$rec" );
146              
147              
148              
149 0 0 0       if ( $param->{field_order} &&
  0            
150             (scalar @{$param->{field_order}} == scalar @columns) ) {
151 0           @forder = @{$param->{field_order}};
  0            
152             }
153             else {
154 0           @forder = (0..(scalar(@columns)-1));
155             }
156              
157 0 0 0       if ( $param->{field_length} &&
  0            
158             (scalar @{$param->{field_length}} == scalar @columns) ) {
159 0           @flength = @{$param->{field_length}};
  0            
160             }
161             else {
162            
163             @flength = map
164             {
165 0 0         if ($_){ ( $_ < $self->{max_flength}) ? $_ : $self->{max_flength}}
  0 0          
  0            
166 0           else { 0; }
167             }
168 0           @{ $sth->{PRECISION} };
169             }
170              
171 0           $self->debug('Number of rows: '.$sth->rows());
172              
173              
174 0           $self->add_request(
175             $self->open_form($rec),
176             $q->hidden( -name => 'where_clause' ),
177             $q->start_table);
178              
179 0           $self->add_request(
180             $q->script({-language => 'JavaScript'},
181             "
182             function set_rc(f, i) {f.record_number.value = Number(f.record_number.value)+i; return true;}
183             function zero_rec(f) {f.record_number.value = 0;}\n"
184             ));
185              
186 0           $self->add_request(
187             $q->start_Tr,"\n",
188             $q->td(' '));
189 0           foreach my $f ( @forder ) {
190 0           $self->add_request( $q->th(ucfirst($fnames[$f])));
191             }
192             $self->add_request(
193 0           $q->end_Tr);
194              
195 0           my $style;
196 0   0       for (my $i = 0; $i < $sth->rows && $i < $self->{max_rows}; $i++) {
197 0           $style = $self->style_class($i);
198 0 0         if ( $row = $sth->fetchrow_hashref('NAME_lc') ) {
199 0           $self->add_request( $q->start_Tr());
200 0           $self->add_request( $q->td({-class => 'Bar'},
201             $q->submit(
202             -name => 'Page',
203             -value => 'Edit',
204             -onClick => "set_rc(this.form, $i);"
205             )
206            
207             ));
208 0           foreach my $f ( @forder ) {
209 0 0         my $v = defined($row->{$columns[$f]}) ?
210             $row->{$columns[$f]} : ' ';
211 0           $self->add_request(
212             $q->td( { -class => "$style"},
213             $v
214             ));
215             }
216 0           $self->add_request( $q->end_Tr());
217             }
218             }
219              
220            
221 0           $self->add_request(
222             $q->start_Tr,"\n",
223             $q->td(' '));
224              
225 0           foreach my $f ( @forder ) {
226 0           my $tf = {-name => 'search.'.$columns[$f],
227             -onChange => 'zero_rec(this.form); this.form.submit();',
228             };
229 0 0         if ($flength[$f]) {$tf->{'-size'} = $flength[$f]};
  0            
230              
231 0           $self->add_request( $q->td(
232             $q->textfield($tf)
233             ));
234             }
235             $self->add_request(
236 0           $q->end_Tr);
237              
238 0           $self->add_request(
239             $q->start_Tr,
240             $q->td(' '),
241             $q->start_td( {
242             -colspan => scalar @fnames,
243             -align => 'center'
244             }));
245              
246 0           $self->navigator('List');
247              
248 0           $self->add_request(
249             $q->end_td,
250             $q->end_Tr);
251              
252 0           $self->add_request(
253             $q->end_table,
254             $self->close_form);
255             # print page
256 0           $self->flush;
257             }
258              
259             #
260             # edit_form
261             #
262             sub edit_form {
263 0     0 1   my $self = shift;
264 0   0       my $param = shift || {};
265 0           my $rownum;
266 0 0         if ( ref($param) ne 'HASH') {
267 0           $rownum = $param;
268 0           $param = {};
269             }
270             else {
271 0           $rownum = shift;
272             }
273 0   0       my $where = shift || $self->{cgi}->param('where_clause');
274              
275              
276 0           my @columns;
277             my @fnames;
278 0           my @flength;
279 0           my @forder;
280              
281 0           my $q = $self->{cgi};
282              
283 0   0       my $rec = ($rownum || $q->param('record_number') || 0 );
284              
285 0           my $last = $self->count( {where => "$where"})-1;
286              
287 0 0         if ($q->param('nextrec')) {
288 0           $rec++;
289             }
290              
291 0 0         if ($q->param('prevrec')) {
292 0           $rec--;
293             }
294              
295 0 0         if ($q->param('firstrec')) {
296 0           $rec = 0;
297             }
298            
299 0 0         if ($q->param('lastrec')) {
300 0           $rec = $last
301             }
302              
303 0 0         $rec = ($rec <= $last ) ? $rec : $last;
304 0 0         $rec = ($rec < 0 ) ? 0 : $rec;
305              
306 0           $q->param(-name => 'record_number', -value => "$rec" );
307              
308 0 0         my $sth = $self->prepare({
309             where => $where,
310             order => $self->row_order,
311             limit => 1,
312             offset => "$rec"
313             }) or $self->die();
314              
315 0 0         $sth->execute() or $self->die();
316 0 0         my $row = $sth->fetchrow_hashref('NAME_lc') or $self->die();
317              
318             #
319             # column names
320             #
321 0           @columns = ( @{$self->{aliases}} );
  0            
322              
323 0 0 0       if ( $param->{field_names} &&
  0            
324             (scalar @{$param->{field_names}} == scalar @columns )) {
325 0           @fnames = @{$param->{field_names}};
  0            
326             } else {
327 0           @fnames = @columns;
328             }
329              
330 0 0 0       if ( $param->{field_order} &&
  0            
331             (scalar @{$param->{field_order}} == scalar @columns) ) {
332 0           @forder = @{$param->{field_order}};
  0            
333             }
334             else {
335 0           @forder = (0..(scalar(@columns)-1));
336             }
337              
338 0 0 0       if ( $param->{field_length} &&
  0            
339             (scalar @{$param->{field_length}} == scalar @columns) ) {
340 0           @flength = @{$param->{field_length}};
  0            
341             }
342             else {
343 0 0         @flength = map
344             {
345 0 0         if ($_) {($_ < $self->{max_flength}) ? $_ : $self->{max_flength}}
  0            
  0            
346             else {0;}
347             }
348 0           @{ $sth->{PRECISION} };
349             }
350             #
351             # actions
352             #
353 0           my $redo_query = 1;
354 0 0         if ( $q->param('add') ) {
    0          
    0          
355 0           my $record = {};
356 0           foreach my $f ( @columns ) {
357 0           $record->{$f} = $q->param($f);
358             }
359 0           $self->insert($record);
360 0           $q->delete('add');
361              
362 0           my $nwhere;
363 0           foreach my $w ( keys %$record ) {
364 0           $nwhere .=
365             $self->{table_aliases}->[0].'.'.$w.
366             " = ".
367             $self->{dbh}->quote($record->{$w})." AND ";
368             }
369 0           $nwhere =~ s/AND $//;
370              
371 0 0         $sth->finish() or $self->die();
372 0           $rec = 0;
373 0 0         $sth = $self->prepare({
374             where => $nwhere,
375             order => $self->pkey_name.' DESC ',
376             limit => 1,
377             offset => "$rec"
378             }) or $self->die();
379              
380             }
381             elsif ( $q->param('update') ) {
382 0           my $record = {};
383 0           foreach my $f ( @columns ) {
384 0           $record->{$f} = $q->param($f);
385             }
386 0           $self->update($record,
387             $self->{primary_key}." = ".
388             $row->{$self->pkey_name}
389             );
390 0           $q->delete('update');
391             }
392             elsif ( $q->param('remove') ){
393 0           $self->delete($row->{$self->pkey_name});
394 0 0         $rec = ( $rec > 0 ) ? ($rec-1) : $rec;
395 0           $q->param(-name => 'record_number', -value => "$rec" );
396 0           $q->delete('remove');
397             }
398             else {
399 0           $redo_query = 0;
400             }
401 0 0         if ( $redo_query ) {
402 0 0         $sth->execute() or $self->die();
403 0 0         $row = $sth->fetchrow_hashref('NAME_lc') or $self->die();
404             }
405              
406             # debug info
407 0 0         if ($self->debug) {
408 0           my $parstr = 'Parameters: ';
409 0           my @P = $q->param;
410 0           foreach my $p ( @P ) {
411 0           $parstr .= "$p = ".$q->param($p).$q->br();
412             }
413 0           $self->debug($parstr);
414             }
415              
416              
417              
418             $self->add_request(
419 0           $self->open_form($rec),
420             $q->hidden( -name => 'where_clause' ));
421             # include search info
422 0           foreach my $f ( @forder ) {
423 0           $self->add_request(
424             $q->hidden({
425             -name => 'search.'.$columns[$f]
426             })
427             );
428             }
429              
430 0           $self->add_request($q->start_table);
431              
432 0           my $style;
433 0           foreach my $f ( @forder ) {
434 0           $style = $self->style_class($f);
435 0           my $tf = {
436             -name => $columns[$f],
437             -default => $row->{$columns[$f]},
438             };
439 0 0         if ($flength[$f]) {$tf->{'-size'} = $flength[$f]};
  0            
440              
441 0           $self->add_request(
442             $q->start_Tr,"\n",
443             $q->th(ucfirst($fnames[$f])),"\n",
444             $q->start_td( {-class => "$style"} ));
445 0 0         if ($f < @{$self->{non_linked}} ) {
  0            
446             # Set the param
447 0           $q->param(-name => $columns[$f],
448             -value => $row->{$columns[$f]});
449 0           $self->add_request( $q->textfield($tf));
450             }
451             else {
452             ### value list ###
453 0           my $fvalues = $self->field_values($f);
454             # Set the param
455 0           $q->param(-name => $columns[$f],
456             -value => $row->{$columns[$f]});
457             # PopUp
458 0           $self->add_request( $q->popup_menu(
459             -name => $columns[$f],
460             -values => $fvalues,
461             -default => $row->{$columns[$f]},
462             ));
463             }
464 0           $self->add_request(
465             $q->end_td,"\n",$q->end_Tr
466             );
467             }
468             # Editor
469             $self->add_request(
470 0           $q->start_Tr,
471             $q->start_td( {
472             -colspan => 2,
473             -align => 'center' }));
474 0           $self->editor();
475 0           $self->add_request(
476             $q->end_td,
477             $q->end_Tr);
478             #Navigator
479 0           $self->add_request(
480             $q->start_Tr,
481             $q->start_td( {
482             -colspan => 2,
483             -align => 'center'
484             }));
485 0           $self->navigator('Edit');
486 0           $self->add_request(
487             $q->end_td,
488             $q->end_Tr);
489             # End table
490 0           $self->add_request(
491             $q->end_table);
492              
493 0           $self->close_form;
494             # print page
495 0           $self->flush;
496             }
497              
498             #
499             # open_form
500             #
501             sub open_form {
502 0     0 0   my $self = shift;
503 0           my $rec = shift;
504 0           my $q = $self->{cgi};
505 0           my $text = '';
506 0           $text = $q->start_multipart_form( -name => 'Browser_'.$self->{table}, -method => 'POST' );
507 0           $text .= "\n".$q->hidden(-name => 'record_number', -value => "$rec");
508 0 0         if( my @fparams = keys %{$self->{form_params}} ) {
  0            
509 0           $self->debug('Form Params: '.join(', ', @fparams));
510 0           foreach my $p ( @fparams ) {
511 0           $text .= $q->hidden(
512             -name => $p,
513             -value => $self->{form_params}->{$p}
514             );
515             }
516             }
517 0           return $text;
518             }
519              
520             #
521             # close_form
522             #
523             sub close_form {
524 0     0 0   my $self = shift;
525 0           my $q = $self->{cgi};
526 0           return $q->end_form;
527             }
528              
529             #
530             # navigator
531             #
532             sub navigator {
533 0     0 0   my $self = shift;
534 0           my $page = shift;
535 0           my $q = $self->{cgi};
536              
537 0           $q->param( -name => 'Page', -value => $page);
538              
539 0           $self->add_request(
540             $q->start_table( -align => 'CENTER' ));
541 0           $self->add_request(
542             $q->hidden(-name => 'Page'),"\n",
543             $q->Tr({ -class => 'Bar'}, "\n",
544             $q->td( { -class => 'Bar'},
545             $q->submit(
546             -name => 'firstrec',
547             -value => 'First'
548             )
549             ),"\n",
550             $q->td(
551             $q->submit(
552             -name => 'prevrec',
553             -value => 'Prev'
554             )
555             ),"\n",
556             $q->td(
557             $q->submit(
558             -name => 'nextrec',
559             -value => 'Next'
560             )
561             ),"\n",
562             $q->td(
563             $q->submit(
564             -name => 'lastrec',
565             -value => 'Last'
566             )
567             )
568             ));
569 0           $self->add_request(
570             $q->end_table);
571             }
572              
573             #
574             # editor
575             #
576             sub editor {
577 0     0 0   my $self = shift;
578 0           my $q = $self->{cgi};
579 0           $self->add_request(
580             $q->start_table( -align => 'CENTER' ));
581 0           $self->add_request(
582             $q->Tr({ -class => 'Bar'}, "\n",
583             $q->td({ -class => 'Bar'},
584             $q->submit(
585             -name => 'update',
586             -value => 'Update',
587             -onClick =>
588             "return window.confirm('Update: Are you sure?');"
589             )
590             ),"\n",
591             $q->td({ -class => 'Bar'},
592             $q->submit(
593             -name => 'remove',
594             -value => 'Remove',
595             -onClick =>
596             "return window.confirm('Remove: Are you sure?');"
597              
598             )
599             ),"\n",
600             $q->td({ -class => 'Bar'},
601             $q->submit(
602             -name => 'add',
603             -value => 'Add',
604             -onClick =>
605             "return window.confirm('Add: Are you sure?');"
606             )
607             ),"\n",
608             $q->td({ -class => 'Bar'},
609             $q->reset(
610             -name => 'Clear',
611             -value => 'Clear'
612             )
613             ),"\n",
614             $q->td({ -class => 'Bar'},
615             $q->submit(
616             -name => 'cancel',
617             -value => ' Back ',
618             -onClick => "this.form.Page.value = 'List';"
619             )
620             )
621             ));
622 0           $self->add_request(
623             $q->end_table);
624             }
625              
626             #
627             # generic browse
628             #
629             sub browse {
630 0     0 1   my $self = shift;
631 0   0       my $param = shift || {};
632              
633 0   0       my $action = ($self->{cgi}->param('Page') or
634             $self->{default_action});
635              
636 0           $self->debug("Action: $action");
637              
638 0           ACTION:
639             {
640 0           foreach my $a ( keys %{$self->{actions}} ) {
  0            
641 0 0         if ( $action eq $a) {
642 0           $self->{actions}->{$a}->($self, $param->{$action});
643 0           last ACTION;
644             }
645             }
646             # We should'n arrive here
647 0           carp "Not a valid action: $action\n";
648             }
649             }
650              
651             #
652             # style_class
653             #
654             sub style_class {
655 0     0 0   my $self = shift;
656 0           my $num = shift;
657 0           my $s = $num % scalar( @{$self->{styles}} );
  0            
658 0           return $self->{styles}->[$s];
659             }
660             #
661             # debug
662             #
663             sub debug {
664 0     0 1   my $self = shift;
665 0 0         return (0) unless $self->{debug};
666 0           my $txt = shift;
667 0 0         $self->add_request( $self->{cgi}->p({-class => 'Debug'},
668             $txt
669             )) if ($txt);
670 0           return 1;
671             }
672              
673             #
674             # print
675             #
676             sub print {
677 0     0 0   my ($self, @args) = @_;
678 0 0         print @args
679             unless($self->{no_print});
680             }
681              
682             #
683             # print error
684             #
685             sub print_error {
686 0     0 0   my $self = shift;
687 0           my $error = shift;
688 0           my $q = $self->{cgi};
689              
690 0           foreach my $er ( split(/\n/m, $error)) {
691 0           $self->add_request( $q->p({-Class => 'Error'}, $er));
692             }
693 0           $self->add_request( $q->end_html());
694             # print page
695 0           $self->flush;
696             }
697              
698             #
699             # row_order
700             #
701             sub row_order {
702 0     0 1   my $self = shift;
703 0           my $order = $self->pkey_name.' ASC ';
704 0 0         $order = $self->{row_order}.', '.$order
705             if $self->{row_order};
706 0           return $order;
707             }
708              
709             #
710             # add to request
711             #
712             sub add_request {
713 0     0 0   my $self = shift;
714 0           my @strings = @_;
715 0           foreach my $s ( @strings ) {
716 0           $self->{cgi_buffer} .= $s."\n";
717             }
718             }
719             #
720             # flush
721             #
722             sub flush {
723 0     0 0   my $self = shift;
724 0           my $request = $self->{cgi_buffer};
725              
726 0 0         print $request
727             unless ($self->{noprint});
728 0           $self->{cgi_buffer} = '';
729 0           return $request;
730             }
731              
732             #########################################################################
733             1;
734             #
735             #
736             #
737             __END__