Version Description
- FEATURE: BOGO On all matching products
- FIX: Changed WooCommerce detection method for better Multi Site support
- FIX: Free products: Fixed an inconsistency that could cause a loop on removal/adding of free variant products
- TWEAK: Free products: Hooking before_calculate_totals for most cases but also on woocommerce_applied_coupon, which is required when one coupon is replaced by another
- INTERNAL: Check if classes already exist before creating them
Download this release
Release Info
Developer | josk79 |
Plugin | WooCommerce Extended Coupon Features |
Version | 2.2.5 |
Comparing to | |
See all releases |
Code changes from version 2.2.4 to 2.2.5
- includes/wjecf-autocoupon.php +16 -10
- includes/wjecf-coupon-extensions.php +58 -16
- readme.txt +8 -1
- woocommerce-jos-autocoupon.php +19 -7
includes/wjecf-autocoupon.php
CHANGED
@@ -1,13 +1,17 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
private $_autocoupon_codes = null;
|
6 |
|
7 |
private $_user_emails = null;
|
8 |
|
9 |
-
private $_check_already_performed = false;
|
10 |
-
|
11 |
protected $_executed_coupon_by_url = false;
|
12 |
|
13 |
public function __construct() {
|
@@ -23,8 +27,8 @@ class WC_Jos_AutoCoupon_Controller{
|
|
23 |
add_action( 'admin_init', array( &$this, 'admin_init' ) );
|
24 |
|
25 |
//Frontend hooks - logic
|
26 |
-
add_action( 'woocommerce_after_calculate_totals', array( &$this, 'update_matched_autocoupons' )
|
27 |
-
add_action( 'woocommerce_check_cart_items', array( &$this, 'update_matched_autocoupons' ) , 0 ); //Remove coupon before WC does it and shows a message
|
28 |
//Last check for coupons with restricted_emails
|
29 |
add_action( 'woocommerce_checkout_update_order_review', array( $this, 'fetch_billing_email' ), 10 ); // AJAX One page checkout
|
30 |
|
@@ -170,18 +174,21 @@ class WC_Jos_AutoCoupon_Controller{
|
|
170 |
return $originaltext;
|
171 |
}
|
172 |
}
|
|
|
|
|
|
|
173 |
|
174 |
/**
|
175 |
* Apply matched autocoupons and remove unmatched autocoupons.
|
176 |
* @return void
|
177 |
*/
|
178 |
function update_matched_autocoupons() {
|
179 |
-
if ( $this->
|
180 |
-
|
181 |
return;
|
182 |
}
|
183 |
-
$this->_check_already_performed = true;
|
184 |
|
|
|
185 |
$calc_needed = $this->remove_unmatched_autocoupons();
|
186 |
foreach ( $this->get_all_auto_coupons() as $coupon_code ) {
|
187 |
if ( ! WC()->cart->has_discount( $coupon_code ) ) {
|
@@ -445,7 +452,6 @@ class WC_Jos_AutoCoupon_Controller{
|
|
445 |
|
446 |
//FOR DEBUGGING ONLY
|
447 |
private function log ( $string ) {
|
448 |
-
error_log($string);
|
449 |
-
// file_put_contents ( "/lamp/www/logfile.log", date("Y-m-d | h:i:sa") . " " . current_filter() . ": " . $string . "\n" , FILE_APPEND );
|
450 |
}
|
451 |
}
|
1 |
<?php
|
2 |
|
3 |
+
defined('ABSPATH') or die();
|
4 |
+
|
5 |
+
if ( class_exists('WC_Jos_AutoCoupon_Controller') ) {
|
6 |
+
return;
|
7 |
+
}
|
8 |
+
|
9 |
+
class WC_Jos_AutoCoupon_Controller {
|
10 |
|
11 |
private $_autocoupon_codes = null;
|
12 |
|
13 |
private $_user_emails = null;
|
14 |
|
|
|
|
|
15 |
protected $_executed_coupon_by_url = false;
|
16 |
|
17 |
public function __construct() {
|
27 |
add_action( 'admin_init', array( &$this, 'admin_init' ) );
|
28 |
|
29 |
//Frontend hooks - logic
|
30 |
+
add_action( 'woocommerce_after_calculate_totals', array( &$this, 'update_matched_autocoupons' ) );
|
31 |
+
add_action( 'woocommerce_check_cart_items', array( &$this, 'update_matched_autocoupons' ) , 0 ); //Remove coupon before WC does it and shows a message
|
32 |
//Last check for coupons with restricted_emails
|
33 |
add_action( 'woocommerce_checkout_update_order_review', array( $this, 'fetch_billing_email' ), 10 ); // AJAX One page checkout
|
34 |
|
174 |
return $originaltext;
|
175 |
}
|
176 |
}
|
177 |
+
|
178 |
+
//Infinite loop protection
|
179 |
+
private $_update_matched_autocoupons_count = 0;
|
180 |
|
181 |
/**
|
182 |
* Apply matched autocoupons and remove unmatched autocoupons.
|
183 |
* @return void
|
184 |
*/
|
185 |
function update_matched_autocoupons() {
|
186 |
+
if ( $this->_update_matched_autocoupons_count++ > 20 ) {
|
187 |
+
$this->log ( 'update_matched_autocoupons counter reached limit 20' );
|
188 |
return;
|
189 |
}
|
|
|
190 |
|
191 |
+
//$this->log ( 'update_matched_autocoupons' );
|
192 |
$calc_needed = $this->remove_unmatched_autocoupons();
|
193 |
foreach ( $this->get_all_auto_coupons() as $coupon_code ) {
|
194 |
if ( ! WC()->cart->has_discount( $coupon_code ) ) {
|
452 |
|
453 |
//FOR DEBUGGING ONLY
|
454 |
private function log ( $string ) {
|
455 |
+
error_log( date("Y-m-d | h:i:sa") . ": " . get_class( $this ) . ": " . $string );
|
|
|
456 |
}
|
457 |
}
|
includes/wjecf-coupon-extensions.php
CHANGED
@@ -1,11 +1,28 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
defined('ABSPATH') or die();
|
5 |
|
|
|
|
|
|
|
|
|
6 |
class WC_Jos_Extended_Coupon_Features_Controller {
|
7 |
private $options = false;
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
public function __construct() {
|
11 |
add_action('init', array( &$this, 'controller_init' ));
|
@@ -34,33 +51,44 @@ class WC_Jos_Extended_Coupon_Features_Controller {
|
|
34 |
}
|
35 |
}
|
36 |
|
37 |
-
private $wc_version = null;
|
38 |
/**
|
39 |
* Check whether WooCommerce version is greater or equal than $req_version
|
40 |
* @param string @req_version The version to compare to
|
41 |
* @return bool true if WooCommerce is at least the given version
|
42 |
*/
|
43 |
-
public function check_woocommerce_version( $req_version ) {
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
// If get_plugins() isn't available, require it
|
46 |
-
if ( ! function_exists( 'get_plugins' ) )
|
47 |
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
|
|
48 |
|
49 |
-
|
50 |
$plugin_folder = get_plugins( '/woocommerce' );
|
51 |
$plugin_file = 'woocommerce.php';
|
52 |
|
53 |
// If the plugin version number is set, return it
|
54 |
if ( isset( $plugin_folder[$plugin_file]['Version'] ) ) {
|
55 |
-
|
|
|
|
|
56 |
}
|
57 |
-
}
|
58 |
-
if ($this->wc_version === false) {
|
59 |
-
return false;
|
60 |
-
}
|
61 |
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
64 |
|
65 |
//Upgrade options on version change
|
66 |
public function auto_upgrade_options() {
|
@@ -663,7 +691,7 @@ class WC_Jos_Extended_Coupon_Features_Controller {
|
|
663 |
|
664 |
//Test if coupon is valid for the product
|
665 |
// (this function is used to count the quantity of matching products)
|
666 |
-
|
667 |
//Ugly hack: $coupon->is_valid_for_product only works for these types
|
668 |
$original_discount_type = $coupon->discount_type;
|
669 |
if ( ! $this->coupon_is_type( $coupon, array( 'fixed_product', 'percent_product' ) ) ) {
|
@@ -677,14 +705,28 @@ class WC_Jos_Extended_Coupon_Features_Controller {
|
|
677 |
|
678 |
|
679 |
|
680 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
681 |
|
682 |
/**
|
683 |
* Get a WC_Coupon object
|
684 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
685 |
* @return WC_Coupon The coupon object
|
686 |
*/
|
687 |
-
|
688 |
if ( ! ( $coupon instanceof WC_Coupon ) ) {
|
689 |
$coupon = new WC_Coupon( $coupon );
|
690 |
}
|
1 |
<?php
|
2 |
|
|
|
3 |
defined('ABSPATH') or die();
|
4 |
|
5 |
+
if ( class_exists('WC_Jos_Extended_Coupon_Features_Controller') ) {
|
6 |
+
return;
|
7 |
+
}
|
8 |
+
|
9 |
class WC_Jos_Extended_Coupon_Features_Controller {
|
10 |
private $options = false;
|
11 |
|
12 |
+
/**
|
13 |
+
* Singleton Instance
|
14 |
+
*
|
15 |
+
* @static
|
16 |
+
* @return Singleton Instance
|
17 |
+
*/
|
18 |
+
public static function instance() {
|
19 |
+
if ( is_null( self::$_instance ) ) {
|
20 |
+
self::$_instance = new self();
|
21 |
+
}
|
22 |
+
return self::$_instance;
|
23 |
+
}
|
24 |
+
protected static $_instance = null;
|
25 |
+
|
26 |
|
27 |
public function __construct() {
|
28 |
add_action('init', array( &$this, 'controller_init' ));
|
51 |
}
|
52 |
}
|
53 |
|
|
|
54 |
/**
|
55 |
* Check whether WooCommerce version is greater or equal than $req_version
|
56 |
* @param string @req_version The version to compare to
|
57 |
* @return bool true if WooCommerce is at least the given version
|
58 |
*/
|
59 |
+
public static function check_woocommerce_version( $req_version ) {
|
60 |
+
return version_compare( self::get_woocommerce_version(), $req_version, '>=' );
|
61 |
+
}
|
62 |
+
|
63 |
+
private static $wc_version = null;
|
64 |
+
/**
|
65 |
+
* Get the WooCommerce version number
|
66 |
+
* @return string|bool WC Version number or false if WC not detected
|
67 |
+
*/
|
68 |
+
public static function get_woocommerce_version() {
|
69 |
+
if (self::$wc_version === null) {
|
70 |
// If get_plugins() isn't available, require it
|
71 |
+
if ( ! function_exists( 'get_plugins' ) ) {
|
72 |
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
73 |
+
}
|
74 |
|
75 |
+
// Create the plugins folder and file variables
|
76 |
$plugin_folder = get_plugins( '/woocommerce' );
|
77 |
$plugin_file = 'woocommerce.php';
|
78 |
|
79 |
// If the plugin version number is set, return it
|
80 |
if ( isset( $plugin_folder[$plugin_file]['Version'] ) ) {
|
81 |
+
self::$wc_version = $plugin_folder[$plugin_file]['Version'];
|
82 |
+
} else {
|
83 |
+
self::$wc_version = false; // Not found
|
84 |
}
|
|
|
|
|
|
|
|
|
85 |
|
86 |
+
//echo "<pre>";var_dump( get_site_option( 'active_sitewide_plugins' ) );die();
|
87 |
+
//echo "<pre>";var_dump( get_plugins() );die();
|
88 |
+
//die(self::$wc_version);
|
89 |
+
}
|
90 |
+
return self::$wc_version;
|
91 |
+
}
|
92 |
|
93 |
//Upgrade options on version change
|
94 |
public function auto_upgrade_options() {
|
691 |
|
692 |
//Test if coupon is valid for the product
|
693 |
// (this function is used to count the quantity of matching products)
|
694 |
+
public function coupon_is_valid_for_product( $coupon, $product, $values = array() ) {
|
695 |
//Ugly hack: $coupon->is_valid_for_product only works for these types
|
696 |
$original_discount_type = $coupon->discount_type;
|
697 |
if ( ! $this->coupon_is_type( $coupon, array( 'fixed_product', 'percent_product' ) ) ) {
|
705 |
|
706 |
|
707 |
|
708 |
+
// =====================
|
709 |
+
|
710 |
+
/**
|
711 |
+
* Retrieve the id of the product or the variation id if it's a variant.
|
712 |
+
* @Returns int|bool The variation or product id. False if not a valid product
|
713 |
+
*/
|
714 |
+
public function get_product_or_variation_id( $product ) {
|
715 |
+
if ( is_a( $product, 'WC_Product_Variation' ) ) {
|
716 |
+
return $product->variation_id;
|
717 |
+
} elseif ( is_a( $product, 'WC_Product' ) ) {
|
718 |
+
return $product->id;
|
719 |
+
} else {
|
720 |
+
return false;
|
721 |
+
}
|
722 |
+
}
|
723 |
|
724 |
/**
|
725 |
* Get a WC_Coupon object
|
726 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
727 |
* @return WC_Coupon The coupon object
|
728 |
*/
|
729 |
+
public function get_coupon( $coupon ) {
|
730 |
if ( ! ( $coupon instanceof WC_Coupon ) ) {
|
731 |
$coupon = new WC_Coupon( $coupon );
|
732 |
}
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5T9XQ
|
|
4 |
Tags: woocommerce, coupons, discount
|
5 |
Requires at least: 4.0.0
|
6 |
Tested up to: 4.3.1
|
7 |
-
Stable tag: 2.2.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -100,6 +100,13 @@ Sure! [This](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5T9XQ
|
|
100 |
4. Additionals restrictions based on shipping or payment method or the customer
|
101 |
|
102 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
= 2.2.4 =
|
104 |
* FEATURE: Online documentation added
|
105 |
* FEATURE: Use AND-operator for the selected categories (default is OR)
|
4 |
Tags: woocommerce, coupons, discount
|
5 |
Requires at least: 4.0.0
|
6 |
Tested up to: 4.3.1
|
7 |
+
Stable tag: 2.2.5
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
100 |
4. Additionals restrictions based on shipping or payment method or the customer
|
101 |
|
102 |
== Changelog ==
|
103 |
+
= 2.2.5 =
|
104 |
+
* FEATURE: BOGO On all matching products
|
105 |
+
* FIX: Changed WooCommerce detection method for better Multi Site support
|
106 |
+
* FIX: Free products: Fixed an inconsistency that could cause a loop on removal/adding of free variant products
|
107 |
+
* TWEAK: Free products: Hooking before_calculate_totals for most cases but also on woocommerce_applied_coupon, which is required when one coupon is replaced by another
|
108 |
+
* INTERNAL: Check if classes already exist before creating them
|
109 |
+
|
110 |
= 2.2.4 =
|
111 |
* FEATURE: Online documentation added
|
112 |
* FEATURE: Use AND-operator for the selected categories (default is OR)
|
woocommerce-jos-autocoupon.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WooCommerce Extended Coupon Features
|
4 |
* Plugin URI: http://www.soft79.nl
|
5 |
* Description: Additional functionality for WooCommerce Coupons: Apply certain coupons automatically, allow applying coupons via an url, etc...
|
6 |
-
* Version: 2.2.
|
7 |
* Author: Jos Koenis
|
8 |
* License: GPL2
|
9 |
*/
|
@@ -19,18 +19,31 @@ require_once( 'includes/wjecf-coupon-extensions.php' );
|
|
19 |
@include_once( 'includes/wjecf-pro-free-products.php' );
|
20 |
|
21 |
/**
|
22 |
-
*
|
23 |
**/
|
24 |
-
if (
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
26 |
if ( ! function_exists( 'wjecf_load_plugin_textdomain' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
function wjecf_load_plugin_textdomain() {
|
28 |
load_plugin_textdomain('woocommerce-jos-autocoupon', false, basename(dirname(__FILE__)) . '/languages/' );
|
29 |
}
|
30 |
add_action('plugins_loaded', 'wjecf_load_plugin_textdomain');
|
31 |
-
|
|
|
32 |
$wjecf_autocoupon = new WC_Jos_AutoCoupon_Controller();
|
33 |
-
if (
|
34 |
if ( class_exists( 'WC_Jos_Pro_Controller' ) ) {
|
35 |
$wjecf_pro = new WC_Jos_Pro_Controller();
|
36 |
}
|
@@ -40,7 +53,6 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
|
|
40 |
}
|
41 |
}
|
42 |
|
43 |
-
|
44 |
}
|
45 |
|
46 |
/**
|
3 |
* Plugin Name: WooCommerce Extended Coupon Features
|
4 |
* Plugin URI: http://www.soft79.nl
|
5 |
* Description: Additional functionality for WooCommerce Coupons: Apply certain coupons automatically, allow applying coupons via an url, etc...
|
6 |
+
* Version: 2.2.5
|
7 |
* Author: Jos Koenis
|
8 |
* License: GPL2
|
9 |
*/
|
19 |
@include_once( 'includes/wjecf-pro-free-products.php' );
|
20 |
|
21 |
/**
|
22 |
+
* Initiate the plugin if WooCommerce is active
|
23 |
**/
|
24 |
+
if ( WC_Jos_Extended_Coupon_Features_Controller::get_woocommerce_version() == false ) {
|
25 |
+
add_action( 'admin_notices', 'wjecf_admin_notice' );
|
26 |
+
function wjecf_admin_notice() {
|
27 |
+
$msg = __( 'WooCommerce Extended Coupon Features is disabled because WooCommerce could not be detected.', 'soft79-wc-pricing-rules' );
|
28 |
+
echo '<div class="error"><p>' . $msg . '</p></div>';
|
29 |
+
}
|
30 |
+
} else {
|
31 |
if ( ! function_exists( 'wjecf_load_plugin_textdomain' ) ) {
|
32 |
+
/**
|
33 |
+
* Get the instance if the WC_Jos_Extended_Coupon_Features_Controller
|
34 |
+
*/
|
35 |
+
function WJECF() {
|
36 |
+
return WC_Jos_Extended_Coupon_Features_Controller::instance();
|
37 |
+
}
|
38 |
+
|
39 |
function wjecf_load_plugin_textdomain() {
|
40 |
load_plugin_textdomain('woocommerce-jos-autocoupon', false, basename(dirname(__FILE__)) . '/languages/' );
|
41 |
}
|
42 |
add_action('plugins_loaded', 'wjecf_load_plugin_textdomain');
|
43 |
+
|
44 |
+
$wjecf_extended_coupon_features = WJECF();
|
45 |
$wjecf_autocoupon = new WC_Jos_AutoCoupon_Controller();
|
46 |
+
if ( WJECF()->is_pro() ) {
|
47 |
if ( class_exists( 'WC_Jos_Pro_Controller' ) ) {
|
48 |
$wjecf_pro = new WC_Jos_Pro_Controller();
|
49 |
}
|
53 |
}
|
54 |
}
|
55 |
|
|
|
56 |
}
|
57 |
|
58 |
/**
|