WooCommerce Extended Coupon Features - Version 2.4.3

Version Description

  • FIX: Customer selector WooCommerce 3.0.0 compatibility
Download this release

Release Info

Developer josk79
Plugin Icon 128x128 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 CHANGED
@@ -4,138 +4,138 @@ defined('ABSPATH') or die();
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
  }
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
- 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,68 +29,68 @@ abstract class Abstract_WJECF_Plugin {
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' );
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
- 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
  ?>
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
- 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,447 +90,438 @@ class WJECF_Admin extends Abstract_WJECF_Plugin {
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
- <input type="hidden" class="wc-customer-search" data-multiple="true" style="width: 50%;" name="wjecf_customer_ids" data-placeholder="<?php _e( 'Any customer', 'woocommerce-jos-autocoupon' ); ?>" data-action="woocommerce_json_search_customers" data-selected="<?php
332
- $coupon_customer_ids = WJECF()->get_coupon_customer_ids( $thepostid );
333
- $json_ids = array();
334
-
335
- foreach ( $coupon_customer_ids as $customer_id ) {
336
- $customer = get_userdata( $customer_id );
337
- if ( is_object( $customer ) ) {
338
- $json_ids[ $customer_id ] = $customer->display_name . ' (#' . $customer->ID . ' &ndash; ' . sanitize_email( $customer->user_email ) . ')';
339
- }
340
- }
341
-
342
- echo esc_attr( json_encode( $json_ids ) );
343
- ?>" value="<?php echo implode( ',', array_keys( $json_ids ) ); ?>" />
344
- <?php echo WJECF_WC()->wc_help_tip( __( 'Only these customers may use this coupon.', 'woocommerce-jos-autocoupon' ) ); ?>
345
- </p>
346
- <?php
347
-
348
- //=============================
349
- // User roles
350
- ?>
351
- <p class="form-field"><label for="wjecf_customer_roles"><?php _e( 'Allowed User Roles', 'woocommerce-jos-autocoupon' ); ?></label>
352
- <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' ); ?>">
353
- <?php
354
- $coupon_customer_roles = WJECF()->get_coupon_customer_roles( $thepostid );
355
-
356
- $available_customer_roles = array_reverse( get_editable_roles() );
357
- foreach ( $available_customer_roles as $role_id => $role ) {
358
- $role_name = translate_user_role($role['name'] );
359
-
360
- echo '<option value="' . esc_attr( $role_id ) . '"'
361
- . selected( in_array( $role_id, $coupon_customer_roles ), true, false ) . '>'
362
- . esc_html( $role_name ) . '</option>';
363
- }
364
- ?>
365
- </select>
366
- <?php echo WJECF_WC()->wc_help_tip( __( 'Only these User Roles may use this coupon.', 'woocommerce-jos-autocoupon' ) ); ?>
367
- </p>
368
- <?php
369
-
370
- //=============================
371
- // Excluded user roles
372
- ?>
373
- <p class="form-field"><label for="wjecf_excluded_customer_roles"><?php _e( 'Disallowed User Roles', 'woocommerce-jos-autocoupon' ); ?></label>
374
- <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' ); ?>">
375
- <?php
376
- $coupon_excluded_customer_roles = WJECF()->get_coupon_excluded_customer_roles( $thepostid );
377
-
378
- foreach ( $available_customer_roles as $role_id => $role ) {
379
- $role_name = translate_user_role($role['name'] );
380
-
381
- echo '<option value="' . esc_attr( $role_id ) . '"'
382
- . selected( in_array( $role_id, $coupon_excluded_customer_roles ), true, false ) . '>'
383
- . esc_html( $role_name ) . '</option>';
384
- }
385
- ?>
386
- </select>
387
- <?php echo WJECF_WC()->wc_help_tip( __( 'These User Roles will be specifically excluded from using this coupon.', 'woocommerce-jos-autocoupon' ) ); ?>
388
- </p>
389
- <?php
390
- }
391
-
392
- public function admin_coupon_metabox_misc( $thepostid, $post ) {
393
- echo "<h3>" . esc_html( __( 'Miscellaneous', 'woocommerce-jos-autocoupon' ) ). "</h3>\n";
394
- //=============================
395
- //2.2.2 Allow if minimum spend not met
396
- woocommerce_wp_checkbox( array(
397
- 'id' => '_wjecf_allow_below_minimum_spend',
398
- 'label' => __( 'Allow when minimum spend not reached', 'woocommerce-jos-autocoupon' ),
399
- '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' ),
400
- ) );
401
- }
402
-
403
- public function process_shop_coupon_meta( $post_id, $post ) {
404
- $wrap_coupon = WJECF_Wrap( $post_id );
405
-
406
- $wjecf_min_matching_product_qty = isset( $_POST['_wjecf_min_matching_product_qty'] ) ? $_POST['_wjecf_min_matching_product_qty'] : '';
407
- $wrap_coupon->set_meta( '_wjecf_min_matching_product_qty', $wjecf_min_matching_product_qty );
408
-
409
- $wjecf_max_matching_product_qty = isset( $_POST['_wjecf_max_matching_product_qty'] ) ? $_POST['_wjecf_max_matching_product_qty'] : '';
410
- $wrap_coupon->set_meta( '_wjecf_max_matching_product_qty', $wjecf_max_matching_product_qty );
411
-
412
- //2.2.2
413
- $wjecf_min_matching_product_subtotal = isset( $_POST['_wjecf_min_matching_product_subtotal'] ) ? $_POST['_wjecf_min_matching_product_subtotal'] : '';
414
- $wrap_coupon->set_meta( '_wjecf_min_matching_product_subtotal', $wjecf_min_matching_product_subtotal );
415
-
416
- $wjecf_max_matching_product_subtotal = isset( $_POST['_wjecf_max_matching_product_subtotal'] ) ? $_POST['_wjecf_max_matching_product_subtotal'] : '';
417
- $wrap_coupon->set_meta( '_wjecf_max_matching_product_subtotal', $wjecf_max_matching_product_subtotal );
418
-
419
- $wjecf_products_and = $_POST['_wjecf_products_and'] == 'yes' ? 'yes' : 'no';
420
- $wrap_coupon->set_meta( '_wjecf_products_and', $wjecf_products_and );
421
-
422
- //2.2.3.1
423
- $wjecf_categories_and = $_POST['_wjecf_categories_and'] == 'yes' ? 'yes' : 'no';
424
- $wrap_coupon->set_meta( '_wjecf_categories_and', $wjecf_categories_and );
425
-
426
- //2.2.2
427
- $wjecf_allow_below_minimum_spend = isset( $_POST['_wjecf_allow_below_minimum_spend'] ) ? 'yes' : 'no';
428
- $wrap_coupon->set_meta( '_wjecf_allow_below_minimum_spend', $wjecf_allow_below_minimum_spend );
429
-
430
- $wjecf_shipping_methods = isset( $_POST['wjecf_shipping_methods'] ) ? $_POST['wjecf_shipping_methods'] : '';
431
- $wrap_coupon->set_meta( '_wjecf_shipping_methods', $wjecf_shipping_methods );
432
-
433
- $wjecf_payment_methods = isset( $_POST['wjecf_payment_methods'] ) ? $_POST['wjecf_payment_methods'] : '';
434
- $wrap_coupon->set_meta( '_wjecf_payment_methods', $wjecf_payment_methods );
435
-
436
- $wjecf_customer_ids = $this->comma_separated_int_array( $_POST['wjecf_customer_ids'] );
437
- $wrap_coupon->set_meta( '_wjecf_customer_ids', $wjecf_customer_ids );
438
-
439
- $wjecf_customer_roles = isset( $_POST['wjecf_customer_roles'] ) ? $_POST['wjecf_customer_roles'] : '';
440
- $wrap_coupon->set_meta( '_wjecf_customer_roles', $wjecf_customer_roles );
441
-
442
- $wjecf_excluded_customer_roles = isset( $_POST['wjecf_excluded_customer_roles'] ) ? $_POST['wjecf_excluded_customer_roles'] : '';
443
- $wrap_coupon->set_meta( '_wjecf_excluded_customer_roles', $wjecf_excluded_customer_roles );
444
-
445
- $wrap_coupon->save();
446
- }
447
-
448
- /**
449
- * 2.3.6
450
- * Add inline style (css) to the admin page. Must be called BEFORE admin_head !
451
- * @param string $css
452
- * @return void
453
- */
454
- public function add_inline_style( $css ) {
455
- $this->admin_css .= $css;
456
- }
457
-
458
-
459
- /**
460
- * 2.3.4
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
- * 2.3.6
475
- * Renders a <SELECT> that has a default value. Relies on woocommerce_wp_select
476
- *
477
- * field['default_value']: The default value (if omitted the first option will be default)
478
- * field['append_default_label']: If true or omitted the text '(DEFAULT)' will be appended to the default option caption
479
- *
480
- * @param array $field see wc-meta-box-functions.php:woocommerce_wp_select
481
- * @return void
482
- */
483
- public function render_select_with_default( $field ) {
484
- global $thepostid, $post;
485
- $thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
486
-
487
- reset( $field['options'] ); //move to first for key()
488
- $default_value = isset( $field['default_value'] ) ? $field['default_value'] : key( $field['options'] );
489
- $append_default_label = isset( $field['append_default_label'] ) ? $field['append_default_label'] : true;
490
-
491
- if ( $append_default_label ) {
492
- $field['options'][$default_value] = sprintf( __( '%s (Default)', 'woocommerce-jos-autocoupon' ), $field['options'][$default_value] );
493
- }
494
-
495
- if ( ! isset( $field['value'] ) ) {
496
- $field['value'] = get_post_meta( $thepostid, $field['id'], true );
497
- }
498
- if ( empty( $field['value'] ) ) {
499
- $field['value'] = $default_value;
500
- }
501
-
502
- woocommerce_wp_select( $field );
503
- }
504
-
505
- public function render_admin_cat_selector( $dom_id, $field_name, $selected_ids, $placeholder = null ) {
506
- if ( $placeholder === null ) $placeholder = __( 'Search for a product…', 'woocommerce' );
507
-
508
- // Categories
509
- ?>
510
- <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 ); ?>">
511
- <?php
512
- $categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
513
-
514
- if ( $categories ) foreach ( $categories as $cat ) {
515
- echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $selected_ids ), true, false ) . '>' . esc_html( $cat->name ) . '</option>';
516
- }
517
- ?>
518
- </select>
519
- <?php
520
- }
521
-
522
- /**
523
- * Add donate-link to plugin page
524
- */
525
- function wjecf_plugin_meta( $links, $file ) {
526
- if ( strpos( $file, 'woocommerce-jos-autocoupon.php' ) !== false ) {
527
- $links = array_merge( $links, array( '<a href="' . WJECF_Admin::get_donate_url() . '" title="Support the development" target="_blank">Donate</a>' ) );
528
- }
529
- return $links;
530
- }
531
-
532
-
533
- public static function get_donate_url() {
534
- return "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5T9XQBCS2QHRY&lc=NL&item_name=Jos%20Koenis&item_number=wordpress%2dplugin&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
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&currency_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
- 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
  }
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