Version Description
- FIX: Customer selector WooCommerce 3.0.0 compatibility
Download this release
Release Info
Developer | josk79 |
Plugin | WooCommerce Extended Coupon Features |
Version | 2.4.3 |
Comparing to | |
See all releases |
Code changes from version 2.4.2.1 to 2.4.3
- includes/WJECF_Debug_CLI.php +134 -134
- includes/abstract-wjecf-plugin.php +57 -57
- includes/admin/wjecf-admin-auto-upgrade.php +63 -63
- includes/admin/wjecf-admin.php +475 -484
- includes/wjecf-autocoupon.php +559 -559
- includes/wjecf-controller.php +712 -712
- includes/wjecf-wc.php +706 -653
- includes/wjecf-wpml.php +36 -36
- readme.txt +4 -1
- woocommerce-jos-autocoupon.php +108 -108
includes/WJECF_Debug_CLI.php
CHANGED
@@ -4,138 +4,138 @@ defined('ABSPATH') or die();
|
|
4 |
|
5 |
class WJECF_Debug_CLI extends WP_CLI_Command {
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
//
|
130 |
-
//
|
131 |
-
//
|
132 |
-
//
|
133 |
-
//
|
134 |
-
//
|
135 |
-
//
|
136 |
-
//
|
137 |
-
//
|
138 |
-
//
|
139 |
-
//
|
140 |
-
|
141 |
}
|
4 |
|
5 |
class WJECF_Debug_CLI extends WP_CLI_Command {
|
6 |
|
7 |
+
/**
|
8 |
+
* Display some debugging information
|
9 |
+
*/
|
10 |
+
public function debug() {
|
11 |
+
WP_CLI::log( sprintf("WJECF Version: %s", WJECF()->version ) );
|
12 |
+
|
13 |
+
$coupon = WJECF_WC()->get_coupon('auto-cheapest-item');
|
14 |
+
|
15 |
+
$args = array(
|
16 |
+
'posts_per_page' => -1,
|
17 |
+
'orderby' => 'title',
|
18 |
+
'order' => 'asc',
|
19 |
+
'post_type' => 'shop_coupon',
|
20 |
+
'post_status' => 'publish',
|
21 |
+
);
|
22 |
+
$posts = get_posts( $args );
|
23 |
+
foreach ( $posts as $post ) {
|
24 |
+
$coupon = WJECF_WC()->get_coupon( $post->ID );
|
25 |
+
$this->execute_test_for_coupon( $coupon );
|
26 |
+
}
|
27 |
+
|
28 |
+
$args = array(
|
29 |
+
'posts_per_page' => -1,
|
30 |
+
'orderby' => 'title',
|
31 |
+
'order' => 'asc',
|
32 |
+
'post_type' => array( 'product', 'product_variation' ),
|
33 |
+
'post_status' => 'publish',
|
34 |
+
);
|
35 |
+
$posts = get_posts( $args );
|
36 |
+
foreach ( $posts as $post ) {
|
37 |
+
$product = wc_get_product( $post->ID );
|
38 |
+
$this->execute_test_for_product( $product );
|
39 |
+
}
|
40 |
+
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function execute_test_for_coupon( $coupon ) {
|
44 |
+
//WP_CLI::log( sprintf("Coupon fields: %s", print_r( $coupon->coupon_custom_fields ) ) );
|
45 |
+
//WP_CLI::log( sprintf("Coupon fields: %s", print_r( $coupon->get_meta_data() ) ) );
|
46 |
+
|
47 |
+
$meta_keys = array_keys( $coupon->coupon_custom_fields );
|
48 |
+
$meta_keys[] = '__non_existing__';
|
49 |
+
|
50 |
+
//WP_CLI::log( sprintf("Coupon fields: %s", print_r( $coupon->coupon_custom_fields ) ) );
|
51 |
+
//WP_CLI::log( sprintf("Coupon fields: %s", print_r( $coupon->get_meta_data() ) ) );
|
52 |
+
|
53 |
+
$wrap_leg = WJECF_WC()->wrap( $coupon, false ); $wrap_leg->use_wc27 = false;
|
54 |
+
$wrap_new = WJECF_WC()->wrap( $coupon, false ); $wrap_new->use_wc27 = true;
|
55 |
+
|
56 |
+
$results = array();
|
57 |
+
$results['new'] = $wrap_new->get_id();
|
58 |
+
$results['legacy'] = $wrap_leg->get_id();
|
59 |
+
$results['old'] = $coupon->id;
|
60 |
+
$this->assert_same( $results, sprintf('Same coupon id %s', current( $results ) ) );
|
61 |
+
|
62 |
+
foreach( $meta_keys as $meta_key ) {
|
63 |
+
for($i=1; $i>=0; $i--) {
|
64 |
+
$single = $i>0;
|
65 |
+
|
66 |
+
$results = array();
|
67 |
+
$results['new'] = $wrap_new->get_meta( $meta_key, $single );
|
68 |
+
$results['legacy'] = $wrap_leg->get_meta( $meta_key, $single );
|
69 |
+
$results['old'] = get_post_meta( $coupon->id, $meta_key, $single );
|
70 |
+
$this->assert_same( $results, sprintf('%s: Same value %s', $meta_key, $single ? 'single' : 'multi' ) );
|
71 |
+
|
72 |
+
}
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
protected function execute_test_for_product( $product ) {
|
77 |
+
$wrap_leg = WJECF_WC()->wrap( $product, false ); $wrap_leg->use_wc27 = false;
|
78 |
+
$wrap_new = WJECF_WC()->wrap( $product, false ); $wrap_new->use_wc27 = true;
|
79 |
+
|
80 |
+
if ($product instanceof WC_Product_Variation) {
|
81 |
+
$results = array();
|
82 |
+
$results['new'] = $wrap_new->get_product_or_variation_id();
|
83 |
+
$results['legacy'] = $wrap_leg->get_product_or_variation_id();
|
84 |
+
$results['old'] = $product->variation_id;
|
85 |
+
$this->assert_same( $results, sprintf('Same variation id %s', current( $results ) ) );
|
86 |
+
|
87 |
+
$results = array();
|
88 |
+
$results['new'] = $wrap_new->get_variable_product_id();
|
89 |
+
$results['legacy'] = $wrap_leg->get_variable_product_id();
|
90 |
+
$results['old'] = $wrap_leg->get_variable_product_id();
|
91 |
+
$this->assert_same( $results, sprintf('Same variable product (parent) id %s', current( $results ) ) );
|
92 |
+
} else {
|
93 |
+
$results = array();
|
94 |
+
$results['new'] = $wrap_new->get_id();
|
95 |
+
$results['legacy'] = $wrap_leg->get_id();
|
96 |
+
$results['old'] = $product->id;
|
97 |
+
$this->assert_same( $results, sprintf('Same product id %s', current( $results ) ) );
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
|
102 |
+
}
|
103 |
+
|
104 |
+
protected function assert_same( $results, $test_description ) {
|
105 |
+
$success = true;
|
106 |
+
foreach( $results as $result ) {
|
107 |
+
if ( isset( $prev_result ) && $result !== $prev_result ) {
|
108 |
+
$success = false;
|
109 |
+
break;
|
110 |
+
}
|
111 |
+
$prev_result = $result;
|
112 |
+
}
|
113 |
+
|
114 |
+
if ( $success ) {
|
115 |
+
WP_CLI::success( $test_description );
|
116 |
+
} else {
|
117 |
+
foreach( $results as $key => $result ) {
|
118 |
+
WP_CLI::log( sprintf("%s : %s", $key, $this->dd( $result ) ) );
|
119 |
+
}
|
120 |
+
WP_CLI::error( $test_description );
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
protected function dd( $variable ) {
|
125 |
+
return print_r( $variable, true );
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
// /**
|
130 |
+
// * Display expiry information for the given product.
|
131 |
+
// *
|
132 |
+
// * ## OPTIONS
|
133 |
+
// *
|
134 |
+
// * <product_id>...
|
135 |
+
// * : The product ID.
|
136 |
+
// *
|
137 |
+
// */
|
138 |
+
// public function product( $args ) {
|
139 |
+
// }
|
140 |
+
|
141 |
}
|
includes/abstract-wjecf-plugin.php
CHANGED
@@ -12,15 +12,15 @@ abstract class Abstract_WJECF_Plugin {
|
|
12 |
* @return void
|
13 |
*/
|
14 |
public function assert_dependencies() {
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
}
|
25 |
|
26 |
/**
|
@@ -29,68 +29,68 @@ abstract class Abstract_WJECF_Plugin {
|
|
29 |
* @return void
|
30 |
*/
|
31 |
protected function assert_wjecf_version( $required_version ) {
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
}
|
36 |
|
37 |
//
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
|
79 |
/**
|
80 |
* Get the description if this WJECF plugin.
|
81 |
* @return string
|
82 |
*/
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
|
87 |
/**
|
88 |
* Get the class name of this WJECF plugin.
|
89 |
* @return string
|
90 |
*/
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
|
95 |
public function get_plugin_dependencies() {
|
96 |
return $this->get_plugin_data( 'dependencies' );
|
12 |
* @return void
|
13 |
*/
|
14 |
public function assert_dependencies() {
|
15 |
+
foreach( $this->get_plugin_dependencies() as $dependency ) {
|
16 |
+
if ( ! isset( $this->plugins[ $dependency ] ) ) {
|
17 |
+
throw new Exception( sprintf( 'Missing dependency %s', $dependency) );
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
if ( ! empty ( $this->plugin_data['required_version_wjecf'] ) ) {
|
22 |
+
$this->assert_wjecf_version( $this->plugin_data['required_version_wjecf'] );
|
23 |
+
}
|
24 |
}
|
25 |
|
26 |
/**
|
29 |
* @return void
|
30 |
*/
|
31 |
protected function assert_wjecf_version( $required_version ) {
|
32 |
+
if ( version_compare( WJECF()->version, $required_version, '<' ) ) {
|
33 |
+
throw new Exception( sprintf( __( 'WooCommerce Extended Coupon Features version %s is required. You have version %s', 'woocommerce-jos-autocoupon' ), $required_version, WJECF()->version ) );
|
34 |
+
}
|
35 |
}
|
36 |
|
37 |
//
|
38 |
|
39 |
+
/**
|
40 |
+
* Log a message (for debugging)
|
41 |
+
*
|
42 |
+
* @param string $message The message to log
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
protected function log ( $message ) {
|
46 |
+
WJECF()->log( $message, 1 );
|
47 |
+
}
|
48 |
+
|
49 |
+
private $plugin_data = array();
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Information about the WJECF plugin
|
53 |
+
* @param string|null $key The data to look up. Will return an array with all data when omitted
|
54 |
+
* @return mixed
|
55 |
+
*/
|
56 |
+
protected function get_plugin_data( $key = null ) {
|
57 |
+
$default_data = array(
|
58 |
+
'description' => '',
|
59 |
+
'can_be_disabled' => false,
|
60 |
+
'dependencies' => array(),
|
61 |
+
'minimal_wjecf_version' => ''
|
62 |
+
);
|
63 |
+
$plugin_data = array_merge( $default_data, $this->plugin_data );
|
64 |
+
if ( $key === null ) {
|
65 |
+
return $plugin_data;
|
66 |
+
}
|
67 |
+
return $plugin_data[$key];
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Set information about the WJECF plugin
|
72 |
+
* @param array $plugin_data The data for this plugin
|
73 |
+
* @return void
|
74 |
+
*/
|
75 |
+
protected function set_plugin_data( $plugin_data ) {
|
76 |
+
$this->plugin_data = $plugin_data;
|
77 |
+
}
|
78 |
|
79 |
/**
|
80 |
* Get the description if this WJECF plugin.
|
81 |
* @return string
|
82 |
*/
|
83 |
+
public function get_plugin_description() {
|
84 |
+
return $this->get_plugin_data( 'description' );
|
85 |
+
}
|
86 |
|
87 |
/**
|
88 |
* Get the class name of this WJECF plugin.
|
89 |
* @return string
|
90 |
*/
|
91 |
+
public function get_plugin_class_name() {
|
92 |
+
return get_class( $this );
|
93 |
+
}
|
94 |
|
95 |
public function get_plugin_dependencies() {
|
96 |
return $this->get_plugin_data( 'dependencies' );
|
includes/admin/wjecf-admin-auto-upgrade.php
CHANGED
@@ -1,78 +1,78 @@
|
|
1 |
<?php
|
2 |
|
3 |
class WJECF_Admin_Auto_Upgrade extends Abstract_WJECF_Plugin {
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
$where = array("meta_key" => "_wjecf_matching_product_qty");
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
$where = array("meta_key" => "woocommerce-jos-autocoupon");
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
//
|
65 |
-
//
|
66 |
-
//
|
67 |
-
//
|
68 |
-
//
|
69 |
-
//
|
70 |
-
//
|
71 |
-
//
|
72 |
-
//
|
73 |
-
//
|
74 |
-
//
|
75 |
-
|
76 |
-
|
77 |
}
|
78 |
?>
|
1 |
<?php
|
2 |
|
3 |
class WJECF_Admin_Auto_Upgrade extends Abstract_WJECF_Plugin {
|
4 |
+
|
5 |
+
public function __construct() {
|
6 |
+
$this->set_plugin_data( array(
|
7 |
+
'description' => __( 'Automatically upgrade data when a new version of this plugin is installed.', 'woocommerce-jos-autocoupon' ),
|
8 |
+
'dependencies' => array(),
|
9 |
+
'can_be_disabled' => true
|
10 |
+
) );
|
11 |
+
}
|
12 |
|
13 |
+
public function init_admin_hook() {
|
14 |
+
$this->auto_upgrade();
|
15 |
+
}
|
16 |
|
17 |
+
//Upgrade options on version change
|
18 |
+
public function auto_upgrade() {
|
19 |
+
if ( ! class_exists('WC_Coupon') ) {
|
20 |
+
return;
|
21 |
+
}
|
22 |
+
|
23 |
+
//WJECF()->options['db_version'] = 1;update_option( 'wjecf_options' , WJECF()->options, false ); // Will force all upgrades
|
24 |
+
global $wpdb;
|
25 |
+
$prev_version = WJECF()->options['db_version'];
|
26 |
+
|
27 |
+
//DB_VERSION 1: Since 2.1.0-b5
|
28 |
+
if ( WJECF()->options['db_version'] < 1 ) {
|
29 |
+
//RENAME meta_key _wjecf_matching_product_qty TO _wjecf_min_matching_product_qty
|
30 |
$where = array("meta_key" => "_wjecf_matching_product_qty");
|
31 |
+
$set = array('meta_key' => "_wjecf_min_matching_product_qty");
|
32 |
+
$wpdb->update( _get_meta_table('post'), $set, $where );
|
33 |
+
|
34 |
+
//RENAME meta_key woocommerce-jos-autocoupon TO _wjecf_is_auto_coupon
|
35 |
$where = array("meta_key" => "woocommerce-jos-autocoupon");
|
36 |
+
$set = array('meta_key' => "_wjecf_is_auto_coupon");
|
37 |
+
$wpdb->update( _get_meta_table('post'), $set, $where );
|
38 |
+
//Now we're version 1
|
39 |
+
WJECF()->options['db_version'] = 1;
|
40 |
+
} //DB VERSION 1
|
41 |
|
42 |
+
//DB_VERSION 2: Since 2.3.3-b3 No changes; but used to omit message if 2.3.3-b3 has been installed before
|
43 |
+
if ( WJECF()->options['db_version'] < 2 ) {
|
44 |
+
WJECF()->options['db_version'] = 2;
|
45 |
+
}
|
46 |
|
47 |
+
if ( WJECF()->options['db_version'] > 2 ) {
|
48 |
+
WJECF_ADMIN()->enqueue_notice( '<p>' . __( '<strong>WooCommerce Extended Coupon Features:</strong> Please note, you\'re using an older version of this plugin, while the data was upgraded to a newer version.' , 'woocommerce-jos-autocoupon' ) . '</p>', 'notice-warning');
|
49 |
+
}
|
50 |
|
51 |
+
//An upgrade took place?
|
52 |
+
if ( WJECF()->options['db_version'] != $prev_version ) {
|
53 |
+
// Set version and write options to database
|
54 |
+
update_option( 'wjecf_options' , WJECF()->options, false );
|
55 |
|
56 |
+
WJECF_ADMIN()->enqueue_notice( '<p>' . __( '<strong>WooCommerce Extended Coupon Features:</strong> Data succesfully upgraded to the newest version.', 'woocommerce-jos-autocoupon' ) . '</p>', 'notice-success');
|
57 |
+
}
|
58 |
+
}
|
59 |
|
60 |
+
// function admin_notice_allow_cart_excluded() {
|
61 |
|
62 |
+
// if( ! empty( $this->admin_notice_allow_cart_excluded_couponcodes ) )
|
63 |
+
// {
|
64 |
+
// $html = '<div class="notice notice-warning">';
|
65 |
+
// $html .= '<p>';
|
66 |
+
// $html .= __( '<strong>WooCommerce Extended Coupon Features:</strong> The following coupons use the deprecated option \'Allow discount on cart with excluded items\'. Please review and save them.', 'woocommerce-jos-autocoupon' );
|
67 |
+
// $html .= '<ul>';
|
68 |
+
// foreach( $this->admin_notice_allow_cart_excluded_couponcodes as $post_id => $coupon_code ) {
|
69 |
+
// $html .= '<li><a class="post-edit-link" href="' . esc_url( get_edit_post_link( $post_id ) ) . '">' . $coupon_code . '</a></li>';
|
70 |
+
// }
|
71 |
+
// $html .= '</ul>';
|
72 |
+
// $html .= '</p>';
|
73 |
+
// $html .= '</div>';
|
74 |
+
// echo $html;
|
75 |
+
// }
|
76 |
+
// }
|
77 |
}
|
78 |
?>
|
includes/admin/wjecf-admin.php
CHANGED
@@ -3,70 +3,70 @@
|
|
3 |
defined('ABSPATH') or die();
|
4 |
|
5 |
if ( class_exists('WJECF_Admin') ) {
|
6 |
-
|
7 |
}
|
8 |
|
9 |
class WJECF_Admin extends Abstract_WJECF_Plugin {
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
add_action( 'admin_notices', array( $this, 'admin_notices'));
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
add_action( 'admin_head', array( $this, 'on_admin_head'));
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
//WORK IN PROGRESS: add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
|
45 |
-
|
46 |
|
47 |
// ===========================================================================
|
48 |
// START - ADMIN NOTICES
|
49 |
// Allows notices to be displayed on the admin pages
|
50 |
// ===========================================================================
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
|
71 |
// ===========================================================================
|
72 |
// END - ADMIN NOTICES
|
@@ -90,447 +90,438 @@ class WJECF_Admin extends Abstract_WJECF_Plugin {
|
|
90 |
<ul>
|
91 |
<?php
|
92 |
foreach ( WJECF()->get_plugins() as $name => $plugin ) {
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
}
|
97 |
?>
|
98 |
-
|
99 |
<?php
|
100 |
|
101 |
}
|
102 |
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
* Parse an array or comma separated string; make sure they are valid ints and return as comma separated string
|
462 |
-
* @param array|string $int_array
|
463 |
-
* @return string comma separated int array
|
464 |
-
*/
|
465 |
-
public function comma_separated_int_array( $int_array ) {
|
466 |
-
//Source can be a comma separated string (select2) , or an int array (chosen)
|
467 |
-
if ( ! is_array( $int_array) ) {
|
468 |
-
$int_array = explode( ',', $int_array );
|
469 |
-
}
|
470 |
return implode( ',', array_filter( array_map( 'intval', $int_array ) ) );
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
}
|
3 |
defined('ABSPATH') or die();
|
4 |
|
5 |
if ( class_exists('WJECF_Admin') ) {
|
6 |
+
return;
|
7 |
}
|
8 |
|
9 |
class WJECF_Admin extends Abstract_WJECF_Plugin {
|
10 |
+
|
11 |
+
public function __construct() {
|
12 |
+
$this->set_plugin_data( array(
|
13 |
+
'description' => __( 'Admin interface of WooCommerce Extended Coupon Features.', 'woocommerce-jos-autocoupon' ),
|
14 |
+
'dependencies' => array(),
|
15 |
+
'can_be_disabled' => false
|
16 |
+
) );
|
17 |
+
}
|
18 |
+
|
19 |
+
public function init_admin_hook() {
|
20 |
add_action( 'admin_notices', array( $this, 'admin_notices'));
|
21 |
|
22 |
+
if ( ! WJECF_WC()->check_woocommerce_version('2.3.0') ) {
|
23 |
+
$this->enqueue_notice( '<p>' .
|
24 |
+
__( '<strong>WooCommerce Extended Coupon Features:</strong> You are using an old version of WooCommerce. Updating of WooCommerce is recommended as using an outdated version might cause unexpected behaviour in combination with modern plugins.' )
|
25 |
+
. '</p>', 'notice-warning' );
|
26 |
+
}
|
27 |
+
//Admin hooks
|
28 |
+
add_filter( 'plugin_row_meta', array( $this, 'wjecf_plugin_meta' ), 10, 2 );
|
29 |
add_action( 'admin_head', array( $this, 'on_admin_head'));
|
30 |
|
31 |
+
add_filter( 'woocommerce_coupon_data_tabs', array( $this, 'admin_coupon_options_tabs' ), 10, 1);
|
32 |
+
add_action( 'woocommerce_coupon_data_panels', array( $this, 'admin_coupon_options_panels' ), 10, 0 );
|
33 |
+
add_action( 'woocommerce_process_shop_coupon_meta', array( $this, 'process_shop_coupon_meta' ), 10, 2 );
|
34 |
+
|
35 |
+
add_action( 'wjecf_coupon_metabox_products', array( $this, 'admin_coupon_metabox_products' ), 10, 2 );
|
36 |
+
add_action( 'wjecf_coupon_metabox_checkout', array( $this, 'admin_coupon_metabox_checkout' ), 10, 2 );
|
37 |
+
add_action( 'wjecf_coupon_metabox_customer', array( $this, 'admin_coupon_metabox_customer' ), 10, 2 );
|
38 |
+
add_action( 'wjecf_coupon_metabox_misc', array( $this, 'admin_coupon_metabox_misc' ), 10, 2 );
|
39 |
|
40 |
+
WJECF_ADMIN()->add_inline_style( '
|
41 |
+
#woocommerce-coupon-data .wjecf-not-wide { width:50% }
|
42 |
+
');
|
43 |
|
44 |
//WORK IN PROGRESS: add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
|
45 |
+
}
|
46 |
|
47 |
// ===========================================================================
|
48 |
// START - ADMIN NOTICES
|
49 |
// Allows notices to be displayed on the admin pages
|
50 |
// ===========================================================================
|
51 |
|
52 |
+
private $notices = array();
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Enqueue a notice to display on the admin page
|
56 |
+
* @param stirng $html Please embed in <p> tags
|
57 |
+
* @param string $class
|
58 |
+
*/
|
59 |
+
public function enqueue_notice( $html, $class = 'notice-info' ) {
|
60 |
+
$this->notices[] = array( 'class' => $class, 'html' => $html );
|
61 |
+
}
|
62 |
+
|
63 |
+
public function admin_notices() {
|
64 |
+
foreach( $this->notices as $notice ) {
|
65 |
+
echo '<div class="notice ' . $notice['class'] . '">';
|
66 |
+
echo $notice['html'];
|
67 |
+
echo '</div>';
|
68 |
+
}
|
69 |
+
}
|
70 |
|
71 |
// ===========================================================================
|
72 |
// END - ADMIN NOTICES
|
90 |
<ul>
|
91 |
<?php
|
92 |
foreach ( WJECF()->get_plugins() as $name => $plugin ) {
|
93 |
+
echo "<li><h3>" . $plugin->get_plugin_class_name() . "</h3>\n";
|
94 |
+
echo "<p>" . $plugin->get_plugin_description() . "</p>\n";
|
95 |
+
echo "</li>\n";
|
96 |
}
|
97 |
?>
|
98 |
+
</ul>
|
99 |
<?php
|
100 |
|
101 |
}
|
102 |
|
103 |
+
//2.3.6 Inline css
|
104 |
+
private $admin_css = '';
|
105 |
+
|
106 |
+
/**
|
107 |
+
* 2.3.6
|
108 |
+
* @return void
|
109 |
+
*/
|
110 |
+
function on_admin_head() {
|
111 |
+
//Output inline style for the admin pages
|
112 |
+
if ( ! empty( $this->admin_css ) ) {
|
113 |
+
echo '<style type="text/css">' . $this->admin_css . '</style>';
|
114 |
+
$this->admin_css = '';
|
115 |
+
}
|
116 |
+
|
117 |
+
//Enqueue scripts
|
118 |
+
wp_enqueue_script( "wjecf-admin", WJECF()->plugin_url . "assets/js/wjecf-admin.js", array( 'jquery' ), WJECF()->version );
|
119 |
+
wp_localize_script( 'wjecf-admin', 'wjecf_admin_i18n', array(
|
120 |
+
'label_and' => __( '(AND)', 'woocommerce-jos-autocoupon' ),
|
121 |
+
'label_or' => __( '(OR)', 'woocommerce-jos-autocoupon' )
|
122 |
+
) );
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
//Add tabs to the coupon option page
|
128 |
+
public function admin_coupon_options_tabs( $tabs ) {
|
129 |
+
|
130 |
+
$tabs['extended_features_products'] = array(
|
131 |
+
'label' => __( 'Products', 'woocommerce-jos-autocoupon' ),
|
132 |
+
'target' => 'wjecf_coupondata_products',
|
133 |
+
'class' => 'wjecf_coupondata_products',
|
134 |
+
);
|
135 |
+
|
136 |
+
$tabs['extended_features_checkout'] = array(
|
137 |
+
'label' => __( 'Checkout', 'woocommerce-jos-autocoupon' ),
|
138 |
+
'target' => 'wjecf_coupondata_checkout',
|
139 |
+
'class' => 'wjecf_coupondata_checkout',
|
140 |
+
);
|
141 |
+
|
142 |
+
$tabs['extended_features_misc'] = array(
|
143 |
+
'label' => __( 'Miscellaneous', 'woocommerce-jos-autocoupon' ),
|
144 |
+
'target' => 'wjecf_coupondata_misc',
|
145 |
+
'class' => 'wjecf_coupondata_misc',
|
146 |
+
);
|
147 |
+
|
148 |
+
return $tabs;
|
149 |
+
}
|
150 |
+
|
151 |
+
//Add panels to the coupon option page
|
152 |
+
public function admin_coupon_options_panels() {
|
153 |
+
global $thepostid, $post;
|
154 |
+
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
|
155 |
+
?>
|
156 |
+
<div id="wjecf_coupondata_products" class="panel woocommerce_options_panel">
|
157 |
+
<?php
|
158 |
+
//Feed the panel with options
|
159 |
+
do_action( 'wjecf_coupon_metabox_products', $thepostid, $post );
|
160 |
+
$this->admin_coupon_data_footer();
|
161 |
+
?>
|
162 |
+
</div>
|
163 |
+
<div id="wjecf_coupondata_checkout" class="panel woocommerce_options_panel">
|
164 |
+
<?php
|
165 |
+
do_action( 'wjecf_coupon_metabox_checkout', $thepostid, $post );
|
166 |
+
do_action( 'wjecf_coupon_metabox_customer', $thepostid, $post );
|
167 |
+
$this->admin_coupon_data_footer();
|
168 |
+
?>
|
169 |
+
</div>
|
170 |
+
<div id="wjecf_coupondata_misc" class="panel woocommerce_options_panel">
|
171 |
+
<?php
|
172 |
+
//Allow other classes to inject options
|
173 |
+
do_action( 'wjecf_woocommerce_coupon_options_extended_features', $thepostid, $post );
|
174 |
+
do_action( 'wjecf_coupon_metabox_misc', $thepostid, $post );
|
175 |
+
$this->admin_coupon_data_footer();
|
176 |
+
?>
|
177 |
+
</div>
|
178 |
+
<?php
|
179 |
+
}
|
180 |
+
|
181 |
+
public function admin_coupon_data_footer() {
|
182 |
+
$documentation_url = plugins_url( 'docs/index.html', dirname( __FILE__ ) );
|
183 |
+
if ( ! WJECF()->is_pro() ) {
|
184 |
+
$documentation_url = 'http://www.soft79.nl/documentation/wjecf';
|
185 |
+
?>
|
186 |
+
<h3><?php _e( 'Do you find WooCommerce Extended Coupon Features useful?', 'woocommerce-jos-autocoupon'); ?></h3>
|
187 |
+
<p class="form-field"><label for="wjecf_donate_button"><?php
|
188 |
+
echo esc_html( __('Express your gratitude', 'woocommerce-jos-autocoupon' ) );
|
189 |
+
?></label>
|
190 |
+
<a id="wjecf_donate_button" href="<?php echo $this->get_donate_url(); ?>" target="_blank" class="button button-primary">
|
191 |
+
<?php
|
192 |
+
echo esc_html( __('Donate to the developer', 'woocommerce-jos-autocoupon' ) );
|
193 |
+
?></a><br>
|
194 |
+
Or get the PRO version at <a href="http://www.soft79.nl" target="_blank">www.soft79.nl</a>.
|
195 |
+
</p>
|
196 |
+
<?php
|
197 |
+
}
|
198 |
+
//Documentation link
|
199 |
+
echo '<h3>' . __( 'Documentation', 'woocommerce-jos-autocoupon' ) . '</h3>';
|
200 |
+
echo '<p><a href="' . $documentation_url . '" target="_blank">' .
|
201 |
+
__( 'WooCommerce Extended Coupon Features Documentation', 'woocommerce-jos-autocoupon' ) . '</a></p>';
|
202 |
+
|
203 |
+
}
|
204 |
+
|
205 |
+
//Tab 'extended features'
|
206 |
+
public function admin_coupon_metabox_products( $thepostid, $post ) {
|
207 |
+
//See WooCommerce class-wc-meta-box-coupon-data.php function ouput
|
208 |
+
|
209 |
+
echo "<h3>" . esc_html( __( 'Matching products', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
|
210 |
+
//=============================
|
211 |
+
// AND instead of OR the products
|
212 |
+
$this->render_select_with_default( array(
|
213 |
+
'id' => '_wjecf_products_and',
|
214 |
+
'label' => __( 'Products Operator', 'woocommerce-jos-autocoupon' ),
|
215 |
+
'options' => array( 'no' => __( 'OR', 'woocommerce-jos-autocoupon' ), 'yes' => __( 'AND', 'woocommerce-jos-autocoupon' ) ),
|
216 |
+
'default_value' => 'no',
|
217 |
+
'class' => 'wjecf-not-wide',
|
218 |
+
/* translators: OLD TEXT: 'Check this box if ALL of the products (see tab \'usage restriction\') must be in the cart to use this coupon (instead of only one of the products).' */
|
219 |
+
'description' => __( 'Use AND if ALL of the products must be in the cart to use this coupon (instead of only one of the products).', 'woocommerce-jos-autocoupon' ),
|
220 |
+
'desc_tip' => true
|
221 |
+
) );
|
222 |
+
|
223 |
+
//=============================
|
224 |
+
// 2.2.3.1 AND instead of OR the categories
|
225 |
+
$this->render_select_with_default( array(
|
226 |
+
'id' => '_wjecf_categories_and',
|
227 |
+
'label' => __( 'Categories Operator', 'woocommerce-jos-autocoupon' ),
|
228 |
+
'options' => array( 'no' => __( 'OR', 'woocommerce-jos-autocoupon' ), 'yes' => __( 'AND', 'woocommerce-jos-autocoupon' ) ),
|
229 |
+
'default_value' => 'no',
|
230 |
+
'class' => 'wjecf-not-wide',
|
231 |
+
/* translators: OLD TEXT: 'Check this box if products from ALL of the categories (see tab \'usage restriction\') must be in the cart to use this coupon (instead of only one from one of the categories).' */
|
232 |
+
'description' => __( 'Use AND if products from ALL of the categories must be in the cart to use this coupon (instead of only one from one of the categories).', 'woocommerce-jos-autocoupon' ),
|
233 |
+
'desc_tip' => true
|
234 |
+
) );
|
235 |
+
|
236 |
+
|
237 |
+
|
238 |
+
// Minimum quantity of matching products (product/category)
|
239 |
+
woocommerce_wp_text_input( array(
|
240 |
+
'id' => '_wjecf_min_matching_product_qty',
|
241 |
+
'label' => __( 'Minimum quantity of matching products', 'woocommerce-jos-autocoupon' ),
|
242 |
+
'placeholder' => __( 'No minimum', 'woocommerce' ),
|
243 |
+
'description' => __( 'Minimum quantity of the products that match the given product or category restrictions (see tab \'usage restriction\'). If no product or category restrictions are specified, the total number of products is used.', 'woocommerce-jos-autocoupon' ),
|
244 |
+
'data_type' => 'decimal',
|
245 |
+
'desc_tip' => true
|
246 |
+
) );
|
247 |
+
|
248 |
+
// Maximum quantity of matching products (product/category)
|
249 |
+
woocommerce_wp_text_input( array(
|
250 |
+
'id' => '_wjecf_max_matching_product_qty',
|
251 |
+
'label' => __( 'Maximum quantity of matching products', 'woocommerce-jos-autocoupon' ),
|
252 |
+
'placeholder' => __( 'No maximum', 'woocommerce' ),
|
253 |
+
'description' => __( 'Maximum quantity of the products that match the given product or category restrictions (see tab \'usage restriction\'). If no product or category restrictions are specified, the total number of products is used.', 'woocommerce-jos-autocoupon' ),
|
254 |
+
'data_type' => 'decimal',
|
255 |
+
'desc_tip' => true
|
256 |
+
) );
|
257 |
+
|
258 |
+
// Minimum subtotal of matching products (product/category)
|
259 |
+
woocommerce_wp_text_input( array(
|
260 |
+
'id' => '_wjecf_min_matching_product_subtotal',
|
261 |
+
'label' => __( 'Minimum subtotal of matching products', 'woocommerce-jos-autocoupon' ),
|
262 |
+
'placeholder' => __( 'No minimum', 'woocommerce' ),
|
263 |
+
'description' => __( 'Minimum price subtotal of the products that match the given product or category restrictions (see tab \'usage restriction\').', 'woocommerce-jos-autocoupon' ),
|
264 |
+
'data_type' => 'price',
|
265 |
+
'desc_tip' => true
|
266 |
+
) );
|
267 |
+
|
268 |
+
// Maximum subtotal of matching products (product/category)
|
269 |
+
woocommerce_wp_text_input( array(
|
270 |
+
'id' => '_wjecf_max_matching_product_subtotal',
|
271 |
+
'label' => __( 'Maximum subtotal of matching products', 'woocommerce-jos-autocoupon' ),
|
272 |
+
'placeholder' => __( 'No maximum', 'woocommerce' ),
|
273 |
+
'description' => __( 'Maximum price subtotal of the products that match the given product or category restrictions (see tab \'usage restriction\').', 'woocommerce-jos-autocoupon' ),
|
274 |
+
'data_type' => 'price',
|
275 |
+
'desc_tip' => true
|
276 |
+
) );
|
277 |
+
}
|
278 |
+
|
279 |
+
public function admin_coupon_metabox_checkout( $thepostid, $post ) {
|
280 |
+
|
281 |
+
echo "<h3>" . esc_html( __( 'Checkout', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
|
282 |
+
|
283 |
+
//=============================
|
284 |
+
// Shipping methods
|
285 |
+
?>
|
286 |
+
<p class="form-field"><label for="wjecf_shipping_methods"><?php _e( 'Shipping methods', 'woocommerce-jos-autocoupon' ); ?></label>
|
287 |
+
<select id="wjecf_shipping_methods" name="wjecf_shipping_methods[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php _e( 'Any shipping method', 'woocommerce-jos-autocoupon' ); ?>">
|
288 |
+
<?php
|
289 |
+
$coupon_shipping_method_ids = WJECF()->get_coupon_shipping_method_ids( $thepostid );
|
290 |
+
$shipping_methods = WC()->shipping->load_shipping_methods();
|
291 |
+
|
292 |
+
if ( $shipping_methods ) foreach ( $shipping_methods as $shipping_method ) {
|
293 |
+
echo '<option value="' . esc_attr( $shipping_method->id ) . '"' . selected( in_array( $shipping_method->id, $coupon_shipping_method_ids ), true, false ) . '>' . esc_html( $shipping_method->method_title ) . '</option>';
|
294 |
+
}
|
295 |
+
?>
|
296 |
+
</select><?php echo WJECF_WC()->wc_help_tip( __( 'One of these shipping methods must be selected in order for this coupon to be valid.', 'woocommerce-jos-autocoupon' ) ); ?>
|
297 |
+
</p>
|
298 |
+
<?php
|
299 |
+
|
300 |
+
//=============================
|
301 |
+
// Payment methods
|
302 |
+
?>
|
303 |
+
<p class="form-field"><label for="wjecf_payment_methods"><?php _e( 'Payment methods', 'woocommerce-jos-autocoupon' ); ?></label>
|
304 |
+
<select id="wjecf_payment_methods" name="wjecf_payment_methods[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php _e( 'Any payment method', 'woocommerce-jos-autocoupon' ); ?>">
|
305 |
+
<?php
|
306 |
+
$coupon_payment_method_ids = WJECF()->get_coupon_payment_method_ids( $thepostid );
|
307 |
+
//DONT USE WC()->payment_gateways->available_payment_gateways() AS IT CAN CRASH IN UNKNOWN OCCASIONS
|
308 |
+
$payment_methods = WC()->payment_gateways->payment_gateways();
|
309 |
+
if ( $payment_methods ) foreach ( $payment_methods as $payment_method ) {
|
310 |
+
if ('yes' === $payment_method->enabled) {
|
311 |
+
echo '<option value="' . esc_attr( $payment_method->id ) . '"' . selected( in_array( $payment_method->id, $coupon_payment_method_ids ), true, false ) . '>' . esc_html( $payment_method->title ) . '</option>';
|
312 |
+
}
|
313 |
+
}
|
314 |
+
?>
|
315 |
+
</select><?php echo WJECF_WC()->wc_help_tip( __( 'One of these payment methods must be selected in order for this coupon to be valid.', 'woocommerce-jos-autocoupon' ) ); ?>
|
316 |
+
</p>
|
317 |
+
<?php
|
318 |
+
}
|
319 |
+
|
320 |
+
public function admin_coupon_metabox_customer( $thepostid, $post ) {
|
321 |
+
|
322 |
+
//=============================
|
323 |
+
//Title: "CUSTOMER RESTRICTIONS"
|
324 |
+
echo "<h3>" . esc_html( __( 'Customer restrictions', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
|
325 |
+
echo "<p><span class='description'>" . __( 'If both a customer and a role restriction are supplied, matching either one of them will suffice.' , 'woocommerce-jos-autocoupon' ) . "</span></p>\n";
|
326 |
+
|
327 |
+
//=============================
|
328 |
+
// User ids
|
329 |
+
?>
|
330 |
+
<p class="form-field"><label><?php _e( 'Allowed Customers', 'woocommerce-jos-autocoupon' ); ?></label>
|
331 |
+
<?php
|
332 |
+
$coupon_customer_ids = WJECF()->get_coupon_customer_ids( $thepostid );
|
333 |
+
WJECF_WC()->render_admin_customer_selector( 'wjecf_customer_ids', 'wjecf_customer_ids', $coupon_customer_ids );
|
334 |
+
echo WJECF_WC()->wc_help_tip( __( 'Only these customers may use this coupon.', 'woocommerce-jos-autocoupon' ) );
|
335 |
+
?>
|
336 |
+
</p>
|
337 |
+
<?php
|
338 |
+
|
339 |
+
//=============================
|
340 |
+
// User roles
|
341 |
+
?>
|
342 |
+
<p class="form-field"><label for="wjecf_customer_roles"><?php _e( 'Allowed User Roles', 'woocommerce-jos-autocoupon' ); ?></label>
|
343 |
+
<select id="wjecf_customer_roles" name="wjecf_customer_roles[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php _e( 'Any role', 'woocommerce-jos-autocoupon' ); ?>">
|
344 |
+
<?php
|
345 |
+
$coupon_customer_roles = WJECF()->get_coupon_customer_roles( $thepostid );
|
346 |
+
|
347 |
+
$available_customer_roles = array_reverse( get_editable_roles() );
|
348 |
+
foreach ( $available_customer_roles as $role_id => $role ) {
|
349 |
+
$role_name = translate_user_role($role['name'] );
|
350 |
+
|
351 |
+
echo '<option value="' . esc_attr( $role_id ) . '"'
|
352 |
+
. selected( in_array( $role_id, $coupon_customer_roles ), true, false ) . '>'
|
353 |
+
. esc_html( $role_name ) . '</option>';
|
354 |
+
}
|
355 |
+
?>
|
356 |
+
</select>
|
357 |
+
<?php echo WJECF_WC()->wc_help_tip( __( 'Only these User Roles may use this coupon.', 'woocommerce-jos-autocoupon' ) ); ?>
|
358 |
+
</p>
|
359 |
+
<?php
|
360 |
+
|
361 |
+
//=============================
|
362 |
+
// Excluded user roles
|
363 |
+
?>
|
364 |
+
<p class="form-field"><label for="wjecf_excluded_customer_roles"><?php _e( 'Disallowed User Roles', 'woocommerce-jos-autocoupon' ); ?></label>
|
365 |
+
<select id="wjecf_customer_roles" name="wjecf_excluded_customer_roles[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php _e( 'Any role', 'woocommerce-jos-autocoupon' ); ?>">
|
366 |
+
<?php
|
367 |
+
$coupon_excluded_customer_roles = WJECF()->get_coupon_excluded_customer_roles( $thepostid );
|
368 |
+
|
369 |
+
foreach ( $available_customer_roles as $role_id => $role ) {
|
370 |
+
$role_name = translate_user_role($role['name'] );
|
371 |
+
|
372 |
+
echo '<option value="' . esc_attr( $role_id ) . '"'
|
373 |
+
. selected( in_array( $role_id, $coupon_excluded_customer_roles ), true, false ) . '>'
|
374 |
+
. esc_html( $role_name ) . '</option>';
|
375 |
+
}
|
376 |
+
?>
|
377 |
+
</select>
|
378 |
+
<?php echo WJECF_WC()->wc_help_tip( __( 'These User Roles will be specifically excluded from using this coupon.', 'woocommerce-jos-autocoupon' ) ); ?>
|
379 |
+
</p>
|
380 |
+
<?php
|
381 |
+
}
|
382 |
+
|
383 |
+
public function admin_coupon_metabox_misc( $thepostid, $post ) {
|
384 |
+
echo "<h3>" . esc_html( __( 'Miscellaneous', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
|
385 |
+
//=============================
|
386 |
+
//2.2.2 Allow if minimum spend not met
|
387 |
+
woocommerce_wp_checkbox( array(
|
388 |
+
'id' => '_wjecf_allow_below_minimum_spend',
|
389 |
+
'label' => __( 'Allow when minimum spend not reached', 'woocommerce-jos-autocoupon' ),
|
390 |
+
'description' => '<b>' . __( 'EXPERIMENTAL: ', 'woocommerce-jos-autocoupon' ) . '</b>' . __( 'Check this box to allow the coupon to be in the cart even when minimum spend (see tab \'usage restriction\') is not reached. Value of the discount will be 0 until minimum spend is reached.', 'woocommerce-jos-autocoupon' ),
|
391 |
+
) );
|
392 |
+
}
|
393 |
+
|
394 |
+
public function process_shop_coupon_meta( $post_id, $post ) {
|
395 |
+
$wrap_coupon = WJECF_Wrap( $post_id );
|
396 |
+
|
397 |
+
$wjecf_min_matching_product_qty = isset( $_POST['_wjecf_min_matching_product_qty'] ) ? $_POST['_wjecf_min_matching_product_qty'] : '';
|
398 |
+
$wrap_coupon->set_meta( '_wjecf_min_matching_product_qty', $wjecf_min_matching_product_qty );
|
399 |
+
|
400 |
+
$wjecf_max_matching_product_qty = isset( $_POST['_wjecf_max_matching_product_qty'] ) ? $_POST['_wjecf_max_matching_product_qty'] : '';
|
401 |
+
$wrap_coupon->set_meta( '_wjecf_max_matching_product_qty', $wjecf_max_matching_product_qty );
|
402 |
+
|
403 |
+
//2.2.2
|
404 |
+
$wjecf_min_matching_product_subtotal = isset( $_POST['_wjecf_min_matching_product_subtotal'] ) ? $_POST['_wjecf_min_matching_product_subtotal'] : '';
|
405 |
+
$wrap_coupon->set_meta( '_wjecf_min_matching_product_subtotal', $wjecf_min_matching_product_subtotal );
|
406 |
+
|
407 |
+
$wjecf_max_matching_product_subtotal = isset( $_POST['_wjecf_max_matching_product_subtotal'] ) ? $_POST['_wjecf_max_matching_product_subtotal'] : '';
|
408 |
+
$wrap_coupon->set_meta( '_wjecf_max_matching_product_subtotal', $wjecf_max_matching_product_subtotal );
|
409 |
+
|
410 |
+
$wjecf_products_and = $_POST['_wjecf_products_and'] == 'yes' ? 'yes' : 'no';
|
411 |
+
$wrap_coupon->set_meta( '_wjecf_products_and', $wjecf_products_and );
|
412 |
+
|
413 |
+
//2.2.3.1
|
414 |
+
$wjecf_categories_and = $_POST['_wjecf_categories_and'] == 'yes' ? 'yes' : 'no';
|
415 |
+
$wrap_coupon->set_meta( '_wjecf_categories_and', $wjecf_categories_and );
|
416 |
+
|
417 |
+
//2.2.2
|
418 |
+
$wjecf_allow_below_minimum_spend = isset( $_POST['_wjecf_allow_below_minimum_spend'] ) ? 'yes' : 'no';
|
419 |
+
$wrap_coupon->set_meta( '_wjecf_allow_below_minimum_spend', $wjecf_allow_below_minimum_spend );
|
420 |
+
|
421 |
+
$wjecf_shipping_methods = isset( $_POST['wjecf_shipping_methods'] ) ? $_POST['wjecf_shipping_methods'] : '';
|
422 |
+
$wrap_coupon->set_meta( '_wjecf_shipping_methods', $wjecf_shipping_methods );
|
423 |
+
|
424 |
+
$wjecf_payment_methods = isset( $_POST['wjecf_payment_methods'] ) ? $_POST['wjecf_payment_methods'] : '';
|
425 |
+
$wrap_coupon->set_meta( '_wjecf_payment_methods', $wjecf_payment_methods );
|
426 |
+
|
427 |
+
$wjecf_customer_ids = $this->comma_separated_int_array( $_POST['wjecf_customer_ids'] );
|
428 |
+
$wrap_coupon->set_meta( '_wjecf_customer_ids', $wjecf_customer_ids );
|
429 |
+
|
430 |
+
$wjecf_customer_roles = isset( $_POST['wjecf_customer_roles'] ) ? $_POST['wjecf_customer_roles'] : '';
|
431 |
+
$wrap_coupon->set_meta( '_wjecf_customer_roles', $wjecf_customer_roles );
|
432 |
+
|
433 |
+
$wjecf_excluded_customer_roles = isset( $_POST['wjecf_excluded_customer_roles'] ) ? $_POST['wjecf_excluded_customer_roles'] : '';
|
434 |
+
$wrap_coupon->set_meta( '_wjecf_excluded_customer_roles', $wjecf_excluded_customer_roles );
|
435 |
+
|
436 |
+
$wrap_coupon->save();
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* 2.3.6
|
441 |
+
* Add inline style (css) to the admin page. Must be called BEFORE admin_head !
|
442 |
+
* @param string $css
|
443 |
+
* @return void
|
444 |
+
*/
|
445 |
+
public function add_inline_style( $css ) {
|
446 |
+
$this->admin_css .= $css;
|
447 |
+
}
|
448 |
+
|
449 |
+
|
450 |
+
/**
|
451 |
+
* 2.3.4
|
452 |
+
* Parse an array or comma separated string; make sure they are valid ints and return as comma separated string
|
453 |
+
* @param array|string $int_array
|
454 |
+
* @return string comma separated int array
|
455 |
+
*/
|
456 |
+
public function comma_separated_int_array( $int_array ) {
|
457 |
+
//Source can be a comma separated string (select2) , or an int array (chosen)
|
458 |
+
if ( ! is_array( $int_array) ) {
|
459 |
+
$int_array = explode( ',', $int_array );
|
460 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
461 |
return implode( ',', array_filter( array_map( 'intval', $int_array ) ) );
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* 2.3.6
|
466 |
+
* Renders a <SELECT> that has a default value. Relies on woocommerce_wp_select
|
467 |
+
*
|
468 |
+
* field['default_value']: The default value (if omitted the first option will be default)
|
469 |
+
* field['append_default_label']: If true or omitted the text '(DEFAULT)' will be appended to the default option caption
|
470 |
+
*
|
471 |
+
* @param array $field see wc-meta-box-functions.php:woocommerce_wp_select
|
472 |
+
* @return void
|
473 |
+
*/
|
474 |
+
public function render_select_with_default( $field ) {
|
475 |
+
global $thepostid, $post;
|
476 |
+
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
|
477 |
+
|
478 |
+
reset( $field['options'] ); //move to first for key()
|
479 |
+
$default_value = isset( $field['default_value'] ) ? $field['default_value'] : key( $field['options'] );
|
480 |
+
$append_default_label = isset( $field['append_default_label'] ) ? $field['append_default_label'] : true;
|
481 |
+
|
482 |
+
if ( $append_default_label ) {
|
483 |
+
$field['options'][$default_value] = sprintf( __( '%s (Default)', 'woocommerce-jos-autocoupon' ), $field['options'][$default_value] );
|
484 |
+
}
|
485 |
+
|
486 |
+
if ( ! isset( $field['value'] ) ) {
|
487 |
+
$field['value'] = get_post_meta( $thepostid, $field['id'], true );
|
488 |
+
}
|
489 |
+
if ( empty( $field['value'] ) ) {
|
490 |
+
$field['value'] = $default_value;
|
491 |
+
}
|
492 |
+
|
493 |
+
woocommerce_wp_select( $field );
|
494 |
+
}
|
495 |
+
|
496 |
+
public function render_admin_cat_selector( $dom_id, $field_name, $selected_ids, $placeholder = null ) {
|
497 |
+
if ( $placeholder === null ) $placeholder = __( 'Search for a product…', 'woocommerce' );
|
498 |
+
|
499 |
+
// Categories
|
500 |
+
?>
|
501 |
+
<select id="<?php esc_attr_e( $dom_id ) ?>" name="<?php esc_attr_e( $field_name ) ?>[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( $placeholder ); ?>">
|
502 |
+
<?php
|
503 |
+
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
|
504 |
+
|
505 |
+
if ( $categories ) foreach ( $categories as $cat ) {
|
506 |
+
echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $selected_ids ), true, false ) . '>' . esc_html( $cat->name ) . '</option>';
|
507 |
+
}
|
508 |
+
?>
|
509 |
+
</select>
|
510 |
+
<?php
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Add donate-link to plugin page
|
515 |
+
*/
|
516 |
+
function wjecf_plugin_meta( $links, $file ) {
|
517 |
+
if ( strpos( $file, 'woocommerce-jos-autocoupon.php' ) !== false ) {
|
518 |
+
$links = array_merge( $links, array( '<a href="' . WJECF_Admin::get_donate_url() . '" title="Support the development" target="_blank">Donate</a>' ) );
|
519 |
+
}
|
520 |
+
return $links;
|
521 |
+
}
|
522 |
+
|
523 |
+
|
524 |
+
public static function get_donate_url() {
|
525 |
+
return "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5T9XQBCS2QHRY&lc=NL&item_name=Jos%20Koenis&item_number=wordpress%2dplugin¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
|
526 |
+
}
|
527 |
}
|
includes/wjecf-autocoupon.php
CHANGED
@@ -4,612 +4,612 @@ defined('ABSPATH') or die();
|
|
4 |
|
5 |
class WJECF_AutoCoupon extends Abstract_WJECF_Plugin {
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
|
50 |
/* ADMIN HOOKS */
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
|
198 |
/* FRONTEND HOOKS */
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
/**
|
253 |
* Overwrite the html created by wc_cart_totals_coupon_label() so a descriptive text will be shown for the discount.
|
254 |
* @param string $originaltext The default text created by wc_cart_totals_coupon_label()
|
255 |
* @param WC_Coupon $coupon The coupon data
|
256 |
* @return string The overwritten text
|
257 |
-
*/
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
/**
|
269 |
* Overwrite the html created by wc_cart_totals_coupon_html(). This function is required to remove the "Remove" link.
|
270 |
* @param string $originaltext The html created by wc_cart_totals_coupon_html()
|
271 |
* @param WC_Coupon $coupon The coupon data
|
272 |
* @return string The overwritten html
|
273 |
*/
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
|
323 |
/**
|
324 |
* Apply matched autocoupons and remove unmatched autocoupons.
|
325 |
* @return void
|
326 |
-
*/
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
|
398 |
/**
|
399 |
* Test whether the coupon is valid and has a discount > 0
|
400 |
* @return bool
|
401 |
*/
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
|
453 |
/**
|
454 |
* Check wether the coupon is an "Auto coupon".
|
455 |
* @param WC_Coupon $coupon The coupon data
|
456 |
* @return bool true if it is an "Auto coupon"
|
457 |
-
*/
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
|
473 |
/**
|
474 |
* Get the coupon excerpt (description)
|
475 |
* @param WC_Coupon $coupon The coupon data
|
476 |
* @return string The excerpt (translated)
|
477 |
-
*/
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
|
483 |
/**
|
484 |
* Get a list of the users' known email addresses
|
485 |
*
|
486 |
*/
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
|
503 |
/**
|
504 |
* Append a single or an array of email addresses.
|
505 |
* @param array|string $append_emails The email address(es) to be added
|
506 |
* @return void
|
507 |
*/
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
/**
|
556 |
* Get a list of all auto coupon codes
|
557 |
* @return array All auto coupon codes
|
558 |
-
*/
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
}
|
4 |
|
5 |
class WJECF_AutoCoupon extends Abstract_WJECF_Plugin {
|
6 |
|
7 |
+
private $_autocoupons = null;
|
8 |
+
|
9 |
+
private $_user_emails = null;
|
10 |
+
|
11 |
+
protected $_executed_coupon_by_url = false;
|
12 |
+
|
13 |
+
public function __construct() {
|
14 |
+
$this->set_plugin_data( array(
|
15 |
+
'description' => __( 'Allow coupons to be automatically applied to the cart when restrictions are met or by url.', 'woocommerce-jos-autocoupon' ),
|
16 |
+
'dependencies' => array(),
|
17 |
+
'can_be_disabled' => true
|
18 |
+
) );
|
19 |
+
}
|
20 |
+
|
21 |
+
public function init_hook() {
|
22 |
+
if ( ! class_exists('WC_Coupon') ) {
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
//Frontend hooks - logic
|
27 |
+
if ( WJECF_WC()->check_woocommerce_version('2.3.0')) {
|
28 |
+
add_action( 'woocommerce_after_calculate_totals', array( &$this, 'update_matched_autocoupons' ) );
|
29 |
+
} else {
|
30 |
+
//WC Versions prior to 2.3.0 don't have after_calculate_totals hook, this is a fallback
|
31 |
+
add_action( 'woocommerce_cart_updated', array( &$this, 'update_matched_autocoupons' ) );
|
32 |
+
}
|
33 |
+
add_action( 'woocommerce_check_cart_items', array( &$this, 'remove_unmatched_autocoupons' ) , 0, 0 ); //Remove coupon before WC does it and shows a message
|
34 |
+
//Last check for coupons with restricted_emails
|
35 |
+
add_action( 'woocommerce_checkout_update_order_review', array( &$this, 'fetch_billing_email' ), 10 ); // AJAX One page checkout
|
36 |
+
|
37 |
+
//Frontend hooks - visualisation
|
38 |
+
add_filter('woocommerce_cart_totals_coupon_label', array( &$this, 'coupon_label' ), 10, 2 );
|
39 |
+
add_filter('woocommerce_cart_totals_coupon_html', array( &$this, 'coupon_html' ), 10, 2 );
|
40 |
+
|
41 |
+
//Inhibit redirect to cart when apply_coupon supplied
|
42 |
+
add_filter('option_woocommerce_cart_redirect_after_add', array ( &$this, 'option_woocommerce_cart_redirect_after_add') );
|
43 |
+
|
44 |
+
if ( ! is_ajax() ) {
|
45 |
+
//Get cart should not be called before the wp_loaded action nor the add_to_cart_action (class-wc-form-handler)
|
46 |
+
add_action( 'wp_loaded', array( &$this, 'coupon_by_url' ), 90 ); //Coupon through url
|
47 |
+
}
|
48 |
+
}
|
49 |
|
50 |
/* ADMIN HOOKS */
|
51 |
+
public function init_admin_hook() {
|
52 |
+
add_action( 'wjecf_woocommerce_coupon_options_extended_features', array( $this, 'admin_coupon_options_extended_features' ), 20, 2 );
|
53 |
+
add_action( 'woocommerce_process_shop_coupon_meta', array( $this, 'process_shop_coupon_meta' ), 10, 2 );
|
54 |
+
|
55 |
+
//Inject columns
|
56 |
+
if ( WJECF()->is_pro() ) {
|
57 |
+
WJECF()->inject_coupon_column(
|
58 |
+
'_wjecf_auto_coupon',
|
59 |
+
__( 'Auto coupon', 'woocommerce-jos-autocoupon' ),
|
60 |
+
array( $this, 'admin_render_shop_coupon_columns' ), 'coupon_code'
|
61 |
+
);
|
62 |
+
WJECF()->inject_coupon_column(
|
63 |
+
'_wjecf_individual_use',
|
64 |
+
__( 'Individual use', 'woocommerce-jos-autocoupon' ),
|
65 |
+
array( $this, 'admin_render_shop_coupon_columns' ), 'coupon_code'
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
add_filter( 'views_edit-shop_coupon', array( $this, 'admin_views_edit_coupon' ) );
|
70 |
+
add_filter( 'request', array( $this, 'admin_request_query' ) );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Output a coupon custom column value
|
75 |
+
*
|
76 |
+
* @param string $column
|
77 |
+
* @param WP_Post The coupon post object
|
78 |
+
*/
|
79 |
+
public function admin_render_shop_coupon_columns( $column, $post ) {
|
80 |
+
$wrap_coupon = WJECF_Wrap( $post->ID );
|
81 |
+
|
82 |
+
switch ( $column ) {
|
83 |
+
case '_wjecf_auto_coupon' :
|
84 |
+
$is_auto_coupon = $wrap_coupon->get_meta( '_wjecf_is_auto_coupon', true ) == 'yes';
|
85 |
+
echo $is_auto_coupon ? __( 'Yes', 'woocommerce' ) : __( 'No', 'woocommerce' );
|
86 |
+
if ( $is_auto_coupon ) {
|
87 |
+
$prio = $wrap_coupon->get_meta( '_wjecf_coupon_priority', true );
|
88 |
+
if ( $prio ) echo " (" . intval( $prio ) . ")";
|
89 |
+
}
|
90 |
+
break;
|
91 |
+
case '_wjecf_individual_use' :
|
92 |
+
$individual = $wrap_coupon->get_individual_use();
|
93 |
+
echo $individual ? __( 'Yes', 'woocommerce' ) : __( 'No', 'woocommerce' );
|
94 |
+
break;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
public function admin_views_edit_coupon( $views ) {
|
99 |
+
global $post_type, $wp_query;
|
100 |
+
|
101 |
+
$class = ( isset( $wp_query->query['meta_key'] ) && $wp_query->query['meta_key'] == '_wjecf_is_auto_coupon' ) ? 'current' : '';
|
102 |
+
$query_string = remove_query_arg(array( 'wjecf_is_auto_coupon' ));
|
103 |
+
$query_string = add_query_arg( 'wjecf_is_auto_coupon', '1', $query_string );
|
104 |
+
$views['wjecf_is_auto_coupon'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Auto coupons', 'woocommerce' ) . '</a>';
|
105 |
+
|
106 |
+
return $views;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Filters and sorting handler
|
111 |
+
*
|
112 |
+
* @param array $vars
|
113 |
+
* @return array
|
114 |
+
*/
|
115 |
+
public function admin_request_query( $vars ) {
|
116 |
+
global $typenow, $wp_query, $wp_post_statuses;
|
117 |
+
|
118 |
+
if ( 'shop_coupon' === $typenow ) {
|
119 |
+
if ( isset( $_GET['wjecf_is_auto_coupon'] ) ) {
|
120 |
+
$vars['meta_key'] = '_wjecf_is_auto_coupon';
|
121 |
+
$vars['meta_value'] = $_GET['wjecf_is_auto_coupon'] == '1' ? 'yes' : 'no';
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
return $vars;
|
126 |
+
}
|
127 |
+
|
128 |
+
public function admin_coupon_options_extended_features( $thepostid, $post ) {
|
129 |
+
|
130 |
+
//=============================
|
131 |
+
//Title
|
132 |
+
echo "<h3>" . esc_html( __( 'Auto coupon', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
|
133 |
+
|
134 |
+
|
135 |
+
//=============================
|
136 |
+
// Auto coupon checkbox
|
137 |
+
woocommerce_wp_checkbox( array(
|
138 |
+
'id' => '_wjecf_is_auto_coupon',
|
139 |
+
'label' => __( 'Auto coupon', 'woocommerce-jos-autocoupon' ),
|
140 |
+
'description' => __( "Automatically add the coupon to the cart if the restrictions are met. Please enter a description when you check this box, the description will be shown in the customer's cart if the coupon is applied.", 'woocommerce-jos-autocoupon' )
|
141 |
+
) );
|
142 |
+
|
143 |
+
echo '<div class="_wjecf_show_if_autocoupon">';
|
144 |
+
if ( WJECF()->is_pro() ) {
|
145 |
+
// Maximum quantity of matching products (product/category)
|
146 |
+
woocommerce_wp_text_input( array(
|
147 |
+
'id' => '_wjecf_coupon_priority',
|
148 |
+
'label' => __( 'Priority', 'woocommerce-jos-autocoupon' ),
|
149 |
+
'placeholder' => __( 'No priority', 'woocommerce' ),
|
150 |
+
'description' => __( 'When \'individual use\' is checked, auto coupons with a higher value will have priority over other auto coupons.', 'woocommerce-jos-autocoupon' ),
|
151 |
+
'data_type' => 'decimal',
|
152 |
+
'desc_tip' => true
|
153 |
+
) );
|
154 |
+
}
|
155 |
+
|
156 |
+
//=============================
|
157 |
+
// Apply without notice
|
158 |
+
woocommerce_wp_checkbox( array(
|
159 |
+
'id' => '_wjecf_apply_silently',
|
160 |
+
'label' => __( 'Apply silently', 'woocommerce-jos-autocoupon' ),
|
161 |
+
'description' => __( "Don't display a message when this coupon is automatically applied.", 'woocommerce-jos-autocoupon' ),
|
162 |
+
) );
|
163 |
+
echo '</div>';
|
164 |
+
|
165 |
+
?>
|
166 |
+
<script type="text/javascript">
|
167 |
+
//Hide/show when AUTO-COUPON value changes
|
168 |
+
function update_wjecf_apply_silently_field( animation ) {
|
169 |
+
if ( animation === undefined ) animation = 'slow';
|
170 |
+
|
171 |
+
if (jQuery("#_wjecf_is_auto_coupon").prop('checked')) {
|
172 |
+
jQuery("._wjecf_show_if_autocoupon").show( animation );
|
173 |
+
} else {
|
174 |
+
jQuery("._wjecf_show_if_autocoupon").hide( animation );
|
175 |
+
}
|
176 |
+
}
|
177 |
+
update_wjecf_apply_silently_field( 0 );
|
178 |
+
|
179 |
+
jQuery("#_wjecf_is_auto_coupon").click( update_wjecf_apply_silently_field );
|
180 |
+
</script>
|
181 |
+
<?php
|
182 |
+
|
183 |
+
}
|
184 |
+
|
185 |
+
public function process_shop_coupon_meta( $post_id, $post ) {
|
186 |
+
$wrap_coupon = WJECF_Wrap( $post_id );
|
187 |
+
|
188 |
+
$autocoupon = isset( $_POST['_wjecf_is_auto_coupon'] );
|
189 |
+
$wrap_coupon->set_meta( '_wjecf_is_auto_coupon', $autocoupon ? 'yes' : 'no' );
|
190 |
+
$wrap_coupon->set_meta( '_wjecf_apply_silently', isset( $_POST['_wjecf_apply_silently'] ) ? 'yes' : 'no' );
|
191 |
+
if ( WJECF()->is_pro() ) {
|
192 |
+
$wrap_coupon->set_meta( '_wjecf_coupon_priority', intval( $_POST['_wjecf_coupon_priority'] ) );
|
193 |
+
}
|
194 |
+
|
195 |
+
$wrap_coupon->save();
|
196 |
+
}
|
197 |
|
198 |
/* FRONTEND HOOKS */
|
199 |
|
200 |
+
/**
|
201 |
+
** Inhibit redirect to cart when apply_coupon supplied
|
202 |
+
*/
|
203 |
+
public function option_woocommerce_cart_redirect_after_add ( $value ) {
|
204 |
+
if ( ! $this->_executed_coupon_by_url && isset( $_GET['apply_coupon'] ) ) {
|
205 |
+
$value = 'no';
|
206 |
+
}
|
207 |
+
return $value;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Add coupon through url
|
212 |
+
*/
|
213 |
+
public function coupon_by_url() {
|
214 |
+
$must_redirect = false;
|
215 |
+
|
216 |
+
//Apply coupon by url
|
217 |
+
if ( isset( $_GET['apply_coupon'] ) ) {
|
218 |
+
$must_redirect = true;
|
219 |
+
$this->_executed_coupon_by_url = true;
|
220 |
+
$split = explode( ",", wc_clean( $_GET['apply_coupon'] ) );
|
221 |
+
//2.2.2 Make sure a session cookie is set
|
222 |
+
if( ! WC()->session->has_session() )
|
223 |
+
{
|
224 |
+
WC()->session->set_customer_session_cookie( true );
|
225 |
+
}
|
226 |
+
|
227 |
+
$cart = WC()->cart;
|
228 |
+
foreach ( $split as $coupon_code ) {
|
229 |
+
$coupon = WJECF_WC()->get_coupon( $coupon_code );
|
230 |
+
if ( WJECF_WC()->check_woocommerce_version('2.3.0') && ! WJECF_Wrap( $coupon )->exists() ) {
|
231 |
+
wc_add_notice( $coupon->get_coupon_error( WC_Coupon::E_WC_COUPON_NOT_EXIST ), 'error' );
|
232 |
+
} else {
|
233 |
+
$valid = $coupon->is_valid();
|
234 |
+
if ( $valid ) {
|
235 |
+
$cart->add_discount( $coupon_code );
|
236 |
+
}
|
237 |
+
}
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
//Redirect to page without autocoupon query args
|
242 |
+
if ( $must_redirect ) {
|
243 |
+
$requested_url = is_ssl() ? 'https://' : 'http://';
|
244 |
+
$requested_url .= $_SERVER['HTTP_HOST'];
|
245 |
+
$requested_url .= $_SERVER['REQUEST_URI'];
|
246 |
+
|
247 |
+
wp_safe_redirect( remove_query_arg( array( 'apply_coupon', 'add-to-cart' ), ( $requested_url ) ) );
|
248 |
+
exit;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
/**
|
253 |
* Overwrite the html created by wc_cart_totals_coupon_label() so a descriptive text will be shown for the discount.
|
254 |
* @param string $originaltext The default text created by wc_cart_totals_coupon_label()
|
255 |
* @param WC_Coupon $coupon The coupon data
|
256 |
* @return string The overwritten text
|
257 |
+
*/
|
258 |
+
function coupon_label( $originaltext, $coupon ) {
|
259 |
+
|
260 |
+
if ( $this->is_auto_coupon($coupon) ) {
|
261 |
+
|
262 |
+
return $this->coupon_excerpt($coupon); //__($this->autocoupons[$coupon->code], 'woocommerce-jos-autocoupon');
|
263 |
+
} else {
|
264 |
+
return $originaltext;
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
/**
|
269 |
* Overwrite the html created by wc_cart_totals_coupon_html(). This function is required to remove the "Remove" link.
|
270 |
* @param string $originaltext The html created by wc_cart_totals_coupon_html()
|
271 |
* @param WC_Coupon $coupon The coupon data
|
272 |
* @return string The overwritten html
|
273 |
*/
|
274 |
+
function coupon_html( $originaltext, $coupon ) {
|
275 |
+
if ( $this->is_auto_coupon($coupon) ) {
|
276 |
+
$value = array();
|
277 |
+
|
278 |
+
if ( $amount = WC()->cart->get_coupon_discount_amount( WJECF_Wrap( $coupon )->get_code(), WC()->cart->display_cart_ex_tax ) ) {
|
279 |
+
$discount_html = '-' . wc_price( $amount );
|
280 |
+
} else {
|
281 |
+
$discount_html = '';
|
282 |
+
}
|
283 |
+
|
284 |
+
$value[] = apply_filters( 'woocommerce_coupon_discount_amount_html', $discount_html, $coupon );
|
285 |
+
|
286 |
+
if ( WJECF_Wrap( $coupon )->get_free_shipping() ) {
|
287 |
+
$value[] = __( 'Free shipping coupon', 'woocommerce' );
|
288 |
+
}
|
289 |
+
|
290 |
+
return implode(', ', array_filter($value)); //Remove empty array elements
|
291 |
+
} else {
|
292 |
+
return $originaltext;
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
|
297 |
+
function remove_unmatched_autocoupons( $valid_coupon_codes = null ) {
|
298 |
+
if ( $valid_coupon_codes === null ) {
|
299 |
+
//Get the coupons that should be in the cart
|
300 |
+
$valid_coupons = $this->get_valid_auto_coupons();
|
301 |
+
$valid_coupons = $this->individual_use_filter( $valid_coupons );
|
302 |
+
$valid_coupon_codes = array();
|
303 |
+
foreach ( $valid_coupons as $coupon ) {
|
304 |
+
$valid_coupon_codes[] = WJECF_Wrap( $coupon )->get_code();
|
305 |
+
}
|
306 |
+
}
|
307 |
+
|
308 |
+
//Remove invalids
|
309 |
+
$calc_needed = false;
|
310 |
+
foreach ( $this->get_all_auto_coupons() as $coupon ) {
|
311 |
+
$coupon_code = WJECF_Wrap( $coupon )->get_code();
|
312 |
+
if ( WC()->cart->has_discount( $coupon_code ) && ! in_array( $coupon_code, $valid_coupon_codes ) ) {
|
313 |
+
$this->log( sprintf( "Removing %s", $coupon_code ) );
|
314 |
+
WC()->cart->remove_coupon( $coupon_code );
|
315 |
+
$calc_needed = true;
|
316 |
+
}
|
317 |
+
}
|
318 |
+
return $calc_needed;
|
319 |
+
}
|
320 |
+
|
321 |
+
private $update_matched_autocoupons_executed = false;
|
322 |
|
323 |
/**
|
324 |
* Apply matched autocoupons and remove unmatched autocoupons.
|
325 |
* @return void
|
326 |
+
*/
|
327 |
+
function update_matched_autocoupons() {
|
328 |
+
if ( $this->update_matched_autocoupons_executed ) {
|
329 |
+
return;
|
330 |
+
}
|
331 |
+
$this->update_matched_autocoupons_executed = true;
|
332 |
+
$this->log( "()" );
|
333 |
+
|
334 |
+
//2.3.3 Keep track of queued coupons and apply when they validate
|
335 |
+
$queuer = WJECF()->get_plugin('WJECF_Pro_Coupon_Queueing');
|
336 |
+
if ( $queuer !== false ) {
|
337 |
+
$queuer->apply_valid_queued_coupons();
|
338 |
+
}
|
339 |
+
|
340 |
+
//Get the coupons that should be in the cart
|
341 |
+
$valid_coupons = $this->get_valid_auto_coupons();
|
342 |
+
$valid_coupons = $this->individual_use_filter( $valid_coupons );
|
343 |
+
|
344 |
+
$valid_coupon_codes = array();
|
345 |
+
foreach ( $valid_coupons as $coupon ) {
|
346 |
+
$valid_coupon_codes[] = WJECF_Wrap( $coupon )->get_code();
|
347 |
+
}
|
348 |
+
|
349 |
+
$this->log( sprintf( "Auto coupons that should be in cart: %s", implode( ', ', $valid_coupon_codes ) ) );
|
350 |
+
|
351 |
+
$calc_needed = $this->remove_unmatched_autocoupons( $valid_coupon_codes );
|
352 |
+
|
353 |
+
//Add valids
|
354 |
+
foreach( $valid_coupons as $coupon ) {
|
355 |
+
$coupon_code = WJECF_Wrap( $coupon )->get_code();
|
356 |
+
if ( ! WC()->cart->has_discount( $coupon_code ) ) {
|
357 |
+
$this->log( sprintf( "Applying auto coupon %s", $coupon_code ) );
|
358 |
+
|
359 |
+
$apply_silently = WJECF_Wrap( $coupon )->get_meta( '_wjecf_apply_silently' ) == 'yes';
|
360 |
+
|
361 |
+
if ( $apply_silently ) {
|
362 |
+
$new_succss_msg = ''; // no message
|
363 |
+
} else {
|
364 |
+
$coupon_excerpt = $this->coupon_excerpt($coupon);
|
365 |
+
$new_succss_msg = sprintf(
|
366 |
+
__("Discount applied: %s", 'woocommerce-jos-autocoupon'),
|
367 |
+
__( empty( $coupon_excerpt ) ? $coupon_code : $coupon_excerpt, 'woocommerce-jos-autocoupon')
|
368 |
+
);
|
369 |
+
}
|
370 |
+
|
371 |
+
WJECF()->start_overwrite_success_message( $coupon, $new_succss_msg );
|
372 |
+
WC()->cart->add_discount( $coupon_code ); //Causes calculation and will remove other coupons if it's a individual coupon
|
373 |
+
WJECF()->stop_overwrite_success_message();
|
374 |
+
|
375 |
+
$calc_needed = false; //Already done by adding the discount
|
376 |
+
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
$this->log( 'Coupons in cart: ' . implode( ', ', WC()->cart->applied_coupons ) . ($calc_needed ? ". RECALC" : "") );
|
381 |
+
|
382 |
+
if ( $calc_needed ) {
|
383 |
+
WC()->cart->calculate_totals();
|
384 |
+
}
|
385 |
+
|
386 |
+
}
|
387 |
+
|
388 |
+
private function get_valid_auto_coupons( ) {
|
389 |
+
$valid_coupons = array();
|
390 |
+
foreach ( $this->get_all_auto_coupons() as $coupon ) {
|
391 |
+
if ( $this->coupon_can_be_applied( $coupon ) && $this->coupon_has_a_value( $coupon ) ) {
|
392 |
+
$valid_coupons[] = $coupon;
|
393 |
+
}
|
394 |
+
}
|
395 |
+
return $valid_coupons;
|
396 |
+
}
|
397 |
|
398 |
/**
|
399 |
* Test whether the coupon is valid and has a discount > 0
|
400 |
* @return bool
|
401 |
*/
|
402 |
+
function coupon_can_be_applied( $coupon ) {
|
403 |
+
$wrap_coupon = WJECF_Wrap( $coupon );
|
404 |
+
$can_be_applied = true;
|
405 |
+
|
406 |
+
//Test validity
|
407 |
+
if ( ! $coupon->is_valid() ) {
|
408 |
+
$can_be_applied = false;
|
409 |
+
}
|
410 |
+
//Test restricted emails
|
411 |
+
//See WooCommerce: class-wc-cart.php function check_customer_coupons
|
412 |
+
else if ( $can_be_applied && is_array( $wrap_coupon->get_email_restrictions() ) && sizeof( $wrap_coupon->get_email_restrictions() ) > 0 ) {
|
413 |
+
$user_emails = array_map( 'sanitize_email', array_map( 'strtolower', $this->get_user_emails() ) );
|
414 |
+
$coupon_emails = array_map( 'sanitize_email', array_map( 'strtolower', $wrap_coupon->get_email_restrictions() ) );
|
415 |
+
|
416 |
+
if ( 0 == sizeof( array_intersect( $user_emails, $coupon_emails ) ) ) {
|
417 |
+
$can_be_applied = false;
|
418 |
+
}
|
419 |
+
}
|
420 |
+
return apply_filters( 'wjecf_coupon_can_be_applied', $can_be_applied, $coupon );
|
421 |
+
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Does the coupon have a value? (autocoupon should not be applied if it has no value)
|
426 |
+
* @param WC_Coupon $coupon The coupon data
|
427 |
+
* @return bool True if it has a value (discount, free shipping, whatever) otherwise false)
|
428 |
+
**/
|
429 |
+
function coupon_has_a_value( $coupon ) {
|
430 |
+
|
431 |
+
$has_a_value = false;
|
432 |
+
|
433 |
+
if ( WJECF_Wrap( $coupon )->get_free_shipping() ) {
|
434 |
+
$has_a_value = true;
|
435 |
+
} else {
|
436 |
+
//Test whether discount > 0
|
437 |
+
//See WooCommerce: class-wc-cart.php function get_discounted_price
|
438 |
+
global $woocommerce;
|
439 |
+
foreach ( $woocommerce->cart->get_cart() as $cart_item ) {
|
440 |
+
if ( $coupon->is_valid_for_cart() || $coupon->is_valid_for_product( $cart_item['data'], $cart_item ) ) {
|
441 |
+
$has_a_value = true;
|
442 |
+
break;
|
443 |
+
}
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
return apply_filters( 'wjecf_coupon_has_a_value', $has_a_value, $coupon );
|
448 |
+
|
449 |
+
}
|
450 |
+
|
451 |
+
|
452 |
|
453 |
/**
|
454 |
* Check wether the coupon is an "Auto coupon".
|
455 |
* @param WC_Coupon $coupon The coupon data
|
456 |
* @return bool true if it is an "Auto coupon"
|
457 |
+
*/
|
458 |
+
public function is_auto_coupon($coupon) {
|
459 |
+
return WJECF_Wrap( $coupon )->get_meta( '_wjecf_is_auto_coupon' ) == 'yes';
|
460 |
+
}
|
461 |
+
|
462 |
+
private function get_coupon_priority($coupon) {
|
463 |
+
if ( WJECF()->is_pro() ) {
|
464 |
+
$prio = WJECF_Wrap( $coupon )->get_meta( '_wjecf_coupon_priority' );
|
465 |
+
if ( ! empty( $prio ) ) {
|
466 |
+
return intval( $prio );
|
467 |
+
}
|
468 |
+
}
|
469 |
+
return 0;
|
470 |
+
}
|
471 |
+
|
472 |
|
473 |
/**
|
474 |
* Get the coupon excerpt (description)
|
475 |
* @param WC_Coupon $coupon The coupon data
|
476 |
* @return string The excerpt (translated)
|
477 |
+
*/
|
478 |
+
private function coupon_excerpt($coupon) {
|
479 |
+
$my_post = get_post( WJECF_Wrap( $coupon )->get_id() );
|
480 |
+
return __( $my_post->post_excerpt, 'woocommerce-jos-autocoupon' );
|
481 |
+
}
|
482 |
|
483 |
/**
|
484 |
* Get a list of the users' known email addresses
|
485 |
*
|
486 |
*/
|
487 |
+
private function get_user_emails() {
|
488 |
+
if ( ! is_array($this->_user_emails) ) {
|
489 |
+
$this->_user_emails = array();
|
490 |
+
//Email of the logged in user
|
491 |
+
if ( is_user_logged_in() ) {
|
492 |
+
$current_user = wp_get_current_user();
|
493 |
+
$this->_user_emails[] = $current_user->user_email;
|
494 |
+
}
|
495 |
+
|
496 |
+
if ( isset( $_POST['billing_email'] ) )
|
497 |
+
$this->_user_emails[] = $_POST['billing_email'];
|
498 |
+
}
|
499 |
+
//$this->log( "User emails: " . implode( ",", $this->_user_emails ) );
|
500 |
+
return $this->_user_emails;
|
501 |
+
}
|
502 |
|
503 |
/**
|
504 |
* Append a single or an array of email addresses.
|
505 |
* @param array|string $append_emails The email address(es) to be added
|
506 |
* @return void
|
507 |
*/
|
508 |
+
private function append_user_emails($append_emails) {
|
509 |
+
//$append_emails must be an array
|
510 |
+
if ( ! is_array( $append_emails ) ) {
|
511 |
+
$append_emails = array( $append_emails );
|
512 |
+
}
|
513 |
+
$this->_user_emails = array_unique( array_merge( $this->get_user_emails(), $append_emails ) );
|
514 |
+
//$this->log('Append emails: ' . implode( ',', $append_emails ) );
|
515 |
+
}
|
516 |
+
|
517 |
+
public function fetch_billing_email( $post_data ) {
|
518 |
+
//post_data can be an array, or a query=string&like=this
|
519 |
+
if ( ! is_array( $post_data ) ) {
|
520 |
+
parse_str( $post_data, $posted );
|
521 |
+
} else {
|
522 |
+
$posted = $post_data;
|
523 |
+
}
|
524 |
+
|
525 |
+
if ( isset ( $posted['billing_email'] ) ) {
|
526 |
+
$this->append_user_emails( $posted['billing_email'] );
|
527 |
+
}
|
528 |
+
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Return an array of WC_Coupons with coupons that shouldn't cause individual use conflicts
|
533 |
+
*/
|
534 |
+
private function individual_use_filter( $valid_auto_coupons ) {
|
535 |
+
$filtered = array();
|
536 |
+
|
537 |
+
//Any individual use non-autocoupons in the cart?
|
538 |
+
foreach ( WC()->cart->get_applied_coupons() as $coupon_code ) {
|
539 |
+
$coupon = new WC_Coupon( $coupon_code );
|
540 |
+
if ( WJECF_Wrap( $coupon )->get_individual_use() && ! $this->is_auto_coupon( $coupon ) ) {
|
541 |
+
return $filtered; //Don't allow any auto coupon
|
542 |
+
}
|
543 |
+
}
|
544 |
+
foreach ( $valid_auto_coupons as $coupon ) {
|
545 |
+
if ( ! WJECF_Wrap( $coupon )->get_individual_use() || empty( $filtered ) ) {
|
546 |
+
$filtered[] = $coupon;
|
547 |
+
if ( WJECF_Wrap( $coupon )->get_individual_use() ) {
|
548 |
+
break;
|
549 |
+
}
|
550 |
+
}
|
551 |
+
}
|
552 |
+
return $filtered;
|
553 |
+
}
|
554 |
+
|
555 |
/**
|
556 |
* Get a list of all auto coupon codes
|
557 |
* @return array All auto coupon codes
|
558 |
+
*/
|
559 |
+
public function get_all_auto_coupons() {
|
560 |
+
if ( ! is_array( $this->_autocoupons ) ) {
|
561 |
+
$this->_autocoupons = array();
|
562 |
+
|
563 |
+
$query_args = array(
|
564 |
+
'posts_per_page' => -1,
|
565 |
+
'post_type' => 'shop_coupon',
|
566 |
+
'post_status' => 'publish',
|
567 |
+
'orderby' => array( 'title' => 'ASC' ),
|
568 |
+
'meta_query' => array(
|
569 |
+
array(
|
570 |
+
'key' => '_wjecf_is_auto_coupon',
|
571 |
+
'compare' => '=',
|
572 |
+
'value' => 'yes',
|
573 |
+
),
|
574 |
+
)
|
575 |
+
);
|
576 |
+
|
577 |
+
$query = new WP_Query($query_args);
|
578 |
+
foreach ($query->posts as $post) {
|
579 |
+
$coupon = new WC_Coupon($post->post_title);
|
580 |
+
if ( $this->is_auto_coupon($coupon) ) {
|
581 |
+
$this->_autocoupons[ WJECF_Wrap( $coupon )->get_code() ] = $coupon;
|
582 |
+
}
|
583 |
+
}
|
584 |
+
|
585 |
+
//Sort by priority
|
586 |
+
@uasort( $this->_autocoupons , array( $this, 'sort_auto_coupons' ) ); //Ignore error PHP Bug #50688
|
587 |
+
|
588 |
+
$coupon_codes = array();
|
589 |
+
foreach( $this->_autocoupons as $coupon ) {
|
590 |
+
$coupon_codes[] = WJECF_Wrap( $coupon )->get_code();
|
591 |
+
}
|
592 |
+
|
593 |
+
$this->log( "Autocoupons: " . implode(", ", $coupon_codes ) );
|
594 |
+
}
|
595 |
+
|
596 |
+
return $this->_autocoupons;
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Compare function to sort coupons by priority
|
601 |
+
* @param type $a
|
602 |
+
* @param type $b
|
603 |
+
* @return type
|
604 |
+
*/
|
605 |
+
private function sort_auto_coupons( $coupon_a, $coupon_b ) {
|
606 |
+
$prio_a = $this->get_coupon_priority( $coupon_a );
|
607 |
+
$prio_b = $this->get_coupon_priority( $coupon_b );
|
608 |
+
$this->log("A: $prio_a B: $prio_b ");
|
609 |
+
if ( $prio_a == $prio_b ) {
|
610 |
+
return $a->code < $b->code ? -1 : 1; //By title ASC
|
611 |
+
} else {
|
612 |
+
return $prio_a > $prio_b ? -1 : 1; //By prio DESC
|
613 |
+
}
|
614 |
+
}
|
615 |
}
|
includes/wjecf-controller.php
CHANGED
@@ -7,759 +7,759 @@ defined('ABSPATH') or die();
|
|
7 |
*/
|
8 |
class WJECF_Controller {
|
9 |
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
foreach ( WJECF()->get_plugins() as $name => $plugin ) {
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
}
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
add_action( 'wp_footer', array( $this, 'render_log' ) ); //Log
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
$this->options = get_option( 'wjecf_options' );
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
|
196 |
/* FRONTEND HOOKS */
|
197 |
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
public function admin_notice_woocommerce_not_found() {
|
203 |
$msg = __( 'WooCommerce Extended Coupon Features is disabled because WooCommerce could not be detected.', 'woocommerce-jos-autocoupon' );
|
204 |
echo '<div class="error"><p>' . $msg . '</p></div>';
|
205 |
}
|
206 |
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
//Filter used by WJECF_WPML hook
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
//Filter used by WJECF_WPML hook
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
|
554 |
/**
|
555 |
* Get array of the selected payment method ids.
|
556 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
557 |
* @return array Id's of the payment methods or an empty array.
|
558 |
-
*/
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
/**
|
569 |
* Get array of the selected customer ids.
|
570 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
571 |
* @return array Id's of the customers (users) or an empty array.
|
572 |
-
*/
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
/**
|
586 |
* Get array of the selected customer role ids.
|
587 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
588 |
* @return array Id's (string) of the customer roles or an empty array.
|
589 |
-
*/
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
|
599 |
/**
|
600 |
* Get array of the excluded customer role ids.
|
601 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
602 |
* @return array Id's (string) of the excluded customer roles or an empty array.
|
603 |
-
*/
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
|
617 |
// ===========================================================================
|
618 |
// START - OVERWRITE INFO MESSAGES
|
619 |
// ===========================================================================
|
620 |
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
|
650 |
// ===========================================================================
|
651 |
// END - OVERWRITE INFO MESSAGES
|
652 |
// ===========================================================================
|
653 |
|
654 |
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
|
765 |
}
|
7 |
*/
|
8 |
class WJECF_Controller {
|
9 |
|
10 |
+
// Coupon message codes
|
11 |
+
//NOTE: I use prefix 79 for this plugin; there's no guarantee that other plugins don't use the same values!
|
12 |
+
const E_WC_COUPON_MIN_MATCHING_SUBTOTAL_NOT_MET = 79100;
|
13 |
+
const E_WC_COUPON_MAX_MATCHING_SUBTOTAL_NOT_MET = 79101;
|
14 |
+
const E_WC_COUPON_MIN_MATCHING_QUANTITY_NOT_MET = 79102;
|
15 |
+
const E_WC_COUPON_MAX_MATCHING_QUANTITY_NOT_MET = 79103;
|
16 |
+
const E_WC_COUPON_SHIPPING_METHOD_NOT_MET = 79104;
|
17 |
+
const E_WC_COUPON_PAYMENT_METHOD_NOT_MET = 79105;
|
18 |
+
const E_WC_COUPON_NOT_FOR_THIS_USER = 79106;
|
19 |
+
|
20 |
+
protected $debug_mode = false;
|
21 |
+
protected $log = array();
|
22 |
+
public $options = false;
|
23 |
+
|
24 |
+
//Plugin data
|
25 |
+
public $plugin_path; // Has trailing slash
|
26 |
+
public $plugin_url; // Has trailing slash
|
27 |
+
public $version; // Use for js
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Singleton Instance
|
31 |
+
*
|
32 |
+
* @static
|
33 |
+
* @return Singleton Instance
|
34 |
+
*/
|
35 |
+
public static function instance() {
|
36 |
+
if ( is_null( self::$_instance ) ) {
|
37 |
+
self::$_instance = new self();
|
38 |
+
}
|
39 |
+
return self::$_instance;
|
40 |
+
}
|
41 |
+
protected static $_instance = null;
|
42 |
+
|
43 |
+
|
44 |
+
public function __construct() {
|
45 |
+
$this->debug_mode = false && defined( 'WP_DEBUG' ) && WP_DEBUG;
|
46 |
+
//Paths
|
47 |
+
$this->plugin_path = plugin_dir_path( dirname(__FILE__) );
|
48 |
+
$this->plugin_url = plugins_url( '/', dirname( __FILE__ ) );
|
49 |
+
|
50 |
+
$filename = $this->is_pro() ? "woocommerce-jos-autocoupon-pro.php" : "woocommerce-jos-autocoupon.php" ;
|
51 |
+
|
52 |
+
//Version
|
53 |
+
$default_headers = array(
|
54 |
+
'Version' => 'Version',
|
55 |
+
);
|
56 |
+
$plugin_data = get_file_data( $this->plugin_path . $filename, $default_headers, 'plugin' );
|
57 |
+
$this->version = $plugin_data['Version'];
|
58 |
+
}
|
59 |
+
|
60 |
+
public function start() {
|
61 |
+
add_action('init', array( $this, 'init_hook' ));
|
62 |
+
}
|
63 |
+
|
64 |
+
public function init_hook() {
|
65 |
+
if ( ! class_exists('WC_Coupon') ) {
|
66 |
+
add_action( 'admin_notices', array( $this, 'admin_notice_woocommerce_not_found' ) );
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
$this->controller_init();
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Fires before the WJECF plugins are initialised.
|
74 |
+
*
|
75 |
+
* Perfect hook for themes or plugins to load custom WJECF plugins.
|
76 |
+
*
|
77 |
+
* @since 2.3.7
|
78 |
+
**/
|
79 |
+
do_action( 'wjecf_init_plugins');
|
80 |
+
|
81 |
+
//Start the plugins
|
82 |
foreach ( WJECF()->get_plugins() as $name => $plugin ) {
|
83 |
+
if ( $plugin->plugin_is_enabled() ) {
|
84 |
+
|
85 |
+
foreach( $plugin->get_plugin_dependencies() as $dependency_name ) {
|
86 |
+
$dependency = $this->get_plugin( $dependency_name );
|
87 |
+
if ( ! $dependency || ! $dependency->plugin_is_enabled() ) {
|
88 |
+
error_log('Unable to initialize ' . $name . ' because it requires ' . $dependency_name );
|
89 |
+
continue;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
$plugin->init_hook();
|
94 |
+
if ( is_admin() ) {
|
95 |
+
$plugin->init_admin_hook();
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
public function controller_init() {
|
102 |
+
|
103 |
+
$this->log( "INIT " . ( is_ajax() ? "AJAX" : is_admin() ? "ADMIN" : "FRONTEND" ) . " " . $_SERVER['REQUEST_URI'] );
|
104 |
+
|
105 |
+
$this->init_options();
|
106 |
+
|
107 |
+
//Frontend hooks
|
108 |
+
|
109 |
+
//assert_coupon_is_valid (which raises exception on invalid coupon) can only be used on WC 2.3.0 and up
|
110 |
+
if ( WJECF_WC()->check_woocommerce_version('2.3.0') ) {
|
111 |
+
add_filter('woocommerce_coupon_is_valid', array( $this, 'assert_coupon_is_valid' ), 10, 2 );
|
112 |
+
} else {
|
113 |
+
add_filter('woocommerce_coupon_is_valid', array( $this, 'coupon_is_valid' ), 10, 2 );
|
114 |
+
}
|
115 |
+
|
116 |
+
add_filter('woocommerce_coupon_error', array( $this, 'woocommerce_coupon_error' ), 10, 3 );
|
117 |
+
add_action('woocommerce_coupon_loaded', array( $this, 'woocommerce_coupon_loaded' ), 10, 1);
|
118 |
+
add_filter('woocommerce_coupon_get_discount_amount', array( $this, 'woocommerce_coupon_get_discount_amount' ), 10, 5);
|
119 |
add_action( 'wp_footer', array( $this, 'render_log' ) ); //Log
|
120 |
+
}
|
121 |
+
|
122 |
+
protected $plugins = array();
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Load a WJECF Plugin (class name)
|
126 |
+
* @param string $class_name The class name of the plugin
|
127 |
+
* @return bool True if succeeded, otherwise false
|
128 |
+
*/
|
129 |
+
public function add_plugin( $class_name ) {
|
130 |
+
if ( isset( $this->plugins[ $class_name ] ) ) {
|
131 |
+
return false; //Already loaded
|
132 |
+
}
|
133 |
+
|
134 |
+
if ( ! class_exists( $class_name ) ) {
|
135 |
+
return false; //Not found
|
136 |
+
}
|
137 |
+
|
138 |
+
$the_plugin = new $class_name();
|
139 |
+
foreach( $the_plugin->get_plugin_dependencies() as $dependency ) {
|
140 |
+
if ( ! class_exists( $dependency ) ) {
|
141 |
+
$this->log( 'Unknown dependency: ' . $dependency . ' for plugin ' . $class_name );
|
142 |
+
return false;
|
143 |
+
}
|
144 |
+
|
145 |
+
if ( isset( $this->plugins[ $class_name ] ) ) {
|
146 |
+
continue; //dependency is al geladen
|
147 |
+
}
|
148 |
+
|
149 |
+
$this->add_plugin( $dependency );
|
150 |
+
}
|
151 |
+
|
152 |
+
//Assert dependencies
|
153 |
+
try {
|
154 |
+
$the_plugin->assert_dependencies();
|
155 |
+
} catch (Exception $ex) {
|
156 |
+
$msg = sprintf('Failed loading %s: %s', $class_name, $ex->getMessage() );
|
157 |
+
if ( $wjecf_admin = WJECF()->get_plugin('WJECF_Admin') ) {
|
158 |
+
$wjecf_admin->enqueue_notice( $msg, 'error' );
|
159 |
+
} else {
|
160 |
+
}
|
161 |
+
error_log("PRINTR".print_r($wjecf_admin, true));
|
162 |
+
error_log( $msg );
|
163 |
+
return false;
|
164 |
+
}
|
165 |
+
|
166 |
+
$this->plugins[ $class_name ] = $the_plugin;
|
167 |
+
$this->log( 'Loaded plugin: ' . $class_name );
|
168 |
+
|
169 |
+
return true;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function get_plugins() {
|
173 |
+
return $this->plugins;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Retrieves the WJECF Plugin
|
178 |
+
* @param string $class_name
|
179 |
+
* @return object|bool The plugin if found, otherwise returns false
|
180 |
+
*/
|
181 |
+
public function get_plugin( $class_name ) {
|
182 |
+
if ( isset( $this->plugins[ $class_name ] ) ) {
|
183 |
+
return $this->plugins[ $class_name ];
|
184 |
+
} else {
|
185 |
+
return false;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
public function init_options() {
|
190 |
$this->options = get_option( 'wjecf_options' );
|
191 |
+
if (false === $this->options) {
|
192 |
+
$this->options = array( 'db_version' => 0 );
|
193 |
+
}
|
194 |
+
}
|
195 |
|
196 |
/* FRONTEND HOOKS */
|
197 |
|
198 |
+
/**
|
199 |
+
* Notifies that WooCommerce has not been detected.
|
200 |
+
* @return void
|
201 |
+
*/
|
202 |
public function admin_notice_woocommerce_not_found() {
|
203 |
$msg = __( 'WooCommerce Extended Coupon Features is disabled because WooCommerce could not be detected.', 'woocommerce-jos-autocoupon' );
|
204 |
echo '<div class="error"><p>' . $msg . '</p></div>';
|
205 |
}
|
206 |
|
207 |
+
//2.2.2
|
208 |
+
public function woocommerce_coupon_loaded ( $coupon ) {
|
209 |
+
if ( ! is_admin() ) {
|
210 |
+
//2.2.2 Allow coupon even if minimum spend not reached
|
211 |
+
if ( WJECF_Wrap( $coupon )->get_meta( '_wjecf_allow_below_minimum_spend' ) == 'yes' ) {
|
212 |
+
//HACK: Overwrite the minimum amount with 0 so WooCommerce will allow the coupon
|
213 |
+
$coupon->wjecf_minimum_amount_for_discount = WJECF_Wrap( $coupon )->get_minimum_amount();
|
214 |
+
$coupon->minimum_amount = 0;
|
215 |
+
}
|
216 |
+
}
|
217 |
+
}
|
218 |
+
|
219 |
+
//2.2.2
|
220 |
+
public function woocommerce_coupon_get_discount_amount ( $discount, $discounting_amount, $cart_item, $single, $coupon ) {
|
221 |
+
//2.2.2 No value if minimum spend not reached
|
222 |
+
if (isset( $coupon->wjecf_minimum_amount_for_discount ) ) {
|
223 |
+
if ( wc_format_decimal( $coupon->wjecf_minimum_amount_for_discount ) > wc_format_decimal( WC()->cart->subtotal ) ) {
|
224 |
+
return 0;
|
225 |
+
};
|
226 |
+
}
|
227 |
+
return $discount;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Overwrite coupon error message, if $err_code is an error code of this plugin
|
232 |
+
* @param string $err Original error message
|
233 |
+
* @param int $err_code Error code
|
234 |
+
* @param WC_Coupon $coupon The coupon
|
235 |
+
* @return string Overwritten error message
|
236 |
+
*/
|
237 |
+
public function woocommerce_coupon_error( $err, $err_code, $coupon ) {
|
238 |
+
switch ( $err_code ) {
|
239 |
+
case self::E_WC_COUPON_MIN_MATCHING_SUBTOTAL_NOT_MET:
|
240 |
+
$min_price = wc_price( WJECF_Wrap( $coupon )->get_meta( '_wjecf_min_matching_product_subtotal' ) );
|
241 |
+
$err = sprintf( __( 'The minimum subtotal of the matching products for this coupon is %s.', 'woocommerce-jos-autocoupon' ), $min_price );
|
242 |
+
break;
|
243 |
+
case self::E_WC_COUPON_MAX_MATCHING_SUBTOTAL_NOT_MET:
|
244 |
+
$max_price = wc_price( WJECF_Wrap( $coupon )->get_meta( '_wjecf_max_matching_product_subtotal' ) );
|
245 |
+
$err = sprintf( __( 'The maximum subtotal of the matching products for this coupon is %s.', 'woocommerce-jos-autocoupon' ), $max_price );
|
246 |
+
break;
|
247 |
+
case self::E_WC_COUPON_MIN_MATCHING_QUANTITY_NOT_MET:
|
248 |
+
$min_matching_product_qty = intval( WJECF_Wrap( $coupon )->get_meta( '_wjecf_min_matching_product_qty' ) );
|
249 |
+
$err = sprintf( __( 'The minimum quantity of matching products for this coupon is %s.', 'woocommerce-jos-autocoupon' ), $min_matching_product_qty );
|
250 |
+
break;
|
251 |
+
case self::E_WC_COUPON_MAX_MATCHING_QUANTITY_NOT_MET:
|
252 |
+
$max_matching_product_qty = intval( WJECF_Wrap( $coupon )->get_meta( '_wjecf_min_matching_product_qty' ) );
|
253 |
+
$err = sprintf( __( 'The maximum quantity of matching products for this coupon is %s.', 'woocommerce-jos-autocoupon' ), $max_matching_product_qty );
|
254 |
+
break;
|
255 |
+
case self::E_WC_COUPON_SHIPPING_METHOD_NOT_MET:
|
256 |
+
$err = __( 'The coupon is not valid for the currently selected shipping method.', 'woocommerce-jos-autocoupon' );
|
257 |
+
break;
|
258 |
+
case self::E_WC_COUPON_PAYMENT_METHOD_NOT_MET:
|
259 |
+
$err = __( 'The coupon is not valid for the currently selected payment method.', 'woocommerce-jos-autocoupon' );
|
260 |
+
break;
|
261 |
+
case self::E_WC_COUPON_NOT_FOR_THIS_USER:
|
262 |
+
$err = sprintf( __( 'Sorry, it seems the coupon "%s" is not yours.', 'woocommerce-jos-autocoupon' ), WJECF_Wrap( $coupon )->get_code() );
|
263 |
+
break;
|
264 |
+
default:
|
265 |
+
//Do nothing
|
266 |
+
break;
|
267 |
+
}
|
268 |
+
return $err;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Extra validation rules for coupons.
|
273 |
+
* @param bool $valid
|
274 |
+
* @param WC_Coupon $coupon
|
275 |
+
* @return bool True if valid; False if not valid.
|
276 |
+
*/
|
277 |
+
public function coupon_is_valid ( $valid, $coupon ) {
|
278 |
+
try {
|
279 |
+
return $this->assert_coupon_is_valid( $valid, $coupon );
|
280 |
+
} catch ( Exception $e ) {
|
281 |
+
return false;
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Extra validation rules for coupons. Throw an exception when not valid.
|
287 |
+
* @param bool $valid
|
288 |
+
* @param WC_Coupon $coupon
|
289 |
+
* @return bool True if valid; False if already invalid on function call. In any other case an Exception will be thrown.
|
290 |
+
*/
|
291 |
+
public function assert_coupon_is_valid ( $valid, $coupon ) {
|
292 |
+
|
293 |
+
$wrap_coupon = WJECF_Wrap( $coupon );
|
294 |
+
|
295 |
+
//Not valid? Then it will never validate, so get out of here
|
296 |
+
if ( ! $valid ) {
|
297 |
+
return false;
|
298 |
+
}
|
299 |
+
|
300 |
+
//============================
|
301 |
+
//Test if ALL products are in the cart (if AND-operator selected instead of the default OR)
|
302 |
+
$products_and = $wrap_coupon->get_meta( '_wjecf_products_and' ) == 'yes';
|
303 |
+
if ( $products_and && sizeof( $wrap_coupon->get_product_ids() ) > 1 ) { // We use > 1, because if size == 1, 'AND' makes no difference
|
304 |
+
//Get array of all cart product and variation ids
|
305 |
+
$cart_item_ids = array();
|
306 |
+
$cart = WC()->cart->get_cart();
|
307 |
+
foreach( $cart as $cart_item_key => $cart_item ) {
|
308 |
+
$cart_item_ids[] = $cart_item['product_id'];
|
309 |
+
$cart_item_ids[] = $cart_item['variation_id'];
|
310 |
+
}
|
311 |
//Filter used by WJECF_WPML hook
|
312 |
+
$cart_item_ids = apply_filters( 'wjecf_get_product_ids', $cart_item_ids );
|
313 |
+
|
314 |
+
//check if every single product is in the cart
|
315 |
+
foreach( apply_filters( 'wjecf_get_product_ids', $wrap_coupon->get_product_ids() ) as $product_id ) {
|
316 |
+
if ( ! in_array( $product_id, $cart_item_ids ) ) {
|
317 |
+
throw new Exception( WC_Coupon::E_WC_COUPON_NOT_APPLICABLE );
|
318 |
+
}
|
319 |
+
}
|
320 |
+
}
|
321 |
+
|
322 |
+
//============================
|
323 |
+
//Test if products form ALL categories are in the cart (if AND-operator selected instead of the default OR)
|
324 |
+
$categories_and = $wrap_coupon->get_meta( '_wjecf_categories_and' ) == 'yes';
|
325 |
+
if ( $categories_and && sizeof( $wrap_coupon->get_product_categories() ) > 1 ) { // We use > 1, because if size == 1, 'AND' makes no difference
|
326 |
+
//Get array of all cart product and variation ids
|
327 |
+
$cart_product_cats = array();
|
328 |
+
$cart = WC()->cart->get_cart();
|
329 |
+
foreach( $cart as $cart_item_key => $cart_item ) {
|
330 |
+
$cart_product_cats = array_merge ( $cart_product_cats, wp_get_post_terms( $cart_item['product_id'], 'product_cat', array( "fields" => "ids" ) ) );
|
331 |
+
}
|
332 |
//Filter used by WJECF_WPML hook
|
333 |
+
$cart_product_cats = apply_filters( 'wjecf_get_product_cat_ids', $cart_product_cats );
|
334 |
+
//check if every single category is in the cart
|
335 |
+
foreach( apply_filters( 'wjecf_get_product_cat_ids', $wrap_coupon->get_product_categories() ) as $cat_id ) {
|
336 |
+
if ( ! in_array( $cat_id, $cart_product_cats ) ) {
|
337 |
+
$this->log( $cat_id . " is not in " . print_r($cart_product_cats, true));
|
338 |
+
throw new Exception( WC_Coupon::E_WC_COUPON_NOT_APPLICABLE );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
//============================
|
344 |
+
//Test min/max quantity of matching products
|
345 |
+
//
|
346 |
+
//For all items in the cart:
|
347 |
+
// If coupon contains both a product AND category inclusion filter: the item is counted if it matches either one of them
|
348 |
+
// If coupon contains either a product OR category exclusion filter: the item will NOT be counted if it matches either one of them
|
349 |
+
// If sale items are excluded by the coupon: the item will NOT be counted if it is a sale item
|
350 |
+
// If no filter exist, all items will be counted
|
351 |
+
|
352 |
+
$multiplier = null; //null = not initialized
|
353 |
+
|
354 |
+
//Validate quantity
|
355 |
+
$min_matching_product_qty = intval( $wrap_coupon->get_meta( '_wjecf_min_matching_product_qty' ) );
|
356 |
+
$max_matching_product_qty = intval( $wrap_coupon->get_meta( '_wjecf_max_matching_product_qty' ) );
|
357 |
+
if ( $min_matching_product_qty > 0 || $max_matching_product_qty > 0 ) {
|
358 |
+
//Count the products
|
359 |
+
$qty = $this->get_quantity_of_matching_products( $coupon );
|
360 |
+
if ( $min_matching_product_qty > 0 && $qty < $min_matching_product_qty ) throw new Exception( self::E_WC_COUPON_MIN_MATCHING_QUANTITY_NOT_MET );
|
361 |
+
if ( $max_matching_product_qty > 0 && $qty > $max_matching_product_qty ) throw new Exception( self::E_WC_COUPON_MAX_MATCHING_QUANTITY_NOT_MET );
|
362 |
+
|
363 |
+
if ( $min_matching_product_qty > 0 ) {
|
364 |
+
$multiplier = self::min_value( floor( $qty / $min_matching_product_qty ), $multiplier );
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
//Validate subtotal (2.2.2)
|
369 |
+
$min_matching_product_subtotal = floatval( $wrap_coupon->get_meta( '_wjecf_min_matching_product_subtotal' ) );
|
370 |
+
$max_matching_product_subtotal = floatval( $wrap_coupon->get_meta( '_wjecf_max_matching_product_subtotal' ) );
|
371 |
+
if ( $min_matching_product_subtotal > 0 || $max_matching_product_subtotal > 0 ) {
|
372 |
+
$subtotal = $this->get_subtotal_of_matching_products( $coupon );
|
373 |
+
if ( $min_matching_product_subtotal > 0 && $subtotal < $min_matching_product_subtotal ) throw new Exception( self::E_WC_COUPON_MIN_MATCHING_SUBTOTAL_NOT_MET );
|
374 |
+
if ( $max_matching_product_subtotal > 0 && $subtotal > $max_matching_product_subtotal ) throw new Exception( self::E_WC_COUPON_MAX_MATCHING_SUBTOTAL_NOT_MET );
|
375 |
+
|
376 |
+
if ( $min_matching_product_subtotal > 0 ) {
|
377 |
+
$multiplier = self::min_value( floor( $subtotal / $min_matching_product_subtotal ), $multiplier );
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
//============================
|
382 |
+
//Test restricted shipping methods
|
383 |
+
$shipping_method_ids = $this->get_coupon_shipping_method_ids( $coupon );
|
384 |
+
if ( sizeof( $shipping_method_ids ) > 0 ) {
|
385 |
+
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
|
386 |
+
$chosen_shipping = empty( $chosen_shipping_methods ) ? '' : $chosen_shipping_methods[0];
|
387 |
+
$chosen_shipping = explode( ':', $chosen_shipping); //UPS and USPS stores extra data, seperated by colon
|
388 |
+
$chosen_shipping = $chosen_shipping[0];
|
389 |
+
|
390 |
+
if ( ! in_array( $chosen_shipping, $shipping_method_ids ) ) {
|
391 |
+
throw new Exception( self::E_WC_COUPON_SHIPPING_METHOD_NOT_MET );
|
392 |
+
}
|
393 |
+
}
|
394 |
+
|
395 |
+
//============================
|
396 |
+
//Test restricted payment methods
|
397 |
+
$payment_method_ids = $this->get_coupon_payment_method_ids( $coupon );
|
398 |
+
if ( sizeof( $payment_method_ids ) > 0 ) {
|
399 |
+
$chosen_payment_method = isset( WC()->session->chosen_payment_method ) ? WC()->session->chosen_payment_method : array();
|
400 |
+
|
401 |
+
if ( ! in_array( $chosen_payment_method, $payment_method_ids ) ) {
|
402 |
+
throw new Exception( self::E_WC_COUPON_PAYMENT_METHOD_NOT_MET );
|
403 |
+
}
|
404 |
+
}
|
405 |
+
|
406 |
+
|
407 |
+
//============================
|
408 |
+
//Test restricted user ids and roles
|
409 |
+
//NOTE: If both customer id and role restrictions are provided, the coupon matches if either the id or the role matches
|
410 |
+
$coupon_customer_ids = $this->get_coupon_customer_ids( $coupon );
|
411 |
+
$coupon_customer_roles = $this->get_coupon_customer_roles( $coupon );
|
412 |
+
if ( sizeof( $coupon_customer_ids ) > 0 || sizeof( $coupon_customer_roles ) > 0 ) {
|
413 |
+
$user = wp_get_current_user();
|
414 |
+
|
415 |
+
//If both fail we invalidate. Otherwise it's ok
|
416 |
+
if ( ! in_array( $user->ID, $coupon_customer_ids ) && ! array_intersect( $user->roles, $coupon_customer_roles ) ) {
|
417 |
+
throw new Exception( self::E_WC_COUPON_NOT_FOR_THIS_USER );
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
//============================
|
422 |
+
//Test excluded user roles
|
423 |
+
$coupon_excluded_customer_roles = $this->get_coupon_excluded_customer_roles( $coupon );
|
424 |
+
if ( sizeof( $coupon_excluded_customer_roles ) > 0 ) {
|
425 |
+
$user = wp_get_current_user();
|
426 |
+
|
427 |
+
//Excluded customer roles
|
428 |
+
if ( array_intersect( $user->roles, $coupon_excluded_customer_roles ) ) {
|
429 |
+
throw new Exception( self::E_WC_COUPON_NOT_FOR_THIS_USER );
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
//We use our own filter (instead of woocommerce_coupon_is_valid) for easier compatibility management
|
434 |
+
//e.g. WC prior to 2.3.0 can't handle Exceptions; while 2.3.0 and above require exceptions
|
435 |
+
do_action( 'wjecf_assert_coupon_is_valid', $coupon );
|
436 |
+
|
437 |
+
if ( $wrap_coupon->get_minimum_amount() ) {
|
438 |
+
$multiplier = self::min_value( floor( WC()->cart->subtotal / $wrap_coupon->get_minimum_amount() ), $multiplier );
|
439 |
+
}
|
440 |
+
|
441 |
+
|
442 |
+
$this->coupon_multiplier_values[ $wrap_coupon->get_code() ] = $multiplier;
|
443 |
+
//error_log("multiplier " . $wrap_coupon->get_code() . " = " . $multiplier );
|
444 |
+
|
445 |
+
return true; // VALID!
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Return the lowest multiplier value
|
450 |
+
*/
|
451 |
+
private static function min_value( $value, $current_multiplier_value = null ) {
|
452 |
+
return ( $current_multiplier_value === null || $value < $current_multiplier_value ) ? $value : $current_multiplier_value;
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* The amount of times the minimum spend / quantity / subtotal values are reached
|
457 |
+
* @return int 1 or more if coupon is valid, otherwise 0
|
458 |
+
*/
|
459 |
+
public function get_coupon_multiplier_value( $coupon ) {
|
460 |
+
$coupon = WJECF_WC()->get_coupon( $coupon );
|
461 |
+
|
462 |
+
//If coupon validation was not executed, the value is unknown
|
463 |
+
if ( ! isset( $this->coupon_multiplier_values[ WJECF_Wrap( $coupon )->get_code() ] ) ) {
|
464 |
+
if ( ! $this->coupon_is_valid( true, $coupon ) ) {
|
465 |
+
return 0;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
$multiplier = $this->coupon_multiplier_values[ WJECF_Wrap( $coupon )->get_code() ];
|
469 |
+
|
470 |
+
//error_log("get multiplier " . WJECF_Wrap( $coupon )->get_code() . " = " . $multiplier );
|
471 |
+
return $multiplier;
|
472 |
+
}
|
473 |
+
|
474 |
+
//Temporary storage
|
475 |
+
private $coupon_multiplier_values = array();
|
476 |
+
|
477 |
+
|
478 |
+
/**
|
479 |
+
* (API FUNCTION)
|
480 |
+
* The total amount of the products in the cart that match the coupon restrictions
|
481 |
+
* since 2.2.2-b3
|
482 |
+
*/
|
483 |
+
public function get_quantity_of_matching_products( $coupon ) {
|
484 |
+
$coupon = WJECF_WC()->get_coupon( $coupon );
|
485 |
+
|
486 |
+
$qty = 0;
|
487 |
+
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
488 |
+
$_product = $cart_item['data'];
|
489 |
+
if ($this->coupon_is_valid_for_product( $coupon, $_product, $cart_item ) ) {
|
490 |
+
$qty += $cart_item['quantity'];
|
491 |
+
}
|
492 |
+
}
|
493 |
+
return $qty;
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* (API FUNCTION)
|
498 |
+
* The total value of the products in the cart that match the coupon restrictions
|
499 |
+
* since 2.2.2-b3
|
500 |
+
*/
|
501 |
+
public function get_subtotal_of_matching_products( $coupon ) {
|
502 |
+
$coupon = WJECF_WC()->get_coupon( $coupon );
|
503 |
+
|
504 |
+
$subtotal = 0;
|
505 |
+
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
506 |
+
$_product = $cart_item['data'];
|
507 |
+
if ($this->coupon_is_valid_for_product( $coupon, $_product, $cart_item ) ) {
|
508 |
+
$subtotal += $_product->get_price() * $cart_item['quantity'];
|
509 |
+
}
|
510 |
+
}
|
511 |
+
return $subtotal;
|
512 |
+
}
|
513 |
+
|
514 |
+
/**
|
515 |
+
* (API FUNCTION)
|
516 |
+
* Test if coupon is valid for the product
|
517 |
+
* (this function is used to count the quantity of matching products)
|
518 |
+
*/
|
519 |
+
public function coupon_is_valid_for_product( $coupon, $product, $values = array() ) {
|
520 |
+
//Do not count the free products
|
521 |
+
if ( isset( $values['_wjecf_free_product_coupon'] ) ) {
|
522 |
+
return false;
|
523 |
+
}
|
524 |
+
|
525 |
+
if ( ! $coupon->is_type( WJECF_WC()->wc_get_cart_coupon_types() ) ) {
|
526 |
+
return $coupon->is_valid_for_product( $product, $values );
|
527 |
+
}
|
528 |
+
|
529 |
+
//$coupon->is_valid_for_product() only works for fixed_product or percent_product discounts
|
530 |
+
//It's not, so we create a temporary duplicate
|
531 |
+
$duplicate_coupon = WJECF_WC()->get_coupon( WJECF_Wrap( $coupon )->get_code() );
|
532 |
+
WJECF_Wrap( $duplicate_coupon )->set_discount_type( 'fixed_product' );
|
533 |
+
return $duplicate_coupon->is_valid_for_product( $product, $values );
|
534 |
+
}
|
535 |
+
|
536 |
+
|
537 |
+
|
538 |
+
// =====================
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Get array of the selected shipping methods ids.
|
542 |
+
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
543 |
+
* @return array Id's of the shipping methods or an empty array.
|
544 |
+
*/
|
545 |
+
public function get_coupon_shipping_method_ids( $coupon ) {
|
546 |
+
$v = WJECF_Wrap( $coupon )->get_meta( '_wjecf_shipping_methods' );
|
547 |
+
if ($v == '') {
|
548 |
+
$v = array();
|
549 |
+
}
|
550 |
+
|
551 |
+
return $v;
|
552 |
+
}
|
553 |
|
554 |
/**
|
555 |
* Get array of the selected payment method ids.
|
556 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
557 |
* @return array Id's of the payment methods or an empty array.
|
558 |
+
*/
|
559 |
+
public function get_coupon_payment_method_ids( $coupon ) {
|
560 |
+
$v = WJECF_Wrap( $coupon )->get_meta( '_wjecf_payment_methods' );
|
561 |
+
if ($v == '') {
|
562 |
+
$v = array();
|
563 |
+
}
|
564 |
+
|
565 |
+
return $v;
|
566 |
+
}
|
567 |
+
|
568 |
/**
|
569 |
* Get array of the selected customer ids.
|
570 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
571 |
* @return array Id's of the customers (users) or an empty array.
|
572 |
+
*/
|
573 |
+
public function get_coupon_customer_ids( $coupon ) {
|
574 |
+
$v = WJECF_Wrap( $coupon )->get_meta( '_wjecf_customer_ids' );
|
575 |
+
|
576 |
+
if ($v == '') {
|
577 |
+
$v = array();
|
578 |
+
} else {
|
579 |
+
$v = array_map( 'intval', explode(",", $v ) );
|
580 |
+
}
|
581 |
+
|
582 |
+
return $v;
|
583 |
+
}
|
584 |
+
|
585 |
/**
|
586 |
* Get array of the selected customer role ids.
|
587 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
588 |
* @return array Id's (string) of the customer roles or an empty array.
|
589 |
+
*/
|
590 |
+
public function get_coupon_customer_roles( $coupon ) {
|
591 |
+
$v = WJECF_Wrap( $coupon )->get_meta( '_wjecf_customer_roles' );
|
592 |
+
if ($v == '') {
|
593 |
+
$v = array();
|
594 |
+
}
|
595 |
+
|
596 |
+
return $v;
|
597 |
+
}
|
598 |
|
599 |
/**
|
600 |
* Get array of the excluded customer role ids.
|
601 |
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
602 |
* @return array Id's (string) of the excluded customer roles or an empty array.
|
603 |
+
*/
|
604 |
+
public function get_coupon_excluded_customer_roles( $coupon ) {
|
605 |
+
$v = WJECF_Wrap( $coupon )->get_meta( '_wjecf_excluded_customer_roles' );
|
606 |
+
if ($v == '') {
|
607 |
+
$v = array();
|
608 |
+
}
|
609 |
+
|
610 |
+
return $v;
|
611 |
+
}
|
612 |
+
|
613 |
+
public function is_pro() {
|
614 |
+
return $this instanceof WJECF_Pro_Controller;
|
615 |
+
}
|
616 |
|
617 |
// ===========================================================================
|
618 |
// START - OVERWRITE INFO MESSAGES
|
619 |
// ===========================================================================
|
620 |
|
621 |
+
/**
|
622 |
+
* 2.3.4
|
623 |
+
* If a 'Coupon applied' message is displayed by WooCommerce, replace it by another message (or no message)
|
624 |
+
* @param WC_Coupon $coupon The coupon to replace the message for
|
625 |
+
* @param string $new_message The new message. Set to empty string if no message must be displayed
|
626 |
+
*/
|
627 |
+
public function start_overwrite_success_message( $coupon, $new_message = '' ) {
|
628 |
+
$this->overwrite_coupon_message[ WJECF_Wrap( $coupon )->get_code() ] = array( $coupon->get_coupon_message( WC_Coupon::WC_COUPON_SUCCESS ) => $new_message );
|
629 |
+
add_filter( 'woocommerce_coupon_message', array( $this, 'filter_woocommerce_coupon_message' ), 10, 3 );
|
630 |
+
}
|
631 |
+
|
632 |
+
/**
|
633 |
+
* 2.3.4
|
634 |
+
* Stop overwriting messages
|
635 |
+
*/
|
636 |
+
public function stop_overwrite_success_message() {
|
637 |
+
remove_filter( 'woocommerce_coupon_message', array( $this, 'filter_woocommerce_coupon_message' ), 10 );
|
638 |
+
$this->overwrite_coupon_message = array();
|
639 |
+
}
|
640 |
+
|
641 |
+
private $overwrite_coupon_message = array(); /* [ 'coupon_code' => [ old_message' => 'new_message' ] ] */
|
642 |
+
|
643 |
+
function filter_woocommerce_coupon_message( $msg, $msg_code, $coupon ) {
|
644 |
+
if ( isset( $this->overwrite_coupon_message[ WJECF_Wrap( $coupon )->get_code() ][ $msg ] ) ) {
|
645 |
+
$msg = $this->overwrite_coupon_message[ WJECF_Wrap( $coupon )->get_code() ][ $msg ];
|
646 |
+
}
|
647 |
+
return $msg;
|
648 |
+
}
|
649 |
|
650 |
// ===========================================================================
|
651 |
// END - OVERWRITE INFO MESSAGES
|
652 |
// ===========================================================================
|
653 |
|
654 |
|
655 |
+
private $_session_data = null;
|
656 |
+
/**
|
657 |
+
* Read something from the session
|
658 |
+
* @param string $key The key for identification
|
659 |
+
* @param any $default The default value (Default: false)
|
660 |
+
*
|
661 |
+
* @return The saved value if found, otherwise the default value
|
662 |
+
*/
|
663 |
+
public function get_session( $key, $default = false ) {
|
664 |
+
if ( $this->_session_data == null) {
|
665 |
+
$this->_session_data = WC()->session->get( '_wjecf_session_data', array() );
|
666 |
+
}
|
667 |
+
return isset( $this->_session_data[ $key ] ) ? $this->_session_data[ $key ] : $default;
|
668 |
+
}
|
669 |
+
|
670 |
+
/**
|
671 |
+
* Save something in the session
|
672 |
+
*
|
673 |
+
* @param string $key The key for identification
|
674 |
+
* @param anything $value The value to store
|
675 |
+
*/
|
676 |
+
public function set_session( $key, $value ) {
|
677 |
+
if ( $this->_session_data == null) {
|
678 |
+
$this->_session_data = WC()->session->get( '_wjecf_session_data', array() );
|
679 |
+
}
|
680 |
+
$this->_session_data[ $key ] = $value;
|
681 |
+
if ( $value !== null ) {
|
682 |
+
WC()->session->set( '_wjecf_session_data', $this->_session_data );
|
683 |
+
} else {
|
684 |
+
|
685 |
+
}
|
686 |
+
}
|
687 |
+
|
688 |
+
|
689 |
+
/**
|
690 |
+
* Get overwritable template filename
|
691 |
+
* @param string $template_name
|
692 |
+
* @return string Template filename
|
693 |
+
*/
|
694 |
+
public function get_template_filename( $template_name ) {
|
695 |
+
$template_path = 'woocommerce-auto-added-coupons';
|
696 |
+
|
697 |
+
$plugin_template_path = plugin_dir_path( dirname(__FILE__) ) . 'templates/';
|
698 |
+
|
699 |
+
//Get template overwritten file
|
700 |
+
$template = locate_template( trailingslashit( $template_path ) . $template_name );
|
701 |
+
|
702 |
+
// Get default template
|
703 |
+
if ( ! $template ) {
|
704 |
+
$template = $plugin_template_path . $template_name;
|
705 |
+
}
|
706 |
+
|
707 |
+
return $template;
|
708 |
+
}
|
709 |
+
|
710 |
+
/**
|
711 |
+
* Include a template file, either from this plugins directory or overwritten in the themes directory
|
712 |
+
* @param type $template_name
|
713 |
+
* @return type
|
714 |
+
*/
|
715 |
+
public function include_template( $template_name, $variables = array() ) {
|
716 |
+
extract( $variables );
|
717 |
+
include( $this->get_template_filename( $template_name ) );
|
718 |
+
}
|
719 |
+
|
720 |
+
/**
|
721 |
+
* Log message for debugging
|
722 |
+
* @param string $string The message to log
|
723 |
+
* @param int $skip_backtrace Defaults to 0, amount of items to skip in backtrace to fetch class and method name
|
724 |
+
*/
|
725 |
+
public function log( $string, $skip_backtrace = 0) {
|
726 |
+
if ( $this->debug_mode ) {
|
727 |
+
$nth = 1 + $skip_backtrace;
|
728 |
+
$bt = debug_backtrace();
|
729 |
+
$class = $bt[$nth]['class'];
|
730 |
+
$function = $bt[$nth]['function'];
|
731 |
+
|
732 |
+
$row = array(
|
733 |
+
'time' => time(),
|
734 |
+
'class' => $class,
|
735 |
+
'function' => $function,
|
736 |
+
'filter' => current_filter(),
|
737 |
+
'message' => $string,
|
738 |
+
);
|
739 |
+
$this->log[] = $row;
|
740 |
+
error_log( $row['filter'] . ' ' . $row['class'] . '::' . $row['function'] . ' ' . $row['message'] );
|
741 |
+
}
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Output the log as html
|
746 |
+
*/
|
747 |
+
public function render_log() {
|
748 |
+
if ( $this->debug_mode && current_user_can( 'manage_options' ) && defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) {
|
749 |
+
echo "<table class='soft79_wjecf_log'>";
|
750 |
+
foreach( $this->log as $row ) {
|
751 |
+
$cells = array(
|
752 |
+
date("H:i:s", $row['time']),
|
753 |
+
esc_html( $row['filter'] ),
|
754 |
+
esc_html( $row['class'] . '::' . $row['function'] ),
|
755 |
+
esc_html( $row['message'] ),
|
756 |
+
);
|
757 |
+
echo "<tr><td>" . implode( "</td><td>", $cells ) . "</td></tr>";
|
758 |
+
}
|
759 |
+
$colspan = isset( $cells ) ? count( $cells ) : 1;
|
760 |
+
echo "<tr><td colspan='" . $colspan . "'>Current coupons in cart: " . implode( ", ", WC()->cart->applied_coupons ) . "</td></tr>";
|
761 |
+
echo "</table>";
|
762 |
+
}
|
763 |
+
}
|
764 |
|
765 |
}
|
includes/wjecf-wc.php
CHANGED
@@ -10,145 +10,145 @@ defined('ABSPATH') or die();
|
|
10 |
*/
|
11 |
class WJECF_WC {
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
|
52 |
/**
|
53 |
* Returns a specific item in the cart.
|
54 |
*
|
55 |
* @param string $cart_item_key Cart item key.
|
56 |
* @return array Item data
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
|
127 |
//ADMIN
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
$product_key_values = array();
|
153 |
foreach ( $selected_ids as $product_id ) {
|
154 |
$product = wc_get_product( $product_id );
|
@@ -157,203 +157,256 @@ class WJECF_WC {
|
|
157 |
}
|
158 |
}
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
|
238 |
//VERSION
|
239 |
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
|
280 |
//INSTANCE
|
281 |
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
}
|
296 |
|
297 |
|
298 |
class WJECF_Wrap {
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
}
|
357 |
|
358 |
}
|
359 |
|
@@ -362,347 +415,347 @@ class WJECF_Wrap {
|
|
362 |
*/
|
363 |
class WJECF_Wrap_Coupon extends WJECF_Wrap {
|
364 |
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
|
601 |
}
|
602 |
|
603 |
class WJECF_Wrap_Product extends WJECF_Wrap {
|
604 |
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
|
708 |
}
|
10 |
*/
|
11 |
class WJECF_WC {
|
12 |
|
13 |
+
protected $wrappers = array();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Wrap a data object (WC 2.7 introduced WC_Data)
|
17 |
+
* @param type $object
|
18 |
+
* @return type
|
19 |
+
*/
|
20 |
+
public function wrap( $object, $use_pool = true ) {
|
21 |
+
if ( $use_pool ) {
|
22 |
+
//Prevent a huge amount of wrappers to be initiated; one wrapper per object instance should do the trick
|
23 |
+
foreach( $this->wrappers as $wrapper ) {
|
24 |
+
if ($wrapper->holds( $object ) ) {
|
25 |
+
//error_log('Reusing wrapper ' . get_class( $object ) );
|
26 |
+
return $wrapper;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
}
|
30 |
+
|
31 |
+
if ( is_numeric( $object ) ) {
|
32 |
+
$post_type = get_post_type( $object );
|
33 |
+
if ( $post_type == 'shop_coupon' ) {
|
34 |
+
$object = WJECF_WC()->get_coupon( $object );
|
35 |
+
} elseif ( $post_type == 'product' ) {
|
36 |
+
$object = new WC_Product( $object );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
|
41 |
+
if ( $object instanceof WC_Coupon ) {
|
42 |
+
return $this->wrappers[] = new WJECF_Wrap_Coupon( $object );
|
43 |
+
}
|
44 |
+
|
45 |
+
if ( $object instanceof WC_Product ) {
|
46 |
+
return $this->wrappers[] = new WJECF_Wrap_Product( $object );
|
47 |
+
}
|
48 |
+
|
49 |
+
throw new Exception( 'Cannot wrap ' . get_class( $object ) );
|
50 |
+
}
|
51 |
|
52 |
/**
|
53 |
* Returns a specific item in the cart.
|
54 |
*
|
55 |
* @param string $cart_item_key Cart item key.
|
56 |
* @return array Item data
|
57 |
+
*/
|
58 |
+
public function get_cart_item( $cart_item_key ) {
|
59 |
+
if ( $this->check_woocommerce_version('2.2.9') ) {
|
60 |
+
return WC()->cart->get_cart_item( $cart_item_key );
|
61 |
+
}
|
62 |
+
|
63 |
+
return isset( WC()->cart->cart_contents[ $cart_item_key ] ) ? WC()->cart->cart_contents[ $cart_item_key ] : array();
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Get categories of a product (and anchestors)
|
68 |
+
* @param int $product_id
|
69 |
+
* @return array product_cat_ids
|
70 |
+
*/
|
71 |
+
public function wc_get_product_cat_ids( $product_id ) {
|
72 |
+
//Since WC 2.5.0
|
73 |
+
if ( function_exists( 'wc_get_product_cat_ids' ) ) {
|
74 |
+
return wc_get_product_cat_ids( $product_id );
|
75 |
+
}
|
76 |
+
|
77 |
+
$product_cats = wp_get_post_terms( $product_id, 'product_cat', array( "fields" => "ids" ) );
|
78 |
+
|
79 |
+
foreach ( $product_cats as $product_cat ) {
|
80 |
+
$product_cats = array_merge( $product_cats, get_ancestors( $product_cat, 'product_cat' ) );
|
81 |
+
}
|
82 |
+
return $product_cats;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Coupon types that apply to individual products. Controls which validation rules will apply.
|
87 |
+
*
|
88 |
+
* @since 2.5.0
|
89 |
+
* @return array
|
90 |
+
*/
|
91 |
+
public function wc_get_product_coupon_types() {
|
92 |
+
//Since WC 2.5.0
|
93 |
+
if ( function_exists( 'wc_get_product_coupon_types' ) ) {
|
94 |
+
return wc_get_product_coupon_types();
|
95 |
+
}
|
96 |
+
return array( 'fixed_product', 'percent_product' );
|
97 |
+
}
|
98 |
+
|
99 |
+
public function wc_get_cart_coupon_types() {
|
100 |
+
//Since WC 2.5.0
|
101 |
+
if ( function_exists( 'wc_get_cart_coupon_types' ) ) {
|
102 |
+
return wc_get_cart_coupon_types();
|
103 |
+
}
|
104 |
+
return array( 'fixed_cart', 'percent' );
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @since 2.4.0 for WC 2.7 compatibility
|
109 |
+
*
|
110 |
+
* Get a WC_Coupon object
|
111 |
+
* @param WC_Coupon|string $coupon The coupon code or a WC_Coupon object
|
112 |
+
* @return WC_Coupon The coupon object
|
113 |
+
*/
|
114 |
+
public function get_coupon( $coupon ) {
|
115 |
+
if ( is_numeric( $coupon ) ) {
|
116 |
+
//By id
|
117 |
+
global $wpdb;
|
118 |
+
$coupon = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $coupon ) );
|
119 |
+
}
|
120 |
+
if ( ! ( $coupon instanceof WC_Coupon ) ) {
|
121 |
+
//By code
|
122 |
+
$coupon = new WC_Coupon( $coupon );
|
123 |
+
}
|
124 |
+
return $coupon;
|
125 |
+
}
|
126 |
|
127 |
//ADMIN
|
128 |
|
129 |
+
/**
|
130 |
+
* Display a WooCommerce help tip
|
131 |
+
* @param string $tip The tip to display
|
132 |
+
* @return string
|
133 |
+
*/
|
134 |
+
public function wc_help_tip( $tip ) {
|
135 |
+
//Since WC 2.5.0
|
136 |
+
if ( function_exists( 'wc_help_tip' ) ) {
|
137 |
+
return wc_help_tip( $tip );
|
138 |
+
}
|
139 |
+
|
140 |
+
return '<img class="help_tip" style="margin-top: 21px;" data-tip="' . esc_attr( $tip ) . '" src="' . esc_url( WC()->plugin_url() ) . '/assets/images/help.png" height="16" width="16" />';
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Renders a product selection <input>. Will use either select2 v4 (WC3.0+) select2 v3 (WC2.3+) or chosen (< WC2.3)
|
145 |
+
* @param string $dom_id
|
146 |
+
* @param string $field_name
|
147 |
+
* @param array $selected_ids Array of integers
|
148 |
+
* @param string|null $placeholder
|
149 |
+
* @return void
|
150 |
+
*/
|
151 |
+
public function render_admin_product_selector( $dom_id, $field_name, $selected_ids, $placeholder = null ) {
|
152 |
$product_key_values = array();
|
153 |
foreach ( $selected_ids as $product_id ) {
|
154 |
$product = wc_get_product( $product_id );
|
157 |
}
|
158 |
}
|
159 |
|
160 |
+
if ( $placeholder === null ) $placeholder = __( 'Search for a product…', 'woocommerce' );
|
161 |
+
|
162 |
+
//In WooCommerce version 2.3.0 chosen was replaced by select2
|
163 |
+
//In WooCommerce version 3.0 select2 v3 was replaced by select2 v4
|
164 |
+
if ( $this->check_woocommerce_version('3.0') ) {
|
165 |
+
$this->render_admin_select2_v4_product_selector( $dom_id, $field_name, $product_key_values, $placeholder );
|
166 |
+
} elseif ( $this->check_woocommerce_version('2.3.0') ) {
|
167 |
+
$this->render_admin_select2_product_selector( $dom_id, $field_name, $product_key_values, $placeholder );
|
168 |
+
} else {
|
169 |
+
$this->render_admin_chosen_product_selector( $dom_id, $field_name, $product_key_values, $placeholder );
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Renders a product selection <input>.
|
176 |
+
* Chosen (Legacy)
|
177 |
+
* @param string $dom_id
|
178 |
+
* @param string $field_name
|
179 |
+
* @param array $selected_ids Array of integers
|
180 |
+
* @param string|null $placeholder
|
181 |
+
*/
|
182 |
+
private function render_admin_chosen_product_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder ) {
|
183 |
+
// $selected_keys_and_values must be an array of [ id => name ]
|
184 |
+
|
185 |
+
echo '<select id="' . esc_attr( $dom_id ) . '" name="' . esc_attr( $field_name ) . '[]" class="ajax_chosen_select_products_and_variations" multiple="multiple" data-placeholder="' . esc_attr( $placeholder ) . '">';
|
186 |
+
foreach ( $selected_keys_and_values as $product_id => $product_name ) {
|
187 |
+
echo '<option value="' . $product_id . '" selected="selected">' . $product_name . '</option>';
|
188 |
+
}
|
189 |
+
echo '</select>';
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* @since 2.4.1 for WC 3.0 compatibility
|
194 |
+
*
|
195 |
+
* Renders a product selection <input>.
|
196 |
+
* Select2 version 3 (Since WC 2.3.0)
|
197 |
+
* @param string $dom_id
|
198 |
+
* @param string $field_name
|
199 |
+
* @param array $selected_ids Array of integers
|
200 |
+
* @param string|null $placeholder
|
201 |
+
*/
|
202 |
+
private function render_admin_select2_product_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder ) {
|
203 |
+
// $selected_keys_and_values must be an array of [ id => name ]
|
204 |
+
|
205 |
+
$json_encoded = esc_attr( json_encode( $selected_keys_and_values ) );
|
206 |
+
echo '<input type="hidden" class="wc-product-search" data-multiple="true" style="width: 50%;" name="'
|
207 |
+
. esc_attr( $field_name ) . '" data-placeholder="'
|
208 |
+
. esc_attr( $placeholder ) . '" data-action="woocommerce_json_search_products_and_variations" data-selected="'
|
209 |
+
. $json_encoded . '" value="' . implode( ',', array_keys( $selected_keys_and_values ) ) . '" />';
|
210 |
+
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Renders a product selection <input>.
|
215 |
+
* Select2 version 4 (Since WC 3.0)
|
216 |
+
* @param string $dom_id
|
217 |
+
* @param string $field_name
|
218 |
+
* @param string $selected_keys_and_values
|
219 |
+
* @param string $placeholder
|
220 |
+
*/
|
221 |
+
private function render_admin_select2_v4_product_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder ) {
|
222 |
+
// $selected_keys_and_values must be an array of [ id => name ]
|
223 |
+
|
224 |
+
$json_encoded = esc_attr( json_encode( $selected_keys_and_values ) );
|
225 |
+
|
226 |
+
echo '<select id="'. esc_attr( $dom_id ) .'" class="wc-product-search" name="'
|
227 |
+
. esc_attr( $field_name ) . '[]" multiple="multiple" style="width: 50%;" data-placeholder="'
|
228 |
+
. esc_attr( $placeholder ) . '" data-action="woocommerce_json_search_products_and_variations">';
|
229 |
+
|
230 |
+
foreach ( $selected_keys_and_values as $product_id => $product_name ) {
|
231 |
+
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product_name ) . '</option>';
|
232 |
+
}
|
233 |
+
|
234 |
+
echo '</select>';
|
235 |
+
}
|
236 |
+
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Renders a customer selection <input>. Will use either select2 v4 (WC3.0+) or select2 v3 (WC2.3+)
|
240 |
+
* @param string $dom_id
|
241 |
+
* @param string $field_name
|
242 |
+
* @param array $selected_customer_ids Array of integers
|
243 |
+
* @param string|null $placeholder
|
244 |
+
* @return void
|
245 |
+
*/
|
246 |
+
public function render_admin_customer_selector( $dom_id, $field_name, $selected_customer_ids, $placeholder = null ) {
|
247 |
+
$selected_keys_and_values = array();
|
248 |
+
foreach ( $selected_customer_ids as $customer_id ) {
|
249 |
+
$customer = get_userdata( $customer_id );
|
250 |
+
if ( is_object( $customer ) ) {
|
251 |
+
$selected_keys_and_values[ $customer_id ] = $customer->display_name . ' (#' . $customer->ID . ' – ' . sanitize_email( $customer->user_email ) . ')';
|
252 |
+
}
|
253 |
+
}
|
254 |
+
if ( $placeholder === null ) $placeholder = __( 'Any customer', 'woocommerce-jos-autocoupon' );
|
255 |
+
|
256 |
+
//In WooCommerce version 2.3.0 chosen was replaced by select2
|
257 |
+
//In WooCommerce version 3.0 select2 v3 was replaced by select2 v4
|
258 |
+
if ( $this->check_woocommerce_version('3.0') ) {
|
259 |
+
$this->render_admin_select2_v4_customer_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder );
|
260 |
+
} else {
|
261 |
+
$this->render_admin_select2_customer_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder );
|
262 |
+
}
|
263 |
+
}
|
264 |
+
|
265 |
+
private function render_admin_select2_customer_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder ) {
|
266 |
+
// $selected_keys_and_values must be an array of [ id => name ] .e.g. [ 12 => 'John Smith (#12 john.smith@example.com)' ]
|
267 |
+
|
268 |
+
$json_encoded = esc_attr( json_encode( $selected_keys_and_values ) );
|
269 |
+
echo '<input type="hidden" class="wc-customer-search" data-multiple="true" style="width: 50%;" name="'
|
270 |
+
. esc_attr( $field_name ) . '" data-placeholder="'
|
271 |
+
. esc_attr( $placeholder ) . '" data-action="woocommerce_json_search_customers" data-selected="'
|
272 |
+
. $json_encoded . '" value="' . implode( ',', array_keys( $selected_keys_and_values ) ) . '" />';
|
273 |
+
}
|
274 |
+
|
275 |
+
private function render_admin_select2_v4_customer_selector( $dom_id, $field_name, $selected_keys_and_values, $placeholder ) {
|
276 |
+
// $selected_keys_and_values must be an array of [ id => name ]
|
277 |
+
|
278 |
+
$json_encoded = esc_attr( json_encode( $selected_keys_and_values ) );
|
279 |
+
|
280 |
+
echo '<select id="'. esc_attr( $dom_id ) .'" class="wc-customer-search" name="'
|
281 |
+
. esc_attr( $field_name ) . '[]" multiple="multiple" style="width: 50%;" data-placeholder="'
|
282 |
+
. esc_attr( $placeholder ) . '" data-action="woocommerce_json_search_customers">';
|
283 |
+
|
284 |
+
foreach ( $selected_keys_and_values as $key => $value ) {
|
285 |
+
echo '<option value="' . esc_attr( $key ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $value ) . '</option>';
|
286 |
+
}
|
287 |
+
|
288 |
+
echo '</select>';
|
289 |
+
}
|
290 |
|
291 |
|
292 |
//VERSION
|
293 |
|
294 |
+
/**
|
295 |
+
* Check whether WooCommerce version is greater or equal than $req_version
|
296 |
+
* @param string @req_version The version to compare to
|
297 |
+
* @return bool true if WooCommerce is at least the given version
|
298 |
+
*/
|
299 |
+
public function check_woocommerce_version( $req_version ) {
|
300 |
+
return version_compare( $this->get_woocommerce_version(), $req_version, '>=' );
|
301 |
+
}
|
302 |
+
|
303 |
+
private $wc_version = null;
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Get the WooCommerce version number
|
307 |
+
* @return string|bool WC Version number or false if WC not detected
|
308 |
+
*/
|
309 |
+
public function get_woocommerce_version() {
|
310 |
+
if ( isset( $this->wc_version ) ) {
|
311 |
+
return $this->wc_version;
|
312 |
+
}
|
313 |
+
|
314 |
+
if ( defined( 'WC_VERSION' ) ) {
|
315 |
+
return $this->wc_version = WC_VERSION;
|
316 |
+
}
|
317 |
+
|
318 |
+
// If get_plugins() isn't available, require it
|
319 |
+
if ( ! function_exists( 'get_plugins' ) ) {
|
320 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
321 |
+
}
|
322 |
+
// Create the plugins folder and file variables
|
323 |
+
$plugin_folder = get_plugins( '/woocommerce' );
|
324 |
+
$plugin_file = 'woocommerce.php';
|
325 |
+
|
326 |
+
// If the plugin version number is set, return it
|
327 |
+
if ( isset( $plugin_folder[$plugin_file]['Version'] ) ) {
|
328 |
+
return $this->wc_version = $plugin_folder[$plugin_file]['Version'];
|
329 |
+
}
|
330 |
+
|
331 |
+
return $this->wc_version = false; // Not found
|
332 |
+
}
|
333 |
|
334 |
//INSTANCE
|
335 |
|
336 |
+
/**
|
337 |
+
* Singleton Instance
|
338 |
+
*
|
339 |
+
* @static
|
340 |
+
* @return Singleton Instance
|
341 |
+
*/
|
342 |
+
public static function instance() {
|
343 |
+
if ( is_null( self::$_instance ) ) {
|
344 |
+
self::$_instance = new self();
|
345 |
+
}
|
346 |
+
return self::$_instance;
|
347 |
+
}
|
348 |
+
protected static $_instance = null;
|
349 |
}
|
350 |
|
351 |
|
352 |
class WJECF_Wrap {
|
353 |
+
protected $object = null;
|
354 |
+
|
355 |
+
public function __construct( $object ) {
|
356 |
+
$this->object = $object;
|
357 |
+
//error_log('Wrapping ' . get_class( $object ) );
|
358 |
+
}
|
359 |
+
|
360 |
+
public function get_id() {
|
361 |
+
//Since WC 2.7
|
362 |
+
if ( is_callable( array( $this->object, 'get_id' ) ) ) {
|
363 |
+
return $this->object->get_id();
|
364 |
+
}
|
365 |
+
return $this->object->id;
|
366 |
+
}
|
367 |
+
|
368 |
+
public function holds( $object ) {
|
369 |
+
return $object === $this->object;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Get Meta Data by Key.
|
374 |
+
* @since 2.4.0
|
375 |
+
* @param string $key
|
376 |
+
* @param bool $single return first found meta, or all
|
377 |
+
* @return mixed
|
378 |
+
*/
|
379 |
+
public function get_meta( $meta_key, $single = true ) {
|
380 |
+
if ( is_callable( array( $this->object, 'get_meta' ) ) ) {
|
381 |
+
return $this->get_meta_wc27( $meta_key, $single );
|
382 |
+
}
|
383 |
+
|
384 |
+
return $this->get_meta_legacy( $meta_key, $single );
|
385 |
+
|
386 |
+
//return get_post_meta( $this->object->id, $meta_key, $single );
|
387 |
+
//If no value found:
|
388 |
+
//If $single is true, an empty string is returned.
|
389 |
+
//If $single is false, an empty array is returned.
|
390 |
+
}
|
391 |
+
|
392 |
+
protected function get_meta_wc27( $meta_key, $single = true ) {
|
393 |
+
$values = $this->object->get_meta( $meta_key, $single );
|
394 |
+
if ($single) {
|
395 |
+
return $values; //it's just one, dispite the plural in the name!
|
396 |
+
}
|
397 |
+
|
398 |
+
if ( $values === '' ) {
|
399 |
+
return array(); //get_meta returns empty string if meta does not exist
|
400 |
+
}
|
401 |
+
|
402 |
+
return wp_list_pluck( array_values( $values ), 'value' ); //when not using array_values; the index might not start with 0
|
403 |
+
}
|
404 |
+
|
405 |
+
protected $meta_cache = array();
|
406 |
+
|
407 |
+
protected function get_meta_legacy( $meta_key, $single = true ) {
|
408 |
+
throw new Exception( sprintf( '%s::get_meta_legacy not implemented', get_class( $this ) ) );
|
409 |
+
}
|
|
|
410 |
|
411 |
}
|
412 |
|
415 |
*/
|
416 |
class WJECF_Wrap_Coupon extends WJECF_Wrap {
|
417 |
|
418 |
+
public function exists() {
|
419 |
+
return $this->get_id() > 0;
|
420 |
+
}
|
421 |
+
|
422 |
+
public function get_code() {
|
423 |
+
if ( is_callable( array( $this->object, 'get_code' ) ) ) {
|
424 |
+
return $this->object->get_code();
|
425 |
+
}
|
426 |
+
|
427 |
+
return $this->object->code;
|
428 |
+
}
|
429 |
+
|
430 |
+
public function get_amount() {
|
431 |
+
if ( is_callable( array( $this->object, 'get_amount' ) ) ) {
|
432 |
+
return $this->object->get_amount();
|
433 |
+
}
|
434 |
+
|
435 |
+
return $this->object->coupon_amount;
|
436 |
+
}
|
437 |
+
|
438 |
+
public function get_individual_use() {
|
439 |
+
if ( is_callable( array( $this->object, 'get_individual_use' ) ) ) {
|
440 |
+
return $this->object->get_individual_use();
|
441 |
+
}
|
442 |
+
|
443 |
+
return $this->object->individual_use == 'yes';
|
444 |
+
}
|
445 |
+
|
446 |
+
public function get_limit_usage_to_x_items() {
|
447 |
+
if ( is_callable( array( $this->object, 'get_limit_usage_to_x_items' ) ) ) {
|
448 |
+
return $this->object->get_limit_usage_to_x_items();
|
449 |
+
}
|
450 |
+
|
451 |
+
return $this->object->limit_usage_to_x_items;
|
452 |
+
}
|
453 |
+
|
454 |
+
public function set_limit_usage_to_x_items( $limit_usage_to_x_items ) {
|
455 |
+
if ( is_callable( array( $this->object, 'set_limit_usage_to_x_items' ) ) ) {
|
456 |
+
$this->object->set_limit_usage_to_x_items( $limit_usage_to_x_items );
|
457 |
+
} else {
|
458 |
+
$this->object->limit_usage_to_x_items = $limit_usage_to_x_items;
|
459 |
+
}
|
460 |
+
}
|
461 |
+
|
462 |
+
public function get_discount_type() {
|
463 |
+
if ( is_callable( array( $this->object, 'get_discount_type' ) ) ) {
|
464 |
+
return $this->object->get_discount_type();
|
465 |
+
}
|
466 |
+
|
467 |
+
return $this->object->discount_type;
|
468 |
+
}
|
469 |
+
|
470 |
+
public function set_discount_type( $discount_type ) {
|
471 |
+
if ( is_callable( array( $this->object, 'set_discount_type' ) ) ) {
|
472 |
+
$this->object->set_discount_type( $discount_type );
|
473 |
+
} else {
|
474 |
+
$this->object->discount_type = $discount_type;
|
475 |
+
$this->object->type = $discount_type;
|
476 |
+
}
|
477 |
+
}
|
478 |
+
|
479 |
+
|
480 |
+
public function get_email_restrictions() {
|
481 |
+
if ( is_callable( array( $this->object, 'get_email_restrictions' ) ) ) {
|
482 |
+
return $this->object->get_email_restrictions();
|
483 |
+
}
|
484 |
+
|
485 |
+
return $this->object->customer_email;
|
486 |
+
}
|
487 |
+
|
488 |
+
public function get_product_ids() {
|
489 |
+
if ( is_callable( array( $this->object, 'get_product_ids' ) ) ) {
|
490 |
+
return $this->object->get_product_ids();
|
491 |
+
}
|
492 |
+
|
493 |
+
return $this->object->product_ids;
|
494 |
+
}
|
495 |
+
|
496 |
+
public function get_free_shipping() {
|
497 |
+
if ( is_callable( array( $this->object, 'get_free_shipping' ) ) ) {
|
498 |
+
return $this->object->get_free_shipping();
|
499 |
+
}
|
500 |
+
|
501 |
+
return $this->object->enable_free_shipping();
|
502 |
+
}
|
503 |
+
|
504 |
+
public function get_product_categories() {
|
505 |
+
if ( is_callable( array( $this->object, 'get_product_categories' ) ) ) {
|
506 |
+
return $this->object->get_product_categories();
|
507 |
+
}
|
508 |
+
|
509 |
+
return $this->object->product_categories;
|
510 |
+
}
|
511 |
+
|
512 |
+
public function get_minimum_amount() {
|
513 |
+
if ( is_callable( array( $this->object, 'get_minimum_amount' ) ) ) {
|
514 |
+
return $this->object->get_minimum_amount();
|
515 |
+
}
|
516 |
+
|
517 |
+
return $this->object->minimum_amount;
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Set the product IDs this coupon cannot be used with.
|
522 |
+
* @since 2.4.2 (For WC3.0)
|
523 |
+
* @param array $excluded_product_ids
|
524 |
+
* @throws WC_Data_Exception
|
525 |
+
*/
|
526 |
+
public function set_excluded_product_ids( $excluded_product_ids ) {
|
527 |
+
if ( is_callable( array( $this->object, 'set_excluded_product_ids' ) ) ) {
|
528 |
+
$this->object->set_excluded_product_ids( $excluded_product_ids );
|
529 |
+
} else {
|
530 |
+
//NOTE: Prior to WC2.7 it was called exclude_ instead of excluded_
|
531 |
+
$this->object->exclude_product_ids = $excluded_product_ids;
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* Set the product category IDs this coupon cannot be used with.
|
537 |
+
* @since 2.4.2 (For WC3.0)
|
538 |
+
* @param array $excluded_product_categories
|
539 |
+
* @throws WC_Data_Exception
|
540 |
+
*/
|
541 |
+
public function set_excluded_product_categories( $excluded_product_categories ) {
|
542 |
+
if ( is_callable( array( $this->object, 'set_excluded_product_categories' ) ) ) {
|
543 |
+
$this->object->set_excluded_product_categories( $excluded_product_categories );
|
544 |
+
} else {
|
545 |
+
//NOTE: Prior to WC2.7 it was called exclude_ instead of excluded_
|
546 |
+
$this->object->exclude_product_categories = $excluded_product_categories;
|
547 |
+
}
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Set if this coupon should excluded sale items or not.
|
552 |
+
* @since 2.4.2 (For WC3.0)
|
553 |
+
* @param bool $exclude_sale_items
|
554 |
+
* @throws WC_Data_Exception
|
555 |
+
*/
|
556 |
+
public function set_exclude_sale_items( $exclude_sale_items ) {
|
557 |
+
if ( is_callable( array( $this->object, 'set_exclude_sale_items' ) ) ) {
|
558 |
+
$this->object->set_exclude_sale_items( $exclude_sale_items );
|
559 |
+
} else {
|
560 |
+
//NOTE: Prior to WC2.7 it was yes/no instead of boolean
|
561 |
+
$this->object->exclude_sale_items = $exclude_sale_items ? 'yes' : 'no';
|
562 |
+
}
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Check the type of the coupon
|
567 |
+
* @param string|array $type The type(s) we want to check for
|
568 |
+
* @return bool True if the coupon is of the type
|
569 |
+
*/
|
570 |
+
public function is_type( $type ) {
|
571 |
+
//Backwards compatibility 2.2.11
|
572 |
+
if ( method_exists( $this->object, 'is_type' ) ) {
|
573 |
+
return $this->object->is_type( $type );
|
574 |
+
}
|
575 |
+
|
576 |
+
return ( $this->object->discount_type == $type || ( is_array( $type ) && in_array( $this->object->discount_type, $type ) ) ) ? true : false;
|
577 |
+
}
|
578 |
+
|
579 |
+
/**
|
580 |
+
* Update single meta data item by meta key.
|
581 |
+
* Call save() afterwards!
|
582 |
+
* @since 2.4.0
|
583 |
+
* @param string $key
|
584 |
+
* @param mixed $value The value; use null to clear
|
585 |
+
*/
|
586 |
+
public function set_meta( $meta_key, $value ) {
|
587 |
+
if ( is_callable( array( $this->object, 'update_meta_data' ) ) ) {
|
588 |
+
if ( $value === null ) {
|
589 |
+
$this->object->delete_meta_data( $meta_key );
|
590 |
+
} else {
|
591 |
+
$this->object->update_meta_data( $meta_key, $value );
|
592 |
+
}
|
593 |
+
return;
|
594 |
+
}
|
595 |
+
|
596 |
+
$this->maybe_get_custom_fields();
|
597 |
+
//WJECF()->log('...setting legacy meta ' . $meta_key );
|
598 |
+
$this->legacy_custom_fields[ $meta_key ] = $value;
|
599 |
+
$this->legacy_unsaved_keys[] = $meta_key;
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Save the metadata
|
604 |
+
* @return id of this object
|
605 |
+
*/
|
606 |
+
public function save() {
|
607 |
+
//WJECF()->log('Saving ' . $this->get_id() );
|
608 |
+
if ( is_callable( array( $this->object, 'save' ) ) ) {
|
609 |
+
return $this->object->save();
|
610 |
+
}
|
611 |
+
|
612 |
+
//Save the unsaved...
|
613 |
+
foreach( $this->legacy_unsaved_keys as $meta_key ) {
|
614 |
+
//WJECF()->log('...saving legacy meta ' . $meta_key );
|
615 |
+
$value = $this->legacy_custom_fields[ $meta_key ];
|
616 |
+
if ( $value === null ) {
|
617 |
+
delete_post_meta( $this->get_id(), $meta_key );
|
618 |
+
} else {
|
619 |
+
update_post_meta( $this->get_id(), $meta_key, $value );
|
620 |
+
}
|
621 |
+
}
|
622 |
+
$this->legacy_unsaved_keys = array();
|
623 |
+
|
624 |
+
return $this->get_id();
|
625 |
+
}
|
626 |
+
|
627 |
+
protected $legacy_custom_fields = null;
|
628 |
+
protected $legacy_unsaved_keys = array();
|
629 |
+
|
630 |
+
protected function maybe_get_custom_fields() {
|
631 |
+
//Read custom fields if not yet done
|
632 |
+
if ( is_null( $this->legacy_custom_fields ) ) {
|
633 |
+
$this->legacy_custom_fields = $this->object->coupon_custom_fields;
|
634 |
+
}
|
635 |
+
}
|
636 |
+
|
637 |
+
protected function get_meta_legacy( $meta_key, $single = true ) {
|
638 |
+
//Read custom fields if not yet done
|
639 |
+
$this->maybe_get_custom_fields();
|
640 |
+
|
641 |
+
if ( isset( $this->legacy_custom_fields[ $meta_key ] ) ) {
|
642 |
+
$values = $this->legacy_custom_fields[ $meta_key ];
|
643 |
+
//WP_CLI::log( "LEGACY:" . print_r( $values, true ));
|
644 |
+
if ($single) {
|
645 |
+
return maybe_unserialize( reset( $values ) ); //reset yields the first
|
646 |
+
}
|
647 |
+
$values = array_map( 'maybe_unserialize', $values );
|
648 |
+
return $values;
|
649 |
+
}
|
650 |
+
|
651 |
+
return $single ? '' : array();
|
652 |
+
}
|
653 |
|
654 |
}
|
655 |
|
656 |
class WJECF_Wrap_Product extends WJECF_Wrap {
|
657 |
|
658 |
+
public function is_variation() {
|
659 |
+
return $this->object instanceof WC_Product_Variation;
|
660 |
+
}
|
661 |
+
|
662 |
+
/**
|
663 |
+
* Retrieve the id of the product or the variation id if it's a variant.
|
664 |
+
*
|
665 |
+
* (2.4.0: Moved from WJECF_Controller to WJECF_WC)
|
666 |
+
*
|
667 |
+
* @param WC_Product $product
|
668 |
+
* @return int|bool The variation or product id. False if not a valid product
|
669 |
+
*/
|
670 |
+
public function get_product_or_variation_id() {
|
671 |
+
if ( $this->is_variation() ) {
|
672 |
+
return $this->get_variation_id();
|
673 |
+
} elseif ( $this->object instanceof WC_Product ) {
|
674 |
+
return $this->get_id();
|
675 |
+
} else {
|
676 |
+
return false;
|
677 |
+
}
|
678 |
+
}
|
679 |
+
|
680 |
+
/**
|
681 |
+
* Retrieve the id of the parent product if it's a variation; otherwise retrieve this products id
|
682 |
+
*
|
683 |
+
* (2.4.0: Moved from WJECF_Controller to WJECF_WC)
|
684 |
+
*
|
685 |
+
* @param WC_Product $product
|
686 |
+
* @return int|bool The product id. False if this product is not a variation
|
687 |
+
*/
|
688 |
+
public function get_variable_product_id() {
|
689 |
+
if ( ! $this->is_variation() ) {
|
690 |
+
return false;
|
691 |
+
}
|
692 |
+
|
693 |
+
if ( is_callable( array( $this->object, 'get_parent_id' ) ) ) {
|
694 |
+
return $this->object->get_parent_id();
|
695 |
+
} else {
|
696 |
+
return wp_get_post_parent_id( $this->object->variation_id );
|
697 |
+
}
|
698 |
+
}
|
699 |
+
|
700 |
+
/**
|
701 |
+
* Get current variation id
|
702 |
+
* @return int|bool False if this is not a variation
|
703 |
+
*/
|
704 |
+
protected function get_variation_id() {
|
705 |
+
if ( ! $this->is_variation() ) {
|
706 |
+
return false;
|
707 |
+
}
|
708 |
+
|
709 |
+
if ( is_callable( array( $this->object, 'get_id' ) ) ) {
|
710 |
+
//WP_CLI::log( "get_variation_id:WC27 " . get_class( $this->object ) );
|
711 |
+
return $this->object->get_id();
|
712 |
+
} elseif ( is_callable( array( $this->object, 'get_variation_id' ) ) ) {
|
713 |
+
//WP_CLI::log( "get_variation_id:LEGACY " . get_class( $this->object ) );
|
714 |
+
return $this->object->get_variation_id();
|
715 |
+
}
|
716 |
+
//WP_CLI::log( "get_variation_id:VERY OLD " . get_class( $this->object ) );
|
717 |
+
return $this->object->variation_id;
|
718 |
+
}
|
719 |
+
|
720 |
+
|
721 |
+
public function get_name() {
|
722 |
+
if ( is_callable( array( $this->object, 'get_name' ) ) ) {
|
723 |
+
return $this->object->get_name();
|
724 |
+
} else {
|
725 |
+
return $this->object->post->post_title;
|
726 |
+
}
|
727 |
+
}
|
728 |
+
|
729 |
+
public function get_description() {
|
730 |
+
if ( is_callable( array( $this->object, 'get_description' ) ) ) {
|
731 |
+
return $this->object->get_description();
|
732 |
+
} else {
|
733 |
+
return $this->object->post->post_content;
|
734 |
+
}
|
735 |
+
}
|
736 |
+
|
737 |
+
public function get_short_description() {
|
738 |
+
if ( is_callable( array( $this->object, 'get_short_description' ) ) ) {
|
739 |
+
return $this->object->get_short_description();
|
740 |
+
} else {
|
741 |
+
return $this->object->post->post_excerpt;
|
742 |
+
}
|
743 |
+
}
|
744 |
+
|
745 |
+
public function get_tag_ids() {
|
746 |
+
if ( is_callable( array( $this->object, 'get_tag_ids' ) ) ) {
|
747 |
+
return $this->object->get_tag_ids();
|
748 |
+
} else {
|
749 |
+
return $this->legacy_get_term_ids( 'product_tag' );
|
750 |
+
}
|
751 |
+
}
|
752 |
+
|
753 |
+
protected function legacy_get_term_ids( $taxonomy ) {
|
754 |
+
$terms = get_the_terms( $this->get_id(), $taxonomy );
|
755 |
+
if ( false === $terms || is_wp_error( $terms ) ) {
|
756 |
+
return array();
|
757 |
+
}
|
758 |
+
return wp_list_pluck( $terms, 'term_id' );
|
759 |
+
}
|
760 |
|
761 |
}
|
includes/wjecf-wpml.php
CHANGED
@@ -7,53 +7,53 @@ defined('ABSPATH') or die();
|
|
7 |
*/
|
8 |
class WJECF_WPML extends Abstract_WJECF_Plugin {
|
9 |
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
|
27 |
//HOOKS
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
|
37 |
|
38 |
//FUNCTIONS
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
|
53 |
$translated_object_ids = array();
|
54 |
foreach( $object_ids as $object_id) {
|
55 |
-
|
56 |
}
|
57 |
return $translated_object_ids;
|
58 |
-
|
59 |
}
|
7 |
*/
|
8 |
class WJECF_WPML extends Abstract_WJECF_Plugin {
|
9 |
|
10 |
+
public function __construct() {
|
11 |
+
$this->set_plugin_data( array(
|
12 |
+
'description' => __( 'Compatiblity with WPML.', 'woocommerce-jos-autocoupon' ),
|
13 |
+
'dependencies' => array(),
|
14 |
+
'can_be_disabled' => true
|
15 |
+
) );
|
16 |
+
}
|
17 |
+
|
18 |
+
public function init_hook() {
|
19 |
+
global $sitepress;
|
20 |
+
if ( isset( $sitepress ) ) {
|
21 |
+
//WJECF_Controller hooks
|
22 |
+
add_filter( 'wjecf_get_product_ids', array( $this, 'filter_get_product_ids' ), 10 );
|
23 |
+
add_filter( 'wjecf_get_product_cat_ids', array( $this, 'filter_get_product_cat_ids' ), 10 );
|
24 |
+
}
|
25 |
+
}
|
26 |
|
27 |
//HOOKS
|
28 |
|
29 |
+
public function filter_get_product_ids( $product_ids ) {
|
30 |
+
return $this->get_translated_object_ids( $product_ids, 'product' );
|
31 |
+
}
|
32 |
|
33 |
+
public function filter_get_product_cat_ids( $product_cat_ids ) {
|
34 |
+
return $this->get_translated_object_ids( $product_cat_ids, 'product_cat' );
|
35 |
+
}
|
36 |
|
37 |
|
38 |
//FUNCTIONS
|
39 |
|
40 |
+
/**
|
41 |
+
* Get the ids of all the translations. Otherwise return the original array
|
42 |
+
*
|
43 |
+
* @param int|array $product_ids The product_ids to find the translations for
|
44 |
+
* @return array The product ids of all translations
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
public function get_translated_object_ids( $object_ids, $object_type ) {
|
48 |
+
//Make sure it's an array
|
49 |
+
if ( ! is_array( $object_ids ) ) {
|
50 |
+
$object_ids = array( $object_ids );
|
51 |
+
}
|
52 |
|
53 |
$translated_object_ids = array();
|
54 |
foreach( $object_ids as $object_id) {
|
55 |
+
$translated_object_ids[] = apply_filters( 'wpml_object_id', $object_id, $object_type );
|
56 |
}
|
57 |
return $translated_object_ids;
|
58 |
+
}
|
59 |
}
|
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.7.3
|
7 |
-
Stable tag: 2.4.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -106,6 +106,9 @@ Sure! [This](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5T9XQ
|
|
106 |
|
107 |
== Changelog ==
|
108 |
|
|
|
|
|
|
|
109 |
= 2.4.2.1 =
|
110 |
* FIX: WooCommerce < 2.7 compatibility
|
111 |
|
4 |
Tags: woocommerce, coupons, discount
|
5 |
Requires at least: 4.0.0
|
6 |
Tested up to: 4.7.3
|
7 |
+
Stable tag: 2.4.3
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
106 |
|
107 |
== Changelog ==
|
108 |
|
109 |
+
= 2.4.3 =
|
110 |
+
* FIX: Customer selector WooCommerce 3.0.0 compatibility
|
111 |
+
|
112 |
= 2.4.2.1 =
|
113 |
* FIX: WooCommerce < 2.7 compatibility
|
114 |
|
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.4.
|
7 |
* Author: Soft79
|
8 |
* License: GPL2
|
9 |
*/
|
@@ -25,103 +25,103 @@ defined('ABSPATH') or die();
|
|
25 |
|
26 |
if ( ! function_exists( 'wjecf_load_plugin_textdomain' ) ) {
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
|
126 |
}
|
127 |
|
@@ -134,8 +134,8 @@ if ( ! function_exists( 'wjecf_load_plugin_textdomain' ) ) {
|
|
134 |
|
135 |
//Update the cart preview when the billing email is changed by the customer
|
136 |
add_filter( 'woocommerce_checkout_fields', function( $checkout_fields ) {
|
137 |
-
|
138 |
-
|
139 |
} );
|
140 |
|
141 |
// */
|
@@ -147,13 +147,13 @@ add_filter( 'woocommerce_checkout_fields', function( $checkout_fields ) {
|
|
147 |
|
148 |
//Update the cart preview when payment method is changed by the customer
|
149 |
add_action( 'woocommerce_review_order_after_submit' , function () {
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
} );
|
159 |
// */
|
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.4.3
|
7 |
* Author: Soft79
|
8 |
* License: GPL2
|
9 |
*/
|
25 |
|
26 |
if ( ! function_exists( 'wjecf_load_plugin_textdomain' ) ) {
|
27 |
|
28 |
+
/**
|
29 |
+
* Include the file once if it exists.
|
30 |
+
* @param string $filename
|
31 |
+
* @return void
|
32 |
+
*/
|
33 |
+
function wjecf_optional_include( $filename ) {
|
34 |
+
if ( ! file_exists( dirname( __FILE__ ) . '/' . $filename ) ) {
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
|
38 |
+
include_once( $filename );
|
39 |
+
return true;
|
40 |
+
}
|
41 |
+
|
42 |
+
require_once( 'includes/wjecf-wc.php' );
|
43 |
+
require_once( 'includes/wjecf-controller.php' );
|
44 |
+
require_once( 'includes/abstract-wjecf-plugin.php' );
|
45 |
+
require_once( 'includes/admin/wjecf-admin.php' );
|
46 |
+
require_once( 'includes/admin/wjecf-admin-auto-upgrade.php' );
|
47 |
+
//Optional
|
48 |
+
wjecf_optional_include( 'includes/wjecf-autocoupon.php' );
|
49 |
+
wjecf_optional_include( 'includes/wjecf-wpml.php' );
|
50 |
+
//PRO
|
51 |
+
wjecf_optional_include( 'includes/wjecf-pro-controller.php' );
|
52 |
+
wjecf_optional_include( 'includes/wjecf-pro-free-products.php' );
|
53 |
+
wjecf_optional_include( 'includes/wjecf-pro-coupon-queueing.php' );
|
54 |
+
wjecf_optional_include( 'includes/wjecf-pro-product-filter.php' );
|
55 |
+
wjecf_optional_include( 'includes/wjecf-pro-limit-discount-quantities.php' );
|
56 |
+
wjecf_optional_include( 'includes/wjecf-pro-api.php' );
|
57 |
+
|
58 |
+
//Translations
|
59 |
+
add_action( 'plugins_loaded', 'wjecf_load_plugin_textdomain' );
|
60 |
+
function wjecf_load_plugin_textdomain() {
|
61 |
+
$locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce' );
|
62 |
+
|
63 |
+
load_textdomain( 'woocommerce-jos-autocoupon', WP_LANG_DIR . '/woocommerce-jos-autocoupon/woocommerce-jos-autocoupon-' . $locale . '.mo' );
|
64 |
+
load_plugin_textdomain('woocommerce-jos-autocoupon', false, basename(dirname(__FILE__)) . '/languages/' );
|
65 |
+
|
66 |
+
// //WP-cli for debugging
|
67 |
+
// if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
68 |
+
// if ( wjecf_optional_include('includes/WJECF_Debug_CLI.php') ) {
|
69 |
+
// WP_CLI::add_command( 'wjecf', 'WJECF_Debug_CLI' );
|
70 |
+
// }
|
71 |
+
// }
|
72 |
+
|
73 |
+
// Only Initiate the plugin if WooCommerce is active
|
74 |
+
if ( WJECF_WC::instance()->get_woocommerce_version() == false ) {
|
75 |
+
add_action( 'admin_notices', 'wjecf_admin_notice' );
|
76 |
+
function wjecf_admin_notice() {
|
77 |
+
$msg = __( 'WooCommerce Extended Coupon Features is disabled because WooCommerce could not be detected.', 'woocommerce-jos-autocoupon' );
|
78 |
+
echo '<div class="error"><p>' . $msg . '</p></div>';
|
79 |
+
}
|
80 |
+
} else {
|
81 |
+
|
82 |
+
function WJECF_WC() {
|
83 |
+
return WJECF_WC::instance();
|
84 |
+
}
|
85 |
+
|
86 |
+
function WJECF_Wrap( $object ) {
|
87 |
+
return WJECF_WC::instance()->wrap( $object );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get the instance of WJECF
|
92 |
+
* @return WJECF_Controller|WJECF_Pro_Controller The instance of WJECF
|
93 |
+
*/
|
94 |
+
function WJECF() {
|
95 |
+
if ( class_exists( 'WJECF_Pro_Controller' ) ) {
|
96 |
+
return WJECF_Pro_Controller::instance();
|
97 |
+
} else {
|
98 |
+
return WJECF_Controller::instance();
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Get the instance of WJECF_Admin
|
104 |
+
* @return WJECF_Admin The instance of WJECF_Admin
|
105 |
+
*/
|
106 |
+
function WJECF_ADMIN() {
|
107 |
+
return WJECF()->get_plugin('WJECF_Admin');
|
108 |
+
}
|
109 |
+
|
110 |
+
$wjecf_extended_coupon_features = WJECF();
|
111 |
+
|
112 |
+
WJECF()->add_plugin('WJECF_Admin');
|
113 |
+
WJECF()->add_plugin('WJECF_Admin_Auto_Upgrade');
|
114 |
+
WJECF()->add_plugin('WJECF_AutoCoupon');
|
115 |
+
WJECF()->add_plugin('WJECF_WPML');
|
116 |
+
if ( WJECF()->is_pro() ) {
|
117 |
+
WJECF()->add_plugin('WJECF_Pro_Free_Products');
|
118 |
+
WJECF()->add_plugin('WJECF_Pro_Coupon_Queueing');
|
119 |
+
WJECF()->add_plugin('WJECF_Pro_Product_Filter');
|
120 |
+
WJECF()->add_plugin('WJECF_Pro_Limit_Discount_Quantities');
|
121 |
+
}
|
122 |
+
WJECF()->start();
|
123 |
+
}
|
124 |
+
}
|
125 |
|
126 |
}
|
127 |
|
134 |
|
135 |
//Update the cart preview when the billing email is changed by the customer
|
136 |
add_filter( 'woocommerce_checkout_fields', function( $checkout_fields ) {
|
137 |
+
$checkout_fields['billing']['billing_email']['class'][] = 'update_totals_on_change';
|
138 |
+
return $checkout_fields;
|
139 |
} );
|
140 |
|
141 |
// */
|
147 |
|
148 |
//Update the cart preview when payment method is changed by the customer
|
149 |
add_action( 'woocommerce_review_order_after_submit' , function () {
|
150 |
+
?><script type="text/javascript">
|
151 |
+
jQuery(document).ready(function($){
|
152 |
+
$(document.body).on('change', 'input[name="payment_method"]', function() {
|
153 |
+
$('body').trigger('update_checkout');
|
154 |
+
//$.ajax( $fragment_refresh );
|
155 |
+
});
|
156 |
+
});
|
157 |
+
</script><?php
|
158 |
} );
|
159 |
// */
|