File Coverage

blib/lib/Dancer/Plugin/Interchange6.pm
Criterion Covered Total %
statement 80 80 100.0
branch 17 18 94.4
condition 6 6 100.0
subroutine 24 24 100.0
pod n/a
total 127 128 99.2


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Interchange6;
2              
3 5     5   1894941 use strict;
  5         8  
  5         124  
4 5     5   17 use warnings;
  5         6  
  5         142  
5              
6 5     5   570 use Dancer qw(:syntax !before !after);
  5         148375  
  5         26  
7 5     5   4150 use Dancer::Plugin;
  5         5136  
  5         300  
8 5     5   2183 use Dancer::Plugin::DBIC;
  5         35697  
  5         230  
9 5     5   2296 use Dancer::Plugin::Auth::Extensible;
  5         18329  
  5         369  
10              
11 5     5   1955 use Dancer::Plugin::Interchange6::Cart;
  5         15  
  5         145  
12 5     5   2325 use Dancer::Plugin::Interchange6::Business::OnlinePayment;
  5         13  
  5         150  
13              
14 5     5   25 use Module::Runtime 'use_module';
  5         8  
  5         31  
15              
16             =head1 NAME
17              
18             Dancer::Plugin::Interchange6 - Interchange6 Shop Plugin for Dancer
19              
20             =head1 VERSION
21              
22             Version 0.121
23              
24             =cut
25              
26             our $VERSION = '0.121';
27              
28             =head1 DESCRIPTION
29              
30             This L<Dancer> plugin is now DEPRECATED since all new development has moved
31             to the L<Dancer2> plugin L<Dancer2::Plugin::Interchange6>.
32              
33             =head1 REQUIREMENTS
34              
35             All Interchange6 Dancer applications need to use the L<Dancer::Session::DBIC>
36             engine.
37              
38             The easiest way to configure this is in your main module, just after all
39             the C<use> statements:
40              
41             set session => 'DBIC';
42             set session_options => {schema => schema};
43              
44             =head1 CONFIGURATION
45              
46             Available configuration options:
47              
48             plugins:
49             Interchange6:
50             cart_class: MyApp::Cart
51             carts_var_name: some_other_var
52              
53             =over
54              
55             =item * cart_class
56              
57             If you wish to subclass the cart you can have L</shop_cart> return your
58             subclassed cart instead. You set the cart class via C<cart_class>.
59             Defaults to L<Dancer::Plugin::Interchange6::Cart>.
60              
61             =item * carts_var_name
62              
63             The plugin caches carts in a L<Dancer/var> and the name of the var used can
64             be set via C<carts_var_name>. Defaults to C<ic6_carts>.
65              
66             =back
67              
68             =head1 ROUTES
69              
70             You can use the L<Dancer::Plugin::Interchange6::Routes> plugin bundled with this
71             plugin to setup standard routes for:
72              
73             =over 4
74              
75             =item product listing
76              
77             =item product display
78              
79             =item cart display
80              
81             =item checkout form
82              
83             =back
84              
85             To enable these routes, you put the C<shop_setup_routes> keyword at the end
86             of your main module:
87              
88             package MyShop;
89              
90             use Dancer ':syntax';
91             use Dancer::Plugin::Interchange6;
92             use Dancer::Plugin::Interchange6::Routes;
93              
94             get '/shop' => sub {
95             ...
96             };
97              
98             ...
99              
100             shop_setup_routes;
101              
102             true;
103              
104             Please refer to L<Dancer::Plugin::Interchange6::Routes> for configuration options
105             and further information.
106              
107             =head1 KEYWORDS
108              
109             =head2 shop_cart
110              
111             Returns L<Dancer::Plugin::Interchange6::Cart> object.
112              
113              
114             =head2 shop_charge
115              
116             Creates payment order and authorizes amount.
117              
118             =head2 shop_redirect
119              
120             Calls L<Interchange6::Schema::ResultSet::UriRedirect/redirect> with given args.
121              
122             =head2 shop_schema
123              
124             Returns L<Interchange6::Schema> object.
125              
126             =head2 shop_...
127              
128             Accessors for L<Interchange6::Schema> result classes. You can use it
129             to retrieve a single object or the corresponding result set.
130              
131             shop_product('F0001')->uri;
132              
133             shop_navigation->search({type => 'manufacturer',
134             active => 1});
135              
136             Available accessors are C<shop_address>, C<shop_attribute>, C<shop_country>,
137             C<shop_message>, C<shop_navigation>, C<shop_order>, C<shop_product>,
138             C<shop_state> and C<shop_user>.
139              
140             =head1 HOOKS
141              
142             This plugin installs the following hooks:
143              
144             =head2 Add to cart
145              
146             The functions registered for these hooks receive the cart object
147             and the item to be added as parameters.
148              
149             =over 4
150              
151             =item before_cart_add_validate
152              
153             Triggered before item is validated for adding to the cart.
154              
155             =item before_cart_add
156              
157             Triggered before item is added to the cart.
158              
159             =item after_cart_add
160              
161             Triggered after item is added to the cart.
162             Used by DBI backend to save item to the database.
163              
164             =back
165              
166             =head2 Update cart
167              
168             The functions registered for these hooks receive the cart object,
169             the current item in the cart and the updated item.
170              
171             =over 4
172              
173             =item before_cart_update
174              
175             Triggered before cart item is updated (changing quantity).
176              
177             =item after_cart_update
178              
179             Triggered after cart item is updated (changing quantity).
180             Used by DBI backend to update item to the database.
181              
182             =back
183              
184             =head2 Remove from cart
185              
186             The functions registered for these hooks receive the cart object
187             and the item to be added as parameters.
188              
189             =over 4
190              
191             =item before_cart_remove_validate
192              
193             Triggered before item is validated for removal.
194             Receives cart object and item SKU.
195              
196             =item before_cart_remove
197              
198             Triggered before item is removed from the cart.
199             Receives cart object and item.
200              
201             =item after_cart_remove
202              
203             Triggered after item is removed from the cart.
204             Used by DBI backend to delete item from the database.
205             Receives cart object and item.
206              
207             =back
208              
209             =head2 Clear cart
210              
211             =over 4
212              
213             =item before_cart_clear
214              
215             Triggered before cart is cleared.
216              
217             =item after_cart_clear
218              
219             Triggered after cart is cleared.
220              
221             =back
222              
223             =head2 Rename cart
224              
225             The functions registered for these hooks receive the cart object,
226             the old name and the new name.
227              
228             =over 4
229              
230             =item before_cart_rename
231              
232             Triggered before cart is renamed.
233              
234             =item after_cart_rename
235              
236             Triggered after cart is renamed.
237              
238             =item before_cart_set_users_id
239              
240             Triggered before users_id is set for the cart.
241              
242             =item after_cart_set_users_id
243              
244             Triggered after users_id is set for the cart.
245              
246             =item before_cart_set_sessions_id
247              
248             Triggered before sessions_id is set for the cart.
249              
250             =item after_cart_set_sessions_id
251              
252             Triggered after sessions_id is set for the cart.
253              
254             =back
255              
256             =head1 EXPIRE DBIC SESSIONS
257              
258             This command expires/manages DBIC sessions and carts. NOTE: For proper
259             functionality please copy/link to Dancer App/bin directory.
260              
261             interchange6-expire-sessions
262              
263             =cut
264              
265             register_hook(qw/before_cart_add_validate
266             before_cart_add after_cart_add
267             before_cart_update after_cart_update
268             before_cart_remove_validate
269             before_cart_remove after_cart_remove
270             before_cart_rename after_cart_rename
271             before_cart_clear after_cart_clear
272             before_cart_set_users_id after_cart_set_users_id
273             before_cart_set_sessions_id after_cart_set_sessions_id
274             /);
275              
276             register shop_schema => sub {
277 107     107   39893 _shop_schema(@_);
278             };
279              
280             register shop_address => sub {
281 3     3   13197 _shop_resultset('Address', @_);
282             };
283              
284             register shop_attribute => sub {
285 3     3   11168 _shop_resultset('Attribute', @_);
286             };
287              
288             register shop_country => sub {
289 4     4   8898 _shop_resultset('Country', @_);
290             };
291              
292             register shop_message => sub {
293 5     5   35200 _shop_resultset('Message', @_);
294             };
295              
296             register shop_navigation => sub {
297 13     13   6325 _shop_resultset('Navigation', @_);
298             };
299              
300             register shop_order => sub {
301 3     3   12908 _shop_resultset('Order', @_);
302             };
303              
304             register shop_product => sub {
305 59     59   11267 _shop_resultset('Product', @_);
306             };
307              
308             register shop_state => sub {
309 3     3   9669 _shop_resultset('State', @_);
310             };
311              
312             register shop_redirect => sub {
313 8     8   13526 return resultset('UriRedirect')->redirect($_[0]);
314             };
315              
316             register shop_user => sub {
317 9     9   12076 _shop_resultset('User', @_);
318             };
319              
320             register shop_charge => sub {
321 6     6   25082 my (%args) = @_;
322 6         8 my ($schema, $bop_object, $payment_settings, $provider, $provider_settings);
323              
324 6         15 $payment_settings = plugin_setting->{payment};
325              
326 6 50       214 die "No payment setting" unless $payment_settings;
327              
328             # determine payment provider
329 6 100       15 if ( $args{provider} ) {
330 4         8 $provider = $args{provider};
331             }
332             else {
333 2         5 $provider = $payment_settings->{default_provider};
334             }
335              
336 6 100       17 if (exists $payment_settings->{providers}->{$provider}) {
337 5         7 $provider_settings = $payment_settings->{providers}->{$provider};
338             }
339             else {
340 1         10 die "Settings for provider $provider missing.";
341             }
342              
343             my %payment_data = (payment_mode => $provider,
344             status => 'request',
345             sessions_id => session->id,
346             payment_action => 'charge',
347             amount => $args{amount},
348 5         16 users_id => session('logged_in_user_id'),
349             );
350              
351             # create payment order
352 5         22264 $schema = _shop_schema();
353              
354 5         247 my $payment_order = $schema->resultset('PaymentOrder')->create(\%payment_data);
355              
356             # create BOP object wrapper with provider settings
357 4         11995 $bop_object = Dancer::Plugin::Interchange6::Business::OnlinePayment->new($provider, %$provider_settings);
358              
359 4         67 $bop_object->payment_order($payment_order);
360              
361             # call charge method
362 4         17 $bop_object->charge(%args);
363              
364 3 100       33 if ($bop_object->is_success) {
365 2         18 $payment_order->update({
366             status => 'success',
367             auth_code => $bop_object->authorization,
368             });
369             }
370             else {
371 1         8 $payment_order->update({
372             status => 'failure',
373             payment_error_code => $bop_object->error_code,
374             payment_error_message => $bop_object->error_message,
375             });
376             }
377              
378 3         5358 return $bop_object;
379             };
380              
381             register cart => \&_shop_cart;
382             register shop_cart => \&_shop_cart;
383              
384             sub _shop_cart {
385              
386 59     59   53102 my ( %args, $user_ref );
387              
388             # cart name from arg or default 'main'
389 59 100       256 $args{name} = @_ == 1 ? $_[0] : 'main';
390              
391             # set name of var we will stash carts in
392 59   100     183 my $var = plugin_setting->{carts_var_name} || 'ic6_carts';
393 59         1845 debug "carts_var_name: $var";
394              
395             # cart class
396             my $cart_class = plugin_setting->{cart_class}
397 59   100     2493 || 'Dancer::Plugin::Interchange6::Cart';
398              
399 59   100     1371 my $carts = var($var) || {};
400              
401 59 100       947 if ( !defined $carts->{ $args{name} } ) {
402              
403             # can't find this cart in stash
404              
405 56         162 $args{sessions_id} = session->id;
406              
407 56 100       125844 if ( $user_ref = logged_in_user ) {
408              
409             # user is logged in
410 12         111535 $args{users_id} = $user_ref->users_id;
411             }
412              
413 56         95375 $carts->{ $args{name} } = use_module($cart_class)->new(%args);
414             }
415              
416             # stash carts back in var
417 59         35390 var $var => $carts;
418              
419 59         965 return $carts->{ $args{name} };
420             }
421              
422             sub _shop_schema {
423 112     112   143 my $schema_key;
424              
425 112 100       310 if (@_) {
426 2         4 $schema_key = $_[0];
427             }
428             else {
429 110         263 $schema_key = 'default';
430             }
431              
432 112         582 return schema($schema_key);
433             };
434              
435             sub _shop_resultset {
436 102     102   156 my ($name, $key) = @_;
437              
438 102 100       266 if (defined $key) {
439 28         120 return resultset($name)->find($key);
440             }
441              
442 74         200 return resultset($name);
443             };
444              
445             register_plugin;
446              
447             =head1 ACKNOWLEDGEMENTS
448              
449             The L<Dancer> developers and community for their great application framework
450             and for their quick and competent support.
451              
452             Peter Mottram for his patches.
453              
454             =head1 LICENSE AND COPYRIGHT
455              
456             Copyright 2010-2016 Stefan Hornburg (Racke).
457              
458             This program is free software; you can redistribute it and/or modify it
459             under the terms of either: the GNU General Public License as published
460             by the Free Software Foundation; or the Artistic License.
461              
462             See http://dev.perl.org/licenses/ for more information.
463              
464             =head1 SEE ALSO
465              
466             L<Dancer2::Plugin::Interchange6>
467              
468             L<Interchange6>, L<Interchange6::Schema>
469              
470             =cut
471              
472             1;