CGI-Application-Plugin-Output-XSV

 view release on metacpan or  search on metacpan

XSV.pm  view on Meta::CPAN

    # 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 )