PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 1.3.0
Subscriptions for WooCommerce with Stripe Recurring Payments v1.3.0
2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 All 61 releases
subscription / includes / Frontend / Cart.php

Cart.php in Subscriptions for WooCommerce with Stripe Recurring Payments 1.3.0, at includes/Frontend/Cart.php

463 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SpringDevs\Subscription\Frontend;
4
5 use SpringDevs\Subscription\Illuminate\Helper;
6 use Automattic\WooCommerce\Blocks\Package;
7 use Automattic\WooCommerce\Blocks\Domain\Services\ExtendRestApi;
8 use Automattic\WooCommerce\StoreApi\Schemas\V1\CartItemSchema;
9 use Automattic\WooCommerce\StoreApi\Schemas\V1\CartSchema;
10
11 /**
12 * Cart class
13 */
14 class Cart {
15
16 /**
17 * Initialize the class
18 */
19 public function __construct() {
20 add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_to_cart_item_data' ), 10, 2 );
21 add_action( 'woocommerce_blocks_loaded', array( $this, 'define_custom_schema' ) );
22 add_filter( 'woocommerce_cart_item_price', array( $this, 'change_price_cart_html' ), 10, 2 );
23 add_filter( 'woocommerce_cart_item_subtotal', array( $this, 'change_price_cart_html' ), 10, 2 );
24 add_action( 'woocommerce_cart_totals_after_order_total', array( $this, 'add_rows_order_total' ) );
25 add_action( 'woocommerce_review_order_after_order_total', array( $this, 'add_rows_order_total' ) );
26 add_filter( 'woocommerce_add_cart_item_data', array( $this, 'set_renew_status' ), 10, 2 );
27 add_action( 'woocommerce_check_cart_items', array( $this, 'check_cart_items' ) );
28 add_filter( 'woocommerce_get_item_data', array( $this, 'set_line_item_meta' ), 10, 2 );
29 add_action( 'woocommerce_before_calculate_totals', array( $this, 'add_calculation_price_filter' ) );
30 add_action( 'woocommerce_calculate_totals', array( $this, 'remove_calculation_price_filter' ) );
31 add_action( 'woocommerce_after_calculate_totals', array( $this, 'remove_calculation_price_filter' ) );
32 add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'add_to_cart_validation' ), 10, 2 );
33 }
34
35 /**
36 * Add to cart validation.
37 *
38 * @param bool $passed Passed ?.
39 * @param int $product_id Product Id.
40 *
41 * @return bool
42 */
43 public function add_to_cart_validation( $passed, $product_id ) {
44 $cart_items = WC()->cart->cart_contents;
45 $error_notice = null;
46 $failed = false;
47 $product = wc_get_product( $product_id );
48 $enabled = $product->get_meta( '_subscrpt_enabled' );
49 foreach ( $cart_items as $key => $cart_item ) {
50 if ( isset( $cart_item['subscription'] ) ) {
51 if ( $enabled ) {
52 $error_notice = __( 'Currently You have an another Subscriptional product on cart !!', 'sdevs_subscrpt' );
53 } else {
54 $error_notice = __( 'Currently You have Subscriptional product in a cart !!', 'sdevs_subscrpt' );
55 }
56 $failed = true;
57 } elseif ( $enabled ) {
58 $failed = true;
59 $error_notice = __( 'Your cart isn\'t empty !!', 'sdevs_subscrpt' );
60 }
61 }
62
63 if ( $failed ) {
64 wc_add_notice( $error_notice, 'error' );
65 return false;
66 }
67
68 return $passed;
69 }
70
71 /**
72 * Add filter before cart calculation.
73 *
74 * @return void
75 */
76 public function add_calculation_price_filter() {
77 add_filter( 'woocommerce_product_get_price', array( $this, 'set_prices_for_calculation' ), 100, 2 );
78 }
79
80 /**
81 * Return 0 if product has trial.
82 *
83 * @param float $price Price.
84 * @param \WC_Product $product Product object.
85 *
86 * @return float
87 */
88 public function set_prices_for_calculation( $price, $product ) {
89 if ( $product->get_meta( '_subscrpt_enabled' ) && $product->is_type( 'simple' ) ) {
90 $trial_time_per = $product->get_meta( '_subscrpt_trial_timing_per' );
91 if ( ! empty( $trial_time_per ) && $trial_time_per > 0 && Helper::check_trial( $product->get_id() ) ) {
92 return 0;
93 }
94 }
95 return $price;
96 }
97
98 /**
99 * Remove filter after calculate calculation.
100 *
101 * @return void
102 */
103 public function remove_calculation_price_filter() {
104 remove_filter( 'woocommerce_product_get_price', array( $this, 'set_prices_for_calculation' ), 100 );
105 }
106
107 /**
108 * Set line item for display meta details.
109 *
110 * @param array $cart_item_data Cart Item Data.
111 * @param array $cart_item Cart Item.
112 *
113 * @return array
114 */
115 public function set_line_item_meta( $cart_item_data, $cart_item ) {
116 if ( isset( $cart_item['subscription'] ) ) {
117 if ( $cart_item['subscription']['trial'] ) {
118 $cart_item_data[] = array(
119 'key' => __( 'Free Trial', 'sdevs_subscrpt' ),
120 'value' => $cart_item['subscription']['trial'],
121 'hidden' => true,
122 '__experimental_woocommerce_blocks_hidden' => false,
123 );
124 }
125 }
126
127 return $cart_item_data;
128 }
129
130 /**
131 * Check cart items if it's valid or not?
132 *
133 * @return void
134 */
135 public function check_cart_items() {
136 if ( subscrpt_pro_activated() ) {
137 return;
138 }
139 $cart_items = WC()->cart->cart_contents;
140 if ( is_array( $cart_items ) ) {
141 foreach ( $cart_items as $key => $value ) {
142 /**
143 * Product Object.
144 *
145 * @var \WC_Product $product
146 */
147 $product = $value['data'];
148 if ( isset( $value['subscription'] ) ) {
149 if ( $product->is_type( 'simple' ) ) {
150 $product_trial_per = $product->get_meta( '_subscrpt_trial_timing_per' );
151 $trial = null;
152 if ( Helper::check_trial( $product->get_id() ) ) {
153 $trial = ( $product_trial_per ? $product_trial_per . ' ' . Helper::get_typos( $product_trial_per ?? 1, $product->get_meta( '_subscrpt_trial_timing_option' ) )
154 : null );
155 }
156 if ( Helper::get_typos( 1, $product->get_meta( '_subscrpt_timing_option' ) ) !== $value['subscription']['type'] || $trial !== $value['subscription']['trial'] ) {
157 // remove the item.
158 wc_add_notice( __( 'An item which is no longer available was removed from your cart.', 'sdevs_subscrpt' ), 'error' );
159 WC()->cart->remove_cart_item( $key );
160 }
161 } else {
162 // remove the item.
163 wc_add_notice( __( 'An item which is no longer available was removed from your cart.', 'sdevs_subscrpt' ), 'error' );
164 WC()->cart->remove_cart_item( $key );
165 }
166 } elseif ( $product->get_meta( '_subscrpt_enabled' ) ) {
167 // remove the item.
168 wc_add_notice( __( 'An item which is no longer available was removed from your cart.', 'sdevs_subscrpt' ), 'error' );
169 WC()->cart->remove_cart_item( $key );
170 }
171 }
172 }
173 }
174
175 /**
176 * Define custom schema.
177 *
178 * @return void
179 */
180 public function define_custom_schema() {
181 $this->register_endpoint_data(
182 array(
183 'endpoint' => CartItemSchema::IDENTIFIER,
184 'namespace' => 'sdevs_subscription',
185 'data_callback' => array( $this, 'extend_cart_item_data' ),
186 'schema_callback' => array( $this, 'extend_cart_item_schema' ),
187 'schema_type' => ARRAY_A,
188 )
189 );
190 $this->register_endpoint_data(
191 array(
192 'endpoint' => CartSchema::IDENTIFIER,
193 'namespace' => 'sdevs_subscription',
194 'data_callback' => array( $this, 'extend_cart_data' ),
195 'schema_callback' => array( $this, 'extend_cart_schema' ),
196 'schema_type' => ARRAY_A,
197 )
198 );
199 }
200
201 /**
202 * Register subscription product schema into cart/items endpoint.
203 *
204 * @return array Registered schema.
205 */
206 public function extend_cart_schema() {
207 return array(
208 'recurring_totals' => array(
209 'description' => __( 'List of recurring totals in cart.', 'sdevs_subscrpt' ),
210 'type' => 'array',
211 'readonly' => true,
212 'recurring_totals' => array(
213 'price' => array(
214 'description' => __( 'price of the subscription.', 'sdevs_subscrpt' ),
215 'type' => array( 'string' ),
216 'readonly' => true,
217 ),
218 'time' => array(
219 'description' => __( 'time of the subscription.', 'sdevs_subscrpt' ),
220 'type' => array( 'number' ),
221 'readonly' => true,
222 ),
223 'type' => array(
224 'description' => __( 'type of the subscription.', 'sdevs_subscrpt' ),
225 'type' => array( 'string' ),
226 'readonly' => true,
227 ),
228 'description' => array(
229 'description' => __( 'price of the subscription description.', 'sdevs_subscrpt' ),
230 'type' => array( 'string' ),
231 'readonly' => true,
232 ),
233 'can_user_cancel' => array(
234 'description' => __( 'Can User Cancel?', 'sdevs_subscrpt' ),
235 'type' => array( 'string' ),
236 'readonly' => true,
237 ),
238 ),
239 ),
240 );
241 }
242
243 /**
244 * Register subscription product data into cart/items endpoint.
245 *
246 * @return array $item_data Registered data or empty array if condition is not satisfied.
247 */
248 public function extend_cart_data() {
249 $cart_items = WC()->cart->cart_contents;
250 $recurrings = array();
251 if ( $cart_items ) {
252 foreach ( $cart_items as $cart_item ) {
253 if ( isset( $cart_item['subscription'] ) && $cart_item['subscription']['type'] ) {
254 $cart_subscription = $cart_item['subscription'];
255 $start_date = Helper::start_date( $cart_subscription['trial'] );
256 $next_date = Helper::next_date(
257 ( $cart_subscription['time'] ?? 1 ) . ' ' . $cart_subscription['type'],
258 $cart_subscription['trial']
259 );
260
261 $recurrings[] = apply_filters(
262 'subscrpt_cart_recurring_data',
263 array(
264 'price' => ( $cart_item['subscription']['per_cost'] * $cart_item['quantity'] ) * 100,
265 'time' => $cart_subscription['time'],
266 'type' => $cart_subscription['type'],
267 'description' => empty( $cart_subscription['trial'] ) ? 'Next billing on: ' . $next_date : 'First billing on: ' . $start_date,
268 'can_user_cancel' => $cart_item['data']->get_meta( '_subscrpt_user_cancel' ),
269 ),
270 $cart_item
271 );
272 }
273 }
274 }
275 return $recurrings;
276 }
277
278 /**
279 * Register subscription product schema into cart/items endpoint.
280 *
281 * @return array Registered schema.
282 */
283 public function extend_cart_item_schema() {
284 return array(
285 'time' => array(
286 'description' => __( 'time of the subscription type.', 'sdevs_subscrpt' ),
287 'type' => array( 'number', 'null' ),
288 'readonly' => true,
289 ),
290 'type' => array(
291 'description' => __( 'the subscription type.', 'sdevs_subscrpt' ),
292 'type' => array( 'string', 'null' ),
293 'readonly' => true,
294 ),
295 'trial' => array(
296 'description' => __( 'the subscription trial.', 'sdevs_subscrpt' ),
297 'type' => array( 'string', 'null' ),
298 'readonly' => true,
299 ),
300 'signup_fee' => array(
301 'description' => __( 'Signup Fee amount.', 'sdevs_subscrpt' ),
302 'type' => array( 'string', 'null' ),
303 'readonly' => true,
304 ),
305 'cost' => array(
306 'description' => __( 'Recurring amount.', 'sdevs_subscrpt' ),
307 'type' => array( 'string', 'null' ),
308 'readonly' => true,
309 ),
310 );
311 }
312
313 /**
314 * Register subscription product data into cart/items endpoint.
315 *
316 * @param array $cart_item Current cart item data.
317 *
318 * @return array $item_data Registered data or empty array if condition is not satisfied.
319 */
320 public function extend_cart_item_data( $cart_item ) {
321 $item_data = array(
322 'time' => null,
323 'type' => null,
324 'trial' => null,
325 'signup_fee' => null,
326 'cost' => null,
327 );
328 if ( isset( $cart_item['subscription'] ) ) {
329 $item_data = $cart_item['subscription'];
330 unset( $item_data['per_cost'] );
331 $item_data['cost'] = $cart_item['subscription']['per_cost'] * $cart_item['quantity'];
332 }
333 if ( ! subscrpt_pro_activated() ) {
334 $item_data['time'] = null;
335 $item_data['signup_fee'] = null;
336 }
337
338 return $item_data;
339 }
340
341 /**
342 * Add product meta on cart item.
343 *
344 * @param array $cart_item_data cart_item_data.
345 * @param int $product_id Product ID.
346 *
347 * @return array
348 */
349 public function add_to_cart_item_data( $cart_item_data, $product_id ) {
350 $product = wc_get_product( $product_id );
351 if ( ! $product->is_type( 'simple' ) ) {
352 return $cart_item_data;
353 }
354 $enabled = $product->get_meta( '_subscrpt_enabled' );
355 if ( $enabled ) :
356 $price_type = $product->get_meta( '_subscrpt_timing_option' );
357 $type = Helper::get_typos( 1, $price_type );
358 $subscription_data = array();
359 $subscription_data['time'] = null;
360 $subscription_data['type'] = $type;
361 $subscription_data['trial'] = null;
362 $trial_timing_per = $product->get_meta( '_subscrpt_trial_timing_per' );
363 if ( $trial_timing_per && Helper::check_trial( $product->get_id() ) ) {
364 $subscription_data['trial'] = $trial_timing_per . ' ' . Helper::get_typos( $trial_timing_per, $product->get_meta( '_subscrpt_trial_timing_option' ) );
365 }
366 $subscription_data['signup_fee'] = null;
367 $subscription_data['per_cost'] = $product->get_price();
368 $cart_item_data['subscription'] = apply_filters( 'subscrpt_block_simple_cart_item_data', $subscription_data, $product, $cart_item_data );
369 endif;
370 return $cart_item_data;
371 }
372
373 /**
374 * Register endpoint data with the API.
375 *
376 * @param array $args Endpoint data to register.
377 */
378 protected function register_endpoint_data( $args ) {
379 if ( function_exists( 'woocommerce_store_api_register_endpoint_data' ) ) {
380 woocommerce_store_api_register_endpoint_data( $args );
381 } else {
382 Package::container()->get( ExtendRestApi::class )->register_endpoint_data( $args );
383 }
384 }
385
386 /**
387 * Display formatted price on cart.
388 *
389 * @param string $price price.
390 * @param array $cart_item cart item.
391 *
392 * @return string
393 */
394 public function change_price_cart_html( $price, $cart_item ) {
395 $product = wc_get_product( $cart_item['product_id'] );
396 if ( ! $product->is_type( 'simple' ) ) {
397 return $price;
398 }
399
400 $enabled = $product->get_meta( '_subscrpt_enabled' );
401 if ( $enabled ) :
402 $has_trial = Helper::check_trial( $product->get_id() );
403 $trial = null;
404 $meta_trial_time = $product->get_meta( '_subscrpt_trial_timing_per' );
405 if ( ! empty( $meta_trial_time ) && $meta_trial_time > 0 && $has_trial ) {
406 $trial = '<br/><small> + Get ' . $meta_trial_time . ' ' . Helper::get_typos( $meta_trial_time, $product->get_meta( '_subscrpt_trial_timing_option' ) ) . ' free trial!</small>';
407 }
408 $timing_option = $product->get_meta( '_subscrpt_timing_option' );
409 $type = Helper::get_typos( 1, $timing_option );
410
411 return apply_filters( 'subscrpt_simple_price_html', ( $price . '/ ' . $type . $trial ), $product, $price, $timing_option, $trial );
412 else :
413 return $price;
414 endif;
415 }
416
417 /**
418 * Display "Recurring totals" on cart
419 *
420 * @return void
421 */
422 public function add_rows_order_total() {
423 $cart_items = WC()->cart->cart_contents;
424 $recurrs = Helper::get_recurrs_for_cart( $cart_items );
425 if ( 0 === count( $recurrs ) ) {
426 return;
427 }
428 ?>
429 <tr class="recurring-total">
430 <th><?php esc_html_e( 'Recurring totals', 'sdevs_subscrpt' ); ?></th>
431 <td data-title="<?php esc_attr_e( 'Recurring totals', 'sdevs_subscrpt' ); ?>">
432 <?php foreach ( $recurrs as $recurr ) : ?>
433 <p>
434 <span><?php echo wp_kses_post( $recurr['price_html'] ); ?></span><br />
435 <small><?php echo esc_html_e( ( $recurr['trial_status'] ? 'First billing on' : 'Next billing on' ), 'sdevs_subscrpt' ); ?>: <?php echo esc_html( $recurr['trial_status'] ? $recurr['start_date'] : $recurr['next_date'] ); ?></small>
436 <?php if ( 'yes' === $recurr['can_user_cancel'] ) : ?>
437 <br>
438 <small><?php echo esc_html_e( 'You can cancel subscription at any time!', 'sdevs_subscrpt' ); ?></small>
439 <?php endif; ?>
440 </p>
441 <?php endforeach; ?>
442 </td>
443 </tr>
444 <?php
445 }
446
447 /**
448 * Add renew status.
449 *
450 * @param array $cart_item_data cart_item_data.
451 * @param int $product_id Product ID.
452 *
453 * @return array
454 */
455 public function set_renew_status( $cart_item_data, $product_id ) {
456 $expired = Helper::subscription_exists( $product_id, 'expired' );
457 if ( $expired ) {
458 $cart_item_data['renew_subscrpt'] = true;
459 }
460 return $cart_item_data;
461 }
462 }
463