PluginProbe
Pay with Vipps and MobilePay for WooCommerce / trunk
Pay with Vipps and MobilePay for WooCommerce vtrunk
6.2.0 6.1.10 6.1.9 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1.0 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 5.4.3 5.4.2 5.4.1 5.4.0 5.3.4 trunk 1.10.0 All 182 releases
woo-vipps / payment / VippsCheckoutShippingMethods.php

VippsCheckoutShippingMethods.php in Pay with Vipps and MobilePay for WooCommerce trunk, at payment/VippsCheckoutShippingMethods.php

560 lines 22.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 add_action( 'woocommerce_shipping_init', function () {
3 //add your shipping method to WooCommers list of Shipping methods
4 add_filter( 'woocommerce_shipping_methods', function ($methods) {
5 $vc_activated = get_option('woo_vipps_checkout_activated', false);
6 if (!$vc_activated) return $methods;
7
8 $gw = Vipps::instance()->gateway();
9 if (!$gw) return $methods;
10
11 $vc_enabled = $gw->get_option('vipps_checkout_enabled') === 'yes';
12 if (!$vc_enabled) return $methods;
13
14 // $methods['vipps_checkout'] = 'VippsCheckout_Shipping_Method';
15 if ("yes" == $gw->get_option('vcs_posten')) $methods['vipps_checkout_posten'] = 'VippsCheckout_Shipping_Method_Posten';
16 if ("yes" == $gw->get_option('vcs_postnord')) $methods['vipps_checkout_postnord'] = 'VippsCheckout_Shipping_Method_Postnord';
17 if ("yes" == $gw->get_option('vcs_helthjem')) $methods['vipps_checkout_helthjem'] = 'VippsCheckout_Shipping_Method_Helthjem';
18 if ("yes" == $gw->get_option('vcs_porterbuddy'))$methods['vipps_checkout_porterbuddy'] = 'VippsCheckout_Shipping_Method_Porterbuddy';
19 if ("yes" == $gw->get_option('vcs_posti')) $methods['vipps_checkout_posti'] = 'VippsCheckout_Shipping_Method_Posti';
20
21 return $methods;
22 });
23
24 $extended_classes = ['flat_rate', 'free_shipping', 'local_pickup'];
25 foreach($extended_classes as $key) {
26 add_filter('woocommerce_shipping_instance_form_fields_' . $key, array('VippsCheckout_Shipping_Method', 'add_description_field'));
27 }
28 }, 20);
29
30
31 /* This file is required_once'd early in woocommerce_shipping_init, only if the classes do not already exist. */
32
33 /* Abstract class used just to mark the special Vipps Checkout shipping methods. Don't instantiate this */
34 class VippsCheckout_Shipping_Method extends WC_Shipping_Method {
35 public $defaulttitle = "";
36 // Basic price, set by options
37 public $cost = 0;
38 // Some methods may support free shipping
39 public $supports_free_shipping = true;
40 // Porterbuddy (only) supports having the cost calculated in Vipps Checkout itself.
41 public $supports_dynamic_cost = false;
42 // Does not need to set "type"
43 public $no_type_needed = true;
44 public $default_delivery_method = '';
45
46 // True for the instances where this has been set to true
47 public $dynamic_cost = false;
48
49 public function preinit () {
50 }
51 public function init () {
52 }
53 public function postinit () {
54 }
55
56 public function instance_form_fields() {
57 return [];
58 }
59
60 // From WooCommerces' NumberUtil class
61 public static function round( $val, int $precision = 0, int $mode = PHP_ROUND_HALF_UP ) : float {
62 if ( ! is_numeric( $val ) ) {
63 $val = floatval( $val );
64 }
65 return round( $val, $precision, $mode );
66 }
67
68 public function free_shipping_form_fields() {
69 return array(
70 'title' => array(
71 'title' => __( 'Title', 'woocommerce' ),
72 'type' => 'text',
73 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
74 'default' => $this->method_title,
75 'desc_tip' => true,
76 ),
77 'requires' => array(
78 'title' => __( 'Free shipping requires...', 'woocommerce' ),
79 'type' => 'select',
80 'class' => 'wc-enhanced-select vipps_checkout_free_shipping',
81 'default' => '',
82 'options' => array(
83 '' => __( 'N/A', 'woocommerce' ),
84 'coupon' => __( 'A valid free shipping coupon', 'woocommerce' ),
85 'min_amount' => __( 'A minimum order amount', 'woocommerce' ),
86 'either' => __( 'A minimum order amount OR a coupon', 'woocommerce' ),
87 'both' => __( 'A minimum order amount AND a coupon', 'woocommerce' ),
88 ),
89 ),
90 'min_amount' => array(
91 'title' => __( 'Minimum order amount', 'woocommerce' ),
92 'type' => 'price',
93 'placeholder' => wc_format_localized_price( 0 ),
94 'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'woocommerce' ),
95 'default' => '0',
96 'class' => 'vipps_checkout_min_amount_field',
97 'desc_tip' => true,
98 ),
99 'ignore_discounts' => array(
100 'title' => __( 'Coupons discounts', 'woocommerce' ),
101 'label' => __( 'Apply minimum order rule before coupon discount', 'woocommerce' ),
102 'type' => 'checkbox',
103 'description' => __( 'If checked, free shipping would be available based on pre-discount order amount.', 'woocommerce' ),
104 'default' => 'no',
105 'class' => 'vipps_checkout_ignore_discounts_field',
106 'desc_tip' => true,
107 ),
108 );
109
110
111
112 }
113
114
115 // Add a description field to a standard shipping method
116 public static function add_description_field($form_fields) {
117 if (! array_key_exists('description', $form_fields)) {
118 $description = array('description' => array(
119 'title' => __( 'Description', 'woo-vipps' ),
120 'type' => 'text',
121 'description' => sprintf(__( 'Short description of shipping method used in %1$s', 'woo-vipps' ), Vipps::CheckoutName()),
122 'default' => "",
123 ));
124 $index = array_search('title', array_keys($form_fields));
125 if ($index === false) {
126 $form_fields['description'] = $description['description'];
127 } else {
128 $pos = $index+1;
129 $form_fields = array_merge(array_slice($form_fields, 0, $pos), $description, array_slice($form_fields, $pos));
130 }
131 }
132 return $form_fields;
133 }
134
135 // Instance setting, common for all submethods
136 public function init_form_fields() {
137 $this->instance_form_fields = array(
138 'title' => array(
139 'title' => __( 'Title', 'woo-vipps' ),
140 'type' => 'text',
141 'description' => __( 'Title to be display on site', 'woo-vipps' ),
142 'default' => $this->defaulttitle
143 ),
144
145 'description' => array(
146 'title' => __( 'Description', 'woo-vipps' ),
147 'type' => 'text',
148 'description' => __( 'Short description of shipping method', 'woo-vipps' ),
149 'default' => "",
150 'desc_tip'=>true
151 ));
152
153 if ($this->supports_dynamic_cost) {
154 $this->instance_form_fields['dynamic_cost'] = array(
155 'title' => __( 'Calculate cost in Checkout', 'woo-vipps' ),
156 'label' => __( 'Calculate costs in the Checkout window', 'woo-vipps' ),
157 'type' => 'checkbox',
158 'class' => 'vipps_checkout_dynamic_cost_field',
159 'description' => sprintf(__( 'If checked, cost of shipping will be calculated dynamically in the %1$s window', 'woo-vipps' ), Vipps::CheckoutName()),
160 'default' => 'no',
161 'desc_tip' => true,
162 );
163
164 }
165 $this->instance_form_fields['cost'] = array(
166 'title' => __( 'Cost', 'woo-vipps' ),
167 'type' => 'price',
168 'class' => 'vipps_checkout_cost_field',
169 'description' => __( 'Cost of shipping', 'woo-vipps' ),
170 'default' => 0,
171 'desc_tip'=>true
172 );
173 // Support pickup point/home delivery where appropriate
174 if (!empty($this->delivery_types)) {
175 $options = array();
176 if ($this->no_type_needed) {
177 $options[''] = __('No delivery method specified', 'woo-vipps');
178 }
179 foreach($this->delivery_types as $type) {
180 switch ($type) {
181 case 'MAILBOX':
182 $options[$type] = __('Deliver to customers\' mailbox', 'woo-vipps');
183 break;
184 case 'PICKUP_POINT':
185 $options[$type] = __('Allow user to choose pickup point', 'woo-vipps');
186 break;
187 case 'HOME_DELIVERY':
188 $options[$type] = __('Deliver to customers\' home address', 'woo-vipps');
189 break;
190 default:
191 // inconceivable!
192 }
193 }
194 $this->instance_form_fields['type'] = array(
195 'title' => __( 'Delivery method', 'woocommerce' ),
196 'type' => 'select',
197 'class' => 'wc-enhanced-select',
198 'description' => sprintf(__( 'If you are using %1$s, you can select extended delivery method options here. If you do, these methods will not appear in Express Checkout or the standard WooCommerce checkout page.', 'woo-vipps' ), Vipps::CheckoutName()),
199 'default' => $this->default_delivery_method,
200 'options' => $options,
201 'desc_tip' => true,
202 );
203 }
204
205 $this->instance_form_fields['tax_status'] = array(
206 'title' => __( 'Tax status', 'woocommerce' ),
207 'type' => 'select',
208 'class' => 'wc-enhanced-select',
209 'default' => 'taxable',
210 'options' => array(
211 'taxable' => __( 'Taxable', 'woocommerce' ),
212 'none' => _x( 'None', 'Tax status', 'woocommerce' ),
213 ),
214 );
215
216
217 // From subclasses
218 foreach($this->instance_form_fields() as $key=>$setting) {
219 $this->instance_form_fields[$key] = $setting;
220 }
221
222 if ($this->supports_free_shipping) {
223 $this->instance_form_fields = array_merge($this->instance_form_fields, $this->free_shipping_form_fields());
224 }
225
226 }
227
228
229 // True if the method contains extended options for Vipps Checkout
230 public function is_extended() {
231 $delivery = $this->get_option('type', false);
232 return ($delivery == "PICKUP_POINT");
233 }
234
235 public function __construct( $instance_id = 0 ) {
236 $this->instance_id = absint( $instance_id );
237
238 //add to shipping zones list
239 $this->supports = array( 'instance-settings', 'instance-settings-modal');
240
241 // Subclasses support shipping zones, parent does not. With this we could add a global
242 // settings page using the never-available parent method.
243 if (get_class($this) == "VippsCheckout_Shipping_Method") {
244 // nop
245 } else {
246 $this->supports[] = 'shipping-zones';
247 }
248
249
250 $this->preinit();
251 // Load the settings API
252 $this->init_form_fields();
253 $this->init_settings();
254
255 $this->title = $this->get_option( 'title' );
256 $this->tax_status = $this->get_option( 'tax_status' );
257 $this->dynamic_cost = $this->supports_dynamic_cost && ('yes' == $this->get_option('dynamic_cost'));
258
259 // Never enable parent method
260 if (get_class($this) == "VippsCheckout_Shipping_Method") {
261 $this->enabled = "no";
262 }
263
264 $this->init();
265 $this->postinit();
266
267 add_action( 'admin_footer', array( 'VippsCheckout_Shipping_Method', 'enqueue_admin_js' ), 10 ); // Priority needs to be higher than wc_print_js (25).
268
269 add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
270 }
271
272
273 public function free_shipping_ok($package) {
274 if (!$this->supports_free_shipping) return false;
275
276 $has_coupon = false;
277 $has_met_min_amount = false;
278
279 $requires = $this->get_option('requires', false);
280
281 if ( in_array( $requires , array( 'coupon', 'either', 'both' ), true ) ) {
282 $coupons = WC()->cart->get_coupons();
283 if ( $coupons ) {
284 foreach ( $coupons as $code => $coupon ) {
285 if ( $coupon->is_valid() && $coupon->get_free_shipping() ) {
286 $has_coupon = true;
287 break;
288 }
289 }
290 }
291 }
292
293 if ( in_array( $requires, array( 'min_amount', 'either', 'both' ), true ) ) {
294 $total = WC()->cart->get_displayed_subtotal();
295
296 if ( WC()->cart->display_prices_including_tax() ) {
297 $total = $total - WC()->cart->get_discount_tax();
298 }
299
300 if ( 'no' === $this->get_option('ignore_discounts')) {
301 $total = $total - WC()->cart->get_discount_total();
302 }
303
304 $total = static::round( $total, wc_get_price_decimals() );
305
306 if ( $total >= $this->get_option('min_amount',0) ) {
307 $has_met_min_amount = true;
308 }
309 }
310
311 switch ( $requires ) {
312 case 'min_amount':
313 $is_available = $has_met_min_amount;
314 break;
315 case 'coupon':
316 $is_available = $has_coupon;
317 break;
318 case 'both':
319 $is_available = $has_met_min_amount && $has_coupon;
320 break;
321 case 'either':
322 $is_available = $has_met_min_amount || $has_coupon;
323 break;
324 default:
325 $is_available = false;
326 break;
327 }
328
329 return $is_available;
330 }
331
332
333 public function get_cost($package) {
334
335 $cost = $this->get_option('cost');
336
337 if ($this->supports_dynamic_cost && $this->dynamic_cost ) {
338 $cost = 0;
339 }
340 if ($this->free_shipping_ok($package)) {
341 $cost = 0;
342 }
343
344 $cost = apply_filters('woo_vipps_vipps_checkout_shipping_cost', $cost, $this);
345 return $cost ?: 0;
346 }
347
348 // Add free shipping trigger etc?
349 public function calculate_shipping( $package = array()) {
350 $instance_settings = $this->instance_settings;
351 $meta = array();
352 $meta['brand'] = $this->brand;
353 $option = $this->get_option('type', false);
354 $description = $this->get_option('description', '');
355
356 if ($option) {
357 $meta['type'] = $option;
358 }
359
360 $cost = $this->get_cost($package);
361 if ($cost == 0 && $this->free_shipping_ok($package)) {
362 $meta['free_shipping'] = true;
363 } else {
364 unset($meta['free_shipping']);
365 }
366
367 $ratedata = array(
368 'id' => $this->get_rate_id(),
369 'label' => $this->get_option('title'),
370 'cost' => $cost,
371 'package' => $package,
372 'meta_data' => $meta,
373 );
374
375
376 $ratedata = apply_filters('woo_vipps_vipps_checkout_shipping_rate', $ratedata, $this);
377
378 $this->add_rate($ratedata);
379 }
380
381 public function is_enabled() {
382 $vc_activated = get_option('woo_vipps_checkout_activated', false);
383 return $vc_activated;
384 }
385
386 public function is_available($package) {
387
388 // Never show the parent method
389 if (get_class($this) == "VippsCheckout_Shipping_Method") {
390 return false;
391 }
392
393 // This handles zones etc as well as the basic filter
394 $ok = parent::is_available($package);
395
396 // We'll show all methods in Vipps Checkout or on the cart page, otherwise
397 // we'll not show the extended methods
398 $is_vipps_checkout = apply_filters('woo_vipps_is_vipps_checkout', false);
399 if ($is_vipps_checkout || is_cart()) {
400 $ok = true;
401 } else if ($this->is_extended()) {
402 $ok = false;
403 }
404
405 return apply_filters('vipps_checkout_shipping_available', $ok, $this, $package);
406 }
407
408
409 // Static so it gets loaded just once; must be loaded before 25. (See Free Shipping).
410 public static function enqueue_admin_js() {
411 wc_enqueue_js( "jQuery(document).ready(function () {
412
413 function vipps_checkout_hide_cost_for_dynamic_pricing (el) {
414 let form = jQuery( el ).closest( 'form' );
415 let costfield = jQuery( '.vipps_checkout_cost_field', form ).closest( 'tr' );
416 if (jQuery(el).is(':checked')) {
417 costfield.hide();
418 } else {
419 costfield.show();
420 }
421 }
422
423 jQuery( document.body ).on( 'change', '.vipps_checkout_dynamic_cost_field', function() {
424 vipps_checkout_hide_cost_for_dynamic_pricing( this );
425 });
426 jQuery( '.vipps_checkout_dynamic_cost_field' ).trigger( 'change' );
427 jQuery(document.body).on( 'wc_backbone_modal_loaded', function( evt, target ) {
428 if ( 'wc-modal-shipping-method-settings' === target ) {
429 vipps_checkout_hide_cost_for_dynamic_pricing(jQuery('#wc-backbone-modal-dialog .vipps_checkout_dynamic_cost_field', evt.currentTarget));
430 }
431 });
432
433
434 /* Support Free Shipping for Vipps Checkout methods */
435 function vipps_checkoutFreeShippingShowHideMinAmountField( el ) {
436 var form = jQuery( el ).closest( 'form' );
437 var minAmountField = jQuery( '.vipps_checkout_min_amount_field', form ).closest( 'tr' );
438 var ignoreDiscountField = jQuery( '.vipps_checkout_ignore_discounts_field', form ).closest( 'tr' );
439 if ( 'coupon' === jQuery( el ).val() || '' === jQuery( el ).val() ) {
440 minAmountField.hide();
441 ignoreDiscountField.hide();
442 } else {
443 minAmountField.show();
444 ignoreDiscountField.show();
445 }
446 }
447 jQuery( document.body ).on( 'change', '.vipps_checkout_free_shipping', function() {
448 vipps_checkoutFreeShippingShowHideMinAmountField( this );
449 });
450 jQuery( '.vipps_checkout_free_shipping' ).trigger( 'change' );
451 jQuery( document.body ).on( 'wc_backbone_modal_loaded', function( evt, target ) {
452 if ( 'wc-modal-shipping-method-settings' === target ) {
453 vipps_checkoutFreeShippingShowHideMinAmountField( jQuery( '#wc-backbone-modal-dialog .vipps_checkout_free_shipping', evt.currentTarget ) );
454 }
455 });
456
457 });");
458
459
460 }
461
462 }
463
464 class VippsCheckout_Shipping_Method_Posten extends VippsCheckout_Shipping_Method {
465 public $id = 'vipps_checkout_posten';
466 public $delivery_types = ['MAILBOX','PICKUP_POINT','HOME_DELIVERY'];
467 public $brand = "POSTEN";
468 public $no_type_needed = false;
469 public $default_delivery_method = "MAILBOX";
470
471 // Called by the parent constructor before loading settings
472 function preinit() {
473 $this->defaulttitle = __( 'Posten Norge', 'woo-vipps' );
474 $this->method_title = sprintf(__( '%1$s: %2$s', 'woo-vipps' ), Vipps::CheckoutName(), $this->defaulttitle);
475 $this->method_description = sprintf(__( 'Shipping method for %1$s only: %2$s', 'woo-vipps'), Vipps::CheckoutName(), $this->defaulttitle);
476 }
477
478 }
479
480 class VippsCheckout_Shipping_Method_Posti extends VippsCheckout_Shipping_Method {
481 public $id = 'vipps_checkout_posti';
482 public $delivery_types = ['PICKUP_POINT'];
483 public $brand = "POSTI";
484 public $no_type_needed = false;
485 public $default_delivery_method = "PICKUP_POINT";
486
487 // Called by the parent constructor before loading settings
488 function preinit() {
489 $this->defaulttitle = __( 'Posti', 'woo-vipps' );
490 $this->method_title = sprintf(__( '%1$s: %2$s', 'woo-vipps' ), Vipps::CheckoutName(), $this->defaulttitle);
491 $this->method_description = sprintf(__( 'Shipping method for %1$s only: %2$s', 'woo-vipps'), Vipps::CheckoutName(), $this->defaulttitle);
492 }
493 }
494
495 class VippsCheckout_Shipping_Method_Helthjem extends VippsCheckout_Shipping_Method {
496 public $id = 'vipps_checkout_helthjem';
497 public $delivery_types = ['HOME_DELIVERY', 'PICKUP_POINT'];
498 public $brand = "HELTHJEM";
499 public $no_type_needed = false;
500 public $default_delivery_method = 'HOME_DELIVERY';
501
502 // Only useable by Vipps Checkout
503 public function is_extended() {
504 return true;
505 }
506
507 // Called by the parent constructor before loading settings
508 function preinit() {
509 $this->defaulttitle = __( 'Helthjem', 'woo-vipps' );
510 $this->method_title = sprintf(__( '%1$s: %2$s', 'woo-vipps' ), Vipps::CheckoutName(), $this->defaulttitle);
511 $this->method_description = sprintf(__( 'Shipping method for %1$s only: %2$s', 'woo-vipps'), Vipps::CheckoutName(), $this->defaulttitle);
512 }
513 }
514
515
516 class VippsCheckout_Shipping_Method_Postnord extends VippsCheckout_Shipping_Method {
517 public $id = 'vipps_checkout_postnord';
518 public $delivery_types = ['PICKUP_POINT','HOME_DELIVERY'];
519 public $brand = "POSTNORD";
520 public $no_type_needed = true;
521 public $default_delivery_method = '';
522
523 // Called by the parent constructor before loading settings
524 function preinit() {
525 $this->defaulttitle = __( 'Postnord', 'woo-vipps' );
526 $this->method_title = sprintf(__( '%1$s: %2$s', 'woo-vipps' ), Vipps::CheckoutName(), $this->defaulttitle);
527 $this->method_description = sprintf(__( 'Shipping method for %1$s only: %2$s', 'woo-vipps'), Vipps::CheckoutName(), $this->defaulttitle);
528 }
529 }
530
531 class VippsCheckout_Shipping_Method_Porterbuddy extends VippsCheckout_Shipping_Method {
532 public $id = 'vipps_checkout_porterbuddy';
533 public $delivery_types = ['HOME_DELIVERY'];
534 public $brand = "PORTERBUDDY";
535 public $supports_free_shipping = true;
536 public $supports_dynamic_cost = true;
537 public $no_type_needed = false;
538 public $default_delivery_method = 'HOME_DELIVERY';
539
540 // Only useable by Vipps Checkout
541 public function is_extended() {
542 return true;
543 }
544
545 // Called by the parent constructor before loading settings
546 function preinit() {
547 $this->defaulttitle = __( 'Porterbuddy', 'woo-vipps' );
548 $this->method_title = sprintf(__( '%1$s: %2$s', 'woo-vipps' ), Vipps::CheckoutName(), $this->defaulttitle);
549 $this->method_description = sprintf(__( 'Shipping method for %1$s only: %2$s', 'woo-vipps'), Vipps::CheckoutName(), $this->defaulttitle);
550 }
551
552
553
554
555
556 }
557
558
559
560