File Coverage

blib/lib/Dancer2/Plugin/Interchange6/Routes/Cart.pm
Criterion Covered Total %
statement 58 58 100.0
branch 22 24 91.6
condition 3 3 100.0
subroutine 3 3 100.0
pod 1 1 100.0
total 87 89 97.7


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Interchange6::Routes::Cart;
2              
3 2     2   7 use Try::Tiny;
  2         3  
  2         1232  
4              
5             =head1 NAME
6              
7             Dancer2::Plugin::Interchange6::Routes::Cart - Cart routes for Interchange6 Shop Machine
8              
9             =cut
10              
11             =head1 FUNCTIONS
12              
13             =head2 cart_route
14              
15             Returns the cart route based on the plugin configuration.
16              
17             =cut
18              
19             sub cart_route {
20 1     1 1 2 my $plugin = shift;
21              
22             return sub {
23 44     44   8294 my $app = shift;
24 44         245 my $params = $app->request->parameters;
25              
26 44         4082 my ( $product, $cart_input, $cart_product, $roles, @errors );
27              
28 44         162 my $cart_name = $params->get('cart');
29              
30 44 100       1054 my $cart =
31             $cart_name ? $plugin->shop_cart($cart_name) : $plugin->shop_cart;
32              
33 44         329 $app->log( "debug", "cart_route cart name: ", $cart->name );
34              
35 44 100 100     21941 if ( my @skus = $params->get_all('remove') ) {
    100          
36              
37             # remove items from cart
38              
39 3         59 foreach my $sku (@skus) {
40             try {
41 3         178 $cart->remove($sku);
42             }
43             catch {
44 1         13 $app->log( "warning", "Cart remove $sku error: $_" );
45 1         378 push @errors, "Failed to remove product $sku from cart: $_";
46 3         32 };
47             }
48              
49             # if GET then URL now contains ugly query params so redirect
50 3 50       120 return $app->redirect('/cart') if $app->request->is_get;
51              
52             }
53             elsif ( $params->get('update')
54             && defined $params->get('quantity') )
55             {
56              
57 3         101 my $sku = $params->get('update');
58 3         15 my $qty = $params->get('quantity');
59              
60             # update existing cart product
61              
62 3         21 $app->log( "debug", "Update $sku with quantity $qty" );
63              
64             try {
65 3         150 $cart->update( $sku => $qty );
66             }
67             catch {
68 1         396 $app->log( "warning", "Update cart product $sku error: $_" );
69 1         385 push @errors, "Failed to update product $sku in cart: $_";
70 3         1125 };
71             }
72              
73 44 100       2094 if ( my $sku = $params->get('sku') ) {
74              
75             # add new product
76              
77             # we currently only support one product at a time
78              
79 25         570 $product = $plugin->shop_product($sku);
80              
81 25 100       105393 unless ( defined $product ) {
82 1         20 $app->log( "warning",
83             "sku $sku not found in POST /cart: $input" );
84 1         427 $app->session->write( shop_cart_error =>
85             { message => "Product not found with sku: $sku" } );
86 1         93 return $app->redirect('/');
87             }
88              
89 24 100       900 if ( defined $product->canonical_sku ) {
90              
91             # this is a variant so we need to add in variant info
92             # into $params if missing
93              
94 2         40 my $rset = $product->product_attributes->search(
95             {
96             'attribute.type' => 'variant',
97             },
98             {
99             prefetch => [
100             'attribute',
101             {
102             product_attribute_values => 'attribute_value'
103             }
104             ],
105             }
106             );
107 2         2930 while ( my $result = $rset->next ) {
108 4         35395 my $name = $result->attribute->name;
109              
110             # WTF! why do we get a resultset of pavs? Surely there
111             # should be only one related pav for pa?
112 4         188 my $value =
113             $result->product_attribute_values->first->attribute_value
114             ->value;
115              
116 4 50       2387 $params->set( $name => $value )
117             unless defined $params->get($name);
118             }
119             }
120              
121             # retrieve product attributes for possible variants
122 24         867 my $attr_ref = $product->attribute_iterator( hashref => 1 );
123 24         420395 my %user_input;
124              
125 24 100       103 if ( keys %$attr_ref ) {
126              
127 11         34 for my $name ( keys %$attr_ref ) {
128 22         131 $user_input{$name} = $params->get($name);
129             }
130              
131             $app->log(
132 11         113 "debug", "Attributes for $input: ",
133             $attr_ref, ", user input: ",
134             \%user_input
135             );
136 11         8155 my %match_info;
137              
138 11 100       69 unless ( $cart_product =
139             $product->find_variant( \%user_input, \%match_info ) )
140             {
141 2         302966 $app->log( "warning", "Variant not found for ",
142             $product->sku );
143              
144 2         1114 $app->session->write(
145             shop_cart_error => {
146             message => 'Variant not found.',
147             info => \%match_info
148             }
149             );
150              
151 2         175 return $app->redirect( $product->uri );
152             }
153             }
154             else {
155             # product without variants
156 13         26 $cart_product = $product;
157             }
158              
159 22 100       546129 my $quantity =
160             $params->get('quantity') ? $params->get('quantity') : 1;
161              
162             try {
163 22         1206 $cart->add(
164             {
165             dbic_product => $cart_product,
166             sku => $cart_product->sku,
167             quantity => $quantity
168             }
169             );
170             }
171             catch {
172 1         546 $app->log( "warning", "Cart add error: $_" );
173 1         638 push @errors, "Failed to add product to cart: $_";
174 22         349 };
175             }
176              
177             # add stuff useful for cart display
178 41         1498 my $values = {
179             cart_subtotal => $cart->subtotal,
180             cart_total => $cart->total,
181             cart => $cart->products,
182             };
183 41 100       56219 $values->{cart_error} = join( ". ", @errors )
184             if scalar @errors;
185              
186             # call before_cart_display route so template tokens
187             # can be injected
188 41         767 $app->execute_hook( 'plugin.interchange6.before_cart_display',
189             $values );
190              
191 41         27484 $app->template( $plugin->cart_template, $values );
192             }
193 1         8 }
194              
195             1;