+<%init>
+
+my(%opt) = @_;
+#warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my %align = (
+ 'l' => 'left',
+ 'r' => 'right',
+ 'c' => 'center',
+ ' ' => '',
+ '.' => '',
+);
+$opt{align} = [ map $align{$_}, split(//, $opt{align}) ],
+ unless !$opt{align} || ref($opt{align});
+
+if ( $opt{'agent_virt'} ) {
+
+ my $agentnums_sql = $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ );
+
+ $opt{'query'}{'extra_sql'} .=
+ ( $opt{'query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ $agentnums_sql;
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ $agentnums_sql;
+
+ if ( $opt{'agent_pos'} || $opt{'agent_pos'} eq '0'
+ and scalar($curuser->agentnums) > 1 ) {
+ #false laziness w/statuspos above
+ my $pos = $opt{'agent_pos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Agent';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, '';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { $_[0]->agentnum ? $_[0]->agent->agent : '(global)'; };
+ splice @{ $opt{'color'} }, $pos, 0, '';
+ splice @{ $opt{'links'} }, $pos, 0, '' #[ 'agent link?', 'agentnum' ]
+ if $opt{'links'};
+ splice @{ $opt{'link_onclicks'} }, $pos, 0, ''
+ if $opt{'link_onclicks'};
+
+ }
+
+}
+
+if ( $opt{'disableable'} ) {
+
+ unless ( $cgi->param('showdisabled') ) { #modify searches
+
+ $opt{'query'}{'hashref'}{'disabled'} = '';
+ $opt{'query'}{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+
+ } elsif ( $opt{'disabled_statuspos'}
+ || $opt{'disabled_statuspos'} eq '0' ) { #add status column
+
+ my $pos = $opt{'disabled_statuspos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Status';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, 'b';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { shift->disabled ? 'DISABLED' : 'Active'; };
+ splice @{ $opt{'color'} }, $pos, 0,
+ sub { shift->disabled ? 'FF0000' : '00CC00'; };
+ splice @{ $opt{'links'} }, $pos, 0, ''
+ if $opt{'links'};
+ splice @{ $opt{'link_onlicks'} }, $pos, 0, ''
+ if $opt{'link_onlicks'};
+ }
+
+ #add show/hide disabled links
+ my $items = $opt{'name'} || PL($opt{'name_singular'});
+ if ( $cgi->param('showdisabled') ) {
+ $cgi->param('showdisabled', 0);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">hide disabled $items</a> )!;
+ $cgi->param('showdisabled', 1);
+ } else {
+ $cgi->param('showdisabled', 1);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">show disabled $items</a> )!;
+ $cgi->param('showdisabled', 0);
+ }
+
+}
+
+my $type = $cgi->param('_type') =~ /^(csv|\w*\.xls|select|html(-print)?)$/
+ ? $1 : 'html';
+
+my $limit = '';
+my($confmax, $maxrecords, $total, $offset, $count_arrayref);
+
+unless ( $type =~ /^(csv|\w*\.xls)$/ ) {
+
+ unless (exists($opt{count_query}) && length($opt{count_query})) {
+ ( $opt{count_query} = $opt{query} ) =~
+ s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i; #silly vim:/
+ }
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ $opt{count_query} .=
+ ( ( $opt{count_query} =~ /WHERE/i ) ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+ }
+
+ unless ( $type eq 'html-print' ) {
+
+ #setup some pagination things if we're in html mode
+
+ my $conf = new FS::Conf;
+ $confmax = $conf->config('maxsearchrecordsperpage');
+ if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
+ $maxrecords = $1;
+ } else {
+ $maxrecords ||= $confmax;
+ }
+
+ $limit = $maxrecords ? "LIMIT $maxrecords" : '';
+
+ $offset = $cgi->param('offset') =~ /^(\d+)$/ ? $1 : 0;
+ $limit .= " OFFSET $offset" if $offset;
+
+ }
+
+ my $count_sth = dbh->prepare($opt{'count_query'})
+ or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
+ $count_sth->execute
+ or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
+ $count_arrayref = $count_sth->fetchrow_arrayref;
+ $total = $count_arrayref->[0];
+
+}
+
+# run the query
+
+my $header = [ map { ref($_) ? $_->{'label'} : $_ } @{$opt{header}} ];
+my $rows;
+if ( ref($opt{query}) ) {
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ #%search = ( 'disabled' => '' );
+ $opt{'query'}->{'hashref'}->{'disabled'} = '';
+ $opt{'query'}->{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+ }
+
+ #eval "use FS::$opt{'query'};";
+ $rows = [ qsearch({
+ 'select' => $opt{'query'}->{'select'},
+ 'table' => $opt{'query'}->{'table'},
+ 'addl_from' => (exists($opt{'query'}->{'addl_from'}) ? $opt{'query'}->{'addl_from'} : ''),
+ 'hashref' => $opt{'query'}->{'hashref'} || {},
+ 'extra_sql' => $opt{'query'}->{'extra_sql'},
+ 'order_by' => $opt{'query'}->{'order_by'}. " $limit",
+ }) ];
+} else {
+ my $sth = dbh->prepare("$opt{'query'} $limit")
+ or die "Error preparing $opt{'query'}: ". dbh->errstr;
+ $sth->execute
+ or die "Error executing $opt{'query'}: ". $sth->errstr;
+
+ #can get # of rows without fetching them all?
+ $rows = $sth->fetchall_arrayref;
+
+ $header ||= $sth->{NAME};
+}