File Coverage

lib/CGI/OptimalQuery/InteractiveQuery.pm
Criterion Covered Total %
statement 12 238 5.0
branch 0 138 0.0
condition 0 78 0.0
subroutine 4 9 44.4
pod 0 5 0.0
total 16 468 3.4


line stmt bran cond sub pod time code
1             package CGI::OptimalQuery::InteractiveQuery;
2              
3 1     1   861 use strict;
  1         4  
  1         23  
4 1     1   4 use warnings;
  1         2  
  1         23  
5 1     1   4 no warnings qw( uninitialized );
  1         2  
  1         28  
6 1     1   5 use base 'CGI::OptimalQuery::Base';
  1         1  
  1         3116  
7              
8             sub new {
9 0     0 0   my $pack = shift;
10 0           my $o = $pack->SUPER::new(@_);
11              
12 0   0       $$o{schema}{options}{'CGI::OptimalQuery::InteractiveQuery'}{WindowWidth} ||= 800;
13 0   0       $$o{schema}{options}{'CGI::OptimalQuery::InteractiveQuery'}{WindowHeight} ||= 600;
14              
15 0           return $o;
16             }
17              
18              
19              
20              
21             sub get_defaultCSS {
22 0     0 0   return <
23              
24             #OQinfo tr td { border: 1px solid #efefef; }
25             #OQinfo tr td.OQinfoName { border: 1px solid #666666; }
26              
27             #OQdataLHead {
28             background-color: #efefef;
29             }
30              
31             td.OQinfoName {
32             width: 1%;
33             font-size: 13px;
34             }
35              
36             .OQinfoVal {
37             background-color: white !important;
38             font-size: 13px;
39             }
40              
41             #OQtitle {
42             width: 40%;
43             padding-left: 10px !important;
44             }
45              
46             #OQhead td {
47             padding: 4px !important;
48             }
49              
50             /* workaround: too bad 'text-align: center' does not work */
51             table.OQpager {
52             margin-left: auto;
53             margin-right: auto;
54             }
55              
56             .OQcolHeadTitle {
57             font-size: 1.1em;
58             color: black;
59             font-weight: bold;
60             }
61              
62             #OQdata tr td {
63             border-right: 1px solid #efefef;
64             }
65              
66             #OQhead, #OQinfo, #OQdata {
67             width: 100%;
68             }
69              
70              
71             #OQdoc td {
72             padding: 2px 5px 2px 5px;
73             }
74              
75              
76             #OQhead {
77             background-color: #666666;
78             }
79              
80             #OQhead td {
81             color: white;
82             padding: 0px;
83             }
84              
85             #OQdoc button {
86             cursor: pointer;
87             background-color: #dddddd;
88             border: 1px outset #333333;
89             font-size: .8em;
90             color: #111111;
91             padding: 0px;
92             }
93              
94             #OQsummary {
95             width: 30%
96             }
97              
98             #OQcmds button {
99             margin-right: 2px;
100             }
101              
102             div.OQcolCmds button {
103             font-size: 10px;
104             }
105             div.OQcolCmds button {
106             margin-right: 1px;
107             }
108             div.OQcolCmds select {
109             margin-top: 3px;
110             }
111              
112             #OQinfo {
113             background-color: #cccccc;
114             }
115              
116             tr.OQdataRowTypeEven {
117             background-color: white;
118             }
119              
120             tr.OQdataRowTypeOdd {
121             background-color: #cccccc;
122             }
123              
124             td.OQdataRCol {
125             width: 1%;
126             }
127              
128             #OQcmds {
129             text-align: right;
130             }
131              
132             td.OQdataLCol { width: 1%; }
133             tr.OQupdatedRow { background-color: #ffdddd }
134              
135             td.OQcolHeader { white-space: nowrap }
136              
137             .OQaddColButton, .OQsortAscButton, .OQsortDescButton, .OQfilterCol, .OQcloseButton{
138             width: 15px; height: 16px; margin: 0; margin-right: 8px !important; padding: 0;
139             border: 0 !important; text-indent: -1000em;
140             }
141              
142             .OQaddColButton { background: transparent url(/OptimalQuery/add.gif) no-repeat center top; }
143             .OQsortAscButton { background: transparent url(/OptimalQuery/sortDown.gif) no-repeat center top; }
144             .OQsortDescButton { background: transparent url(/OptimalQuery/sortUp.gif) no-repeat center top; }
145             .OQfilterCol { background: transparent url(/OptimalQuery/filter.gif) no-repeat center top; }
146             .OQcloseButton { background: transparent url(/OptimalQuery/close.gif) no-repeat center top; }
147              
148             #cmdOptions {
149             margin-top: 10px;
150             position: absolute;
151             width: 20em;
152             height: 16em;
153             right: 20px;
154             background-color: #efefef;
155             border: 4px groove #666666;
156             padding-right: 8px;
157             padding-left: 8px;
158             padding-bottom: 8px;
159             font-size: .8em;
160             color: #444444;
161             overflow: auto;
162             display: none;
163             }
164              
165             #cmdOptions button.closeButton {
166             position: absolute;
167             right: 0;
168             color: black;
169             font-weight: bold;
170             padding: 0px;
171             margin: 0px;
172             background-color: white;
173             border: 1px outset black;
174             text-align: center;
175             vertical-align: middle;
176             cursor: pointer;
177             font-size: .8em;
178             }
179              
180             #cmdOptions h1 {
181             color: #222222;
182             margin: 0px;
183             font-size: 1.2em;
184             padding: 0;
185             }
186              
187             #cmdOptions span.note {
188             font-size: .7em;
189             }
190              
191             #OQdata { border-bottom: 1px solid #666666; }
192              
193             #OQkey button { margin-left: 10px; }
194              
195             TILEND
196             }
197              
198              
199              
200              
201              
202              
203              
204              
205              
206              
207              
208              
209              
210              
211              
212              
213 0     0 0   sub can_embed { 1 }
214              
215             sub getPager {
216 0     0 0   my $o = shift;
217              
218 0           my $doc = "
219            
220            
221            
222             ";
223             # print previous page button if user is not on first page
224 0 0         $doc .= "
225             ($o->get_current_page() - 1)."); OQrefresh();\">previous"
226             if $o->get_current_page() > 1;
227              
228 0           $doc .= "
229            
230            
231              
232             # print results per page picker
233 0           foreach my $p (@{ $$o{schema}{results_per_page_picker_nums} }) {
  0            
234 0 0 0       next if $p ne 'All' && $p > $o->get_count();
235 0           $doc .= "
236 0 0         $doc .= " selected='selected'" if $p eq $o->get_rows_page();
237 0           $doc .= ">View $p results";
238 0 0         $doc .= " per page" if $p !~ /all/i;
239 0           $doc .= "";
240             }
241 0           $doc .= "
242              
243             Page (";
244             # print current page picker
245 0 0         if ($o->get_num_pages() <= 1) {
246 0           $doc .= $o->get_num_pages();
247             } else {
248 0           $doc .= "
249              
250             # only show page markers for pages 1 - 10,
251             # 5 pages before current page, 5 pages after current page, and last 10 pages
252 0           my @page_markers_to_show = sort { $a <=> $b } (
253             (1 .. 10),
254 0           (($$o{page} - 5) .. ($$o{page} + 5)),
255             (($o->get_num_pages() - 10) .. $o->get_num_pages() ) );
256 0           my $lastP;
257 0           foreach my $p (@page_markers_to_show) {
258 0 0 0       next if $p < 1 || $p == $lastP || $p > $o->get_num_pages();
      0        
259 0           $doc .= "
260 0 0         $doc .= " selected='selected'" if $p == $$o{page};
261 0           $doc .= ">".$o->commify($p);
262 0           $doc .= "";
263 0           $lastP = $p;
264             }
265 0           $doc .= "\n";
266             }
267              
268 0           $doc .= " of ".$o->commify($o->get_num_pages).")\n";
269              
270             # print previous page button if user is not on last page
271             $doc .= "
272 0 0         ; OQrefresh();\">next" if $$o{page} < $o->get_num_pages();
273 0           $doc .= "
274            
275            
276             ";
277              
278 0           return $doc;
279             }
280              
281              
282             sub output {
283 0     0 0   my $o = shift;
284 0           my $current_pack = __PACKAGE__;
285 0           my %opts;
286 0 0         %opts = %{ $$o{schema}{options}{$current_pack} } if exists $$o{schema}{options}{$current_pack};
  0            
287              
288 0 0         if (! exists $opts{httpHeader}) {
289 0           $opts{httpHeader} = $$o{httpHeader}->('text/html');
290             }
291              
292 0           my $inlineCSS = "\n\n";
327 0 0         if (!($opts{htmlHeader} =~ s/(<\/head>)/$inlineCSS$1/i)) {
328 0           $opts{htmlHeader} .= $inlineCSS;
329             }
330              
331             $opts{htmlFooter} = "\n\n"
332 0 0         unless exists $opts{htmlFooter};
333              
334             # eval if code ref
335 0           foreach my $key (qw( OQdocTop OQdocBottom OQformTop OQformBottom )) {
336 0 0         $opts{$key} = $opts{$key}->() if ref($opts{$key}) eq 'CODE';
337             }
338              
339 0   0       $opts{OQdocTop} ||= '';
340 0   0       $opts{OQdocBottom} ||= '';
341 0   0       $opts{OQformTop} ||= '';
342 0   0       $opts{OQformBottom} ||= '';
343 0   0       $opts{editButtonLabel} ||= 'edit';
344 0   0       $opts{disable_sort} ||= 0;
345 0   0       $opts{disable_filter} ||= 0;
346 0   0       $opts{disable_select} ||= 0;
347 0   0       $opts{mutateRecord} ||= undef;
348 0   0       $opts{noEscapeCol} ||= [];
349 0   0       $opts{editLink} ||= undef;
350              
351             # carry hidden state params
352 0           my $state_params = '';
353 0 0         if (ref($$o{schema}{state_params}) eq 'ARRAY') {
354 0           foreach my $p (@{ $$o{schema}{state_params} }) {
  0            
355 0           $state_params .= ";$p=".$o->escape_uri($o->{q}->param($p));
356             }
357             }
358 0 0         $state_params .= ';' if $state_params;
359              
360              
361              
362             my $doc = $opts{httpHeader}.$opts{htmlHeader}."
363            
364            
$opts{OQdocTop}
365              
366            
367            
368            
369              
370            
507              
508             "; ";
509            
510             show
511 0           escape_html(join(',',@{$$o{show}}))."\" />
512            
513            
514             filter
515             escape_html($$o{filter})."\" />
516            
517            
518             hiddenFilter
519             escape_html($$o{hiddenFilter})."\" />
520            
521            
522             queryDescr
523             escape_html($$o{queryDescr})."\" />
524            
525            
526             sort
527             escape_html($$o{sort})."\" />
528            
529            
530             page
531             escape_html($$o{page})."\" />
532            
533            
534             module
535             escape_html($$o{module})."\" />
536            
537            
538             rows_page
539             escape_html($$o{rows_page})."\" />
540            
541            
542             updated_uid
543            
544            
545            
546             on_select
547 0           escape_html($$o{q}->param('on_select'))."\" />
548            
549              
550 0 0         if (ref($$o{schema}{state_params}) eq 'ARRAY') {
551 0           foreach my $p (@{ $$o{schema}{state_params} }) {
  0            
552 0           $doc .= "
$p
553             }
554             }
555              
556             $doc .= "
557            
558              
559            
560              
561            
".
562             (($$o{q}->param('updated_uid') eq '')?"":
563 0 0         "UID: ".$o->escape_html($$o{q}->param('updated_uid'))." updated")."
564            
565              
566              
567            
$opts{OQformTop}
568              
569            
570            
571             ".$o->escape_html($o->get_title)."
572             Result(s) (".$o->commify($o->get_lo_rec)." - ".$o->commify($o->get_hi_rec).") of ".$o->commify($o->get_count)."
573             ";
574              
575 0 0 0       if (ref($opts{buildNewLink}) eq 'CODE') {
    0          
    0          
576 0           my $link = $opts{buildNewLink}->($o, \%opts);
577 0 0         if ($link ne '') {
578 0           $doc .= "";
579             }
580             }
581             elsif (exists $opts{buildNewLink} && $opts{buildNewLink} eq '') {}
582             elsif ($opts{editLink} ne '') {
583 0 0         my $link = $opts{editLink}.(($opts{editLink} =~ /\?/)?'&':'?')."on_update=OQrefresh&act=new";
584 0 0         if ($link ne '') {
585 0           $doc .= "";
586             }
587             }
588              
589 0           $doc .= "";
590             $doc .= "
591             if (document.getElementById('savedSearchesOptions').style.display != 'none') this.form.OQsaveSearchTitle.focus();
592 0 0         \">saved searches" if $$o{schema}{savedSearchUserID};
593 0           $doc .= "
594            
595            
596            
597              
598            
599            
600              
601            
602            

select download file type

603             Printer Friendly
604            
605             CSV comma separated values (use in Microsoft Excel)
606            
607             XML ";
608              
609 0 0         if ($$o{rows_page} ne 'All') {
610 0           $doc .= "
export all results"
611             }
612 0           $doc .= "
613            
614            
615            
616              
617            
618             ";
619              
620            
621             # if saved searches are enabled ..
622 0 0         if ($$o{schema}{savedSearchUserID}) {
623 0           local $$o{dbh}->{LongReadLen};
624 0           $doc .= "
625            

save search

626             name

";
627              
628 0 0         if ($$o{dbh}{Driver}{Name} eq 'Oracle') {
629 0           my ($readLen) = $$o{dbh}->selectrow_array("SELECT max(dbms_lob.getlength(params)) FROM oq_saved_search WHERE user_id = ?", undef, $$o{schema}{savedSearchUserID});
630 0 0         $$o{dbh}->{LongReadLen} = $readLen if $readLen > $$o{dbh}->{LongReadLen};
631             }
632              
633 0           my $sth = $$o{dbh}->prepare("
634             SELECT id, user_title, params
635             FROM oq_saved_search
636             WHERE user_id = ?
637             AND upper(uri) = upper(?)
638             AND oq_title = ?");
639 0           $sth->execute($$o{schema}{savedSearchUserID}, $$o{schema}{URI},$$o{schema}{title});
640              
641 0           my $buffer = '';
642 0           while (my ($id, $title, $params) = $sth->fetchrow_array()) {
643              
644 0           my $stateArgs = '';
645 0 0         if ($params ne '') {
646 0           $params = eval '{'.$params.'}';
647 0 0         if (ref($params) eq 'HASH') {
648 0           delete $$params{show};
649 0           delete $$params{rows_page};
650 0           delete $$params{page};
651 0           delete $$params{hiddenFilter};
652 0           delete $$params{filter};
653 0           delete $$params{queryDescr};
654 0           delete $$params{sort};
655 0           while (my ($k,$v) = each %$params) {
656 0           $stateArgs .= "&$k=";
657 0 0         $stateArgs .= (ref($v) eq 'ARRAY') ?
658             CGI::escape($$v[0]) : CGI::escape($v);
659             }
660             }
661             }
662              
663 0           $buffer .= "".$o->escape_html($title)."
";
664             }
665 0 0         $doc .= "

load search

$buffer" if $buffer;
666             }
667              
668 0           $doc .= "
669            
670            
671             "; ";
672              
673 0 0 0       if (!( $opts{disable_select} && $opts{disable_sort} && $opts{disable_filter} )) {
      0        
674 0           $doc .= "
675            
Key:
676             ";
677              
678             $doc .= "add column"
679 0 0         unless $opts{disable_select};
680              
681             $doc .= "sort
682             reverse sort"
683 0 0         unless $opts{disable_sort};
684              
685             $doc .= "filter column"
686 0 0         unless $opts{disable_filter};
687              
688             $doc .= "close column"
689 0 0         unless $opts{disable_select};
690 0           $doc .= "
691             }
692             $doc .= "
693 0          
Query:".$o->escape_html($$o{queryDescr})."
694            
Filter:".$o->escape_html($o->get_filter());
695              
696 0 0         $doc .= "" unless $opts{disable_filter};
697              
698 0           $doc .=
699             "
700            
Sort:";
701              
702 0           my @sort = $o->sth->sort_descr();
703 0 0         if (@sort) {
704             # create new sort description
705 0           my @buffer;
706 0           for (my $i=0; $i < @sort; $i++) {
707 0           my $buf = '';
708 0 0         $buf .= "" unless $opts{disable_sort};
709 0           $buf .= $o->escape_html($sort[$i]);
710 0 0         $buf .= "" unless $opts{disable_sort};
711 0           push @buffer, $buf;
712             }
713 0           $doc .= join(', ',@buffer);
714             }
715              
716 0           $doc .= "
717            
718              
719             "; "; "; \n"; \n"; \n\n\n";
720            
721            
722              
723            
724            
725              
726              
727              
728              
729 0           foreach my $i (0 .. ($o->get_num_usersel_cols() - 1)) {
730 0           my $colAlias = $o->get_usersel_cols->[$i];
731 0           $doc .= "
732            
733             .
734             ";
735              
736 0 0 0       if (! ($$o{schema}{select}{$colAlias}[3]{disable_select} || $opts{disable_select})) {
737 0           $doc .= "";
738             }
739 0 0 0       if (! ($$o{schema}{select}{$colAlias}[3]{disable_sort} || $opts{disable_sort}) ) {
740 0           $doc .= "
741             ";
742             }
743 0 0 0       if (! ($$o{schema}{select}{$colAlias}[3]{disable_filter} || $opts{disable_filter}) ) {
744 0           $doc .= "";
745             }
746 0 0 0       if (! ($$o{schema}{select}{$colAlias}[3]{disable_select} || $opts{disable_select})) {
747 0           $doc .= "
";
748             }
749              
750 0 0 0       if ($$o{schema}{select}{$colAlias}[3]{disable_select} || $opts{'disable_select'}) {
751 0           $doc .= "
".$o->escape_html($$o{schema}{select}{$colAlias}[2])."
";
752             }
753              
754             else {
755 0           $doc .= "
756              
757             # create possible cols to select
758 0           my $s = $$o{schema}{select};
759              
760 0           foreach my $col (sort { uc($s->{$a}->[2]) cmp uc($s->{$b}->[2]) } keys %{$$o{schema}{select}}) {
  0            
  0            
761 0   0       my $col_opts = $s->{$col}->[3] || {};
762 0 0 0       next if $col_opts->{'is_hidden'} || ! $$s{$col}[2];
763 0           my $nice = $o->get_nice_name($col);
764              
765 0           $doc .= "
766 0 0         $doc .= " selected='selected'" if ($o->{'show'}->[$i] eq $col);
767 0           $doc .= ">".$o->escape_html($nice)."";
768             }
769 0           $doc .= "";
770             }
771              
772 0           $doc .= "
773             }
774              
775 0           $doc .= "
776            
777            
778            
779              
780            
781            
782              
783            
784              
785             # print data
786 0           my $rowType = 'Odd';
787              
788 0           my %noEsc = map { $_ => 1 } @{ $opts{noEscapeCol} };
  0            
  0            
789              
790 0           my $recs_in_buffer = 0;
791 0           while (my $r = $o->sth->fetchrow_hashref()) {
792 0 0         $opts{mutateRecord}->($r) if ref($opts{mutateRecord}) eq 'CODE';
793 0 0         $$o{schema}{mutateRecord}->($r) if ref($$o{schema}{mutateRecord}) eq 'CODE';
794              
795 0           my $class = "OQdataRowType$rowType";
796             $class .= " OQupdatedRow"
797 0 0 0       if $$r{U_ID} ne '' && $$r{U_ID} eq $$o{q}->param('updated_uid');
798              
799 0           $doc .= "
";
800 0 0 0       if (ref($opts{OQdataLCol}) eq 'CODE') { $doc .= $opts{OQdataLCol}->($r); }
  0 0          
    0          
801             elsif (ref($opts{buildEditLink}) eq 'CODE') {
802 0           my $link = $opts{buildEditLink}->($o, $r, \%opts);
803 0 0         if ($link ne '') {
804 0           $doc .= "";
805             }
806             } elsif ($opts{editLink} ne '' && $$r{U_ID} ne '') {
807 0 0         my $link = $opts{editLink}.(($opts{editLink} =~ /\?/)?'&':'?')."on_update=OQrefresh&act=load&id=$$r{U_ID}";
808 0           $doc .= "";
809             }
810 0           $doc .= "\n
811              
812             # print table cell with value
813 0           foreach my $col (@{ $o->get_usersel_cols }) {
  0            
814 0           my $val;
815 0 0         if (exists $noEsc{$col}) {
816 0           $val = $$r{$col};
817             } else {
818 0 0         if (ref($$r{$col}) eq 'ARRAY') {
819 0           $val = join(', ', map { $o->escape_html($_) } @{ $$r{$col} });
  0            
  0            
820             } else {
821 0           $val = $o->escape_html($$r{$col});
822             }
823             }
824 0           $doc .= "$val
825             }
826              
827             # still need to add code for on_select functionality
828 0           $doc .= "\n";
829              
830 0 0 0       if (ref($opts{OQdataRCol}) eq 'CODE') { $doc .= $opts{OQdataRCol}->($r); }
  0 0          
831             elsif ($o->{q}->param('on_select') ne '' && $$r{U_ID} ne '') {
832 0           my $on_select = $o->{q}->param('on_select');
833 0           $doc .= "";
834             }
835              
836 0           $doc .= "\n
837              
838 0 0         $rowType = ($rowType eq "Odd") ? "Even" : "Odd";
839              
840 0           $recs_in_buffer++;
841 0 0         if ($recs_in_buffer == 20) { $$o{output_handler}->($doc); $doc = ''; $recs_in_buffer = 0; }
  0            
  0            
  0            
842             }
843 0           $o->sth->finish();
844              
845 0           $doc .= "
846            
847            
";
848              
849 0           $doc .= $o->getPager();
850              
851             $doc .= "
852 0          
".$opts{OQformBottom}."
853            
854              
855            
859              
860            
861            
862             $opts{htmlFooter}";
863              
864 0           $$o{output_handler}->($doc);
865 0           return undef;
866             }
867              
868             1;