package HTML::SearchPage; our $VERSION = '0.05'; # $Id: SearchPage.pm,v 1.24 2007/09/19 21:30:18 canaran Exp $ use warnings; use strict; use HTML::SearchPage::Files; use Carp; use CGI; use CGI::Session; use DBI; use List::Util qw(first); use LWP::Simple; use Spreadsheet::WriteExcel; use Tie::IxHash; use Time::Format qw(%time); ############### # CONSTRUCTOR # ############### sub new { my ($class, %raw_params) = @_; # Remove dashes from param names my %params = map { my $key = $_; my $value = $raw_params{$key}; $key =~ s/^-//; $key => $value; } keys %raw_params; my $self = bless {}, $class; eval { # CGI obj created initially my $cgi = CGI->new; $self->cgi($cgi); my $cgi_params = $self->cgi->Vars; $self->cgi_params($cgi_params); # Temp dir $params{temp_dir} or croak("A temp_dir param is required!"); $self->temp_dir($params{temp_dir}); $params{temp_dir_eq} or croak("A temp_dir_eq param is required!"); $self->temp_dir_eq($params{temp_dir_eq}); # Cookie params my $cookie = defined $params{cookie} ? $params{cookie} : 'html-searchpage'; $self->cookie($cookie); my $cookie_expires_in_min = defined $params{cookie_expires_in_min} ? $params{cookie_expires_in_min} : 30; $self->cookie_expires_in_min($cookie_expires_in_min); # Session id from URL/cookie my $session_id = $self->cgi_params->{session_id} || $self->cgi->cookie($self->cookie) || undef; my $session_dir = $self->temp_dir . '/sessions'; my $session = CGI::Session->new('file', $session_id, {Directory => $session_dir}); # Session id may change at this step $self->session_id($session->id); $self->session($session); # Required params $params{db_access_params} or croak("A db_access_params is required!"); $self->db_access_params($params{db_access_params}); $params{temp_dir} or croak("A temp_dir param is required!"); $self->temp_dir($params{temp_dir}); $params{temp_dir_eq} or croak("A temp_dir_eq param is required!"); $self->temp_dir_eq($params{temp_dir_eq}); $params{base_sql_table} or croak("A base_sql_table is required!"); $self->base_sql_table($params{base_sql_table}); $params{base_sql_fields} or croak("A base_sql_fields is required!"); $self->base_sql_fields($params{base_sql_fields}); $params{base_output_headers} or croak("A base_output_headers is required!"); $self->base_output_headers($params{base_output_headers}); # Create image files HTML::SearchPage::Files->new(temp_dir => $self->temp_dir); # Required param for only display_info $self->base_identifier($params{base_identifier}); # Optional params my $page_title = defined $params{page_title} ? $params{page_title} : 'Search Page'; $self->page_title($page_title); $self->header($params{header}); $self->footer($params{footer}); $self->css($params{css}); $self->instructions($params{instructions}); $self->distinct($params{distinct}); $self->no_reset($params{no_reset}); $self->new_search($params{new_search}); $self->group_by($params{group_by}); $self->sort_fields($params{sort_fields}); $self->sort_defaults($params{sort_defaults}); my $method = defined $params{method} ? $params{method} : 'GET'; $self->method($method); unless ($method eq 'GET' or $method eq 'POST') { croak("Invalid method ($method)!"); } my $action = defined $params{action} ? $params{action} : $ENV{SCRIPT_NAME}; $self->action($action); my $page_size = defined $params{page_size} ? $params{page_size} : 50; $self->page_size($page_size); $self->show_search_url($params{show_search_url}); $self->debug_level($params{debug_level}); my $go_to_results = defined $params{go_to_results} ? $params{go_to_results} : 1; $self->go_to_results($go_to_results); $self->modifier($params{modifier}); $self->external_where_clauses($params{external_where_clauses}); # If reset, empty cgi_params if ($self->cgi_params->{reset}) { $self->cgi_params({}); } # If new search, redirect if ($self->cgi_params->{new_search}) { my $url = "http://" . $ENV{HTTP_HOST} . $self->new_search; print $self->cgi->redirect($url); exit 0; } # Calculate super headers $self->_calculate_super_headers(); # Validate cgi params $self->_validate_cgi_params(); # Create db_handle from db_access_params my $db_access_params = $self->db_access_params; # -- Re-format if a single db is entered if ( ref($db_access_params) and ref($db_access_params) eq 'ARRAY') { my ($datasource, $username, $password) = @$db_access_params; my $db_access_params = { database => [ { alias => 'default', display => 'Default Database', datasource => $datasource, username => $username, password => $password, } ] }; } $self->db_access_params($db_access_params); # -- Extract params my $database = $self->cgi_params->{database} || $self->session->param('db_selected'); my @available_databases = ( ref $db_access_params->{database} && ref $db_access_params->{database} eq 'ARRAY') ? @{$db_access_params->{database}} : ($db_access_params->{database}); unless (@available_databases) { croak("No database specified!"); } if (!$database) { $database = $available_databases[0]->{alias}; } my $selected_db = first { $_->{alias} eq $database } @available_databases; if (!defined($selected_db)) { croak("Cannot determine database ($database)!"); } my $dbh = DBI->connect( $selected_db->{datasource}, $selected_db->{username}, $selected_db->{password}, {PrintError => 1, RaiseError => 1} ) || croak("Cannot connect to database!"); $self->dbh($dbh); $self->db_selected($database); $self->db_display($selected_db->{display}); $self->session->param('db_selected', $database); # Adjust URL if "go_to_results" if ($self->go_to_results) { my $action = $self->action; $self->action("$action#results"); } # Create an empty param_fields container $self->{param_fields} = {}; # Create an empty modifications container $self->{modifications} = []; }; $self->display_error_page($@) if $@; return $self; } ################## # PUBLIC METHODS # ################## # Function : Adds/retrieves param_field. # Arguments : $id [$ParamField_object] # Returns : $ParamField_object # Notes : None specified. sub param_field { my ($self, $id, $value) = @_; if (defined $value) { croak( "A HTML::SearchPage::Param object is needed to add param_field!") unless ref $value eq 'HTML::SearchPage::Param'; my $max = 0; foreach (keys %{$self->param_fields}) { my $pf = $self->param_fields->{$_}; $max = $pf->rank if $pf->rank > $max; } $value->rank(++$max); $self->param_fields->{$id} = $value; } croak("This param_field ($id) does not exist!") unless exists $self->param_fields->{$id}; return $self->param_fields->{$id}; } # Function : Adds modification. # Arguments : $hashref # Returns : 1 # Notes : None specified. sub add_modification { my ($self, %value) = @_; croak("A modification hashref is needed!") unless %value; push @{$self->modifications}, \%value; return 1; } # Function : Performs the necessary operations and # displays a complete search page. # Arguments : None # Returns : 1 # Notes : None specified. sub display_page { my ($self) = @_; my $submit = $self->cgi_params->{'submit'}; eval { $self->_generate_search_form unless $self->search_form; $self->_generate_sql_statements if ($submit and !$self->query_sql_statement); $self->_get_debug_info if $self->debug_level; $self->_retrieve_data if ($submit and !$self->data); $self->_retrieve_count if ($submit and !(defined $self->count)); $self->_format_data if ($submit and !$self->formatted_data); }; $self->display_error_page($@) if $@; eval { $self->_print_page; }; $self->display_error_page($@) if $@; return 1; } # Function : Generates an error page. # Arguments : $error # Returns : - exists with 0 - # Notes : None specified. sub display_error_page { my ($self, $error) = @_; my $cookie = $self->cookie; my $session_id = $self->session_id; my $cookie_expires_in_min = $self->cookie_expires_in_min; my $cookie_obj = CGI::cookie( -name => $cookie, -value => $session_id, -expires => "+${cookie_expires_in_min}m", ); print $self->cgi->header(-cookie => $cookie_obj); my $header = $self->_content($self->header); my $css = $self->_content($self->css); my $page_title = $self->page_title ? 'Error: ' . $self->page_title : 'Error Page'; my $instructions = $self->_content($self->instructions); my $debug_info = $self->debug_info; my $footer = $self->_content($self->footer); my $temp_dir_eq = $self->temp_dir_eq; print <
| $header | |
$page_title | |
| An error occured: $error | |
| $debug_info | |
| $footer | |