File Coverage

blib/lib/Data/Report/Plugin/Csv.pm
Criterion Covered Total %
statement 65 78 83.3
branch 16 30 53.3
condition 5 9 55.5
subroutine 14 15 93.3
pod 0 5 0.0
total 100 137 72.9


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