File Coverage

blib/lib/Locale/Object/Currency/Converter.pm
Criterion Covered Total %
statement 76 93 81.7
branch 23 48 47.9
condition n/a
subroutine 16 17 94.1
pod 10 11 90.9
total 125 169 73.9


line stmt bran cond sub pod time code
1             package Locale::Object::Currency::Converter;
2              
3 1     1   549 use strict;
  1         3  
  1         27  
4 1     1   4 use warnings;;
  1         2  
  1         28  
5 1     1   5 use Carp;
  1         1  
  1         58  
6              
7 1     1   6 use Scalar::Util qw(looks_like_number);
  1         2  
  1         1323  
8              
9             our $VERSION = '0.78';
10              
11             my ($use_xe, $xe_error, $use_yahoo, $yahoo_error);
12              
13             # Check if we have the two modules that actually do the work of conversions.
14             eval {
15             require Finance::Currency::Convert::XE;
16             };
17              
18             if ($@)
19             {
20             $use_xe = 0;
21             $xe_error = $@;
22             }
23             else
24             {
25             $use_xe = 1;
26             }
27              
28             eval {
29             require Finance::Currency::Convert::Yahoo;
30             };
31              
32             if ($@)
33             {
34             $use_yahoo = 0;
35             $yahoo_error = $@;
36             }
37             else
38             {
39             $use_yahoo = 1;
40             }
41              
42              
43             sub new
44             {
45 1     1 1 11 my $class = shift;
46 1         5 my %params = @_;
47              
48 1         3 my $self = bless {}, $class;
49            
50             # Initialize the new object or return an existing one.
51 1         6 $self->init(%params);
52             }
53              
54             # Initialize the object.
55             sub init
56             {
57 1     1 0 2 my $self = shift;
58 1         2 my %params = @_;
59            
60             # Make a hash of valid parameters.
61 1         3 my %allowed_params = map { $_ => undef }
  3         7  
62             qw(service from to);
63              
64 1         4 foreach my $key (keys %params)
65             {
66             # Go no further if the specified parameter wasn't one.
67 3 50       7 croak "Error: You can only specify a service to use and currencies to convert between for initialization." unless exists $allowed_params{$key};
68             }
69              
70             # Set an attribute of the chosen currency conversion service.
71 1 50       3 if ($params{service})
72             {
73 1 50       7 croak "Error: Values for service can be 'XE' or 'Yahoo'; you said $params{service}." unless $params{service} =~ /^Yahoo$|^XE$/;
74            
75 1         6 $self->{service} = $params{service};
76             }
77            
78             # Set an attribute of the currency to convert from.
79 1 50       3 if ($params{from})
80             {
81 1 50       8 croak "Error: you can only use a Locale::Object::Currency object to convert from." unless $params{from}->isa('Locale::Object::Currency');
82            
83 1         3 $self->{from} = $params{from};
84             }
85              
86             # Set an attribute of the currency to convert to.
87 1 50       3 if ($params{to})
88             {
89 1 50       4 croak "Error: you can only use a Locale::Object::Currency object to convert from." unless $params{to}->isa('Locale::Object::Currency');
90              
91 1         2 $self->{to} = $params{to};
92             }
93            
94             # Return the object.
95 1         4 $self;
96             }
97              
98             # Set currency service to be used.
99             sub service
100             {
101 1     1 1 6 my $self = shift;
102 1         2 my $service = shift;
103            
104             # Be generous in what we accept.
105 1         2 $service = lc($service);
106            
107 1 50       7 if ($service eq 'xe')
    50          
108             {
109             # Check that we can use Finance::Currency::Convert::XE.
110 0 0       0 if ($use_xe == 1)
111             {
112 0         0 $self->{service} = $service;
113 0         0 return $self;
114             }
115             else
116             {
117 0         0 carp "WARNING: Cannot set service to XE: $xe_error";
118             }
119             }
120             elsif ($service eq 'yahoo')
121             {
122             # Check that we can use Finance::Currency::Convert::Yahoo.
123 1 50       5 if ($use_yahoo == 1)
124             {
125 1         3 $self->{service} = $service;
126 1         3 return $self;
127             }
128             else
129             {
130 0         0 carp "WARNING: Cannot set service to Yahoo: $yahoo_error";
131             }
132             }
133             else
134             {
135 0         0 carp "ERROR: Values for service can be 'XE' or 'Yahoo' (case-insensitive); you said '$service'.";
136             }
137            
138             }
139              
140             # Set currency to be converted from.
141             sub from
142             {
143 1     1 1 415 my $self = shift;
144 1         2 my $from = shift;
145              
146 1 50       8 croak "Error: you can only use a Locale::Object::Currency object to convert from." unless $from->isa('Locale::Object::Currency');
147            
148 1         6 $self->{from} = $from;
149             }
150              
151             # Set currency to converted to.
152             sub to
153             {
154 1     1 1 3 my $self = shift;
155 1         2 my $to = shift;
156              
157 1 50       6 croak "Error: you can only use a Locale::Object::Currency object to convert to." unless $to->isa('Locale::Object::Currency');
158            
159 1         5 $self->{to} = $to;
160              
161             }
162              
163             # Do currency conversions.
164             sub convert
165             {
166 3     3 1 502 my $self = shift;
167 3         5 my $value = shift;
168            
169             # Test if $value is numeric with Scalar::Util.
170 3 50       15 croak "Error: Argument '$value' to convert not numeric" unless looks_like_number($value);
171              
172 3 50       9 croak "Error: No currency set to convert from" unless $self->{from};
173 3 50       11 croak "Error: No currency set to convert to" unless $self->{to};
174 3 50       5 croak "Error: No service specified for conversion" unless $self->{service};
175              
176 3         5 my $result;
177            
178 3 50       14 if ($self->{service} eq 'Yahoo')
    100          
179             {
180 0         0 $result = _yahoo($self, $value);
181             }
182             elsif ($self->{service} eq 'XE')
183             {
184 1         3 $result = _xe($self, $value);
185             }
186            
187 3         10 $result;
188             }
189              
190             # Internal method to do Yahoo! currency conversions.
191             sub _yahoo
192             {
193 0     0   0 my $self = shift;
194 0         0 my $value = shift;
195            
196             # We're not in a talkative mood.
197 0         0 $Finance::Currency::Convert::Yahoo::CHAT = undef;
198              
199 0         0 my $result;
200            
201 0         0 eval {
202 0         0 $result = Finance::Currency::Convert::Yahoo::convert($value,$self->{from}->code,$self->{to}->code);
203             };
204            
205 0 0       0 return "ERROR: $!" if $! ne '';
206            
207 0         0 $result;
208             }
209              
210             # Internal method to do XE currency conversions.
211             sub _xe
212             {
213 1     1   2 my $self = shift;
214 1         2 my $value = shift;
215              
216 1 50       20 my $xe = Finance::Currency::Convert::XE->new() or croak "Error: Couldn't create Finance::Currency::Convert::XE object: $!";
217              
218 1         1713 my $result;
219              
220             eval
221 1         3 {
222             $result = $xe->convert(
223             'source' => $self->{from}->code,
224             'target' => $self->{to}->code,
225 1         7 'value' => $value
226             );
227             };
228            
229 1 50       175030 return "ERROR: $!" if $! ne '';
230            
231 0         0 $result;
232             }
233              
234             # Give the exchange rate of the currencies.
235             sub rate
236             {
237 1     1 1 246 my $self = shift;
238              
239             # If there's no rate stored, set one.
240 1 50       7 $self->refresh unless $self->{_rate};
241              
242 1         3 return $self->{_rate};
243             }
244              
245             # Give the time that the rate was stored.
246             sub timestamp
247             {
248 1     1 1 244 my $self = shift;
249            
250 1 50       4 if ($self->{_timestamp})
251             {
252 1         3 return $self->{_timestamp};
253             }
254             else
255             {
256 0         0 return undef;
257             }
258             }
259              
260             # Update the exchange rate.
261             sub refresh
262             {
263 1     1 1 2 my $self = shift;
264              
265             # Do a conversion to get the rate.
266 1         4 my $rate = $self->convert(1);
267              
268             # Make a note of the rate and the time.
269 1         3 $self->{_rate} = $rate;
270 1         2 $self->{_timestamp} = time;
271             }
272              
273             # Can you use Finance::Currency::Convert::XE?
274             sub use_xe
275             {
276 1     1 1 610 $use_xe;
277             }
278              
279             # Can you use Finance::Currency::Convert::Yahoo?
280             sub use_yahoo
281             {
282 1     1 1 3 $use_yahoo;
283             }
284              
285              
286             1;
287              
288             __END__
289              
290             =head1 NAME
291              
292             Locale::Object::Currency::Converter - convert between currencies
293              
294             =head1 DESCRIPTION
295              
296             C<Locale::Object::Currency::Converter> allows you to convert between values of currencies represented by L<Locale::Object::Currency> objects.
297              
298             =head1 SYNOPSIS
299              
300             use Locale::Object::Currency;
301             use Locale::Object::Currency::Converter;
302            
303             my $usd = Locale::Object::Currency->new( code => 'USD' );
304             my $gbp = Locale::Object::Currency->new( code => 'GBP' );
305             my $eur = Locale::Object::Currency->new( code => 'EUR' );
306             my $jpy = Locale::Object::Currency->new( code => 'JPY' );
307            
308             my $converter = Locale::Object::Currency::Converter->new(
309             from => $usd,
310             to => $gbp,
311             service => 'XE'
312             );
313              
314             my $result = $converter->convert(5);
315             my $rate = $converter->rate;
316             my $timestamp = $converter->timestamp;
317              
318             print $converter->use_xe;
319             print $converter->use_yahoo;
320            
321             $converter->from($eur);
322             $converter->to($jpy);
323             $converter->service('Yahoo');
324              
325             $converter->refresh;
326              
327             =head1 PREREQUISITES
328              
329             This module requires L<Finance::Currency::Convert::XE> and L<Finance::Currency::Convert::Yahoo>.
330            
331             =head1 METHODS
332              
333             =head2 C<new()>
334              
335             my $converter = Locale::Object::Currency::Converter->new();
336              
337             Creates a new converter object. With no arguments, creates a blank object. Possible arguments are C<from>, C<to> and C<service>, all or none of which may be given. C<from> and C<to> must be L<Locale::Object::Currency> objects. C<service> must be one of either 'XE' or 'Yahoo', to specify the conversion should be done by L<http://xe.com/ucc/> or L<http://finance.yahoo.com/> respectively.
338              
339             =head2 C<use_xe()>
340              
341             print $converter->use_xe;
342            
343             Returns 1 or 0 depending on whether a C<use Finance::Currency::Convert::XE;> was successful. If 1, you can do conversions using the XE.com service.
344              
345             =head2 C<use_yahoo()>
346              
347             print $converter->use_yahoo;
348            
349             Returns 1 or 0 depending on whether a C<use Finance::Currency::Convert::Yahoo;> was successful. If 1, you can do conversions using the finance.yahoo.com service.
350              
351             =head2 C<from()>
352              
353             $converter->from($eur);
354              
355             Sets a currency to do conversions from. Takes a L<Locale::Object::Currency> object.
356              
357             =head2 C<to()>
358              
359             $converter->to($jpy);
360              
361             Sets a currency to do conversions to. Takes a L<Locale::Object::Currency> object.
362              
363             =head2 C<service()>
364              
365             $converter->service('Yahoo');
366              
367             Sets which currency conversion service to use. Depends on two other modules; see C<use_xe()> and C<use_yahoo()> above.
368              
369             =head2 C<convert()>
370              
371             my $result = $converter->convert(5);
372              
373             Does the currency conversion. Takes a numeric argument representng the amount of the 'from' currency to convert into the 'to' currency, gives the result. Will croak if you didn't select a conversion service, 'from' and 'to' currency when you did C<new()> or afterwards with the associated methods (see above).
374              
375             =head2 C<rate()>
376              
377             my $rate = $converter->rate;
378              
379             Returns the conversion rate between your 'from' currency and your 'to' currency, as of the time you last did a conversion. If you haven't done any conversions yet, will do one first (the result for converting 1 unit of a currency into another currency is the rate) and give you that.
380              
381             =head2 C<timestamp()>
382              
383             my $timestamp = $converter->timestamp;
384              
385             Returns the L<time> timestamp of the last time the currency exchange rate was stored, either the last time you did a C<convert()> or a C<refresh()>.
386              
387             =head2 C<refresh()>
388              
389             $converter->refresh;
390            
391             Will update the stored conversion rate and timestamp by doing another conversion. Doesn't return anything.
392              
393             =head1 AUTHOR
394              
395             Originally by Earle Martin
396              
397             =head1 COPYRIGHT AND LICENSE
398              
399             Originally by Earle Martin. To the extent possible under law, the author has dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
400              
401             =cut
402