File Coverage

lib/Dancer/Plugin/Interchange6/Routes/Cart.pm
Criterion Covered Total %
statement 75 75 100.0
branch 23 26 88.4
condition 3 3 100.0
subroutine 8 8 100.0
pod 1 1 100.0
total 110 113 97.3


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Interchange6::Routes::Cart;
2              
3 2     2   769 use Data::Dumper::Concise;
  2         444  
  2         100  
4 2     2   9 use Dancer ':syntax';
  2         2  
  2         9  
5 2     2   527 use Dancer::Plugin;
  2         3  
  2         95  
6 2     2   8 use Dancer::Plugin::Interchange6;
  2         2  
  2         117  
7 2     2   7 use Dancer::Plugin::Auth::Extensible;
  2         4  
  2         153  
8 2     2   8 use Try::Tiny;
  2         2  
  2         1365  
9              
10             =head1 NAME
11              
12             Dancer::Plugin::Interchange6::Routes::Cart - Cart routes for Interchange6 Shop Machine
13              
14             =cut
15              
16             register_hook 'before_cart_display';
17              
18             =head1 FUNCTIONS
19              
20             =head2 cart_route
21              
22             Returns the cart route based on the passed routes configuration.
23              
24             =cut
25              
26             sub cart_route {
27 1     1 1 1 my $routes_config = shift;
28              
29             return sub {
30 35     35   152872 my %values;
31 35         74 my ($input, $product, $cart, $cart_name, $cart_input,
32             $cart_product, $roles, @errors);
33              
34 35         149 $cart_name = param('cart');
35 35 100       5210 $cart = $cart_name ? cart($cart_name) : cart;
36              
37 35         356 debug "cart_route cart name: " . $cart->name;
38              
39 35 100 100     1827 if ( param('remove') ) {
    100          
40              
41             # removing item from cart
42              
43             try {
44 3         81 $cart->remove( param('remove') );
45             # if GET then URL now contains ugly query params so redirect
46 2 50       73 return redirect '/cart' if request->is_get;
47             }
48             catch {
49 1         15 warning "Cart remove error: $_";
50 1         40 push @errors, "Failed to remove product from cart: $_";
51 3         131 };
52             }
53             elsif ( param('update') && defined param('quantity') ) {
54              
55             # update existing cart product
56              
57 3         218 debug "Update "
58             . param('update')
59             . " with quantity "
60             . param('quantity');
61              
62             try {
63 3         81 $cart->update( param('update') => param('quantity') );
64             }
65             catch {
66 1         443 warning "Update cart product error: $_";
67 1         43 push @errors, "Failed to update product in cart: $_";
68 3         189 };
69             }
70              
71 35 100       2094 if ( $input = param('sku') ) {
72              
73             # add new product
74              
75             # we currently only support one product at a time so check that
76             # the param is a scalar
77              
78 19 50       419 if ( ref($input) eq '' ) {
79              
80 19         77 $product = shop_product($input);
81              
82 19 100       75772 unless ( defined $product ) {
83 1         18 warning "sku not found in POST /cart: $input";
84 1         41 session shop_cart_error =>
85             { message => "Product not found with sku: $input" };
86 1         6798 return redirect '/';
87             }
88              
89             # store params in hash
90 18         339 my %params = params;
91              
92 18 100       977 if ( defined $product->canonical_sku ) {
93              
94             # this is a variant so we need to add in variant info
95             # into %params if missing
96              
97 2         40 my $rset = $product->product_attributes->search(
98             {
99             'attribute.type' => 'variant',
100             },
101             {
102             prefetch => [
103             'attribute',
104             {
105             product_attribute_values =>
106             'attribute_value'
107             }
108             ],
109             }
110             );
111 2         3135 while ( my $result = $rset->next ) {
112 4         36562 my $name = $result->attribute->name;
113             # WTF! why do we get a resultset of pavs? Surely there
114             # should be only one related pav for pa?
115 4         172 my $value = $result->product_attribute_values->first
116             ->attribute_value->value;
117 4 50       2388 $params{$name} = $value unless defined $params{$name};
118              
119             }
120             }
121             # retrieve product attributes for possible variants
122 18         783 my $attr_ref = $product->attribute_iterator( hashref => 1 );
123 18         324250 my %user_input;
124              
125 18 100       72 if ( keys %$attr_ref ) {
126              
127 11         33 for my $name ( keys %$attr_ref ) {
128 22         57 $user_input{$name} = $params{$name};
129             }
130              
131 11         81 debug "Attributes for $input: ", $attr_ref,
132             ", user input: ", \%user_input;
133 11         3272 my %match_info;
134              
135 11 100       63 unless ( $cart_product =
136             $product->find_variant( \%user_input, \%match_info ) )
137             {
138 2         316744 warning "Variant not found for ", $product->sku;
139 2         167 session shop_cart_error => {
140             message => 'Variant not found.',
141             info => \%match_info
142             };
143 2         13633 return redirect $product->uri;
144             }
145             }
146             else {
147             # product without variants
148 7         13 $cart_product = $product;
149             }
150              
151 16         541743 my $quantity = 1;
152 16 100       83 if ( param('quantity') ) {
153 4         180 $quantity = param('quantity');
154             }
155              
156             try {
157 16         843 $cart->add(
158             {
159             dbic_product => $cart_product,
160             sku => $cart_product->sku,
161             quantity => $quantity
162             }
163             );
164             }
165             catch {
166 1         604 warning "Cart add error: $_";
167 1         295 push @errors, "Failed to add product to cart: $_";
168 16         654 };
169             }
170             }
171              
172             # add stuff useful for cart display
173 32         1565 $values{cart_subtotal} = $cart->subtotal;
174 32         41787 $values{cart_total} = $cart->total;
175 32         1913 $values{cart} = $cart->products;
176 32 100       136 $values{cart_error} = join(". ", @errors) if scalar @errors;
177              
178             # call before_cart_display route so template tokens
179             # can be injected
180 32         129 execute_hook('before_cart_display', \%values);
181              
182 32         6327 template $routes_config->{cart}->{template}, \%values;
183             }
184 1         15 }
185              
186             1;