File Coverage

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


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

select download file type

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

save search

624             name

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

load search

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