File Coverage

lib/Google/Chart.pm
Criterion Covered Total %
statement 51 80 63.7
branch 0 16 0.0
condition n/a
subroutine 17 21 80.9
pod n/a
total 68 117 58.1


line stmt bran cond sub pod time code
1             # $Id$
2              
3             package Google::Chart;
4 1     1   30 use 5.008;
  1         3  
  1         39  
5 1     1   6 use Moose;
  1         2  
  1         10  
6 1     1   7703 use Google::Chart::Axis;
  1         3  
  1         22  
7 1     1   7 use Google::Chart::Legend;
  1         2  
  1         27  
8 1     1   6 use Google::Chart::Grid;
  1         2  
  1         19  
9 1     1   6 use Google::Chart::Color;
  1         2  
  1         25  
10 1     1   6 use Google::Chart::Data;
  1         2  
  1         25  
11 1     1   6 use Google::Chart::Size;
  1         2  
  1         19  
12 1     1   5 use Google::Chart::Type;
  1         2  
  1         27  
13 1     1   5 use Google::Chart::Types;
  1         3  
  1         8  
14 1     1   730 use Google::Chart::Title;
  1         2  
  1         38  
15 1     1   9 use Google::Chart::Margin;
  1         2  
  1         19  
16 1     1   33902 use LWP::UserAgent;
  1         90538  
  1         44  
17 1     1   13 use URI;
  1         3  
  1         36  
18             use overload
19 1         15 '""' => \&as_uri,
20             fallback => 1,
21 1     1   8 ;
  1         3  
22              
23 1     1   116 use constant BASE_URI => URI->new("http://chart.apis.google.com/chart");
  1         4  
  1         8  
24              
25             our $VERSION = '0.05014';
26             our $AUTHORITY = 'cpan:DMAKI';
27              
28             my %COMPONENTS = (
29             type => {
30             is => 'rw',
31             does => 'Google::Chart::Type',
32             coerce => 1,
33             required => 1,
34             },
35             data => {
36             is => 'rw',
37             does => 'Google::Chart::Data',
38             coerce => 1,
39             },
40             color => {
41             is => 'rw',
42             isa => 'Google::Chart::Color',
43             coerce => 1,
44             },
45             legend => {
46             is => 'rw',
47             does => 'Google::Chart::Legend',
48             coerce => 1,
49             },
50             grid => {
51             is => 'rw',
52             isa => 'Google::Chart::Grid',
53             coerce => 1,
54             },
55             size => {
56             is => 'rw',
57             isa => 'Google::Chart::Size',
58             coerce => 1,
59             required => 1,
60             lazy => 1,
61             default => sub { Google::Chart::Size->new( width => 400, height => 300 ) },
62             },
63             marker => {
64             is => 'rw',
65             isa => 'Google::Chart::Marker',
66             coerce => 1,
67             },
68             axis => {
69             is => 'rw',
70             isa => 'Google::Chart::Axis',
71             coerce => 1,
72             },
73             fill => {
74             is => 'rw',
75             does => 'Google::Chart::Fill',
76             coerce => 1
77             },
78             title => {
79             is => 'rw',
80             does => 'Google::Chart::Title',
81             coerce => 1
82             },
83             margin => {
84             is => 'rw',
85             does => 'Google::Chart::Margin',
86             coerce => 1
87             },
88             );
89             my @COMPONENTS = keys %COMPONENTS;
90              
91             {
92             while (my ($name, $spec) = each %COMPONENTS ) {
93             has $name => %$spec;
94             }
95             }
96              
97             has 'ua' => (
98             is => 'rw',
99             isa => 'LWP::UserAgent',
100             required => 1,
101             lazy_build => 1,
102             );
103              
104             __PACKAGE__->meta->make_immutable;
105              
106 1     1   13410 no Moose;
  1         4  
  1         13  
