PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 1.4.1
Subscriptions for WooCommerce with Stripe Recurring Payments v1.4.1
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.4.1, at includes/Frontend/Cart.php

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