#
# $Id: Output.pm,v 1.4 2005/07/14 20:26:15 scottb Exp $
#
package DBIx::Knowledge::Output;
use strict;
use DBIx::Knowledge;
use HTML::Entities;
use DBI;
=head1 NAME
DBIx::Knowledge::Output - Output generator (HTML currently)
=cut
sub new
{
my ($caller,$header_repeat) = @_;
my $class = ref($caller) || $caller;
my $obj = {};
$obj->{header_repeat} = $header_repeat;
return bless($obj,$class);
}
sub generate_html
{
my ($self,$report_sth,$select_fields,$want_subtotal_fields) = @_;
$want_subtotal_fields ||= {};
my $html = <
HTML
$html .= header_row_html($select_fields);
my $last_was_group = 1;
my @recent_row = ();
my $grouping_id = 0;
my $want_sub = scalar(%$want_subtotal_fields);
my @sum_row = ();
while (my @row = $report_sth->fetchrow_array)
{
# The class will always add a psuedo-column to the result set at the end which is the GROUPING_ID() but only if subtotal fields were requested
$grouping_id = pop(@row) if $want_sub;
if ($want_sub && $grouping_id != 0)
{
my $field_text;
my $field_position;
my $html_class;
my $grouping_advice = $want_subtotal_fields->{$grouping_id};
if ($grouping_advice->{FIELD_ID} eq $DBIx::Knowledge::REPORT_TOTAL_KEY)
{
$field_text = 'Report Summary';
$field_position = 0;
$html_class = 'report_summary';
@sum_row = @row;
$sum_row[0] = 'Report Summary';
next;
}
else
{
$field_text = "Summary for " . $recent_row[$grouping_advice->{POSITION}];
$field_text .= aux_info_text(\@row,$select_fields);
$field_position = $grouping_advice->{POSITION};
$html_class = "data_subtotal$grouping_advice->{SUBTOTAL_RANK}";
}
$row[$field_position] = $field_text;
$html .= data_row_html(\@row,$select_fields,$html_class,\@recent_row);
$html .= header_row_html($select_fields) if $self->{header_repeat};
$last_was_group = 1;
}
else
{
if ($last_was_group)
{
@recent_row = @row;
}
my $recent = undef;
$recent = $last_was_group ? [] : \@recent_row if $want_sub;
##at watch oblique dependency for html_class arg (should be undef)
$html .= data_row_html(\@row,$select_fields,undef,$recent);
$last_was_group = 0;
}
@recent_row = @row;
}
if (@sum_row)
{
$html .= data_row_html(\@sum_row,$select_fields,'report_summary');
}
return undef if $report_sth->err;
$html .= qq[\n];
return \$html;
}
sub header_row_html
{
my $header_fields = shift;
my $html = "
\n";
foreach my $header_field (@$header_fields)
{
# Don't output and aux_info fields. These fields are only to
# be added to a summary row.
unless ($header_field->{aux_info}) {
$html .= "| " . encode_entities($header_field->{header}) . " | ";
}
}
$html .= "
\n";
return $html;
}
sub data_row_html
{
my ($row,$select_fields,$html_class,$recent_row) = @_;
my $class = '';
$class = qq[ class="$html_class" ] if defined($html_class);
my $html = "";
my $i = 0;
# If this row only contains aux_info data suppress it - but only
# if this is not a summary row. We can tell if this is a summary
# row because $html_class is currently only defined for summary rows.
if (is_aux_info_row($row,$select_fields) && !defined $html_class)
{
return '';
}
foreach my $val_orig (@$row)
{
# Do not output an aux info fields
if ($select_fields->[$i]{aux_info}) {
$i++;
next;
}
my $val = $val_orig; # Copy, don't modify ref
if (ref($recent_row))
{
my $prev_val = $recent_row->[$i];
$val = '' if $prev_val eq $val && $select_fields->[$i]{no_repeat} && ($i == 0 || $i == 1);
}
if (length($val))
{
$val = encode_entities($val);
# After escaping turn any newlines into HTML
tags
$val =~ s|\n|
|gs;
}
else
{
$val = ' ';
}
my $classes = $select_fields->[$i]{html_class} || [];
if (($html_class =~ /^data_subtotal/ || $html_class eq 'report_summary') && ($val =~ /^Summary for / || $val eq 'Report Summary'))
{
push(@$classes,'subtotal_label');
}
my $td_class = '';
$td_class = qq[class="] . join(' ',@$classes) . qq["] if ref($classes);
$html .= qq[[$i]{td_attr}) ? join(' ',@{$select_fields->[$i]{td_attr}}) : '') . qq[>$val | ];
$i++;
}
$html .= "
\n";
return $html;
}
# Extract the aux info summary information and return a string that
# can be added to the report summary row. Search the query select
# fields looking for an aux_info marker. If found output the select
# header and corresponding value from the db result row. Arguments are
# a reference to an array of row values returned from the db and a
# reference to an array of the query select fields.
sub aux_info_text
{
my ($select_data, $select_fields) = @_;
my $aux_info_string = '';
for (my $i=0; $i < scalar(@$select_fields); $i++) {
my $select_field = $select_fields->[$i];
if ($select_field->{aux_info}) {
$aux_info_string .= sprintf("\n %s %s",
$select_field->{header},
$select_data->[$i]);
}
}
return $aux_info_string;
}
# Check a database row to see if it contains the data for an aux_info
# column. Normally these rows should not be displayed in the report
# body but the value in the aux_info column is appended to the summary
# text in the summary row. The test is not rigorous. First find if
# any aux_info_fields are defined, if so collect them. Then check
# each element of the db_row array corresponding to an an aux_info
# column and see if the element in that position is not numerically 0.
# If the value is non-zero, consider this db_row an aux_info row and
# return true. Arguments are an array ref to a database row and an
# array ref containing the query select fields.
sub is_aux_info_row
{
my ($db_row, $select_fields) = @_;
##at this is a constant - should be populated once, not every time in this loop
my @aux_info_fields = ();
my $col;
for ($col=0; $col[$col]{aux_info};
}
foreach $col (@aux_info_fields)
{
if ($db_row->[$col] != 0)
{
return 1;
}
}
return 0;
}
1;
__END__
=head1 SEE ALSO
L, SmartCruddy! L
=head1 AUTHOR
Reed Sandberg, Ereed_sandberg Ӓ yahooE
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2004-2008 Reed Sandberg
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
The full text of the license can be found in the
LICENSE file included with this module.