107              
108             sub _build_ua {
109 0     0     my $self = shift;
110 0 0         my $ua = LWP::UserAgent->new(
111             agent => "perl/Google-Chart-$VERSION",
112             env_proxy => exists $ENV{GOOGLE_CHART_ENV_PROXY} ? $ENV{GOOGLE_CHART_ENV_PROXY} : 1,
113             );
114 0           return $ua;
115             }
116              
117             # XXX
118             # We need a trigger function that gets called whenever a component
119             # is set, so we can validate if the combination of components are
120             # actually feasible.
121              
122             sub as_uri {
123 0     0     my $self = shift;
124              
125 0           my %query;
126 0           foreach my $c (@COMPONENTS) {
127 0           my $component = $self->$c;
128 0 0         next unless $component;
129 0           my @params = $component->as_query;
130 0           while (@params) {
131 0           my ($name, $value) = splice(@params, 0, 2);
132 0 0         next unless length $value;
133 0           $query{$name} = $value;
134             }
135             }
136              
137             # If in case you want to change this for debugging or whatever...
138 0 0         my $uri = $ENV{GOOGLE_CHART_URI} ?
139             URI->new($ENV{GOOGLE_CHART_URI}) :
140             BASE_URI->clone;
141 0           $uri->query_form( %query );
142 0           return $uri;
143             }
144              
145             sub render {
146 0     0     my $self = shift;
147 0           my $response = $self->ua->get($self->as_uri);
148              
149 0 0         if ($response->is_success) {
150 0           return $response->content;
151             } else {
152 0           die $response->status_line;
153             }
154             }
155              
156             sub render_to_file {
157             # XXX - This is done like this because there was a document-implementation
158             # mismatch. In the future, single argument form should be deprecated
159 0     0     my $self = shift;
160 0 0         my $filename = (@_ > 1) ? do {
161 0           my %args = @_;
162 0           $args{filename};
163             }: $_[0];
164              
165 0 0         open my $fh, '>', $filename or die "can't open $filename for writing: $!\n";
166 0           binmode($fh); # be nice to windows
167 0           print $fh $self->render;
168 0 0         close $fh or die "can't close $filename: $!\n";
169             }
170              
171             1;
172              
173             __END__
174              
175             =encoding UTF-8
176              
177             =head1 NAME
178              
179             Google::Chart - Interface to Google Charts API
180              
181             =head1 SYNOPSIS
182              
183             use Google::Chart;
184              
185             my $chart = Google::Chart->new(
186             type => "Bar",
187             data => [ 1, 2, 3, 4, 5 ]
188             );
189              
190             print $chart->as_uri, "\n"; # or simply print $chart, "\n"
191              
192             $chart->render_to_file( filename => 'filename.png' );
193              
194             =head1 DESCRITPION
195              
196             Google::Chart provides a Perl Interface to Google Charts API
197             (http://code.google.com/apis/chart/).
198              
199             Please note that version 0.05000 is a major rewrite, and has little to no
200             backwards compatibility.
201              
202             =head1 METHODS
203              
204             =head2 new(%args)
205              
206             Creates a new Google::Chart instance.
207              
208             =over 4
209              
210             =item type
211              
212             Specifies the chart type, such as line, bar, pie, etc. If given a string like
213             'Bar', it will instantiate an instance of Google::Chart::Type::Bar by
214             invoking argument-less constructor.
215              
216             If you want to pass parameters to the constructor, either pass in an
217             already instanstiated object, or pass in a hash, which will be coerced to
218             the appropriate object
219              
220             my $chart = Google::Chart->new(
221             type => Google::Chart::Bar->new(
222             orientation => "horizontal"
223             )
224             );
225              
226             # or
227              
228             my $chart = Google::Chart->new(
229             type => {
230             module => "Bar",
231             args => {
232             orientation => "horizontal"
233             }
234             }
235             );
236              
237             =item size
238              
239             Specifies the chart size. Strings like "400x300", hash references, or already
240             instantiated objects can be used:
241              
242             my $chart = Google::Chart->new(
243             size => "400x300",
244             );
245              
246             my $chart = Google::Chart->new(
247             size => {
248             width => 400,
249             height => 300
250             }
251             );
252              
253             =item marker
254              
255             Specifies the markers that go on line charts.
256              
257             =item axis
258              
259             Specifies the axis labels and such that go on line and bar charts
260              
261             =item legend
262              
263             =item color
264              
265             =item fill
266              
267             =item
268              
269             =back
270              
271             =head2 as_uri()
272              
273             Returns the URI that represents the chart object.
274              
275             =head2 render()
276              
277             Generates the chart image, and returns the contents.
278             This method internally uses LWP::UserAgent. If you want to customize LWP settings, create an instance of LWP::UserAgent and pass it in the constructor
279              
280             Google::Chart->new(
281             ....,
282             ua => LWP::UserAgent->new( %your_args )
283             );
284              
285             Proxy settings are automatically read via LWP::UserAgent->env_proxy(), unless you specify GOOGLE_CHART_ENV_PROXY environment variable to 0
286              
287             =head2 render_to_file( %args )
288              
289             Generates the chart, and writes the contents out to the file specified by
290             `filename' parameter
291              
292             =head2 BASE_URI
293              
294             The base URI for Google Chart
295              
296             =head1 FEEDBACK
297              
298             We don't believe that we fully utilize Google Chart's abilities. So there
299             might be things missing, things that should be changed for easier use.
300             If you find any such case, PLEASE LET US KNOW! Suggestions are welcome, but
301             code snippets, pseudocode, or even better, test cases, are most welcome.
302              
303             =head1 TODO
304              
305             =over 4
306              
307             =item Standardize Interface
308              
309             Objects need to expect data in a standard format. This is not the case yet.
310             (comments welcome)
311              
312             =item Moose-ish Errors
313              
314             I've been reported that some Moose-related errors occur on certain platforms.
315             I have not been able to reproduce it myself, so if you do, please let me
316             know.
317              
318             =back
319              
320             =head1 AUTHORS
321              
322             Daisuke Maki C<< <daisuke@endeworks.jp> >> (current maintainer)
323              
324             Nobuo Danjou C<< <nobuo.danjou@gmail.com> >>
325              
326             Marcel Grünauer C<< <marcel@cpan.org> >> (original author)
327              
328             =head1 LICENSE
329              
330             This program is free software; you can redistribute it and/or modify it
331             under the same terms as Perl itself.
332              
333             See http://www.perl.com/perl/misc/Artistic.html
334              
335             =cut