File Coverage

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


line stmt bran cond sub pod time code
1             package CGI::OptimalQuery::InteractiveQuery;
2              
3 1     1   797 use strict;
  1         2  
  1         22  
4 1     1   4 use warnings;
  1         2  
  1         20  
5 1     1   4 no warnings qw( uninitialized );
  1         1  
  1         22  
6 1     1   3 use base 'CGI::OptimalQuery::Base';
  1         2  
  1         2890  
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         $opts{httpHeader} = $$o{q}->header('text/html') if ! exists $opts{httpHeader};
289              
290              
291 0           my $inlineCSS = "\n\n";
326 0 0         if (!($opts{htmlHeader} =~ s/(<\/head>)/$inlineCSS$1/i)) {
327 0           $opts{htmlHeader} .= $inlineCSS;
328             }
329              
330             $opts{htmlFooter} = "\n\n"
331 0 0         unless exists $opts{htmlFooter};
332              
333             # eval if code ref
334 0           foreach my $key (qw( OQdocTop OQdocBottom OQformTop OQformBottom )) {
335 0 0         $opts{$key} = $opts{$key}->() if ref($opts{$key}) eq 'CODE';
336             }
337              
338 0   0       $opts{OQdocTop} ||= '';
339 0   0       $opts{OQdocBottom} ||= '';
340 0   0       $opts{OQformTop} ||= '';
341 0   0       $opts{OQformBottom} ||= '';
342 0   0       $opts{editButtonLabel} ||= 'edit';
343 0   0       $opts{disable_sort} ||= 0;
344 0   0       $opts{disable_filter} ||= 0;
345 0   0       $opts{disable_select} ||= 0;
346 0   0       $opts{mutateRecord} ||= undef;
347 0   0       $opts{noEscapeCol} ||= [];
348 0   0       $opts{editLink} ||= undef;
349              
350             # carry hidden state params
351 0           my $state_params = '';
352 0 0         if (ref($$o{schema}{state_params}) eq 'ARRAY') {
353 0           foreach my $p (@{ $$o{schema}{state_params} }) {
  0            
354 0           $state_params .= ";$p=".$o->escape_uri($o->{q}->param($p));
355             }
356             }
357 0 0         $state_params .= ';' if $state_params;
358              
359              
360              
361             my $doc = $opts{httpHeader}.$opts{htmlHeader}."
362            
363            
$opts{OQdocTop}
364              
365            
366            
367            
368              
369            
506              
507             "; ";
508            
509             show
510 0           escape_html(join(',',@{$$o{show}}))."\" />
511            
512            
513             filter
514             escape_html($$o{filter})."\" />
515            
516            
517             hiddenFilter
518             escape_html($$o{hiddenFilter})."\" />
519            
520            
521             queryDescr
522             escape_html($$o{queryDescr})."\" />
523            
524            
525             sort
526             escape_html($$o{sort})."\" />
527            
528            
529             page
530             escape_html($$o{page})."\" />
531            
532            
533             module
534             escape_html($$o{module})."\" />
535            
536            
537             rows_page
538             escape_html($$o{rows_page})."\" />
539            
540            
541             updated_uid
542            
543            
544            
545             on_select
546 0           escape_html($$o{q}->param('on_select'))."\" />
547            
548              
549 0 0         if (ref($$o{schema}{state_params}) eq 'ARRAY') {
550 0           foreach my $p (@{ $$o{schema}{state_params} }) {
  0            
551 0           $doc .= "
$p
552             }
553             }
554              
555             $doc .= "
556            
557              
558            
559              
560            
".
561             (($$o{q}->param('updated_uid') eq '')?"":
562 0 0         "UID: ".$o->escape_html($$o{q}->param('updated_uid'))." updated")."
563            
564              
565              
566            
$opts{OQformTop}
567              
568            
569            
570             ".$o->escape_html($o->get_title)."
571             Result(s) (".$o->commify($o->get_lo_rec)." - ".$o->commify($o->get_hi_rec).") of ".$o->commify($o->get_count)."
572             ";
573              
574 0 0 0       if (ref($opts{buildNewLink}) eq 'CODE') {
    0          
    0          
575 0           my $link = $opts{buildNewLink}->($o, \%opts);
576 0 0         if ($link ne '') {
577 0           $doc .= "";
578             }
579             }
580             elsif (exists $opts{buildNewLink} && $opts{buildNewLink} eq '') {}
581             elsif ($opts{editLink} ne '') {
582 0 0         my $link = $opts{editLink}.(($opts{editLink} =~ /\?/)?'&':'?')."on_update=OQrefresh&act=new";
583 0 0         if ($link ne '') {
584 0           $doc .= "";
585             }
586             }
587              
588 0           $doc .= "";
589             $doc .= "
590             if (document.getElementById('savedSearchesOptions').style.display != 'none') this.form.OQsaveSearchTitle.focus();
591 0 0         \">saved searches" if $$o{schema}{savedSearchUserID};
592 0           $doc .= "
593            
594            
595            
596              
597            
598            
599              
600            
601            

select download file type

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

save search

625             name

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

load search

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