File Coverage

blib/lib/Dancer/Plugin/Piwik.pm
Criterion Covered Total %
statement 15 73 20.5
branch 0 20 0.0
condition 0 9 0.0
subroutine 5 12 41.6
pod n/a
total 20 114 17.5


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Piwik;
2              
3 2     2   24363 use 5.010001;
  2         6  
  2         78  
4 2     2   9 use strict;
  2         3  
  2         62  
5 2     2   9 use warnings FATAL => 'all';
  2         10  
  2         80  
6 2     2   1215 use Dancer qw/:syntax/;
  2         436640  
  2         14  
7 2     2   2091 use Dancer::Plugin;
  2         2662  
  2         1673  
8              
9             =head1 NAME
10              
11             Dancer::Plugin::Piwik - Generate JS code for Piwik
12              
13             =head1 VERSION
14              
15             Version 0.03
16              
17             =cut
18              
19             our $VERSION = '0.03';
20              
21              
22             =head1 SYNOPSIS
23              
24             In your configuration:
25              
26             plugins:
27             Piwik:
28             id: "your-id"
29             url: "your-url"
30              
31             In your module
32              
33             use Dancer ':syntax';
34             use Dancer::Plugin::Piwik;
35              
36              
37             =head1 CONFIGURATION
38              
39             Two keys are required:
40              
41             =head2 id
42              
43             The numeric id of the tracked site (you find it in the Piwik admin).
44              
45             =head2 url
46              
47             The url of the tracking site, B and B
48             trailing slash>. E.g.
49              
50             mysite.org/stats
51              
52             =head1 EXPORTED KEYWORDS
53              
54             All the following keywords support the boolean argument C.
55             Instead of the javascript, a perl structure will be returned.
56              
57             =head2 piwik
58              
59             Return generic code for page view tracking. No argument required.
60              
61             =head2 piwik_category(category => "name")
62              
63             Generate js for category pages. Requires a named argument C
64             with the name of the category to track.
65              
66             =head2 piwik_view(product => { sku => $sku, description => $desc, categories => \@categories, price => $price })
67              
68             Generate js for flypages. Expects a named argument product, paired
69             with an hashref with the product data, having the following keys
70              
71             =over 4
72              
73             =item sku
74              
75             =item description
76              
77             =item categories
78              
79             (an arrayref with the names of the categories). An empty arrayref can
80             do as well).
81              
82             =item price
83              
84             The price of the item
85              
86             =back
87              
88             =head2 piwik_cart(cart => \@items, subtotal => $subtotal)
89              
90             Generate js for cart view. Requires two named arguments. The C
91             argument must point to an arrayref of hashref products, with the same
92             keys of C, and an additional key C.
93              
94             =cut
95              
96             sub _piwik {
97 0     0     my %args = @_;
98 0           return _generate_js($args{ajax});
99             }
100              
101             sub _piwik_category {
102 0     0     my %args = @_;
103 0           my $category = $args{category};
104 0 0         unless ($category) {
105 0           return _generate_js($args{ajax});
106             }
107 0           return _generate_js($args{ajax}, [ setEcommerceView => \0, \0, $category ]);
108             }
109              
110             sub _piwik_view {
111 0     0     my %args = @_;
112 0           my $product = $args{product};
113 0 0         unless ($product) {
114 0           return _generate_js($args{ajax});
115             }
116 0           my $arg = [
117             setEcommerceView => $product->{sku},
118             $product->{description},
119 0           [ @{ $product->{categories} } ],
120             $product->{price} + 0,
121             ];
122 0           return _generate_js($args{ajax}, $arg);
123             }
124              
125             sub _piwik_cart {
126 0     0     my %args = @_;
127 0           my $subtotal = $args{subtotal};
128 0           my $cart = $args{cart};
129 0 0 0       unless ($cart && defined($subtotal)) {
130 0           return _generate_js($args{ajax});
131             }
132 0           my @addendum = _unroll_cart($cart);
133 0           push @addendum, [ trackEcommerceCartUpdate => $subtotal + 0 ];
134 0           return _generate_js($args{ajax}, @addendum);
135             }
136              
137             sub _unroll_cart {
138 0     0     my $cart = shift;
139 0           my @addendum;
140 0           foreach my $item (@$cart) {
141 0           push @addendum, [
142             addEcommerceItem => $item->{sku},
143             $item->{description},
144 0           [ @{ $item->{categories} } ],
145             $item->{price} + 0,
146             $item->{quantity} + 0,
147             ];
148             }
149 0           return @addendum;
150             }
151              
152             =head2 piwik_order(cart => \@items, order => { order_number => $id, total_cost => $total, subtotal => $subtotal, taxes => $taxes, shipping => $shipping, discount => $discount }
153              
154             Generate js for the receipt. Two required arguments: C is the
155             same as C, while order is an hashref with the following keys:
156              
157             =over 4
158              
159             =item order_number (required)
160              
161             =item total_cost (required)
162              
163             =item subtotal (optional)
164              
165             =item taxes (optional)
166              
167             =item shipping (optional)
168              
169             =item discount (optional)
170              
171             =back
172              
173             =cut
174              
175             sub _piwik_order {
176 0     0     my %args = @_;
177 0           my $cart = $args{cart};
178 0           my $order = $args{order};
179 0 0 0       unless ($cart && $order) {
180 0           return _generate_js($args{ajax});
181             }
182 0           my @addendum = _unroll_cart($cart);
183 0           foreach my $i (qw/total_cost order_number/) {
184 0 0         die "Missing $i" unless $order->{$i};
185             }
186             # avoid touching the original
187 0           $order = { %$order };
188              
189 0           foreach my $i (qw/subtotal taxes shipping discount/) {
190 0 0         if (defined $order->{$i}) {
191             # coerce it to a number
192 0           $order->{$i} += 0;
193             }
194             else {
195             # set it to false
196 0           $order->{$i} = \0;
197             }
198             }
199 0           push @addendum, [trackEcommerceOrder => $order->{order_number} .'',
200             $order->{total_cost} + 0,
201             $order->{subtotal},
202             $order->{taxes},
203             $order->{shipping},
204             $order->{discount},
205             ];
206 0           return _generate_js($args{ajax}, @addendum);
207             }
208              
209             sub _generate_js {
210 0     0     my ($ajax, @args) = @_;
211 0           my $piwik_url = plugin_setting->{url};
212 0           my $piwik_id = plugin_setting->{id};
213              
214 0 0 0       unless ($piwik_url && defined($piwik_id)) {
215 0           warning "Missing url and id for Piwiki, plugin is disabled";
216 0 0         $ajax ? return {} : return '';
217             }
218 0 0         if ($ajax) {
219 0           my @elements = (['trackPageView'],
220             ['enableLinkTracking']);
221 0 0         push @elements, @args if @args;
222             return {
223 0           piwik_url => $piwik_url,
224             piwik_id => $piwik_id,
225             elements => \@elements,
226             };
227             }
228 0           my $addendum = '';
229 0           foreach my $arg (@args) {
230 0           $addendum .= '_paq.push(' . to_json($arg) . ");\n";
231             }
232              
233 0           my $js = <<"JAVASCRIPT";
234            
247            
248             JAVASCRIPT
249 0           return $js;
250             }
251              
252             register piwik => \&_piwik;
253             register piwik_category => \&_piwik_category;
254             register piwik_view => \&_piwik_view;
255             register piwik_cart => \&_piwik_cart;
256             register piwik_order => \&_piwik_order;
257              
258             register_plugin;
259              
260              
261             =head1 AUTHOR
262              
263             Stefan Hornburg (Racke), C<< >>
264              
265             =head1 BUGS
266              
267             Please report any bugs or feature requests to C, or through
268             the web interface at L. I will be notified, and then you'll
269             automatically be notified of progress on your bug as I make changes.
270              
271              
272              
273              
274             =head1 SUPPORT
275              
276             You can find documentation for this module with the perldoc command.
277              
278             perldoc Dancer::Plugin::Piwik
279              
280              
281             You can also look for information at:
282              
283             =over 4
284              
285             =item * RT: CPAN's request tracker (report bugs here)
286              
287             L
288              
289             =item * AnnoCPAN: Annotated CPAN documentation
290              
291             L
292              
293             =item * CPAN Ratings
294              
295             L
296              
297             =item * Search CPAN
298              
299             L
300              
301             =back
302              
303              
304             =head1 ACKNOWLEDGEMENTS
305              
306              
307             =head1 LICENSE AND COPYRIGHT
308              
309             Copyright 2014 Stefan Hornburg (Racke).
310              
311             This program is free software; you can redistribute it and/or modify it
312             under the terms of the the Artistic License (2.0). You may obtain a
313             copy of the full license at:
314              
315             L
316              
317             Any use, modification, and distribution of the Standard or Modified
318             Versions is governed by this Artistic License. By using, modifying or
319             distributing the Package, you accept this license. Do not use, modify,
320             or distribute the Package, if you do not accept this license.
321              
322             If your Modified Version has been derived from a Modified Version made
323             by someone other than you, you are nevertheless required to ensure that
324             your Modified Version complies with the requirements of this license.
325              
326             This license does not grant you the right to use any trademark, service
327             mark, tradename, or logo of the Copyright Holder.
328              
329             This license includes the non-exclusive, worldwide, free-of-charge
330             patent license to make, have made, use, offer to sell, sell, import and
331             otherwise transfer the Package with respect to any patent claims
332             licensable by the Copyright Holder that are necessarily infringed by the
333             Package. If you institute patent litigation (including a cross-claim or
334             counterclaim) against any party alleging that the Package constitutes
335             direct or contributory patent infringement, then this Artistic License
336             to you shall terminate on the date that such litigation is filed.
337              
338             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
339             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
340             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
341             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
342             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
343             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
344             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
345             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
346              
347              
348             =cut
349              
350             1; # End of Dancer::Plugin::Piwik