CGI-Application-Plugin-Output-XSV
view release on metacpan or search on metacpan
# simple defaults for slices
my $list_type = ref( $opts{values}[0] );
if ( $list_type eq 'HASH' ) {
$row_filter = sub { my ($row, $fields)= @_; return [ @$row{@$fields} ] };
}
elsif ( $list_type eq 'ARRAY' ) {
$row_filter = sub { my ($row, $fields)= @_; return [ @$row[@$fields] ] };
}
else {
croak "unknown list type [$list_type]";
}
}
else {
# using iterator, no filter
$row_filter = sub { $_[0] };
}
my $csv = Text::CSV_XS->new( $opts{csv_opts} );
my $output = '';
if ( $opts{include_headers} ) {
if ( ! $opts{headers} ) {
if ( ! ($opts{headers_cb} && ref( $opts{headers_cb} ) eq 'CODE') ) {
croak "need headers or headers_cb to include headers";
}
elsif ( ! @{$fields} ) {
carp "passing empty fields list to headers_cb";
}
}
# formatted column headers
my $readable_headers = $opts{headers} || $opts{headers_cb}->( $fields )
or croak "can't generate headers";
croak "return value from headers_cb is not an array reference, aborting"
if ref ( $readable_headers ) ne 'ARRAY';
$output .= add_to_xsv( $csv, $readable_headers, $opts{line_ending} );
if ( $opts{stream} ) {
print $output;
$output = '';
}
}
if ( $opts{values} ) {
foreach my $list_ref ( @{ $opts{values} } ) {
$output .= add_to_xsv(
$csv, $row_filter->($list_ref, $fields), $opts{line_ending}
);
if ( $opts{stream} ) {
print $output;
$output = '';
}
}
}
# using iterator
else {
my $iterations = 0;
while ( my $list_ref = $opts{iterator}->($fields) ) {
croak "return value from iterator is not an array reference, aborting"
if ref( $list_ref ) ne 'ARRAY';
# XXX infinite loop?
croak "iterator exceeded maximum iterations ($opts{maximum_iters})"
if ++$iterations > $opts{maximum_iters};
$output .= add_to_xsv(
$csv, $row_filter->($list_ref, $fields), $opts{line_ending}
);
if ( $opts{stream} ) {
print $output;
$output = '';
}
}
}
return $output;
}
# send xsv output directly to browser for download
# same params as xsv_report, plus
# filename => 'download.csv',
sub xsv_report_web {
my ($self, $args) = @_;
$args ||= {};
croak "argument to xsv_report_web must be a hash reference"
if ref( $args ) ne 'HASH';
my %defaults = (
filename => 'download.csv',
);
my %opts = ( %defaults, %$args );
my %headers = (
-type => 'application/x-csv',
'-content-disposition' => "attachment; filename=$opts{filename}",
);
# we're doing our own output
if ( $opts{stream} ) {
$self->header_type('none');
print $self->query->header( %headers );
}
else {
$self->header_props( %headers );
}
# consider use of magic goto in case of croak() inside xsv_report
return xsv_report( \%opts );
}
# default field name generator:
# underscores to spaces, upper case first letter of each word
sub clean_field_names {
my $fields = shift;
# using temp var to avoid modifying $fields
my @fields_copy = @{$fields};
return [
map { tr/_/ /; s/\b(\w+)/\u$1/g; $_ } @fields_copy
];
( run in 1.701 second using v1.01-cache-2.11-cpan-96521ef73a4 )