File Coverage

blib/lib/Data/Report/Plugin/Csv.pm
Criterion Covered Total %
statement 71 78 91.0
branch 20 30 66.6
condition 6 9 66.6
subroutine 14 15 93.3
pod 0 5 0.0
total 111 137 81.0


line stmt bran cond sub pod time code
1             # Data::Report::Plugin::Csv.pm -- CSV plugin for Data::Report
2             # RCS Info : $Id: Csv.pm,v 1.9 2008/08/18 09:51:23 jv Exp $
3             # Author : Johan Vromans
4             # Created On : Thu Jan 5 18:47:37 2006
5             # Last Modified By: Johan Vromans
6             # Last Modified On: Mon Aug 18 11:45:48 2008
7             # Update Count : 119
8             # Status : Unknown, Use with caution!
9              
10             package Data::Report::Plugin::Csv;
11              
12 7     7   987 use strict;
  7         15  
  7         262  
13 7     7   39 use warnings;
  7         10  
  7         282  
14 7     7   68 use base qw(Data::Report::Base);
  7         12  
  7         4264  
15              
16             ################ API ################
17              
18             my $csv_implementation = 0;
19              
20             sub start {
21 7     7 0 82 my ($self, @args) = @_;
22 7         59 $self->SUPER::start(@args);
23 7 50       19 $self->set_separator(",") unless $self->get_separator;
24 7 100       29 $self->_select_csv_method unless $csv_implementation;
25 7         27 return;
26             }
27              
28             sub finish {
29 7     7 0 44 my ($self) = @_;
30 7         68 $self->SUPER::finish();
31             }
32              
33             sub add {
34 18     18 0 186 my ($self, $data) = @_;
35              
36 18         44 my $style = delete($data->{_style});
37              
38 18         45 my $sep = $self->get_separator;
39              
40 18         96 $self->SUPER::add($data);
41              
42 18 50       46 return unless %$data;
43              
44 18 100 66     67 if ( $style and my $t = $self->_getstyle($style) ) {
45 4 50       65 return if $t->{ignore};
46             }
47              
48 14         64 $self->_checkhdr;
49              
50 14         26 my $line;
51              
52 53 50       314 $line = $self->_csv
53             ( map {
54 56         179 $data->{$_->{name}} || ""
55             }
56             grep {
57 14         36 my $t = $self->_getstyle($style, $_->{name});
58 56         162 ! $t->{ignore};
59             }
60 14         21 @{$self->_get_fields}
61             );
62 14         107 $self->_print($line, "\n");
63             }
64              
65 2     2 0 12 sub set_separator { $_[0]->{sep} = $_[1] }
66 47 100   47 0 292 sub get_separator { $_[0]->{sep} || "," }
67              
68             ################ Pseudo-Internal (used by Base class) ################
69              
70             sub _std_heading {
71 6     6   14 my ($self) = @_;
72 6         36 my $sep = $self->get_separator;
73              
74              
75 23         60 $self->_print($self->_csv
76             (map {
77 24         113 $_->{title}
78             }
79             grep {
80 6         41 my $t = $self->_getstyle("_head", $_->{name});
81 24         78 ! $t->{ignore};
82             }
83 6         18 @{$self->_get_fields}),
84             "\n");
85             }
86              
87             ################ Internal (used if no alternatives) ################
88              
89             sub _csv_internal {
90 36         48 join(shift->get_separator,
91             map {
92             # Quotes must be doubled.
93 10     10   21 s/"/""/g;
94             # Always quote (compatible with Text::CSV)
95 36         49 $_ = '"' . $_ . '"';
96 36         72 $_;
97             } @_);
98             }
99              
100             sub _set_csv_method {
101 8     8   27 my ($self, $class) = @_;
102 7     7   54 no warnings qw(redefine);
  7         11  
  7         2875  
103              
104 8 50 66     163 if ( $class && $class->isa("Text::CSV_XS") ) {
    100 66        
105              
106             # Use always_quote to be compatible with Text::CSV.
107             # Use binary to deal with non-ASCII text.
108 0         0 $csv_implementation = Text::CSV_XS->new
109             ({ sep_char => $self->get_separator,
110             always_quote => 1,
111             binary => 1,
112             });
113              
114             # Assign the method.
115             *_csv = sub {
116 0     0   0 shift;
117 0         0 $csv_implementation->combine(@_);
118 0         0 $csv_implementation->string;
119 0         0 };
120 0 0       0 warn("# CSV plugin uses Text::CSV_XS $Text::CSV_XS::VERSION\n")
121             if $ENV{AUTOMATED_TESTING};
122             }
123             elsif ( $class && $class->isa("Text::CSV") ) {
124              
125             # With modern Text::CSV, it will use Text::CSV_XS if possible.
126             # So this gotta be Text::CSV_PP...
127              
128 5         40 $csv_implementation = Text::CSV->new
129             ({ always_quote => 1,
130             binary => 1,
131             });
132              
133             # Assign the method.
134             *_csv = sub {
135 10     10   16 shift;
136 10         93 $csv_implementation->combine(@_);
137 10         1352 $csv_implementation->string;
138 5         575 };
139 5 50       2303 warn("# CSV plugin uses Text::CSV $Text::CSV::VERSION, PP version $Text::CSV_PP::VERSION\n")
140             if $ENV{AUTOMATED_TESTING};
141             }
142             else {
143             # Use our internal method.
144 3         24 *_csv = \&_csv_internal;
145 3         8 $csv_implementation = "Data::Report::Plugin::Csv::_csv_internal";
146 3 50       433 warn("# CSV plugin uses built-in CSV packer\n")
147             if $ENV{AUTOMATED_TESTING};
148             }
149              
150 8         38 return $csv_implementation;
151             }
152              
153             sub _select_csv_method {
154 6     6   10 my $self = shift;
155              
156 6         9 $csv_implementation = 0;
157 6         22 eval {
158 6         2755 require Text::CSV_XS;
159 0         0 $self->_set_csv_method(Text::CSV_XS::);
160             };
161 6 50       38 return $csv_implementation if $csv_implementation;
162              
163 6 100       26 if ( $self->get_separator eq "," ) {
164 4         7 eval {
165 4         3835 require Text::CSV;
166 4         48703 $self->_set_csv_method(Text::CSV::);
167             };
168             }
169 6 100       77 return $csv_implementation if $csv_implementation;
170              
171             # Use our internal method.
172 2         7 $self->_set_csv_method();
173              
174 2         3 return $csv_implementation;
175             }
176              
177             1;