Passed
Branch master (3a0618)
by Stiofan
05:00
created
includes/class-getpaid-template.php 1 patch
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if ( ! defined( 'ABSPATH' ) ) {
3
-	exit;
3
+    exit;
4 4
 }
5 5
 
6 6
 /**
@@ -20,29 +20,29 @@  discard block
 block discarded – undo
20 20
     public $templates_url;
21 21
 
22 22
     /**
23
-	 * Class constructor.
24
-	 *
25
-	 * @since 1.0.19
26
-	 */
27
-	public function __construct() {
23
+     * Class constructor.
24
+     *
25
+     * @since 1.0.19
26
+     */
27
+    public function __construct() {
28 28
 
29 29
         $this->templates_dir = apply_filters( 'getpaid_default_templates_dir', WPINV_PLUGIN_DIR . 'templates' );
30 30
         $this->templates_url = apply_filters( 'getpaid_default_templates_url', WPINV_PLUGIN_URL . 'templates' );
31 31
 
32 32
         // Oxygen plugin
33
-		if ( defined( 'CT_VERSION' ) ) {
34
-			add_filter( 'wpinv_locate_template', array( $this, 'oxygen_override_template' ), 11, 4 );
35
-		}
33
+        if ( defined( 'CT_VERSION' ) ) {
34
+            add_filter( 'wpinv_locate_template', array( $this, 'oxygen_override_template' ), 11, 4 );
35
+        }
36 36
 
37 37
     }
38 38
 
39 39
     /**
40
-	 * Checks if this is a preview page
41
-	 *
42
-	 * @since 1.0.19
43
-	 * @return bool
44
-	 */
45
-	public function is_preview() {
40
+     * Checks if this is a preview page
41
+     *
42
+     * @since 1.0.19
43
+     * @return bool
44
+     */
45
+    public function is_preview() {
46 46
         return 
47 47
             $this->is_divi_preview() ||
48 48
             $this->is_elementor_preview() ||
@@ -54,73 +54,73 @@  discard block
 block discarded – undo
54 54
     }
55 55
 
56 56
     /**
57
-	 * Checks if this is an elementor preview page
58
-	 *
59
-	 * @since 1.0.19
60
-	 * @return bool
61
-	 */
62
-	public function is_elementor_preview() {
63
-		return isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax' );
64
-	}
65
-
66
-	/**
67
-	 * Checks if this is a DIVI preview page
68
-	 *
69
-	 * @since 1.0.19
70
-	 * @return bool
71
-	 */
72
-	public function is_divi_preview() {
73
-		return isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'et_pb' );
74
-	}
75
-
76
-	/**
77
-	 * Checks if this is a beaver builder preview page
78
-	 *
79
-	 * @since 1.0.19
80
-	 * @return bool
81
-	 */
82
-	public function is_beaver_preview() {
83
-		return isset( $_REQUEST['fl_builder'] );
84
-	}
85
-
86
-	/**
87
-	 * Checks if this is a siteorigin builder preview page
88
-	 *
89
-	 * @since 1.0.19
90
-	 * @return bool
91
-	 */
92
-	public function is_siteorigin_preview() {
93
-		return ! empty( $_REQUEST['siteorigin_panels_live_editor'] );
94
-	}
95
-
96
-	/**
97
-	 * Checks if this is a cornerstone builder preview page
98
-	 *
99
-	 * @since 1.0.19
100
-	 * @return bool
101
-	 */
102
-	public function is_cornerstone_preview() {
103
-		return ! empty( $_REQUEST['cornerstone_preview'] ) || basename( $_SERVER['REQUEST_URI'] ) == 'cornerstone-endpoint';
104
-	}
105
-
106
-	/**
107
-	 * Checks if this is a fusion builder preview page
108
-	 *
109
-	 * @since 1.0.19
110
-	 * @return bool
111
-	 */
112
-	public function is_fusion_preview() {
113
-		return ! empty( $_REQUEST['fb-edit'] ) || ! empty( $_REQUEST['fusion_load_nonce'] );
114
-	}
115
-
116
-	/**
117
-	 * Checks if this is an oxygen builder preview page
118
-	 *
119
-	 * @since 1.0.19
120
-	 * @return bool
121
-	 */
122
-	public function is_oxygen_preview() {
123
-		return ! empty( $_REQUEST['ct_builder'] ) || ( ! empty( $_REQUEST['action'] ) && ( substr( $_REQUEST['action'], 0, 11 ) === "oxy_render_" || substr( $_REQUEST['action'], 0, 10 ) === "ct_render_" ) );
57
+     * Checks if this is an elementor preview page
58
+     *
59
+     * @since 1.0.19
60
+     * @return bool
61
+     */
62
+    public function is_elementor_preview() {
63
+        return isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax' );
64
+    }
65
+
66
+    /**
67
+     * Checks if this is a DIVI preview page
68
+     *
69
+     * @since 1.0.19
70
+     * @return bool
71
+     */
72
+    public function is_divi_preview() {
73
+        return isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'et_pb' );
74
+    }
75
+
76
+    /**
77
+     * Checks if this is a beaver builder preview page
78
+     *
79
+     * @since 1.0.19
80
+     * @return bool
81
+     */
82
+    public function is_beaver_preview() {
83
+        return isset( $_REQUEST['fl_builder'] );
84
+    }
85
+
86
+    /**
87
+     * Checks if this is a siteorigin builder preview page
88
+     *
89
+     * @since 1.0.19
90
+     * @return bool
91
+     */
92
+    public function is_siteorigin_preview() {
93
+        return ! empty( $_REQUEST['siteorigin_panels_live_editor'] );
94
+    }
95
+
96
+    /**
97
+     * Checks if this is a cornerstone builder preview page
98
+     *
99
+     * @since 1.0.19
100
+     * @return bool
101
+     */
102
+    public function is_cornerstone_preview() {
103
+        return ! empty( $_REQUEST['cornerstone_preview'] ) || basename( $_SERVER['REQUEST_URI'] ) == 'cornerstone-endpoint';
104
+    }
105
+
106
+    /**
107
+     * Checks if this is a fusion builder preview page
108
+     *
109
+     * @since 1.0.19
110
+     * @return bool
111
+     */
112
+    public function is_fusion_preview() {
113
+        return ! empty( $_REQUEST['fb-edit'] ) || ! empty( $_REQUEST['fusion_load_nonce'] );
114
+    }
115
+
116
+    /**
117
+     * Checks if this is an oxygen builder preview page
118
+     *
119
+     * @since 1.0.19
120
+     * @return bool
121
+     */
122
+    public function is_oxygen_preview() {
123
+        return ! empty( $_REQUEST['ct_builder'] ) || ( ! empty( $_REQUEST['action'] ) && ( substr( $_REQUEST['action'], 0, 11 ) === "oxy_render_" || substr( $_REQUEST['action'], 0, 10 ) === "ct_render_" ) );
124 124
     }
125 125
 
126 126
     /**
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
      * @param string $template_path The template path relative to the theme's root dir. Defaults to 'invoicing'.
131 131
      * @param string $default_path The root path to the default template. Defaults to invoicing/templates
132 132
      */
133
-	public function locate_template( $template_name, $template_path = '', $default_path = '' ) {
133
+    public function locate_template( $template_name, $template_path = '', $default_path = '' ) {
134 134
 
135 135
         // Load the defaults for the template path and default path.
136 136
         $template_path = empty( $template_path ) ? 'invoicing' : $template_path;
@@ -151,22 +151,22 @@  discard block
 block discarded – undo
151 151
     }
152 152
     
153 153
     /**
154
-	 * Loads a template
155
-	 *
156
-	 * @since 1.0.19
157
-	 * @return bool
158
-	 */
159
-	protected function load_template( $template_name, $template_path, $args ) {
154
+     * Loads a template
155
+     *
156
+     * @since 1.0.19
157
+     * @return bool
158
+     */
159
+    protected function load_template( $template_name, $template_path, $args ) {
160 160
 
161 161
         if ( is_array( $args ) ){
162 162
             extract( $args );
163 163
         }
164 164
 
165 165
         // Fires before loading a template.
166
-	    do_action( 'wpinv_before_template_part', $template_name, $template_path, $args );
166
+        do_action( 'wpinv_before_template_part', $template_name, $template_path, $args );
167 167
 
168 168
         // Load the template.
169
-	    include( $template_path );
169
+        include( $template_path );
170 170
 
171 171
         // Fires after loading a template.
172 172
         do_action( 'wpinv_after_template_part', $template_name, $template_path, $args );
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
      * @param string $template_path The templates directory relative to the theme's root dir. Defaults to 'invoicing'.
184 184
      * @param string $default_path The root path to the default template. Defaults to invoicing/templates
185 185
      */
186
-	public function display_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
186
+    public function display_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
187 187
 
188 188
         // Locate the template.
189 189
         $located = $this->locate_template( $template_name, $template_path, $default_path );
@@ -208,74 +208,74 @@  discard block
 block discarded – undo
208 208
      * @param string $template_path The templates directory relative to the theme's root dir. Defaults to 'invoicing'.
209 209
      * @param string $default_path The root path to the default template. Defaults to invoicing/templates
210 210
      */
211
-	public function get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
211
+    public function get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
212 212
         ob_start();
213 213
         $this->display_template( $template_name, $args, $template_path, $default_path );
214 214
         return ob_get_clean();
215 215
     }
216 216
 
217 217
     /**
218
-	 * Get the geodirectory templates theme path.
219
-	 *
220
-	 *
221
-	 * @return string Template path.
222
-	 */
223
-	public static function get_theme_template_path() {
224
-		$template   = get_template();
225
-		$theme_root = get_theme_root( $template );
226
-
227
-		return $theme_root . '/' . $template . '/' . untrailingslashit( wpinv_get_theme_template_dir_name() );
228
-
229
-	}
230
-
231
-	/**
232
-	 * Oxygen locate theme template.
233
-	 *
234
-	 * @param string $template The template.
235
-	 * @return string The theme template.
236
-	 */
237
-	public static function oxygen_locate_template( $template ) {
238
-
239
-		if ( empty( $template ) ) {
240
-			return '';
241
-		}
242
-
243
-		$has_filter = has_filter( 'template', 'ct_oxygen_template_name' );
244
-
245
-		// Remove template filter
246
-		if ( $has_filter ) {
247
-			remove_filter( 'template', 'ct_oxygen_template_name' );
248
-		}
249
-
250
-		$template = self::get_theme_template_path() . '/' . $template;
251
-
252
-		if ( ! file_exists( $template ) ) {
253
-			$template = '';
254
-		}
255
-
256
-		// Add template filter
257
-		if ( $has_filter ) {
258
-			add_filter( 'template', 'ct_oxygen_template_name' );
259
-		}
260
-
261
-		return $template;
262
-	}
263
-
264
-	/**
265
-	 * Oxygen override theme template.
266
-	 *
267
-	 * @param string $located Located template.
268
-	 * @param string $template_name Template name.
269
-	 * @return string Located template.
270
-	 */
271
-	public function oxygen_override_template( $located, $template_name ) {
218
+     * Get the geodirectory templates theme path.
219
+     *
220
+     *
221
+     * @return string Template path.
222
+     */
223
+    public static function get_theme_template_path() {
224
+        $template   = get_template();
225
+        $theme_root = get_theme_root( $template );
226
+
227
+        return $theme_root . '/' . $template . '/' . untrailingslashit( wpinv_get_theme_template_dir_name() );
228
+
229
+    }
230
+
231
+    /**
232
+     * Oxygen locate theme template.
233
+     *
234
+     * @param string $template The template.
235
+     * @return string The theme template.
236
+     */
237
+    public static function oxygen_locate_template( $template ) {
238
+
239
+        if ( empty( $template ) ) {
240
+            return '';
241
+        }
242
+
243
+        $has_filter = has_filter( 'template', 'ct_oxygen_template_name' );
244
+
245
+        // Remove template filter
246
+        if ( $has_filter ) {
247
+            remove_filter( 'template', 'ct_oxygen_template_name' );
248
+        }
249
+
250
+        $template = self::get_theme_template_path() . '/' . $template;
251
+
252
+        if ( ! file_exists( $template ) ) {
253
+            $template = '';
254
+        }
255
+
256
+        // Add template filter
257
+        if ( $has_filter ) {
258
+            add_filter( 'template', 'ct_oxygen_template_name' );
259
+        }
260
+
261
+        return $template;
262
+    }
263
+
264
+    /**
265
+     * Oxygen override theme template.
266
+     *
267
+     * @param string $located Located template.
268
+     * @param string $template_name Template name.
269
+     * @return string Located template.
270
+     */
271
+    public function oxygen_override_template( $located, $template_name ) {
272 272
 
273 273
         $oxygen_overide = self::oxygen_locate_template( $template_name );
274
-		if ( ! empty( $oxygen_overide ) ) {
275
-			return $oxygen_overide;
276
-		}
274
+        if ( ! empty( $oxygen_overide ) ) {
275
+            return $oxygen_overide;
276
+        }
277 277
 
278
-		return $located;
279
-	}
278
+        return $located;
279
+    }
280 280
 
281 281
 }
Please login to merge, or discard this patch.
includes/payments/class-getpaid-form-item.php 1 patch
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if ( ! defined( 'ABSPATH' ) ) {
3
-	exit;
3
+    exit;
4 4
 }
5 5
 
6 6
 /**
@@ -10,67 +10,67 @@  discard block
 block discarded – undo
10 10
 class GetPaid_Form_Item  extends WPInv_Item {
11 11
 
12 12
     /**
13
-	 * Stores a custom description for the item.
14
-	 *
15
-	 * @var string
16
-	 */
17
-	protected $custom_description = null;
18
-
19
-	/**
20
-	 * Stores the item quantity.
21
-	 *
22
-	 * @var float
23
-	 */
24
-	protected $quantity = 1;
25
-
26
-	/**
27
-	 * Stores the item meta.
28
-	 *
29
-	 * @var array
30
-	 */
31
-	protected $meta = array();
32
-
33
-	/**
34
-	 * Is this item required?
35
-	 *
36
-	 * @var int
37
-	 */
38
-	protected $is_required = true;
39
-
40
-	/**
41
-	 * Are quantities allowed?
42
-	 *
43
-	 * @var int
44
-	 */
45
-	protected $allow_quantities = false;
46
-
47
-	/**
48
-	 * Associated invoice.
49
-	 *
50
-	 * @var int
51
-	 */
52
-	public $invoice_id = 0;
53
-
54
-	/**
55
-	 * Item discount.
56
-	 *
57
-	 * @var float
58
-	 */
59
-	public $item_discount = 0;
60
-
61
-	/**
62
-	 * Recurring item discount.
63
-	 *
64
-	 * @var float
65
-	 */
66
-	public $recurring_item_discount = 0;
67
-
68
-	/**
69
-	 * Item tax.
70
-	 *
71
-	 * @var float
72
-	 */
73
-	public $item_tax = 0;
13
+     * Stores a custom description for the item.
14
+     *
15
+     * @var string
16
+     */
17
+    protected $custom_description = null;
18
+
19
+    /**
20
+     * Stores the item quantity.
21
+     *
22
+     * @var float
23
+     */
24
+    protected $quantity = 1;
25
+
26
+    /**
27
+     * Stores the item meta.
28
+     *
29
+     * @var array
30
+     */
31
+    protected $meta = array();
32
+
33
+    /**
34
+     * Is this item required?
35
+     *
36
+     * @var int
37
+     */
38
+    protected $is_required = true;
39
+
40
+    /**
41
+     * Are quantities allowed?
42
+     *
43
+     * @var int
44
+     */
45
+    protected $allow_quantities = false;
46
+
47
+    /**
48
+     * Associated invoice.
49
+     *
50
+     * @var int
51
+     */
52
+    public $invoice_id = 0;
53
+
54
+    /**
55
+     * Item discount.
56
+     *
57
+     * @var float
58
+     */
59
+    public $item_discount = 0;
60
+
61
+    /**
62
+     * Recurring item discount.
63
+     *
64
+     * @var float
65
+     */
66
+    public $recurring_item_discount = 0;
67
+
68
+    /**
69
+     * Item tax.
70
+     *
71
+     * @var float
72
+     */
73
+    public $item_tax = 0;
74 74
 
75 75
     /*
76 76
 	|--------------------------------------------------------------------------
@@ -88,234 +88,234 @@  discard block
 block discarded – undo
88 88
     */
89 89
 
90 90
     /**
91
-	 * Get the item name.
92
-	 *
93
-	 * @since 1.0.19
94
-	 * @param  string $context View or edit context.
95
-	 * @return string
96
-	 */
97
-	public function get_name( $context = 'view' ) {
98
-		$name = parent::get_name( $context );
99
-		return $name . wpinv_get_item_suffix( $this );
100
-	}
101
-
102
-	/**
103
-	 * Get the item name without a suffix.
104
-	 *
105
-	 * @since 1.0.19
106
-	 * @param  string $context View or edit context.
107
-	 * @return string
108
-	 */
109
-	public function get_raw_name( $context = 'view' ) {
110
-		return parent::get_name( $context );
111
-	}
112
-
113
-	/**
114
-	 * Get the item description.
115
-	 *
116
-	 * @since 1.0.19
117
-	 * @param  string $context View or edit context.
118
-	 * @return string
119
-	 */
120
-	public function get_description( $context = 'view' ) {
121
-
122
-		if ( isset( $this->custom_description ) ) {
123
-			return $this->custom_description;
124
-		}
125
-
126
-		return parent::get_description( $context );
127
-	}
128
-
129
-	/**
130
-	 * Returns the sub total.
131
-	 *
132
-	 * @since 1.0.19
133
-	 * @param  string $context View or edit context.
134
-	 * @return float
135
-	 */
136
-	public function get_sub_total( $context = 'view' ) {
137
-		return $this->get_quantity( $context ) * $this->get_initial_price( $context );
138
-	}
139
-
140
-	/**
141
-	 * Returns the recurring sub total.
142
-	 *
143
-	 * @since 1.0.19
144
-	 * @param  string $context View or edit context.
145
-	 * @return float
146
-	 */
147
-	public function get_recurring_sub_total( $context = 'view' ) {
148
-
149
-		if ( $this->is_recurring() ) {
150
-			return $this->get_quantity( $context ) * $this->get_price( $context );
151
-		}
152
-
153
-		return 0;
154
-	}
155
-
156
-	/**
157
-	 * @deprecated
158
-	 */
159
-	public function get_qantity( $context = 'view' ) {
160
-		return $this->get_quantity( $context );
161
-	}
162
-
163
-	/**
164
-	 * Get the item quantity.
165
-	 *
166
-	 * @since 1.0.19
167
-	 * @param  string $context View or edit context.
168
-	 * @return float
169
-	 */
170
-	public function get_quantity( $context = 'view' ) {
171
-		$quantity = (float) $this->quantity;
172
-
173
-		if ( empty( $quantity ) || 1 > $quantity ) {
174
-			$quantity = 1;
175
-		}
176
-
177
-		if ( 'view' == $context ) {
178
-			return apply_filters( 'getpaid_payment_form_item_quantity', $quantity, $this );
179
-		}
180
-
181
-		return $quantity;
182
-
183
-	}
184
-
185
-	/**
186
-	 * Get the item meta data.
187
-	 *
188
-	 * @since 1.0.19
189
-	 * @param  string $context View or edit context.
190
-	 * @return meta
191
-	 */
192
-	public function get_item_meta( $context = 'view' ) {
193
-		$meta = $this->meta;
194
-
195
-		if ( 'view' == $context ) {
196
-			return apply_filters( 'getpaid_payment_form_item_meta', $meta, $this );
197
-		}
198
-
199
-		return $meta;
200
-
201
-	}
202
-
203
-	/**
204
-	 * Returns whether or not customers can update the item quantity.
205
-	 *
206
-	 * @since 1.0.19
207
-	 * @param  string $context View or edit context.
208
-	 * @return bool
209
-	 */
210
-	public function get_allow_quantities( $context = 'view' ) {
211
-		$allow_quantities = (bool) $this->allow_quantities;
212
-
213
-		if ( 'view' == $context ) {
214
-			return apply_filters( 'getpaid_payment_form_item_allow_quantities', $allow_quantities, $this );
215
-		}
216
-
217
-		return $allow_quantities;
218
-
219
-	}
220
-
221
-	/**
222
-	 * Returns whether or not the item is required.
223
-	 *
224
-	 * @since 1.0.19
225
-	 * @param  string $context View or edit context.
226
-	 * @return bool
227
-	 */
228
-	public function get_is_required( $context = 'view' ) {
229
-		$is_required = (bool) $this->is_required;
230
-
231
-		if ( 'view' == $context ) {
232
-			return apply_filters( 'getpaid_payment_form_item_is_required', $is_required, $this );
233
-		}
234
-
235
-		return $is_required;
236
-
237
-	}
238
-
239
-	/**
240
-	 * Prepares form data for use.
241
-	 *
242
-	 * @since 1.0.19
243
-	 * @return array
244
-	 */
245
-	public function prepare_data_for_use( $required = null ) {
246
-
247
-		$required = is_null( $required ) ? $this->is_required() : $required;
248
-		return array(
249
-			'title'            => strip_tags( $this->get_name() ),
250
-			'id'               => $this->get_id(),
251
-			'price'            => $this->get_price(),
252
-			'recurring'        => $this->is_recurring(),
253
-			'description'      => $this->get_description(),
254
-			'allow_quantities' => $this->allows_quantities(),
255
-			'required'         => $required,
256
-		);
257
-
258
-	}
259
-
260
-	/**
261
-	 * Prepares form data for ajax use.
262
-	 *
263
-	 * @since 1.0.19
264
-	 * @return array
265
-	 */
266
-	public function prepare_data_for_invoice_edit_ajax( $currency = '', $is_renewal = false ) {
267
-
268
-		$description = getpaid_item_recurring_price_help_text( $this, $currency );
269
-
270
-		if ( $description ) {
271
-			$description = "<div class='getpaid-subscription-help-text'>$description</div>";
272
-		}
273
-
274
-		$price    = ! $is_renewal ? $this->get_price() : $this->get_recurring_price();
275
-		$subtotal = ! $is_renewal ? $this->get_sub_total() : $this->get_recurring_sub_total();
276
-		return array(
277
-			'id'     => $this->get_id(),
278
-			'texts'  => array(
279
-				'item-name'        => sanitize_text_field( $this->get_name() ),
280
-				'item-description' => wp_kses_post( $this->get_description() ) . $description,
281
-				'item-quantity'    => floatval( $this->get_quantity() ),
282
-				'item-price'       => wpinv_price( $price, $currency ),
283
-				'item-total'       => wpinv_price( $subtotal, $currency ),
284
-			),
285
-			'inputs' => array(
286
-				'item-id'          => $this->get_id(),
287
-				'item-name'        => sanitize_text_field( $this->get_name() ),
288
-				'item-description' => wp_kses_post( $this->get_description() ),
289
-				'item-quantity'    => floatval( $this->get_quantity() ),
290
-				'item-price'       => $price,
291
-			)
292
-		);
293
-
294
-	}
295
-
296
-	/**
297
-	 * Prepares form data for saving (cart_details).
298
-	 *
299
-	 * @since 1.0.19
300
-	 * @return array
301
-	 */
302
-	public function prepare_data_for_saving() {
303
-
304
-		return array(
305
-			'post_id'           => $this->invoice_id,
306
-			'item_id'           => $this->get_id(),
307
-			'item_name'         => sanitize_text_field( $this->get_raw_name() ),
308
-			'item_description'  => $this->get_description(),
309
-			'tax'               => $this->item_tax,
310
-			'item_price'        => $this->get_price(),
311
-			'quantity'          => (float) $this->get_quantity(),
312
-			'discount'          => $this->item_discount,
313
-			'subtotal'          => $this->get_sub_total(),
314
-			'price'             => $this->get_sub_total() + $this->item_tax - $this->item_discount,
315
-			'meta'              => $this->get_item_meta(),
316
-		);
317
-
318
-	}
91
+     * Get the item name.
92
+     *
93
+     * @since 1.0.19
94
+     * @param  string $context View or edit context.
95
+     * @return string
96
+     */
97
+    public function get_name( $context = 'view' ) {
98
+        $name = parent::get_name( $context );
99
+        return $name . wpinv_get_item_suffix( $this );
100
+    }
101
+
102
+    /**
103
+     * Get the item name without a suffix.
104
+     *
105
+     * @since 1.0.19
106
+     * @param  string $context View or edit context.
107
+     * @return string
108
+     */
109
+    public function get_raw_name( $context = 'view' ) {
110
+        return parent::get_name( $context );
111
+    }
112
+
113
+    /**
114
+     * Get the item description.
115
+     *
116
+     * @since 1.0.19
117
+     * @param  string $context View or edit context.
118
+     * @return string
119
+     */
120
+    public function get_description( $context = 'view' ) {
121
+
122
+        if ( isset( $this->custom_description ) ) {
123
+            return $this->custom_description;
124
+        }
125
+
126
+        return parent::get_description( $context );
127
+    }
128
+
129
+    /**
130
+     * Returns the sub total.
131
+     *
132
+     * @since 1.0.19
133
+     * @param  string $context View or edit context.
134
+     * @return float
135
+     */
136
+    public function get_sub_total( $context = 'view' ) {
137
+        return $this->get_quantity( $context ) * $this->get_initial_price( $context );
138
+    }
139
+
140
+    /**
141
+     * Returns the recurring sub total.
142
+     *
143
+     * @since 1.0.19
144
+     * @param  string $context View or edit context.
145
+     * @return float
146
+     */
147
+    public function get_recurring_sub_total( $context = 'view' ) {
148
+
149
+        if ( $this->is_recurring() ) {
150
+            return $this->get_quantity( $context ) * $this->get_price( $context );
151
+        }
152
+
153
+        return 0;
154
+    }
155
+
156
+    /**
157
+     * @deprecated
158
+     */
159
+    public function get_qantity( $context = 'view' ) {
160
+        return $this->get_quantity( $context );
161
+    }
162
+
163
+    /**
164
+     * Get the item quantity.
165
+     *
166
+     * @since 1.0.19
167
+     * @param  string $context View or edit context.
168
+     * @return float
169
+     */
170
+    public function get_quantity( $context = 'view' ) {
171
+        $quantity = (float) $this->quantity;
172
+
173
+        if ( empty( $quantity ) || 1 > $quantity ) {
174
+            $quantity = 1;
175
+        }
176
+
177
+        if ( 'view' == $context ) {
178
+            return apply_filters( 'getpaid_payment_form_item_quantity', $quantity, $this );
179
+        }
180
+
181
+        return $quantity;
182
+
183
+    }
184
+
185
+    /**
186
+     * Get the item meta data.
187
+     *
188
+     * @since 1.0.19
189
+     * @param  string $context View or edit context.
190
+     * @return meta
191
+     */
192
+    public function get_item_meta( $context = 'view' ) {
193
+        $meta = $this->meta;
194
+
195
+        if ( 'view' == $context ) {
196
+            return apply_filters( 'getpaid_payment_form_item_meta', $meta, $this );
197
+        }
198
+
199
+        return $meta;
200
+
201
+    }
202
+
203
+    /**
204
+     * Returns whether or not customers can update the item quantity.
205
+     *
206
+     * @since 1.0.19
207
+     * @param  string $context View or edit context.
208
+     * @return bool
209
+     */
210
+    public function get_allow_quantities( $context = 'view' ) {
211
+        $allow_quantities = (bool) $this->allow_quantities;
212
+
213
+        if ( 'view' == $context ) {
214
+            return apply_filters( 'getpaid_payment_form_item_allow_quantities', $allow_quantities, $this );
215
+        }
216
+
217
+        return $allow_quantities;
218
+
219
+    }
220
+
221
+    /**
222
+     * Returns whether or not the item is required.
223
+     *
224
+     * @since 1.0.19
225
+     * @param  string $context View or edit context.
226
+     * @return bool
227
+     */
228
+    public function get_is_required( $context = 'view' ) {
229
+        $is_required = (bool) $this->is_required;
230
+
231
+        if ( 'view' == $context ) {
232
+            return apply_filters( 'getpaid_payment_form_item_is_required', $is_required, $this );
233
+        }
234
+
235
+        return $is_required;
236
+
237
+    }
238
+
239
+    /**
240
+     * Prepares form data for use.
241
+     *
242
+     * @since 1.0.19
243
+     * @return array
244
+     */
245
+    public function prepare_data_for_use( $required = null ) {
246
+
247
+        $required = is_null( $required ) ? $this->is_required() : $required;
248
+        return array(
249
+            'title'            => strip_tags( $this->get_name() ),
250
+            'id'               => $this->get_id(),
251
+            'price'            => $this->get_price(),
252
+            'recurring'        => $this->is_recurring(),
253
+            'description'      => $this->get_description(),
254
+            'allow_quantities' => $this->allows_quantities(),
255
+            'required'         => $required,
256
+        );
257
+
258
+    }
259
+
260
+    /**
261
+     * Prepares form data for ajax use.
262
+     *
263
+     * @since 1.0.19
264
+     * @return array
265
+     */
266
+    public function prepare_data_for_invoice_edit_ajax( $currency = '', $is_renewal = false ) {
267
+
268
+        $description = getpaid_item_recurring_price_help_text( $this, $currency );
269
+
270
+        if ( $description ) {
271
+            $description = "<div class='getpaid-subscription-help-text'>$description</div>";
272
+        }
273
+
274
+        $price    = ! $is_renewal ? $this->get_price() : $this->get_recurring_price();
275
+        $subtotal = ! $is_renewal ? $this->get_sub_total() : $this->get_recurring_sub_total();
276
+        return array(
277
+            'id'     => $this->get_id(),
278
+            'texts'  => array(
279
+                'item-name'        => sanitize_text_field( $this->get_name() ),
280
+                'item-description' => wp_kses_post( $this->get_description() ) . $description,
281
+                'item-quantity'    => floatval( $this->get_quantity() ),
282
+                'item-price'       => wpinv_price( $price, $currency ),
283
+                'item-total'       => wpinv_price( $subtotal, $currency ),
284
+            ),
285
+            'inputs' => array(
286
+                'item-id'          => $this->get_id(),
287
+                'item-name'        => sanitize_text_field( $this->get_name() ),
288
+                'item-description' => wp_kses_post( $this->get_description() ),
289
+                'item-quantity'    => floatval( $this->get_quantity() ),
290
+                'item-price'       => $price,
291
+            )
292
+        );
293
+
294
+    }
295
+
296
+    /**
297
+     * Prepares form data for saving (cart_details).
298
+     *
299
+     * @since 1.0.19
300
+     * @return array
301
+     */
302
+    public function prepare_data_for_saving() {
303
+
304
+        return array(
305
+            'post_id'           => $this->invoice_id,
306
+            'item_id'           => $this->get_id(),
307
+            'item_name'         => sanitize_text_field( $this->get_raw_name() ),
308
+            'item_description'  => $this->get_description(),
309
+            'tax'               => $this->item_tax,
310
+            'item_price'        => $this->get_price(),
311
+            'quantity'          => (float) $this->get_quantity(),
312
+            'discount'          => $this->item_discount,
313
+            'subtotal'          => $this->get_sub_total(),
314
+            'price'             => $this->get_sub_total() + $this->item_tax - $this->item_discount,
315
+            'meta'              => $this->get_item_meta(),
316
+        );
317
+
318
+    }
319 319
 
320 320
     /*
321 321
 	|--------------------------------------------------------------------------
@@ -327,70 +327,70 @@  discard block
 block discarded – undo
327 327
 	| object.
328 328
     */
329 329
 
330
-	/**
331
-	 * Set the item qantity.
332
-	 *
333
-	 * @since 1.0.19
334
-	 * @param  float $quantity The item quantity.
335
-	 */
336
-	public function set_quantity( $quantity ) {
337
-
338
-		if ( empty( $quantity ) || ! is_numeric( $quantity ) ) {
339
-			$quantity = 1;
340
-		}
341
-
342
-		$this->quantity = (float) $quantity;
343
-
344
-	}
345
-
346
-	/**
347
-	 * Set the item meta data.
348
-	 *
349
-	 * @since 1.0.19
350
-	 * @param  array $meta The item meta data.
351
-	 */
352
-	public function set_item_meta( $meta ) {
353
-		$this->meta = maybe_unserialize( $meta );
354
-	}
355
-
356
-	/**
357
-	 * Set whether or not the quantities are allowed.
358
-	 *
359
-	 * @since 1.0.19
360
-	 * @param  bool $allow_quantities
361
-	 */
362
-	public function set_allow_quantities( $allow_quantities ) {
363
-		$this->allow_quantities = (bool) $allow_quantities;
364
-	}
365
-
366
-	/**
367
-	 * Set whether or not the item is required.
368
-	 *
369
-	 * @since 1.0.19
370
-	 * @param  bool $is_required
371
-	 */
372
-	public function set_is_required( $is_required ) {
373
-		$this->is_required = (bool) $is_required;
374
-	}
375
-
376
-	/**
377
-	 * Sets the custom item description.
378
-	 *
379
-	 * @since 1.0.19
380
-	 * @param  string $description
381
-	 */
382
-	public function set_custom_description( $description ) {
383
-		$this->custom_description = $description;
384
-	}
330
+    /**
331
+     * Set the item qantity.
332
+     *
333
+     * @since 1.0.19
334
+     * @param  float $quantity The item quantity.
335
+     */
336
+    public function set_quantity( $quantity ) {
337
+
338
+        if ( empty( $quantity ) || ! is_numeric( $quantity ) ) {
339
+            $quantity = 1;
340
+        }
341
+
342
+        $this->quantity = (float) $quantity;
343
+
344
+    }
345
+
346
+    /**
347
+     * Set the item meta data.
348
+     *
349
+     * @since 1.0.19
350
+     * @param  array $meta The item meta data.
351
+     */
352
+    public function set_item_meta( $meta ) {
353
+        $this->meta = maybe_unserialize( $meta );
354
+    }
355
+
356
+    /**
357
+     * Set whether or not the quantities are allowed.
358
+     *
359
+     * @since 1.0.19
360
+     * @param  bool $allow_quantities
361
+     */
362
+    public function set_allow_quantities( $allow_quantities ) {
363
+        $this->allow_quantities = (bool) $allow_quantities;
364
+    }
365
+
366
+    /**
367
+     * Set whether or not the item is required.
368
+     *
369
+     * @since 1.0.19
370
+     * @param  bool $is_required
371
+     */
372
+    public function set_is_required( $is_required ) {
373
+        $this->is_required = (bool) $is_required;
374
+    }
375
+
376
+    /**
377
+     * Sets the custom item description.
378
+     *
379
+     * @since 1.0.19
380
+     * @param  string $description
381
+     */
382
+    public function set_custom_description( $description ) {
383
+        $this->custom_description = $description;
384
+    }
385 385
 
386 386
     /**
387 387
      * We do not want to save items to the database.
388 388
      * 
389
-	 * @return int item id
389
+     * @return int item id
390 390
      */
391 391
     public function save( $data = array() ) {
392 392
         return $this->get_id();
393
-	}
393
+    }
394 394
 
395 395
     /*
396 396
 	|--------------------------------------------------------------------------
@@ -402,23 +402,23 @@  discard block
 block discarded – undo
402 402
 	*/
403 403
 
404 404
     /**
405
-	 * Checks whether the item has enabled dynamic pricing.
406
-	 *
407
-	 * @since 1.0.19
408
-	 * @return bool
409
-	 */
410
-	public function is_required() {
405
+     * Checks whether the item has enabled dynamic pricing.
406
+     *
407
+     * @since 1.0.19
408
+     * @return bool
409
+     */
410
+    public function is_required() {
411 411
         return (bool) $this->get_is_required();
412
-	}
413
-
414
-	/**
415
-	 * Checks whether users can edit the quantities.
416
-	 *
417
-	 * @since 1.0.19
418
-	 * @return bool
419
-	 */
420
-	public function allows_quantities() {
412
+    }
413
+
414
+    /**
415
+     * Checks whether users can edit the quantities.
416
+     *
417
+     * @since 1.0.19
418
+     * @return bool
419
+     */
420
+    public function allows_quantities() {
421 421
         return (bool) $this->get_allow_quantities();
422
-	}
422
+    }
423 423
 
424 424
 }
Please login to merge, or discard this patch.
includes/data-stores/class-getpaid-data.php 1 patch
Indentation   +862 added lines, -862 removed lines patch added patch discarded remove patch
@@ -9,7 +9,7 @@  discard block
 block discarded – undo
9 9
  */
10 10
 
11 11
 if ( ! defined( 'ABSPATH' ) ) {
12
-	exit;
12
+    exit;
13 13
 }
14 14
 
15 15
 /**
@@ -21,356 +21,356 @@  discard block
 block discarded – undo
21 21
  */
22 22
 abstract class GetPaid_Data {
23 23
 
24
-	/**
25
-	 * ID for this object.
26
-	 *
27
-	 * @since 1.0.19
28
-	 * @var int
29
-	 */
30
-	protected $id = 0;
31
-
32
-	/**
33
-	 * Core data for this object. Name value pairs (name + default value).
34
-	 *
35
-	 * @since 1.0.19
36
-	 * @var array
37
-	 */
38
-	protected $data = array();
39
-
40
-	/**
41
-	 * Core data changes for this object.
42
-	 *
43
-	 * @since 1.0.19
44
-	 * @var array
45
-	 */
46
-	protected $changes = array();
47
-
48
-	/**
49
-	 * This is false until the object is read from the DB.
50
-	 *
51
-	 * @since 1.0.19
52
-	 * @var bool
53
-	 */
54
-	protected $object_read = false;
55
-
56
-	/**
57
-	 * This is the name of this object type.
58
-	 *
59
-	 * @since 1.0.19
60
-	 * @var string
61
-	 */
62
-	protected $object_type = 'data';
63
-
64
-	/**
65
-	 * Extra data for this object. Name value pairs (name + default value).
66
-	 * Used as a standard way for sub classes (like item types) to add
67
-	 * additional information to an inherited class.
68
-	 *
69
-	 * @since 1.0.19
70
-	 * @var array
71
-	 */
72
-	protected $extra_data = array();
73
-
74
-	/**
75
-	 * Set to _data on construct so we can track and reset data if needed.
76
-	 *
77
-	 * @since 1.0.19
78
-	 * @var array
79
-	 */
80
-	protected $default_data = array();
81
-
82
-	/**
83
-	 * Contains a reference to the data store for this class.
84
-	 *
85
-	 * @since 1.0.19
86
-	 * @var GetPaid_Data_Store
87
-	 */
88
-	protected $data_store;
89
-
90
-	/**
91
-	 * Stores meta in cache for future reads.
92
-	 * A group must be set to to enable caching.
93
-	 *
94
-	 * @since 1.0.19
95
-	 * @var string
96
-	 */
97
-	protected $cache_group = '';
98
-
99
-	/**
100
-	 * Stores the last error.
101
-	 *
102
-	 * @since 1.0.19
103
-	 * @var string
104
-	 */
105
-	public $last_error = '';
106
-
107
-	/**
108
-	 * Stores additional meta data.
109
-	 *
110
-	 * @since 1.0.19
111
-	 * @var array
112
-	 */
113
-	protected $meta_data = null;
114
-
115
-	/**
116
-	 * Default constructor.
117
-	 *
118
-	 * @param int|object|array|string $read ID to load from the DB (optional) or already queried data.
119
-	 */
120
-	public function __construct( $read = 0 ) {
121
-		$this->data         = array_merge( $this->data, $this->extra_data );
122
-		$this->default_data = $this->data;
123
-	}
124
-
125
-	/**
126
-	 * Only store the object ID to avoid serializing the data object instance.
127
-	 *
128
-	 * @return array
129
-	 */
130
-	public function __sleep() {
131
-		return array( 'id' );
132
-	}
133
-
134
-	/**
135
-	 * Re-run the constructor with the object ID.
136
-	 *
137
-	 * If the object no longer exists, remove the ID.
138
-	 */
139
-	public function __wakeup() {
140
-		$this->__construct( absint( $this->id ) );
141
-
142
-		if ( ! empty( $this->last_error ) ) {
143
-			$this->set_id( 0 );
144
-		}
145
-
146
-	}
147
-
148
-	/**
149
-	 * When the object is cloned, make sure meta is duplicated correctly.
150
-	 *
151
-	 * @since 1.0.19
152
-	 */
153
-	public function __clone() {
154
-		$this->maybe_read_meta_data();
155
-		if ( ! empty( $this->meta_data ) ) {
156
-			foreach ( $this->meta_data as $array_key => $meta ) {
157
-				$this->meta_data[ $array_key ] = clone $meta;
158
-				if ( ! empty( $meta->id ) ) {
159
-					$this->meta_data[ $array_key ]->id = null;
160
-				}
161
-			}
162
-		}
163
-	}
164
-
165
-	/**
166
-	 * Get the data store.
167
-	 *
168
-	 * @since  1.0.19
169
-	 * @return object
170
-	 */
171
-	public function get_data_store() {
172
-		return $this->data_store;
173
-	}
174
-
175
-	/**
176
-	 * Get the object type.
177
-	 *
178
-	 * @since  1.0.19
179
-	 * @return string
180
-	 */
181
-	public function get_object_type() {
182
-		return $this->object_type;
183
-	}
184
-
185
-	/**
186
-	 * Returns the unique ID for this object.
187
-	 *
188
-	 * @since  1.0.19
189
-	 * @return int
190
-	 */
191
-	public function get_id() {
192
-		return $this->id;
193
-	}
194
-
195
-	/**
196
-	 * Get form status.
197
-	 *
198
-	 * @since 1.0.19
199
-	 * @param  string $context View or edit context.
200
-	 * @return string
201
-	 */
202
-	public function get_status( $context = 'view' ) {
203
-		return $this->get_prop( 'status', $context );
204
-    }
205
-
206
-	/**
207
-	 * Delete an object, set the ID to 0, and return result.
208
-	 *
209
-	 * @since  1.0.19
210
-	 * @param  bool $force_delete Should the data be deleted permanently.
211
-	 * @return bool result
212
-	 */
213
-	public function delete( $force_delete = false ) {
214
-		if ( $this->data_store && $this->exists() ) {
215
-			$this->data_store->delete( $this, array( 'force_delete' => $force_delete ) );
216
-			$this->set_id( 0 );
217
-			return true;
218
-		}
219
-		return false;
220
-	}
221
-
222
-	/**
223
-	 * Save should create or update based on object existence.
224
-	 *
225
-	 * @since  1.0.19
226
-	 * @return int
227
-	 */
228
-	public function save() {
229
-		if ( ! $this->data_store ) {
230
-			return $this->get_id();
231
-		}
232
-
233
-		/**
234
-		 * Trigger action before saving to the DB. Allows you to adjust object props before save.
235
-		 *
236
-		 * @param GetPaid_Data          $this The object being saved.
237
-		 * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
238
-		 */
239
-		do_action( 'getpaid_before_' . $this->object_type . '_object_save', $this, $this->data_store );
240
-
241
-		if ( $this->get_id() ) {
242
-			$this->data_store->update( $this );
243
-		} else {
244
-			$this->data_store->create( $this );
245
-		}
246
-
247
-		/**
248
-		 * Trigger action after saving to the DB.
249
-		 *
250
-		 * @param GetPaid_Data          $this The object being saved.
251
-		 * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
252
-		 */
253
-		do_action( 'getpaid_after_' . $this->object_type . '_object_save', $this, $this->data_store );
254
-
255
-		return $this->get_id();
256
-	}
257
-
258
-	/**
259
-	 * Change data to JSON format.
260
-	 *
261
-	 * @since  1.0.19
262
-	 * @return string Data in JSON format.
263
-	 */
264
-	public function __toString() {
265
-		return wp_json_encode( $this->get_data() );
266
-	}
267
-
268
-	/**
269
-	 * Returns all data for this object.
270
-	 *
271
-	 * @since  1.0.19
272
-	 * @return array
273
-	 */
274
-	public function get_data() {
275
-		return array_merge( array( 'id' => $this->get_id() ), $this->data, array( 'meta_data' => $this->get_meta_data() ) );
276
-	}
277
-
278
-	/**
279
-	 * Returns array of expected data keys for this object.
280
-	 *
281
-	 * @since   1.0.19
282
-	 * @return array
283
-	 */
284
-	public function get_data_keys() {
285
-		return array_keys( $this->data );
286
-	}
287
-
288
-	/**
289
-	 * Returns all "extra" data keys for an object (for sub objects like item types).
290
-	 *
291
-	 * @since  1.0.19
292
-	 * @return array
293
-	 */
294
-	public function get_extra_data_keys() {
295
-		return array_keys( $this->extra_data );
296
-	}
297
-
298
-	/**
299
-	 * Filter null meta values from array.
300
-	 *
301
-	 * @since  1.0.19
302
-	 * @param mixed $meta Meta value to check.
303
-	 * @return bool
304
-	 */
305
-	protected function filter_null_meta( $meta ) {
306
-		return ! is_null( $meta->value );
307
-	}
308
-
309
-	/**
310
-	 * Get All Meta Data.
311
-	 *
312
-	 * @since 1.0.19
313
-	 * @return array of objects.
314
-	 */
315
-	public function get_meta_data() {
316
-		$this->maybe_read_meta_data();
317
-		return array_values( array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) ) );
318
-	}
319
-
320
-	/**
321
-	 * Check if the key is an internal one.
322
-	 *
323
-	 * @since  1.0.19
324
-	 * @param  string $key Key to check.
325
-	 * @return bool   true if it's an internal key, false otherwise
326
-	 */
327
-	protected function is_internal_meta_key( $key ) {
328
-		$internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true );
329
-
330
-		if ( ! $internal_meta_key ) {
331
-			return false;
332
-		}
333
-
334
-		$has_setter_or_getter = is_callable( array( $this, 'set_' . $key ) ) || is_callable( array( $this, 'get_' . $key ) );
335
-
336
-		if ( ! $has_setter_or_getter ) {
337
-			return false;
338
-		}
339
-
340
-		/* translators: %s: $key Key to check */
341
-		getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
342
-
343
-		return true;
344
-	}
345
-
346
-	/**
347
-	 * Magic method for setting data fields.
348
-	 *
349
-	 * This method does not update custom fields in the database.
350
-	 *
351
-	 * @since 1.0.19
352
-	 * @access public
353
-	 *
354
-	 */
355
-	public function __set( $key, $value ) {
356
-
357
-		if ( 'id' == strtolower( $key ) ) {
358
-			return $this->set_id( $value );
359
-		}
360
-
361
-		if ( method_exists( $this, "set_$key") ) {
362
-
363
-			/* translators: %s: $key Key to set */
364
-			getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Object data such as "%s" should not be accessed directly. Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
365
-
366
-			call_user_func( array( $this, "set_$key" ), $value );
367
-		} else {
368
-			$this->set_prop( $key, $value );
369
-		}
370
-
371
-	}
372
-
373
-	/**
24
+    /**
25
+     * ID for this object.
26
+     *
27
+     * @since 1.0.19
28
+     * @var int
29
+     */
30
+    protected $id = 0;
31
+
32
+    /**
33
+     * Core data for this object. Name value pairs (name + default value).
34
+     *
35
+     * @since 1.0.19
36
+     * @var array
37
+     */
38
+    protected $data = array();
39
+
40
+    /**
41
+     * Core data changes for this object.
42
+     *
43
+     * @since 1.0.19
44
+     * @var array
45
+     */
46
+    protected $changes = array();
47
+
48
+    /**
49
+     * This is false until the object is read from the DB.
50
+     *
51
+     * @since 1.0.19
52
+     * @var bool
53
+     */
54
+    protected $object_read = false;
55
+
56
+    /**
57
+     * This is the name of this object type.
58
+     *
59
+     * @since 1.0.19
60
+     * @var string
61
+     */
62
+    protected $object_type = 'data';
63
+
64
+    /**
65
+     * Extra data for this object. Name value pairs (name + default value).
66
+     * Used as a standard way for sub classes (like item types) to add
67
+     * additional information to an inherited class.
68
+     *
69
+     * @since 1.0.19
70
+     * @var array
71
+     */
72
+    protected $extra_data = array();
73
+
74
+    /**
75
+     * Set to _data on construct so we can track and reset data if needed.
76
+     *
77
+     * @since 1.0.19
78
+     * @var array
79
+     */
80
+    protected $default_data = array();
81
+
82
+    /**
83
+     * Contains a reference to the data store for this class.
84
+     *
85
+     * @since 1.0.19
86
+     * @var GetPaid_Data_Store
87
+     */
88
+    protected $data_store;
89
+
90
+    /**
91
+     * Stores meta in cache for future reads.
92
+     * A group must be set to to enable caching.
93
+     *
94
+     * @since 1.0.19
95
+     * @var string
96
+     */
97
+    protected $cache_group = '';
98
+
99
+    /**
100
+     * Stores the last error.
101
+     *
102
+     * @since 1.0.19
103
+     * @var string
104
+     */
105
+    public $last_error = '';
106
+
107
+    /**
108
+     * Stores additional meta data.
109
+     *
110
+     * @since 1.0.19
111
+     * @var array
112
+     */
113
+    protected $meta_data = null;
114
+
115
+    /**
116
+     * Default constructor.
117
+     *
118
+     * @param int|object|array|string $read ID to load from the DB (optional) or already queried data.
119
+     */
120
+    public function __construct( $read = 0 ) {
121
+        $this->data         = array_merge( $this->data, $this->extra_data );
122
+        $this->default_data = $this->data;
123
+    }
124
+
125
+    /**
126
+     * Only store the object ID to avoid serializing the data object instance.
127
+     *
128
+     * @return array
129
+     */
130
+    public function __sleep() {
131
+        return array( 'id' );
132
+    }
133
+
134
+    /**
135
+     * Re-run the constructor with the object ID.
136
+     *
137
+     * If the object no longer exists, remove the ID.
138
+     */
139
+    public function __wakeup() {
140
+        $this->__construct( absint( $this->id ) );
141
+
142
+        if ( ! empty( $this->last_error ) ) {
143
+            $this->set_id( 0 );
144
+        }
145
+
146
+    }
147
+
148
+    /**
149
+     * When the object is cloned, make sure meta is duplicated correctly.
150
+     *
151
+     * @since 1.0.19
152
+     */
153
+    public function __clone() {
154
+        $this->maybe_read_meta_data();
155
+        if ( ! empty( $this->meta_data ) ) {
156
+            foreach ( $this->meta_data as $array_key => $meta ) {
157
+                $this->meta_data[ $array_key ] = clone $meta;
158
+                if ( ! empty( $meta->id ) ) {
159
+                    $this->meta_data[ $array_key ]->id = null;
160
+                }
161
+            }
162
+        }
163
+    }
164
+
165
+    /**
166
+     * Get the data store.
167
+     *
168
+     * @since  1.0.19
169
+     * @return object
170
+     */
171
+    public function get_data_store() {
172
+        return $this->data_store;
173
+    }
174
+
175
+    /**
176
+     * Get the object type.
177
+     *
178
+     * @since  1.0.19
179
+     * @return string
180
+     */
181
+    public function get_object_type() {
182
+        return $this->object_type;
183
+    }
184
+
185
+    /**
186
+     * Returns the unique ID for this object.
187
+     *
188
+     * @since  1.0.19
189
+     * @return int
190
+     */
191
+    public function get_id() {
192
+        return $this->id;
193
+    }
194
+
195
+    /**
196
+     * Get form status.
197
+     *
198
+     * @since 1.0.19
199
+     * @param  string $context View or edit context.
200
+     * @return string
201
+     */
202
+    public function get_status( $context = 'view' ) {
203
+        return $this->get_prop( 'status', $context );
204
+    }
205
+
206
+    /**
207
+     * Delete an object, set the ID to 0, and return result.
208
+     *
209
+     * @since  1.0.19
210
+     * @param  bool $force_delete Should the data be deleted permanently.
211
+     * @return bool result
212
+     */
213
+    public function delete( $force_delete = false ) {
214
+        if ( $this->data_store && $this->exists() ) {
215
+            $this->data_store->delete( $this, array( 'force_delete' => $force_delete ) );
216
+            $this->set_id( 0 );
217
+            return true;
218
+        }
219
+        return false;
220
+    }
221
+
222
+    /**
223
+     * Save should create or update based on object existence.
224
+     *
225
+     * @since  1.0.19
226
+     * @return int
227
+     */
228
+    public function save() {
229
+        if ( ! $this->data_store ) {
230
+            return $this->get_id();
231
+        }
232
+
233
+        /**
234
+         * Trigger action before saving to the DB. Allows you to adjust object props before save.
235
+         *
236
+         * @param GetPaid_Data          $this The object being saved.
237
+         * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
238
+         */
239
+        do_action( 'getpaid_before_' . $this->object_type . '_object_save', $this, $this->data_store );
240
+
241
+        if ( $this->get_id() ) {
242
+            $this->data_store->update( $this );
243
+        } else {
244
+            $this->data_store->create( $this );
245
+        }
246
+
247
+        /**
248
+         * Trigger action after saving to the DB.
249
+         *
250
+         * @param GetPaid_Data          $this The object being saved.
251
+         * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
252
+         */
253
+        do_action( 'getpaid_after_' . $this->object_type . '_object_save', $this, $this->data_store );
254
+
255
+        return $this->get_id();
256
+    }
257
+
258
+    /**
259
+     * Change data to JSON format.
260
+     *
261
+     * @since  1.0.19
262
+     * @return string Data in JSON format.
263
+     */
264
+    public function __toString() {
265
+        return wp_json_encode( $this->get_data() );
266
+    }
267
+
268
+    /**
269
+     * Returns all data for this object.
270
+     *
271
+     * @since  1.0.19
272
+     * @return array
273
+     */
274
+    public function get_data() {
275
+        return array_merge( array( 'id' => $this->get_id() ), $this->data, array( 'meta_data' => $this->get_meta_data() ) );
276
+    }
277
+
278
+    /**
279
+     * Returns array of expected data keys for this object.
280
+     *
281
+     * @since   1.0.19
282
+     * @return array
283
+     */
284
+    public function get_data_keys() {
285
+        return array_keys( $this->data );
286
+    }
287
+
288
+    /**
289
+     * Returns all "extra" data keys for an object (for sub objects like item types).
290
+     *
291
+     * @since  1.0.19
292
+     * @return array
293
+     */
294
+    public function get_extra_data_keys() {
295
+        return array_keys( $this->extra_data );
296
+    }
297
+
298
+    /**
299
+     * Filter null meta values from array.
300
+     *
301
+     * @since  1.0.19
302
+     * @param mixed $meta Meta value to check.
303
+     * @return bool
304
+     */
305
+    protected function filter_null_meta( $meta ) {
306
+        return ! is_null( $meta->value );
307
+    }
308
+
309
+    /**
310
+     * Get All Meta Data.
311
+     *
312
+     * @since 1.0.19
313
+     * @return array of objects.
314
+     */
315
+    public function get_meta_data() {
316
+        $this->maybe_read_meta_data();
317
+        return array_values( array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) ) );
318
+    }
319
+
320
+    /**
321
+     * Check if the key is an internal one.
322
+     *
323
+     * @since  1.0.19
324
+     * @param  string $key Key to check.
325
+     * @return bool   true if it's an internal key, false otherwise
326
+     */
327
+    protected function is_internal_meta_key( $key ) {
328
+        $internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true );
329
+
330
+        if ( ! $internal_meta_key ) {
331
+            return false;
332
+        }
333
+
334
+        $has_setter_or_getter = is_callable( array( $this, 'set_' . $key ) ) || is_callable( array( $this, 'get_' . $key ) );
335
+
336
+        if ( ! $has_setter_or_getter ) {
337
+            return false;
338
+        }
339
+
340
+        /* translators: %s: $key Key to check */
341
+        getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
342
+
343
+        return true;
344
+    }
345
+
346
+    /**
347
+     * Magic method for setting data fields.
348
+     *
349
+     * This method does not update custom fields in the database.
350
+     *
351
+     * @since 1.0.19
352
+     * @access public
353
+     *
354
+     */
355
+    public function __set( $key, $value ) {
356
+
357
+        if ( 'id' == strtolower( $key ) ) {
358
+            return $this->set_id( $value );
359
+        }
360
+
361
+        if ( method_exists( $this, "set_$key") ) {
362
+
363
+            /* translators: %s: $key Key to set */
364
+            getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Object data such as "%s" should not be accessed directly. Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
365
+
366
+            call_user_func( array( $this, "set_$key" ), $value );
367
+        } else {
368
+            $this->set_prop( $key, $value );
369
+        }
370
+
371
+    }
372
+
373
+    /**
374 374
      * Margic method for retrieving a property.
375 375
      */
376 376
     public function __get( $key ) {
@@ -378,10 +378,10 @@  discard block
 block discarded – undo
378 378
         // Check if we have a helper method for that.
379 379
         if ( method_exists( $this, 'get_' . $key ) ) {
380 380
 
381
-			if ( 'post_type' != $key ) {
382
-				/* translators: %s: $key Key to set */
383
-				getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Object data such as "%s" should not be accessed directly. Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
384
-			}
381
+            if ( 'post_type' != $key ) {
382
+                /* translators: %s: $key Key to set */
383
+                getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Object data such as "%s" should not be accessed directly. Use getters and setters.', 'invoicing' ), $key ), '1.0.19' );
384
+            }
385 385
 
386 386
             return call_user_func( array( $this, 'get_' . $key ) );
387 387
         }
@@ -391,514 +391,514 @@  discard block
 block discarded – undo
391 391
             return $this->post->$key;
392 392
         }
393 393
 
394
-		return $this->get_prop( $key );
395
-
396
-    }
397
-
398
-	/**
399
-	 * Get Meta Data by Key.
400
-	 *
401
-	 * @since  1.0.19
402
-	 * @param  string $key Meta Key.
403
-	 * @param  bool   $single return first found meta with key, or all with $key.
404
-	 * @param  string $context What the value is for. Valid values are view and edit.
405
-	 * @return mixed
406
-	 */
407
-	public function get_meta( $key = '', $single = true, $context = 'view' ) {
408
-
409
-		// Check if this is an internal meta key.
410
-		$_key = str_replace( '_wpinv', '', $key );
411
-		$_key = str_replace( 'wpinv', '', $_key );
412
-		if ( $this->is_internal_meta_key( $key ) ) {
413
-			$function = 'get_' . $_key;
414
-
415
-			if ( is_callable( array( $this, $function ) ) ) {
416
-				return $this->{$function}();
417
-			}
418
-		}
419
-
420
-		// Read the meta data if not yet read.
421
-		$this->maybe_read_meta_data();
422
-		$meta_data  = $this->get_meta_data();
423
-		$array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true );
424
-		$value      = $single ? '' : array();
425
-
426
-		if ( ! empty( $array_keys ) ) {
427
-			// We don't use the $this->meta_data property directly here because we don't want meta with a null value (i.e. meta which has been deleted via $this->delete_meta_data()).
428
-			if ( $single ) {
429
-				$value = $meta_data[ current( $array_keys ) ]->value;
430
-			} else {
431
-				$value = array_intersect_key( $meta_data, array_flip( $array_keys ) );
432
-			}
433
-		}
434
-
435
-		if ( 'view' === $context ) {
436
-			$value = apply_filters( $this->get_hook_prefix() . $key, $value, $this );
437
-		}
438
-
439
-		return $value;
440
-	}
441
-
442
-	/**
443
-	 * See if meta data exists, since get_meta always returns a '' or array().
444
-	 *
445
-	 * @since  1.0.19
446
-	 * @param  string $key Meta Key.
447
-	 * @return boolean
448
-	 */
449
-	public function meta_exists( $key = '' ) {
450
-		$this->maybe_read_meta_data();
451
-		$array_keys = wp_list_pluck( $this->get_meta_data(), 'key' );
452
-		return in_array( $key, $array_keys, true );
453
-	}
454
-
455
-	/**
456
-	 * Set all meta data from array.
457
-	 *
458
-	 * @since 1.0.19
459
-	 * @param array $data Key/Value pairs.
460
-	 */
461
-	public function set_meta_data( $data ) {
462
-		if ( ! empty( $data ) && is_array( $data ) ) {
463
-			$this->maybe_read_meta_data();
464
-			foreach ( $data as $meta ) {
465
-				$meta = (array) $meta;
466
-				if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) {
467
-					$this->meta_data[] = new GetPaid_Meta_Data(
468
-						array(
469
-							'id'    => $meta['id'],
470
-							'key'   => $meta['key'],
471
-							'value' => $meta['value'],
472
-						)
473
-					);
474
-				}
475
-			}
476
-		}
477
-	}
478
-
479
-	/**
480
-	 * Add meta data.
481
-	 *
482
-	 * @since 1.0.19
483
-	 *
484
-	 * @param string       $key Meta key.
485
-	 * @param string|array $value Meta value.
486
-	 * @param bool         $unique Should this be a unique key?.
487
-	 */
488
-	public function add_meta_data( $key, $value, $unique = false ) {
489
-		if ( $this->is_internal_meta_key( $key ) ) {
490
-			$function = 'set_' . $key;
491
-
492
-			if ( is_callable( array( $this, $function ) ) ) {
493
-				return $this->{$function}( $value );
494
-			}
495
-		}
496
-
497
-		$this->maybe_read_meta_data();
498
-		if ( $unique ) {
499
-			$this->delete_meta_data( $key );
500
-		}
501
-		$this->meta_data[] = new GetPaid_Meta_Data(
502
-			array(
503
-				'key'   => $key,
504
-				'value' => $value,
505
-			)
506
-		);
507
-
508
-		$this->save();
509
-	}
510
-
511
-	/**
512
-	 * Update meta data by key or ID, if provided.
513
-	 *
514
-	 * @since  1.0.19
515
-	 *
516
-	 * @param  string       $key Meta key.
517
-	 * @param  string|array $value Meta value.
518
-	 * @param  int          $meta_id Meta ID.
519
-	 */
520
-	public function update_meta_data( $key, $value, $meta_id = 0 ) {
521
-		if ( $this->is_internal_meta_key( $key ) ) {
522
-			$function = 'set_' . $key;
523
-
524
-			if ( is_callable( array( $this, $function ) ) ) {
525
-				return $this->{$function}( $value );
526
-			}
527
-		}
528
-
529
-		$this->maybe_read_meta_data();
530
-
531
-		$array_key = false;
532
-
533
-		if ( $meta_id ) {
534
-			$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id, true );
535
-			$array_key  = $array_keys ? current( $array_keys ) : false;
536
-		} else {
537
-			// Find matches by key.
538
-			$matches = array();
539
-			foreach ( $this->meta_data as $meta_data_array_key => $meta ) {
540
-				if ( $meta->key === $key ) {
541
-					$matches[] = $meta_data_array_key;
542
-				}
543
-			}
544
-
545
-			if ( ! empty( $matches ) ) {
546
-				// Set matches to null so only one key gets the new value.
547
-				foreach ( $matches as $meta_data_array_key ) {
548
-					$this->meta_data[ $meta_data_array_key ]->value = null;
549
-				}
550
-				$array_key = current( $matches );
551
-			}
552
-		}
553
-
554
-		if ( false !== $array_key ) {
555
-			$meta        = $this->meta_data[ $array_key ];
556
-			$meta->key   = $key;
557
-			$meta->value = $value;
558
-		} else {
559
-			$this->add_meta_data( $key, $value, true );
560
-		}
561
-	}
562
-
563
-	/**
564
-	 * Delete meta data.
565
-	 *
566
-	 * @since 1.0.19
567
-	 * @param string $key Meta key.
568
-	 */
569
-	public function delete_meta_data( $key ) {
570
-		$this->maybe_read_meta_data();
571
-		$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true );
572
-
573
-		if ( $array_keys ) {
574
-			foreach ( $array_keys as $array_key ) {
575
-				$this->meta_data[ $array_key ]->value = null;
576
-			}
577
-		}
578
-	}
579
-
580
-	/**
581
-	 * Delete meta data.
582
-	 *
583
-	 * @since 1.0.19
584
-	 * @param int $mid Meta ID.
585
-	 */
586
-	public function delete_meta_data_by_mid( $mid ) {
587
-		$this->maybe_read_meta_data();
588
-		$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true );
589
-
590
-		if ( $array_keys ) {
591
-			foreach ( $array_keys as $array_key ) {
592
-				$this->meta_data[ $array_key ]->value = null;
593
-			}
594
-		}
595
-	}
596
-
597
-	/**
598
-	 * Read meta data if null.
599
-	 *
600
-	 * @since 1.0.19
601
-	 */
602
-	protected function maybe_read_meta_data() {
603
-		if ( is_null( $this->meta_data ) ) {
604
-			$this->read_meta_data();
605
-		}
606
-	}
607
-
608
-	/**
609
-	 * Read Meta Data from the database. Ignore any internal properties.
610
-	 * Uses it's own caches because get_metadata does not provide meta_ids.
611
-	 *
612
-	 * @since 1.0.19
613
-	 * @param bool $force_read True to force a new DB read (and update cache).
614
-	 */
615
-	public function read_meta_data( $force_read = false ) {
616
-
617
-		// Reset meta data.
618
-		$this->meta_data = array();
619
-
620
-		// Maybe abort early.
621
-		if ( ! $this->get_id() || ! $this->data_store ) {
622
-			return;
623
-		}
624
-
625
-		// Only read from cache if the cache key is set.
626
-		$cache_key = null;
627
-		if ( ! $force_read && ! empty( $this->cache_group ) ) {
628
-			$cache_key     = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id();
629
-			$raw_meta_data = wp_cache_get( $cache_key, $this->cache_group );
630
-		}
631
-
632
-		// Should we force read?
633
-		if ( empty( $raw_meta_data ) ) {
634
-			$raw_meta_data = $this->data_store->read_meta( $this );
635
-
636
-			if ( ! empty( $cache_key ) ) {
637
-				wp_cache_set( $cache_key, $raw_meta_data, $this->cache_group );
638
-			}
639
-
640
-		}
641
-
642
-		// Set meta data.
643
-		if ( is_array( $raw_meta_data ) ) {
644
-
645
-			foreach ( $raw_meta_data as $meta ) {
646
-				$this->meta_data[] = new GetPaid_Meta_Data(
647
-					array(
648
-						'id'    => (int) $meta->meta_id,
649
-						'key'   => $meta->meta_key,
650
-						'value' => maybe_unserialize( $meta->meta_value ),
651
-					)
652
-				);
653
-			}
654
-
655
-		}
656
-
657
-	}
658
-
659
-	/**
660
-	 * Update Meta Data in the database.
661
-	 *
662
-	 * @since 1.0.19
663
-	 */
664
-	public function save_meta_data() {
665
-		if ( ! $this->data_store || is_null( $this->meta_data ) ) {
666
-			return;
667
-		}
668
-		foreach ( $this->meta_data as $array_key => $meta ) {
669
-			if ( is_null( $meta->value ) ) {
670
-				if ( ! empty( $meta->id ) ) {
671
-					$this->data_store->delete_meta( $this, $meta );
672
-					unset( $this->meta_data[ $array_key ] );
673
-				}
674
-			} elseif ( empty( $meta->id ) ) {
675
-				$meta->id = $this->data_store->add_meta( $this, $meta );
676
-				$meta->apply_changes();
677
-			} else {
678
-				if ( $meta->get_changes() ) {
679
-					$this->data_store->update_meta( $this, $meta );
680
-					$meta->apply_changes();
681
-				}
682
-			}
683
-		}
684
-		if ( ! empty( $this->cache_group ) ) {
685
-			$cache_key = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id();
686
-			wp_cache_delete( $cache_key, $this->cache_group );
687
-		}
688
-	}
689
-
690
-	/**
691
-	 * Set ID.
692
-	 *
693
-	 * @since 1.0.19
694
-	 * @param int $id ID.
695
-	 */
696
-	public function set_id( $id ) {
697
-		$this->id = absint( $id );
698
-	}
699
-
700
-	/**
701
-	 * Sets item status.
702
-	 *
703
-	 * @since 1.0.19
704
-	 * @param string $status New status.
705
-	 * @return array details of change.
706
-	 */
707
-	public function set_status( $status ) {
394
+        return $this->get_prop( $key );
395
+
396
+    }
397
+
398
+    /**
399
+     * Get Meta Data by Key.
400
+     *
401
+     * @since  1.0.19
402
+     * @param  string $key Meta Key.
403
+     * @param  bool   $single return first found meta with key, or all with $key.
404
+     * @param  string $context What the value is for. Valid values are view and edit.
405
+     * @return mixed
406
+     */
407
+    public function get_meta( $key = '', $single = true, $context = 'view' ) {
408
+
409
+        // Check if this is an internal meta key.
410
+        $_key = str_replace( '_wpinv', '', $key );
411
+        $_key = str_replace( 'wpinv', '', $_key );
412
+        if ( $this->is_internal_meta_key( $key ) ) {
413
+            $function = 'get_' . $_key;
414
+
415
+            if ( is_callable( array( $this, $function ) ) ) {
416
+                return $this->{$function}();
417
+            }
418
+        }
419
+
420
+        // Read the meta data if not yet read.
421
+        $this->maybe_read_meta_data();
422
+        $meta_data  = $this->get_meta_data();
423
+        $array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true );
424
+        $value      = $single ? '' : array();
425
+
426
+        if ( ! empty( $array_keys ) ) {
427
+            // We don't use the $this->meta_data property directly here because we don't want meta with a null value (i.e. meta which has been deleted via $this->delete_meta_data()).
428
+            if ( $single ) {
429
+                $value = $meta_data[ current( $array_keys ) ]->value;
430
+            } else {
431
+                $value = array_intersect_key( $meta_data, array_flip( $array_keys ) );
432
+            }
433
+        }
434
+
435
+        if ( 'view' === $context ) {
436
+            $value = apply_filters( $this->get_hook_prefix() . $key, $value, $this );
437
+        }
438
+
439
+        return $value;
440
+    }
441
+
442
+    /**
443
+     * See if meta data exists, since get_meta always returns a '' or array().
444
+     *
445
+     * @since  1.0.19
446
+     * @param  string $key Meta Key.
447
+     * @return boolean
448
+     */
449
+    public function meta_exists( $key = '' ) {
450
+        $this->maybe_read_meta_data();
451
+        $array_keys = wp_list_pluck( $this->get_meta_data(), 'key' );
452
+        return in_array( $key, $array_keys, true );
453
+    }
454
+
455
+    /**
456
+     * Set all meta data from array.
457
+     *
458
+     * @since 1.0.19
459
+     * @param array $data Key/Value pairs.
460
+     */
461
+    public function set_meta_data( $data ) {
462
+        if ( ! empty( $data ) && is_array( $data ) ) {
463
+            $this->maybe_read_meta_data();
464
+            foreach ( $data as $meta ) {
465
+                $meta = (array) $meta;
466
+                if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) {
467
+                    $this->meta_data[] = new GetPaid_Meta_Data(
468
+                        array(
469
+                            'id'    => $meta['id'],
470
+                            'key'   => $meta['key'],
471
+                            'value' => $meta['value'],
472
+                        )
473
+                    );
474
+                }
475
+            }
476
+        }
477
+    }
478
+
479
+    /**
480
+     * Add meta data.
481
+     *
482
+     * @since 1.0.19
483
+     *
484
+     * @param string       $key Meta key.
485
+     * @param string|array $value Meta value.
486
+     * @param bool         $unique Should this be a unique key?.
487
+     */
488
+    public function add_meta_data( $key, $value, $unique = false ) {
489
+        if ( $this->is_internal_meta_key( $key ) ) {
490
+            $function = 'set_' . $key;
491
+
492
+            if ( is_callable( array( $this, $function ) ) ) {
493
+                return $this->{$function}( $value );
494
+            }
495
+        }
496
+
497
+        $this->maybe_read_meta_data();
498
+        if ( $unique ) {
499
+            $this->delete_meta_data( $key );
500
+        }
501
+        $this->meta_data[] = new GetPaid_Meta_Data(
502
+            array(
503
+                'key'   => $key,
504
+                'value' => $value,
505
+            )
506
+        );
507
+
508
+        $this->save();
509
+    }
510
+
511
+    /**
512
+     * Update meta data by key or ID, if provided.
513
+     *
514
+     * @since  1.0.19
515
+     *
516
+     * @param  string       $key Meta key.
517
+     * @param  string|array $value Meta value.
518
+     * @param  int          $meta_id Meta ID.
519
+     */
520
+    public function update_meta_data( $key, $value, $meta_id = 0 ) {
521
+        if ( $this->is_internal_meta_key( $key ) ) {
522
+            $function = 'set_' . $key;
523
+
524
+            if ( is_callable( array( $this, $function ) ) ) {
525
+                return $this->{$function}( $value );
526
+            }
527
+        }
528
+
529
+        $this->maybe_read_meta_data();
530
+
531
+        $array_key = false;
532
+
533
+        if ( $meta_id ) {
534
+            $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id, true );
535
+            $array_key  = $array_keys ? current( $array_keys ) : false;
536
+        } else {
537
+            // Find matches by key.
538
+            $matches = array();
539
+            foreach ( $this->meta_data as $meta_data_array_key => $meta ) {
540
+                if ( $meta->key === $key ) {
541
+                    $matches[] = $meta_data_array_key;
542
+                }
543
+            }
544
+
545
+            if ( ! empty( $matches ) ) {
546
+                // Set matches to null so only one key gets the new value.
547
+                foreach ( $matches as $meta_data_array_key ) {
548
+                    $this->meta_data[ $meta_data_array_key ]->value = null;
549
+                }
550
+                $array_key = current( $matches );
551
+            }
552
+        }
553
+
554
+        if ( false !== $array_key ) {
555
+            $meta        = $this->meta_data[ $array_key ];
556
+            $meta->key   = $key;
557
+            $meta->value = $value;
558
+        } else {
559
+            $this->add_meta_data( $key, $value, true );
560
+        }
561
+    }
562
+
563
+    /**
564
+     * Delete meta data.
565
+     *
566
+     * @since 1.0.19
567
+     * @param string $key Meta key.
568
+     */
569
+    public function delete_meta_data( $key ) {
570
+        $this->maybe_read_meta_data();
571
+        $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true );
572
+
573
+        if ( $array_keys ) {
574
+            foreach ( $array_keys as $array_key ) {
575
+                $this->meta_data[ $array_key ]->value = null;
576
+            }
577
+        }
578
+    }
579
+
580
+    /**
581
+     * Delete meta data.
582
+     *
583
+     * @since 1.0.19
584
+     * @param int $mid Meta ID.
585
+     */
586
+    public function delete_meta_data_by_mid( $mid ) {
587
+        $this->maybe_read_meta_data();
588
+        $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true );
589
+
590
+        if ( $array_keys ) {
591
+            foreach ( $array_keys as $array_key ) {
592
+                $this->meta_data[ $array_key ]->value = null;
593
+            }
594
+        }
595
+    }
596
+
597
+    /**
598
+     * Read meta data if null.
599
+     *
600
+     * @since 1.0.19
601
+     */
602
+    protected function maybe_read_meta_data() {
603
+        if ( is_null( $this->meta_data ) ) {
604
+            $this->read_meta_data();
605
+        }
606
+    }
607
+
608
+    /**
609
+     * Read Meta Data from the database. Ignore any internal properties.
610
+     * Uses it's own caches because get_metadata does not provide meta_ids.
611
+     *
612
+     * @since 1.0.19
613
+     * @param bool $force_read True to force a new DB read (and update cache).
614
+     */
615
+    public function read_meta_data( $force_read = false ) {
616
+
617
+        // Reset meta data.
618
+        $this->meta_data = array();
619
+
620
+        // Maybe abort early.
621
+        if ( ! $this->get_id() || ! $this->data_store ) {
622
+            return;
623
+        }
624
+
625
+        // Only read from cache if the cache key is set.
626
+        $cache_key = null;
627
+        if ( ! $force_read && ! empty( $this->cache_group ) ) {
628
+            $cache_key     = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id();
629
+            $raw_meta_data = wp_cache_get( $cache_key, $this->cache_group );
630
+        }
631
+
632
+        // Should we force read?
633
+        if ( empty( $raw_meta_data ) ) {
634
+            $raw_meta_data = $this->data_store->read_meta( $this );
635
+
636
+            if ( ! empty( $cache_key ) ) {
637
+                wp_cache_set( $cache_key, $raw_meta_data, $this->cache_group );
638
+            }
639
+
640
+        }
641
+
642
+        // Set meta data.
643
+        if ( is_array( $raw_meta_data ) ) {
644
+
645
+            foreach ( $raw_meta_data as $meta ) {
646
+                $this->meta_data[] = new GetPaid_Meta_Data(
647
+                    array(
648
+                        'id'    => (int) $meta->meta_id,
649
+                        'key'   => $meta->meta_key,
650
+                        'value' => maybe_unserialize( $meta->meta_value ),
651
+                    )
652
+                );
653
+            }
654
+
655
+        }
656
+
657
+    }
658
+
659
+    /**
660
+     * Update Meta Data in the database.
661
+     *
662
+     * @since 1.0.19
663
+     */
664
+    public function save_meta_data() {
665
+        if ( ! $this->data_store || is_null( $this->meta_data ) ) {
666
+            return;
667
+        }
668
+        foreach ( $this->meta_data as $array_key => $meta ) {
669
+            if ( is_null( $meta->value ) ) {
670
+                if ( ! empty( $meta->id ) ) {
671
+                    $this->data_store->delete_meta( $this, $meta );
672
+                    unset( $this->meta_data[ $array_key ] );
673
+                }
674
+            } elseif ( empty( $meta->id ) ) {
675
+                $meta->id = $this->data_store->add_meta( $this, $meta );
676
+                $meta->apply_changes();
677
+            } else {
678
+                if ( $meta->get_changes() ) {
679
+                    $this->data_store->update_meta( $this, $meta );
680
+                    $meta->apply_changes();
681
+                }
682
+            }
683
+        }
684
+        if ( ! empty( $this->cache_group ) ) {
685
+            $cache_key = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id();
686
+            wp_cache_delete( $cache_key, $this->cache_group );
687
+        }
688
+    }
689
+
690
+    /**
691
+     * Set ID.
692
+     *
693
+     * @since 1.0.19
694
+     * @param int $id ID.
695
+     */
696
+    public function set_id( $id ) {
697
+        $this->id = absint( $id );
698
+    }
699
+
700
+    /**
701
+     * Sets item status.
702
+     *
703
+     * @since 1.0.19
704
+     * @param string $status New status.
705
+     * @return array details of change.
706
+     */
707
+    public function set_status( $status ) {
708 708
         $old_status = $this->get_status();
709 709
 
710
-		$this->set_prop( 'status', $status );
711
-
712
-		return array(
713
-			'from' => $old_status,
714
-			'to'   => $status,
715
-		);
716
-    }
717
-
718
-	/**
719
-	 * Set all props to default values.
720
-	 *
721
-	 * @since 1.0.19
722
-	 */
723
-	public function set_defaults() {
724
-		$this->data    = $this->default_data;
725
-		$this->changes = array();
726
-		$this->set_object_read( false );
727
-	}
728
-
729
-	/**
730
-	 * Set object read property.
731
-	 *
732
-	 * @since 1.0.19
733
-	 * @param boolean $read Should read?.
734
-	 */
735
-	public function set_object_read( $read = true ) {
736
-		$this->object_read = (bool) $read;
737
-	}
738
-
739
-	/**
740
-	 * Get object read property.
741
-	 *
742
-	 * @since  1.0.19
743
-	 * @return boolean
744
-	 */
745
-	public function get_object_read() {
746
-		return (bool) $this->object_read;
747
-	}
748
-
749
-	/**
750
-	 * Set a collection of props in one go, collect any errors, and return the result.
751
-	 * Only sets using public methods.
752
-	 *
753
-	 * @since  1.0.19
754
-	 *
755
-	 * @param array  $props Key value pairs to set. Key is the prop and should map to a setter function name.
756
-	 * @param string $context In what context to run this.
757
-	 *
758
-	 * @return bool|WP_Error
759
-	 */
760
-	public function set_props( $props, $context = 'set' ) {
761
-		$errors = false;
762
-
763
-		foreach ( $props as $prop => $value ) {
764
-			try {
765
-				/**
766
-				 * Checks if the prop being set is allowed, and the value is not null.
767
-				 */
768
-				if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) {
769
-					continue;
770
-				}
771
-				$setter = "set_$prop";
772
-
773
-				if ( is_callable( array( $this, $setter ) ) ) {
774
-					$this->{$setter}( $value );
775
-				}
776
-			} catch ( Exception $e ) {
777
-				if ( ! $errors ) {
778
-					$errors = new WP_Error();
779
-				}
780
-				$errors->add( $e->getCode(), $e->getMessage() );
781
-				$this->last_error = $e->getMessage();
782
-			}
783
-		}
784
-
785
-		return $errors && count( $errors->get_error_codes() ) ? $errors : true;
786
-	}
787
-
788
-	/**
789
-	 * Sets a prop for a setter method.
790
-	 *
791
-	 * This stores changes in a special array so we can track what needs saving
792
-	 * the the DB later.
793
-	 *
794
-	 * @since 1.0.19
795
-	 * @param string $prop Name of prop to set.
796
-	 * @param mixed  $value Value of the prop.
797
-	 */
798
-	protected function set_prop( $prop, $value ) {
799
-		if ( array_key_exists( $prop, $this->data ) ) {
800
-			if ( true === $this->object_read ) {
801
-				if ( $value !== $this->data[ $prop ] || array_key_exists( $prop, $this->changes ) ) {
802
-					$this->changes[ $prop ] = $value;
803
-				}
804
-			} else {
805
-				$this->data[ $prop ] = $value;
806
-			}
807
-		}
808
-	}
809
-
810
-	/**
811
-	 * Return data changes only.
812
-	 *
813
-	 * @since 1.0.19
814
-	 * @return array
815
-	 */
816
-	public function get_changes() {
817
-		return $this->changes;
818
-	}
819
-
820
-	/**
821
-	 * Merge changes with data and clear.
822
-	 *
823
-	 * @since 1.0.19
824
-	 */
825
-	public function apply_changes() {
826
-		$this->data    = array_replace( $this->data, $this->changes );
827
-		$this->changes = array();
828
-	}
829
-
830
-	/**
831
-	 * Prefix for action and filter hooks on data.
832
-	 *
833
-	 * @since  1.0.19
834
-	 * @return string
835
-	 */
836
-	protected function get_hook_prefix() {
837
-		return 'wpinv_get_' . $this->object_type . '_';
838
-	}
839
-
840
-	/**
841
-	 * Gets a prop for a getter method.
842
-	 *
843
-	 * Gets the value from either current pending changes, or the data itself.
844
-	 * Context controls what happens to the value before it's returned.
845
-	 *
846
-	 * @since  1.0.19
847
-	 * @param  string $prop Name of prop to get.
848
-	 * @param  string $context What the value is for. Valid values are view and edit.
849
-	 * @return mixed
850
-	 */
851
-	protected function get_prop( $prop, $context = 'view' ) {
852
-		$value = null;
853
-
854
-		if ( array_key_exists( $prop, $this->data ) ) {
855
-			$value = array_key_exists( $prop, $this->changes ) ? $this->changes[ $prop ] : $this->data[ $prop ];
856
-
857
-			if ( 'view' === $context ) {
858
-				$value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this );
859
-			}
860
-		}
861
-
862
-		return $value;
863
-	}
864
-
865
-	/**
866
-	 * Sets a date prop whilst handling formatting and datetime objects.
867
-	 *
868
-	 * @since 1.0.19
869
-	 * @param string         $prop Name of prop to set.
870
-	 * @param string|integer $value Value of the prop.
871
-	 */
872
-	protected function set_date_prop( $prop, $value ) {
873
-
874
-		if ( empty( $value ) ) {
875
-			$this->set_prop( $prop, null );
876
-			return;
877
-		}
878
-		$this->set_prop( $prop, $value );
879
-
880
-	}
881
-
882
-	/**
883
-	 * When invalid data is found, throw an exception unless reading from the DB.
884
-	 *
885
-	 * @since 1.0.19
886
-	 * @param string $code             Error code.
887
-	 * @param string $message          Error message.
888
-	 */
889
-	protected function error( $code, $message ) {
890
-		$this->last_error = $message;
891
-	}
892
-
893
-	/**
894
-	 * Checks if the object is saved in the database
895
-	 *
896
-	 * @since 1.0.19
897
-	 * @return bool
898
-	 */
899
-	public function exists() {
900
-		$id = $this->get_id();
901
-		return ! empty( $id );
902
-	}
710
+        $this->set_prop( 'status', $status );
711
+
712
+        return array(
713
+            'from' => $old_status,
714
+            'to'   => $status,
715
+        );
716
+    }
717
+
718
+    /**
719
+     * Set all props to default values.
720
+     *
721
+     * @since 1.0.19
722
+     */
723
+    public function set_defaults() {
724
+        $this->data    = $this->default_data;
725
+        $this->changes = array();
726
+        $this->set_object_read( false );
727
+    }
728
+
729
+    /**
730
+     * Set object read property.
731
+     *
732
+     * @since 1.0.19
733
+     * @param boolean $read Should read?.
734
+     */
735
+    public function set_object_read( $read = true ) {
736
+        $this->object_read = (bool) $read;
737
+    }
738
+
739
+    /**
740
+     * Get object read property.
741
+     *
742
+     * @since  1.0.19
743
+     * @return boolean
744
+     */
745
+    public function get_object_read() {
746
+        return (bool) $this->object_read;
747
+    }
748
+
749
+    /**
750
+     * Set a collection of props in one go, collect any errors, and return the result.
751
+     * Only sets using public methods.
752
+     *
753
+     * @since  1.0.19
754
+     *
755
+     * @param array  $props Key value pairs to set. Key is the prop and should map to a setter function name.
756
+     * @param string $context In what context to run this.
757
+     *
758
+     * @return bool|WP_Error
759
+     */
760
+    public function set_props( $props, $context = 'set' ) {
761
+        $errors = false;
762
+
763
+        foreach ( $props as $prop => $value ) {
764
+            try {
765
+                /**
766
+                 * Checks if the prop being set is allowed, and the value is not null.
767
+                 */
768
+                if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) {
769
+                    continue;
770
+                }
771
+                $setter = "set_$prop";
772
+
773
+                if ( is_callable( array( $this, $setter ) ) ) {
774
+                    $this->{$setter}( $value );
775
+                }
776
+            } catch ( Exception $e ) {
777
+                if ( ! $errors ) {
778
+                    $errors = new WP_Error();
779
+                }
780
+                $errors->add( $e->getCode(), $e->getMessage() );
781
+                $this->last_error = $e->getMessage();
782
+            }
783
+        }
784
+
785
+        return $errors && count( $errors->get_error_codes() ) ? $errors : true;
786
+    }
787
+
788
+    /**
789
+     * Sets a prop for a setter method.
790
+     *
791
+     * This stores changes in a special array so we can track what needs saving
792
+     * the the DB later.
793
+     *
794
+     * @since 1.0.19
795
+     * @param string $prop Name of prop to set.
796
+     * @param mixed  $value Value of the prop.
797
+     */
798
+    protected function set_prop( $prop, $value ) {
799
+        if ( array_key_exists( $prop, $this->data ) ) {
800
+            if ( true === $this->object_read ) {
801
+                if ( $value !== $this->data[ $prop ] || array_key_exists( $prop, $this->changes ) ) {
802
+                    $this->changes[ $prop ] = $value;
803
+                }
804
+            } else {
805
+                $this->data[ $prop ] = $value;
806
+            }
807
+        }
808
+    }
809
+
810
+    /**
811
+     * Return data changes only.
812
+     *
813
+     * @since 1.0.19
814
+     * @return array
815
+     */
816
+    public function get_changes() {
817
+        return $this->changes;
818
+    }
819
+
820
+    /**
821
+     * Merge changes with data and clear.
822
+     *
823
+     * @since 1.0.19
824
+     */
825
+    public function apply_changes() {
826
+        $this->data    = array_replace( $this->data, $this->changes );
827
+        $this->changes = array();
828
+    }
829
+
830
+    /**
831
+     * Prefix for action and filter hooks on data.
832
+     *
833
+     * @since  1.0.19
834
+     * @return string
835
+     */
836
+    protected function get_hook_prefix() {
837
+        return 'wpinv_get_' . $this->object_type . '_';
838
+    }
839
+
840
+    /**
841
+     * Gets a prop for a getter method.
842
+     *
843
+     * Gets the value from either current pending changes, or the data itself.
844
+     * Context controls what happens to the value before it's returned.
845
+     *
846
+     * @since  1.0.19
847
+     * @param  string $prop Name of prop to get.
848
+     * @param  string $context What the value is for. Valid values are view and edit.
849
+     * @return mixed
850
+     */
851
+    protected function get_prop( $prop, $context = 'view' ) {
852
+        $value = null;
853
+
854
+        if ( array_key_exists( $prop, $this->data ) ) {
855
+            $value = array_key_exists( $prop, $this->changes ) ? $this->changes[ $prop ] : $this->data[ $prop ];
856
+
857
+            if ( 'view' === $context ) {
858
+                $value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this );
859
+            }
860
+        }
861
+
862
+        return $value;
863
+    }
864
+
865
+    /**
866
+     * Sets a date prop whilst handling formatting and datetime objects.
867
+     *
868
+     * @since 1.0.19
869
+     * @param string         $prop Name of prop to set.
870
+     * @param string|integer $value Value of the prop.
871
+     */
872
+    protected function set_date_prop( $prop, $value ) {
873
+
874
+        if ( empty( $value ) ) {
875
+            $this->set_prop( $prop, null );
876
+            return;
877
+        }
878
+        $this->set_prop( $prop, $value );
879
+
880
+    }
881
+
882
+    /**
883
+     * When invalid data is found, throw an exception unless reading from the DB.
884
+     *
885
+     * @since 1.0.19
886
+     * @param string $code             Error code.
887
+     * @param string $message          Error message.
888
+     */
889
+    protected function error( $code, $message ) {
890
+        $this->last_error = $message;
891
+    }
892
+
893
+    /**
894
+     * Checks if the object is saved in the database
895
+     *
896
+     * @since 1.0.19
897
+     * @return bool
898
+     */
899
+    public function exists() {
900
+        $id = $this->get_id();
901
+        return ! empty( $id );
902
+    }
903 903
 
904 904
 }
Please login to merge, or discard this patch.
includes/class-getpaid-subscription-notification-emails.php 1 patch
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -13,288 +13,288 @@
 block discarded – undo
13 13
 class GetPaid_Subscription_Notification_Emails {
14 14
 
15 15
     /**
16
-	 * The array of subscription email actions.
17
-	 *
18
-	 * @param array
19
-	 */
20
-	public $subscription_actions;
16
+     * The array of subscription email actions.
17
+     *
18
+     * @param array
19
+     */
20
+    public $subscription_actions;
21 21
 
22 22
     /**
23
-	 * Class constructor
23
+     * Class constructor
24 24
      *
25
-	 */
26
-	public function __construct() {
27
-
28
-		$this->subscription_actions = apply_filters(
29
-			'getpaid_notification_email_subscription_triggers',
30
-			array(
31
-				'getpaid_subscription_trialling' => 'subscription_trial',
32
-				'getpaid_subscription_cancelled' => 'subscription_cancelled',
33
-				'getpaid_subscription_expired'   => 'subscription_expired',
34
-				'getpaid_subscription_completed' => 'subscription_complete',
35
-				'getpaid_daily_maintenance'      => 'renewal_reminder',
36
-			)
37
-		);
38
-
39
-		$this->init_hooks();
25
+     */
26
+    public function __construct() {
27
+
28
+        $this->subscription_actions = apply_filters(
29
+            'getpaid_notification_email_subscription_triggers',
30
+            array(
31
+                'getpaid_subscription_trialling' => 'subscription_trial',
32
+                'getpaid_subscription_cancelled' => 'subscription_cancelled',
33
+                'getpaid_subscription_expired'   => 'subscription_expired',
34
+                'getpaid_subscription_completed' => 'subscription_complete',
35
+                'getpaid_daily_maintenance'      => 'renewal_reminder',
36
+            )
37
+        );
38
+
39
+        $this->init_hooks();
40 40
 
41 41
     }
42 42
 
43 43
     /**
44
-	 * Registers email hooks.
45
-	 */
46
-	public function init_hooks() {
47
-
48
-		add_filter( 'getpaid_get_email_merge_tags', array( $this, 'subscription_merge_tags' ), 10, 2 );
49
-		foreach ( $this->subscription_actions as $hook => $email_type ) {
50
-
51
-			$email = new GetPaid_Notification_Email( $email_type );
52
-
53
-			if ( ! $email->is_active() ) {
54
-				continue;
55
-			}
56
-
57
-			if ( method_exists( $this, $email_type ) ) {
58
-				add_action( $hook, array( $this, $email_type ), 100, 2 );
59
-				continue;
60
-			}
61
-
62
-			do_action( 'getpaid_subscription_notification_email_register_hook', $email_type, $hook );
63
-
64
-		}
65
-
66
-	}
67
-
68
-	/**
69
-	 * Filters subscription merge tags.
70
-	 *
71
-	 * @param array $merge_tags
72
-	 * @param mixed|WPInv_Invoice|WPInv_Subscription $object
73
-	 */
74
-	public function subscription_merge_tags( $merge_tags, $object ) {
75
-
76
-		if ( is_a( $object, 'WPInv_Subscription' ) ) {
77
-			$merge_tags = array_merge(
78
-				$merge_tags,
79
-				$this->get_subscription_merge_tags( $object )
80
-			);
81
-		}
82
-
83
-		return $merge_tags;
84
-
85
-	}
86
-
87
-	/**
88
-	 * Generates subscription merge tags.
89
-	 *
90
-	 * @param WPInv_Subscription $subscription
91
-	 * @return array
92
-	 */
93
-	public function get_subscription_merge_tags( $subscription ) {
94
-
95
-		// Abort if it does not exist.
96
-		if ( ! $subscription->get_id() ) {
97
-			return array();
98
-		}
99
-
100
-		$invoice    = $subscription->get_parent_invoice();
101
-		return array(
102
-			'{subscription_renewal_date}'     => getpaid_format_date_value( $subscription->get_next_renewal_date(), __( 'Never', 'invoicing' ) ),
103
-			'{subscription_created}'          => getpaid_format_date_value( $subscription->get_date_created() ),
104
-			'{subscription_status}'           => sanitize_text_field( $subscription->get_status_label() ),
105
-			'{subscription_profile_id}'       => sanitize_text_field( $subscription->get_profile_id() ),
106
-			'{subscription_id}'               => absint( $subscription->get_id() ),
107
-			'{subscription_recurring_amount}' => sanitize_text_field( wpinv_price( $subscription->get_recurring_amount(), $invoice->get_currency() ) ),
108
-			'{subscription_initial_amount}'   => sanitize_text_field( wpinv_price( $subscription->get_initial_amount(), $invoice->get_currency() ) ),
109
-			'{subscription_recurring_period}' => getpaid_get_subscription_period_label( $subscription->get_period(), $subscription->get_frequency(), '' ),
110
-			'{subscription_bill_times}'       => $subscription->get_bill_times(),
111
-			'{subscription_url}'              => esc_url( $subscription->get_view_url() ),
112
-		);
113
-
114
-	}
115
-
116
-	/**
117
-	 * Checks if we should send a notification for a subscription.
118
-	 *
119
-	 * @param WPInv_Invoice $invoice
120
-	 * @return bool
121
-	 */
122
-	public function should_send_notification( $invoice ) {
123
-		return 0 != $invoice->get_id();
124
-	}
125
-
126
-	/**
127
-	 * Returns notification recipients.
128
-	 *
129
-	 * @param WPInv_Invoice $invoice
130
-	 * @return array
131
-	 */
132
-	public function get_recipients( $invoice ) {
133
-		$recipients = array( $invoice->get_email() );
134
-
135
-		$cc = $invoice->get_email_cc();
136
-
137
-		if ( ! empty( $cc ) ) {
138
-			$cc = array_map( 'sanitize_email', wpinv_parse_list( $cc ) );
139
-			$recipients = array_filter( array_unique( array_merge( $recipients, $cc ) ) );
140
-		}
141
-
142
-		return $recipients;
143
-	}
144
-
145
-	/**
146
-	 * Helper function to send an email.
147
-	 *
148
-	 * @param WPInv_Subscription $subscription
149
-	 * @param GetPaid_Notification_Email $email
150
-	 * @param string $type
151
-	 * @param array $extra_args Extra template args.
152
-	 */
153
-	public function send_email( $subscription, $email, $type, $extra_args = array() ) {
154
-
155
-		// Abort in case the parent invoice does not exist.
156
-		$invoice = $subscription->get_parent_invoice();
157
-		if ( ! $this->should_send_notification( $invoice ) ) {
158
-			return;
159
-		}
160
-
161
-		if ( apply_filters( 'getpaid_skip_subscription_email', false, $type, $subscription ) ) {
162
-			return;
163
-		}
164
-
165
-		do_action( 'getpaid_before_send_subscription_notification', $type, $subscription, $email );
166
-
167
-		$recipients  = $this->get_recipients( $invoice );
168
-		$mailer      = new GetPaid_Notification_Email_Sender();
169
-		$merge_tags  = $email->get_merge_tags();
170
-		$content     = $email->get_content( $merge_tags, $extra_args );
171
-		$subject     = $email->add_merge_tags( $email->get_subject(), $merge_tags );
172
-		$attachments = $email->get_attachments();
173
-
174
-		$result = $mailer->send(
175
-			apply_filters( 'getpaid_subscription_email_recipients', wpinv_parse_list( $recipients ), $email ),
176
-			$subject,
177
-			$content,
178
-			$attachments
179
-		);
180
-
181
-		// Maybe send a copy to the admin.
182
-		if ( $email->include_admin_bcc() ) {
183
-			$mailer->send(
184
-				wpinv_get_admin_email(),
185
-				$subject . __( ' - ADMIN BCC COPY', 'invoicing' ),
186
-				$content,
187
-				$attachments
188
-			);
189
-		}
190
-
191
-		if ( $result ) {
192
-			$subscription->get_parent_invoice()->add_note( sprintf( __( 'Successfully sent %s notification email.', 'invoicing' ), sanitize_key( $type ) ), false, false, true );
193
-		} else {
194
-			$subscription->get_parent_invoice()->add_note( sprintf( __( 'Failed sending %s notification email.', 'invoicing' ), sanitize_key( $type ) ), false, false, true );
195
-		}
196
-
197
-		do_action( 'getpaid_after_send_subscription_notification', $type, $subscription, $email );
198
-
199
-	}
44
+     * Registers email hooks.
45
+     */
46
+    public function init_hooks() {
47
+
48
+        add_filter( 'getpaid_get_email_merge_tags', array( $this, 'subscription_merge_tags' ), 10, 2 );
49
+        foreach ( $this->subscription_actions as $hook => $email_type ) {
50
+
51
+            $email = new GetPaid_Notification_Email( $email_type );
52
+
53
+            if ( ! $email->is_active() ) {
54
+                continue;
55
+            }
56
+
57
+            if ( method_exists( $this, $email_type ) ) {
58
+                add_action( $hook, array( $this, $email_type ), 100, 2 );
59
+                continue;
60
+            }
61
+
62
+            do_action( 'getpaid_subscription_notification_email_register_hook', $email_type, $hook );
63
+
64
+        }
65
+
66
+    }
200 67
 
201 68
     /**
202
-	 * Sends a new trial notification.
203
-	 *
204
-	 * @param WPInv_Subscription $subscription
205
-	 */
206
-	public function subscription_trial( $subscription ) {
69
+     * Filters subscription merge tags.
70
+     *
71
+     * @param array $merge_tags
72
+     * @param mixed|WPInv_Invoice|WPInv_Subscription $object
73
+     */
74
+    public function subscription_merge_tags( $merge_tags, $object ) {
207 75
 
208
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
209
-		$this->send_email( $subscription, $email, __FUNCTION__ );
76
+        if ( is_a( $object, 'WPInv_Subscription' ) ) {
77
+            $merge_tags = array_merge(
78
+                $merge_tags,
79
+                $this->get_subscription_merge_tags( $object )
80
+            );
81
+        }
210 82
 
211
-	}
83
+        return $merge_tags;
212 84
 
213
-	/**
214
-	 * Sends a cancelled subscription notification.
215
-	 *
216
-	 * @param WPInv_Subscription $subscription
217
-	 */
218
-	public function subscription_cancelled( $subscription ) {
85
+    }
219 86
 
220
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
221
-		$this->send_email( $subscription, $email, __FUNCTION__ );
87
+    /**
88
+     * Generates subscription merge tags.
89
+     *
90
+     * @param WPInv_Subscription $subscription
91
+     * @return array
92
+     */
93
+    public function get_subscription_merge_tags( $subscription ) {
94
+
95
+        // Abort if it does not exist.
96
+        if ( ! $subscription->get_id() ) {
97
+            return array();
98
+        }
99
+
100
+        $invoice    = $subscription->get_parent_invoice();
101
+        return array(
102
+            '{subscription_renewal_date}'     => getpaid_format_date_value( $subscription->get_next_renewal_date(), __( 'Never', 'invoicing' ) ),
103
+            '{subscription_created}'          => getpaid_format_date_value( $subscription->get_date_created() ),
104
+            '{subscription_status}'           => sanitize_text_field( $subscription->get_status_label() ),
105
+            '{subscription_profile_id}'       => sanitize_text_field( $subscription->get_profile_id() ),
106
+            '{subscription_id}'               => absint( $subscription->get_id() ),
107
+            '{subscription_recurring_amount}' => sanitize_text_field( wpinv_price( $subscription->get_recurring_amount(), $invoice->get_currency() ) ),
108
+            '{subscription_initial_amount}'   => sanitize_text_field( wpinv_price( $subscription->get_initial_amount(), $invoice->get_currency() ) ),
109
+            '{subscription_recurring_period}' => getpaid_get_subscription_period_label( $subscription->get_period(), $subscription->get_frequency(), '' ),
110
+            '{subscription_bill_times}'       => $subscription->get_bill_times(),
111
+            '{subscription_url}'              => esc_url( $subscription->get_view_url() ),
112
+        );
222 113
 
223
-	}
114
+    }
224 115
 
225
-	/**
226
-	 * Sends a subscription expired notification.
227
-	 *
228
-	 * @param WPInv_Subscription $subscription
229
-	 */
230
-	public function subscription_expired( $subscription ) {
116
+    /**
117
+     * Checks if we should send a notification for a subscription.
118
+     *
119
+     * @param WPInv_Invoice $invoice
120
+     * @return bool
121
+     */
122
+    public function should_send_notification( $invoice ) {
123
+        return 0 != $invoice->get_id();
124
+    }
231 125
 
232
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
233
-		$this->send_email( $subscription, $email, __FUNCTION__ );
126
+    /**
127
+     * Returns notification recipients.
128
+     *
129
+     * @param WPInv_Invoice $invoice
130
+     * @return array
131
+     */
132
+    public function get_recipients( $invoice ) {
133
+        $recipients = array( $invoice->get_email() );
234 134
 
235
-	}
135
+        $cc = $invoice->get_email_cc();
236 136
 
237
-	/**
238
-	 * Sends a completed subscription notification.
239
-	 *
240
-	 * @param WPInv_Subscription $subscription
241
-	 */
242
-	public function subscription_complete( $subscription ) {
137
+        if ( ! empty( $cc ) ) {
138
+            $cc = array_map( 'sanitize_email', wpinv_parse_list( $cc ) );
139
+            $recipients = array_filter( array_unique( array_merge( $recipients, $cc ) ) );
140
+        }
243 141
 
244
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
245
-		$this->send_email( $subscription, $email, __FUNCTION__ );
142
+        return $recipients;
143
+    }
246 144
 
247
-	}
145
+    /**
146
+     * Helper function to send an email.
147
+     *
148
+     * @param WPInv_Subscription $subscription
149
+     * @param GetPaid_Notification_Email $email
150
+     * @param string $type
151
+     * @param array $extra_args Extra template args.
152
+     */
153
+    public function send_email( $subscription, $email, $type, $extra_args = array() ) {
154
+
155
+        // Abort in case the parent invoice does not exist.
156
+        $invoice = $subscription->get_parent_invoice();
157
+        if ( ! $this->should_send_notification( $invoice ) ) {
158
+            return;
159
+        }
160
+
161
+        if ( apply_filters( 'getpaid_skip_subscription_email', false, $type, $subscription ) ) {
162
+            return;
163
+        }
164
+
165
+        do_action( 'getpaid_before_send_subscription_notification', $type, $subscription, $email );
166
+
167
+        $recipients  = $this->get_recipients( $invoice );
168
+        $mailer      = new GetPaid_Notification_Email_Sender();
169
+        $merge_tags  = $email->get_merge_tags();
170
+        $content     = $email->get_content( $merge_tags, $extra_args );
171
+        $subject     = $email->add_merge_tags( $email->get_subject(), $merge_tags );
172
+        $attachments = $email->get_attachments();
173
+
174
+        $result = $mailer->send(
175
+            apply_filters( 'getpaid_subscription_email_recipients', wpinv_parse_list( $recipients ), $email ),
176
+            $subject,
177
+            $content,
178
+            $attachments
179
+        );
180
+
181
+        // Maybe send a copy to the admin.
182
+        if ( $email->include_admin_bcc() ) {
183
+            $mailer->send(
184
+                wpinv_get_admin_email(),
185
+                $subject . __( ' - ADMIN BCC COPY', 'invoicing' ),
186
+                $content,
187
+                $attachments
188
+            );
189
+        }
190
+
191
+        if ( $result ) {
192
+            $subscription->get_parent_invoice()->add_note( sprintf( __( 'Successfully sent %s notification email.', 'invoicing' ), sanitize_key( $type ) ), false, false, true );
193
+        } else {
194
+            $subscription->get_parent_invoice()->add_note( sprintf( __( 'Failed sending %s notification email.', 'invoicing' ), sanitize_key( $type ) ), false, false, true );
195
+        }
196
+
197
+        do_action( 'getpaid_after_send_subscription_notification', $type, $subscription, $email );
248 198
 
249
-	/**
250
-	 * Sends a subscription renewal reminder notification.
251
-	 *
252
-	 */
253
-	public function renewal_reminder() {
199
+    }
254 200
 
255
-		$email = new GetPaid_Notification_Email( __FUNCTION__ );
201
+    /**
202
+     * Sends a new trial notification.
203
+     *
204
+     * @param WPInv_Subscription $subscription
205
+     */
206
+    public function subscription_trial( $subscription ) {
256 207
 
257
-		// Fetch reminder days.
258
-		$reminder_days = array_unique( wp_parse_id_list( $email->get_option( 'days' ) ) );
208
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
209
+        $this->send_email( $subscription, $email, __FUNCTION__ );
259 210
 
260
-		// Abort if non is set.
261
-		if ( empty( $reminder_days ) ) {
262
-			return;
263
-		}
211
+    }
264 212
 
265
-		// Fetch matching subscriptions.
213
+    /**
214
+     * Sends a cancelled subscription notification.
215
+     *
216
+     * @param WPInv_Subscription $subscription
217
+     */
218
+    public function subscription_cancelled( $subscription ) {
219
+
220
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
221
+        $this->send_email( $subscription, $email, __FUNCTION__ );
222
+
223
+    }
224
+
225
+    /**
226
+     * Sends a subscription expired notification.
227
+     *
228
+     * @param WPInv_Subscription $subscription
229
+     */
230
+    public function subscription_expired( $subscription ) {
231
+
232
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
233
+        $this->send_email( $subscription, $email, __FUNCTION__ );
234
+
235
+    }
236
+
237
+    /**
238
+     * Sends a completed subscription notification.
239
+     *
240
+     * @param WPInv_Subscription $subscription
241
+     */
242
+    public function subscription_complete( $subscription ) {
243
+
244
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $subscription );
245
+        $this->send_email( $subscription, $email, __FUNCTION__ );
246
+
247
+    }
248
+
249
+    /**
250
+     * Sends a subscription renewal reminder notification.
251
+     *
252
+     */
253
+    public function renewal_reminder() {
254
+
255
+        $email = new GetPaid_Notification_Email( __FUNCTION__ );
256
+
257
+        // Fetch reminder days.
258
+        $reminder_days = array_unique( wp_parse_id_list( $email->get_option( 'days' ) ) );
259
+
260
+        // Abort if non is set.
261
+        if ( empty( $reminder_days ) ) {
262
+            return;
263
+        }
264
+
265
+        // Fetch matching subscriptions.
266 266
         $args  = array(
267 267
             'number'             => -1,
268
-			'count_total'        => false,
269
-			'status'             => 'trialling active',
268
+            'count_total'        => false,
269
+            'status'             => 'trialling active',
270 270
             'date_expires_query' => array(
271
-				'relation'  => 'OR'
271
+                'relation'  => 'OR'
272 272
             ),
273
-		);
273
+        );
274 274
 
275
-		foreach ( $reminder_days as $days ) {
276
-			$date = date_parse( date( 'Y-m-d', strtotime( "+$days days", current_time( 'timestamp' ) ) ) );
275
+        foreach ( $reminder_days as $days ) {
276
+            $date = date_parse( date( 'Y-m-d', strtotime( "+$days days", current_time( 'timestamp' ) ) ) );
277 277
 
278
-			$args['date_expires_query'][] = array(
279
-				'year'  => $date['year'],
280
-				'month' => $date['month'],
281
-				'day'   => $date['day'],
282
-			);
278
+            $args['date_expires_query'][] = array(
279
+                'year'  => $date['year'],
280
+                'month' => $date['month'],
281
+                'day'   => $date['day'],
282
+            );
283 283
 
284
-		}
284
+        }
285 285
 
286
-		$subscriptions = new GetPaid_Subscriptions_Query( $args );
286
+        $subscriptions = new GetPaid_Subscriptions_Query( $args );
287 287
 
288 288
         foreach ( $subscriptions as $subscription ) {
289 289
 
290
-			// Skip packages.
291
-			if ( get_post_meta( $subscription->get_product_id(), '_wpinv_type', true ) != 'package' ) {
292
-				$email->object = $subscription;
293
-            	$this->send_email( $subscription, $email, __FUNCTION__ );
294
-			}
290
+            // Skip packages.
291
+            if ( get_post_meta( $subscription->get_product_id(), '_wpinv_type', true ) != 'package' ) {
292
+                $email->object = $subscription;
293
+                $this->send_email( $subscription, $email, __FUNCTION__ );
294
+            }
295 295
 
296
-		}
296
+        }
297 297
 
298
-	}
298
+    }
299 299
 
300 300
 }
Please login to merge, or discard this patch.
includes/wpinv-item-functions.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -411,9 +411,9 @@
 block discarded – undo
411 411
     $bill_times      = $item->get_recurring_limit();
412 412
 
413 413
     if ( ! empty( $bill_times ) ) {
414
-		$bill_times = $item->get_recurring_interval() * $bill_times;
415
-		$bill_times = getpaid_get_subscription_period_label( $item->get_recurring_period(), $bill_times );
416
-	}
414
+        $bill_times = $item->get_recurring_interval() * $bill_times;
415
+        $bill_times = getpaid_get_subscription_period_label( $item->get_recurring_period(), $bill_times );
416
+    }
417 417
 
418 418
     if ( $item instanceof GetPaid_Form_Item && false === $_initial_price ) {
419 419
         $initial_price   = wpinv_price( $item->get_sub_total(), $currency );
Please login to merge, or discard this patch.
includes/payments/class-getpaid-payment-exception.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -14,51 +14,51 @@
 block discarded – undo
14 14
  */
15 15
 class GetPaid_Payment_Exception extends Exception {
16 16
 
17
-	/**
18
-	 * Sanitized error code.
19
-	 *
20
-	 * @var string
21
-	 */
22
-	protected $error_code;
17
+    /**
18
+     * Sanitized error code.
19
+     *
20
+     * @var string
21
+     */
22
+    protected $error_code;
23 23
 
24
-	/**
25
-	 * Error extra data.
26
-	 *
27
-	 * @var array
28
-	 */
29
-	protected $error_data;
24
+    /**
25
+     * Error extra data.
26
+     *
27
+     * @var array
28
+     */
29
+    protected $error_data;
30 30
 
31
-	/**
32
-	 * Setup exception.
33
-	 *
34
-	 * @param string $code             Machine-readable error code, e.g `getpaid-discount-error`.
35
-	 * @param string $message          User-friendly translated error message, e.g. 'Discount is invalid'.
36
-	 * @param int    $http_status_code Proper HTTP status code to respond with, e.g. 400.
37
-	 * @param array  $data             Extra error data.
38
-	 */
39
-	public function __construct( $code, $message, $http_status_code = 400, $data = array() ) {
40
-		$this->error_code = $code;
41
-		$this->error_data = array_merge( array( 'status' => $http_status_code ), $data );
31
+    /**
32
+     * Setup exception.
33
+     *
34
+     * @param string $code             Machine-readable error code, e.g `getpaid-discount-error`.
35
+     * @param string $message          User-friendly translated error message, e.g. 'Discount is invalid'.
36
+     * @param int    $http_status_code Proper HTTP status code to respond with, e.g. 400.
37
+     * @param array  $data             Extra error data.
38
+     */
39
+    public function __construct( $code, $message, $http_status_code = 400, $data = array() ) {
40
+        $this->error_code = $code;
41
+        $this->error_data = array_merge( array( 'status' => $http_status_code ), $data );
42 42
 
43
-		parent::__construct( $message, $http_status_code );
44
-	}
43
+        parent::__construct( $message, $http_status_code );
44
+    }
45 45
 
46
-	/**
47
-	 * Returns the error code.
48
-	 *
49
-	 * @return string
50
-	 */
51
-	public function getErrorCode() {
52
-		return $this->error_code;
53
-	}
46
+    /**
47
+     * Returns the error code.
48
+     *
49
+     * @return string
50
+     */
51
+    public function getErrorCode() {
52
+        return $this->error_code;
53
+    }
54 54
 
55
-	/**
56
-	 * Returns error data.
57
-	 *
58
-	 * @return array
59
-	 */
60
-	public function getErrorData() {
61
-		return $this->error_data;
62
-	}
55
+    /**
56
+     * Returns error data.
57
+     *
58
+     * @return array
59
+     */
60
+    public function getErrorData() {
61
+        return $this->error_data;
62
+    }
63 63
 
64 64
 }
Please login to merge, or discard this patch.
includes/payments/class-getpaid-payment-form-submission-discount.php 1 patch
Indentation   +154 added lines, -154 removed lines patch added patch discarded remove patch
@@ -12,162 +12,162 @@
 block discarded – undo
12 12
  */
13 13
 class GetPaid_Payment_Form_Submission_Discount {
14 14
 
15
-	/**
16
-	 * Submission discounts.
17
-	 * @var array
18
-	 */
19
-	public $discounts = array();
15
+    /**
16
+     * Submission discounts.
17
+     * @var array
18
+     */
19
+    public $discounts = array();
20
+
21
+    /**
22
+     * Class constructor
23
+     *
24
+     * @param GetPaid_Payment_Form_Submission $submission
25
+     * @param float                           $initial_total
26
+     * @param float                           $recurring_total
27
+     */
28
+    public function __construct( $submission, $initial_total, $recurring_total ) {
29
+
30
+        // Process any existing invoice discounts.
31
+        if ( $submission->has_invoice() ) {
32
+            $this->discounts = $submission->get_invoice()->get_discounts();
33
+        }
34
+
35
+        // Do we have a discount?
36
+        $discount = $submission->get_field( 'discount' );
37
+
38
+        if ( empty( $discount ) ) {
39
+
40
+            if ( isset( $this->discounts['discount_code'] ) ) {
41
+                unset( $this->discounts['discount_code'] );
42
+            }
43
+
44
+            return;
45
+        }
46
+
47
+        // Processes the discount code.
48
+        $amount = max( $initial_total, $recurring_total );
49
+        $this->process_discount( $submission, $discount, $amount );
50
+
51
+    }
20 52
 
21 53
     /**
22
-	 * Class constructor
23
-	 *
24
-	 * @param GetPaid_Payment_Form_Submission $submission
25
-	 * @param float                           $initial_total
26
-	 * @param float                           $recurring_total
27
-	 */
28
-	public function __construct( $submission, $initial_total, $recurring_total ) {
29
-
30
-		// Process any existing invoice discounts.
31
-		if ( $submission->has_invoice() ) {
32
-			$this->discounts = $submission->get_invoice()->get_discounts();
33
-		}
34
-
35
-		// Do we have a discount?
36
-		$discount = $submission->get_field( 'discount' );
37
-
38
-		if ( empty( $discount ) ) {
39
-
40
-			if ( isset( $this->discounts['discount_code'] ) ) {
41
-				unset( $this->discounts['discount_code'] );
42
-			}
43
-
44
-			return;
45
-		}
46
-
47
-		// Processes the discount code.
48
-		$amount = max( $initial_total, $recurring_total );
49
-		$this->process_discount( $submission, $discount, $amount );
50
-
51
-	}
52
-
53
-	/**
54
-	 * Processes a submission discount.
55
-	 *
56
-	 * @param GetPaid_Payment_Form_Submission $submission
57
-	 * @param string                          $discount
58
-	 * @param float                           $amount
59
-	 */
60
-	public function process_discount( $submission, $discount, $amount ) {
61
-
62
-		// Fetch the discount.
63
-		$discount = new WPInv_Discount( $discount );
64
-
65
-		// Ensure it is active.
54
+     * Processes a submission discount.
55
+     *
56
+     * @param GetPaid_Payment_Form_Submission $submission
57
+     * @param string                          $discount
58
+     * @param float                           $amount
59
+     */
60
+    public function process_discount( $submission, $discount, $amount ) {
61
+
62
+        // Fetch the discount.
63
+        $discount = new WPInv_Discount( $discount );
64
+
65
+        // Ensure it is active.
66 66
         if ( ! $this->is_discount_active( $discount ) ) {
67
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'Invalid or expired discount code', 'invoicing' ) );
68
-		}
69
-
70
-		// Exceeded limit.
71
-		if ( $discount->has_exceeded_limit() ) {
72
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'This discount code has been used up', 'invoicing' ) );
73
-		}
74
-
75
-		// Validate usages.
76
-		$this->validate_single_use_discount( $submission, $discount );
77
-
78
-		// Validate amount.
79
-		$this->validate_discount_amount( $submission, $discount, $amount );
80
-
81
-		// Save the discount.
82
-		$this->discounts['discount_code'] = $this->calculate_discount( $submission, $discount );
83
-	}
84
-
85
-	/**
86
-	 * Validates a single use discount.
87
-	 *
88
-	 * @param WPInv_Discount                  $discount
89
-	 * @return bool
90
-	 */
91
-	public function is_discount_active(  $discount ) {
92
-		return $discount->exists() && $discount->is_active() && $discount->has_started() && ! $discount->is_expired();
93
-	}
94
-
95
-	/**
96
-	 * Returns a user's id or email.
97
-	 *
98
-	 * @param string $email
99
-	 * @return int|string|false
100
-	 */
101
-	public function get_user_id_or_email( $email ) {
102
-
103
-		if ( is_user_logged_in() ) {
104
-			return get_current_user_id();
105
-		}
106
-
107
-		return empty( $email ) ? false : sanitize_email( $email );
108
-	}
109
-
110
-	/**
111
-	 * Validates a single use discount.
112
-	 *
113
-	 * @param GetPaid_Payment_Form_Submission $submission
114
-	 * @param WPInv_Discount                  $discount
115
-	 */
116
-	public function validate_single_use_discount( $submission, $discount ) {
117
-
118
-		// Abort if it is not a single use discount.
119
-		if ( ! $discount->is_single_use() ) {
120
-			return;
121
-		}
122
-
123
-		// Ensure there is a valid billing email.
124
-		$user = $this->get_user_id_or_email( $submission->get_billing_email() );
125
-
126
-		if ( empty( $user ) ) {
127
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You need to either log in or enter your billing email before applying this discount', 'invoicing' ) );
128
-		}
129
-
130
-		// Has the user used this discount code before?
131
-		if ( ! $discount->is_valid_for_user( $user ) ) {
132
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You have already used this discount', 'invoicing' ) );
133
-		}
134
-
135
-	}
136
-
137
-	/**
138
-	 * Validates the discount's amount.
139
-	 *
140
-	 * @param GetPaid_Payment_Form_Submission $submission
141
-	 * @param WPInv_Discount         $discount
142
-	 * @param float                  $amount
143
-	 */
144
-	public function validate_discount_amount( $submission, $discount, $amount ) {
145
-
146
-		// Validate minimum amount.
147
-		if ( ! $discount->is_minimum_amount_met( $amount ) ) {
148
-			$min = wpinv_price( $discount->get_minimum_total(), $submission->get_currency() );
149
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The minimum total for using this discount is %s', 'invoicing' ), $min ) );
150
-		}
151
-
152
-		// Validate the maximum amount.
153
-		if ( ! $discount->is_maximum_amount_met( $amount ) ) {
154
-			$max = wpinv_price( $discount->get_maximum_total(), $submission->get_currency() );
155
-			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The maximum total for using this discount is %s', 'invoicing' ), $max ) );
156
-		}
157
-
158
-	}
159
-
160
-	/**
161
-	 * Calculates the discount code's amount.
162
-	 *
163
-	 * Ensure that the discount exists and has been validated before calling this method.
164
-	 *
165
-	 * @param GetPaid_Payment_Form_Submission $submission
166
-	 * @param WPInv_Discount                  $discount
167
-	 * @return array
168
-	 */
169
-	public function calculate_discount( $submission, $discount ) {
170
-		return getpaid_calculate_invoice_discount( $submission, $discount );
171
-	}
67
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'Invalid or expired discount code', 'invoicing' ) );
68
+        }
69
+
70
+        // Exceeded limit.
71
+        if ( $discount->has_exceeded_limit() ) {
72
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'This discount code has been used up', 'invoicing' ) );
73
+        }
74
+
75
+        // Validate usages.
76
+        $this->validate_single_use_discount( $submission, $discount );
77
+
78
+        // Validate amount.
79
+        $this->validate_discount_amount( $submission, $discount, $amount );
80
+
81
+        // Save the discount.
82
+        $this->discounts['discount_code'] = $this->calculate_discount( $submission, $discount );
83
+    }
84
+
85
+    /**
86
+     * Validates a single use discount.
87
+     *
88
+     * @param WPInv_Discount                  $discount
89
+     * @return bool
90
+     */
91
+    public function is_discount_active(  $discount ) {
92
+        return $discount->exists() && $discount->is_active() && $discount->has_started() && ! $discount->is_expired();
93
+    }
94
+
95
+    /**
96
+     * Returns a user's id or email.
97
+     *
98
+     * @param string $email
99
+     * @return int|string|false
100
+     */
101
+    public function get_user_id_or_email( $email ) {
102
+
103
+        if ( is_user_logged_in() ) {
104
+            return get_current_user_id();
105
+        }
106
+
107
+        return empty( $email ) ? false : sanitize_email( $email );
108
+    }
109
+
110
+    /**
111
+     * Validates a single use discount.
112
+     *
113
+     * @param GetPaid_Payment_Form_Submission $submission
114
+     * @param WPInv_Discount                  $discount
115
+     */
116
+    public function validate_single_use_discount( $submission, $discount ) {
117
+
118
+        // Abort if it is not a single use discount.
119
+        if ( ! $discount->is_single_use() ) {
120
+            return;
121
+        }
122
+
123
+        // Ensure there is a valid billing email.
124
+        $user = $this->get_user_id_or_email( $submission->get_billing_email() );
125
+
126
+        if ( empty( $user ) ) {
127
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You need to either log in or enter your billing email before applying this discount', 'invoicing' ) );
128
+        }
129
+
130
+        // Has the user used this discount code before?
131
+        if ( ! $discount->is_valid_for_user( $user ) ) {
132
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You have already used this discount', 'invoicing' ) );
133
+        }
134
+
135
+    }
136
+
137
+    /**
138
+     * Validates the discount's amount.
139
+     *
140
+     * @param GetPaid_Payment_Form_Submission $submission
141
+     * @param WPInv_Discount         $discount
142
+     * @param float                  $amount
143
+     */
144
+    public function validate_discount_amount( $submission, $discount, $amount ) {
145
+
146
+        // Validate minimum amount.
147
+        if ( ! $discount->is_minimum_amount_met( $amount ) ) {
148
+            $min = wpinv_price( $discount->get_minimum_total(), $submission->get_currency() );
149
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The minimum total for using this discount is %s', 'invoicing' ), $min ) );
150
+        }
151
+
152
+        // Validate the maximum amount.
153
+        if ( ! $discount->is_maximum_amount_met( $amount ) ) {
154
+            $max = wpinv_price( $discount->get_maximum_total(), $submission->get_currency() );
155
+            throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The maximum total for using this discount is %s', 'invoicing' ), $max ) );
156
+        }
157
+
158
+    }
159
+
160
+    /**
161
+     * Calculates the discount code's amount.
162
+     *
163
+     * Ensure that the discount exists and has been validated before calling this method.
164
+     *
165
+     * @param GetPaid_Payment_Form_Submission $submission
166
+     * @param WPInv_Discount                  $discount
167
+     * @return array
168
+     */
169
+    public function calculate_discount( $submission, $discount ) {
170
+        return getpaid_calculate_invoice_discount( $submission, $discount );
171
+    }
172 172
 
173 173
 }
Please login to merge, or discard this patch.
includes/reports/class-getpaid-reports-helper.php 1 patch
Indentation   +276 added lines, -276 removed lines patch added patch discarded remove patch
@@ -12,294 +12,294 @@
 block discarded – undo
12 12
  */
13 13
 class GetPaid_Reports_Helper {
14 14
 
15
-	/**
16
-	 * Get report totals such as invoice totals and discount amounts.
17
-	 *
18
-	 * Data example:
19
-	 *
20
-	 * 'subtotal' => array(
21
-	 *     'type'     => 'invoice_data',
22
-	 *     'function' => 'SUM',
23
-	 *     'name'     => 'subtotal'
24
-	 * )
25
-	 *
26
-	 * @param  array $args
27
-	 * @return mixed depending on query_type
28
-	 */
29
-	public static function get_invoice_report_data( $args = array() ) {
30
-		global $wpdb;
31
-
32
-		$default_args = array(
33
-			'data'                  => array(), // The data to retrieve.
34
-			'where'                 => array(), // An array of where queries.
35
-			'query_type'            => 'get_row', // wpdb query to run.
36
-			'group_by'              => '', // What to group results by.
37
-			'order_by'              => '', // What to order by.
38
-			'limit'                 => '', // Results limit.
39
-			'filter_range'          => array(), // An array of before and after dates to limit results by.
40
-			'invoice_types'         => array( 'wpi_invoice' ), // An array of post types to retrieve.
41
-			'invoice_status'        => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
42
-			'parent_invoice_status' => false, // Optionally filter by parent invoice status.
43
-		);
44
-
45
-		$args         = apply_filters( 'getpaid_reports_get_invoice_report_data_args', $args );
46
-		$args         = wp_parse_args( $args, $default_args );
47
-
48
-		extract( $args );
49
-
50
-		if ( empty( $data ) ) {
51
-			return '';
52
-		}
53
-
54
-		$query           = array();
55
-		$query['select'] = 'SELECT ' . implode( ',', self::prepare_invoice_data( $data ) );
56
-		$query['from']   = "FROM {$wpdb->posts} AS posts";
57
-		$query['join']   = implode( ' ', self::prepare_invoice_joins( $data + $where, ! empty( $parent_invoice_status ) ) );
58
-
59
-		$query['where']  = "
15
+    /**
16
+     * Get report totals such as invoice totals and discount amounts.
17
+     *
18
+     * Data example:
19
+     *
20
+     * 'subtotal' => array(
21
+     *     'type'     => 'invoice_data',
22
+     *     'function' => 'SUM',
23
+     *     'name'     => 'subtotal'
24
+     * )
25
+     *
26
+     * @param  array $args
27
+     * @return mixed depending on query_type
28
+     */
29
+    public static function get_invoice_report_data( $args = array() ) {
30
+        global $wpdb;
31
+
32
+        $default_args = array(
33
+            'data'                  => array(), // The data to retrieve.
34
+            'where'                 => array(), // An array of where queries.
35
+            'query_type'            => 'get_row', // wpdb query to run.
36
+            'group_by'              => '', // What to group results by.
37
+            'order_by'              => '', // What to order by.
38
+            'limit'                 => '', // Results limit.
39
+            'filter_range'          => array(), // An array of before and after dates to limit results by.
40
+            'invoice_types'         => array( 'wpi_invoice' ), // An array of post types to retrieve.
41
+            'invoice_status'        => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
42
+            'parent_invoice_status' => false, // Optionally filter by parent invoice status.
43
+        );
44
+
45
+        $args         = apply_filters( 'getpaid_reports_get_invoice_report_data_args', $args );
46
+        $args         = wp_parse_args( $args, $default_args );
47
+
48
+        extract( $args );
49
+
50
+        if ( empty( $data ) ) {
51
+            return '';
52
+        }
53
+
54
+        $query           = array();
55
+        $query['select'] = 'SELECT ' . implode( ',', self::prepare_invoice_data( $data ) );
56
+        $query['from']   = "FROM {$wpdb->posts} AS posts";
57
+        $query['join']   = implode( ' ', self::prepare_invoice_joins( $data + $where, ! empty( $parent_invoice_status ) ) );
58
+
59
+        $query['where']  = "
60 60
 			WHERE 	posts.post_type 	IN ( '" . implode( "','", $invoice_types ) . "' )
61 61
 			";
62 62
 
63
-		if ( ! empty( $invoice_status ) ) {
64
-			$query['where'] .= "
63
+        if ( ! empty( $invoice_status ) ) {
64
+            $query['where'] .= "
65 65
 				AND 	posts.post_status 	IN ( '" . implode( "','", $invoice_status ) . "' )
66 66
 			";
67
-		}
68
-
69
-		if ( ! empty( $parent_invoice_status ) ) {
70
-			if ( ! empty( $invoice_status ) ) {
71
-				$query['where'] .= " AND ( parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) OR parent.ID IS NULL ) ";
72
-			} else {
73
-				$query['where'] .= " AND parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) ";
74
-			}
75
-		}
76
-
77
-		if ( ! empty( $filter_range['before'] ) ) {
78
-			$query['where'] .= "
67
+        }
68
+
69
+        if ( ! empty( $parent_invoice_status ) ) {
70
+            if ( ! empty( $invoice_status ) ) {
71
+                $query['where'] .= " AND ( parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) OR parent.ID IS NULL ) ";
72
+            } else {
73
+                $query['where'] .= " AND parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) ";
74
+            }
75
+        }
76
+
77
+        if ( ! empty( $filter_range['before'] ) ) {
78
+            $query['where'] .= "
79 79
 				AND 	posts.post_date < '" . date( 'Y-m-d H:i:s', strtotime( $filter_range['before'] ) ) . "'
80 80
 			";
81
-		}
81
+        }
82 82
 
83
-		if ( ! empty( $filter_range['after'] ) ) {
84
-			$query['where'] .= "
83
+        if ( ! empty( $filter_range['after'] ) ) {
84
+            $query['where'] .= "
85 85
 				AND 	posts.post_date > '" . date( 'Y-m-d H:i:s', strtotime( $filter_range['after'] ) ) . "'
86 86
 			";
87
-		}
87
+        }
88 88
 
89
-		if ( ! empty( $where ) ) {
89
+        if ( ! empty( $where ) ) {
90 90
 
91
-			foreach ( $where as $value ) {
91
+            foreach ( $where as $value ) {
92 92
 
93
-				if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
94
-
95
-					if ( is_array( $value['value'] ) ) {
96
-						$value['value'] = implode( "','", $value['value'] );
97
-					}
98
-
99
-					if ( ! empty( $value['value'] ) ) {
100
-						$where_value = "{$value['operator']} ('{$value['value']}')";
101
-					}
102
-				} else {
103
-					$where_value = "{$value['operator']} '{$value['value']}'";
104
-				}
105
-
106
-				if ( ! empty( $where_value ) ) {
107
-					$query['where'] .= " AND {$value['key']} {$where_value}";
108
-				}
109
-			}
110
-		}
111
-
112
-		if ( $group_by ) {
113
-			$query['group_by'] = "GROUP BY {$group_by}";
114
-		}
115
-
116
-		if ( $order_by ) {
117
-			$query['order_by'] = "ORDER BY {$order_by}";
118
-		}
119
-
120
-		if ( $limit ) {
121
-			$query['limit'] = "LIMIT {$limit}";
122
-		}
123
-
124
-		$query = apply_filters( 'getpaid_reports_get_invoice_report_query', $query, $data );
125
-		$query = implode( ' ', $query );
126
-
127
-		return self::execute( $query_type, $query );
128
-
129
-	}
130
-
131
-	/**
132
-	 * Prepares the data to select.
133
-	 *
134
-	 *
135
-	 * @param  array $data
136
-	 * @return array
137
-	 */
138
-	public static function prepare_invoice_data( $data ) {
139
-
140
-		$prepared = array();
141
-
142
-		foreach ( $data as $raw_key => $value ) {
143
-			$key      = sanitize_key( $raw_key );
144
-			$distinct = '';
145
-
146
-			if ( isset( $value['distinct'] ) ) {
147
-				$distinct = 'DISTINCT';
148
-			}
149
-
150
-			$get_key = self::get_invoice_table_key( $key, $value['type'] );
151
-
152
-			if ( false === $get_key ) {
153
-				// Skip to the next foreach iteration else the query will be invalid.
154
-				continue;
155
-			}
156
-
157
-			if ( ! empty( $value['function'] ) ) {
158
-				$get = "{$value['function']}({$distinct} {$get_key})";
159
-			} else {
160
-				$get = "{$distinct} {$get_key}";
161
-			}
162
-
163
-			$prepared[] = "{$get} as {$value['name']}";
164
-		}
165
-
166
-		return $prepared;
167
-
168
-	}
169
-
170
-	/**
171
-	 * Prepares the joins to use.
172
-	 *
173
-	 *
174
-	 * @param  array $data
175
-	 * @param  bool $with_parent
176
-	 * @return array
177
-	 */
178
-	public static function prepare_invoice_joins( $data, $with_parent ) {
179
-		global $wpdb;
180
-
181
-		$prepared = array();
182
-
183
-		foreach ( $data as $raw_key => $value ) {
184
-			$join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
185
-			$type      = isset( $value['type'] ) ? $value['type'] : false;
186
-			$key       = sanitize_key( $raw_key );
187
-
188
-			switch ( $type ) {
189
-				case 'meta':
190
-					$prepared[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
191
-					break;
192
-				case 'parent_meta':
193
-					$prepared[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$raw_key}')";
194
-					break;
195
-				case 'invoice_data':
196
-					$prepared['invoices'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoices AS invoices ON posts.ID = invoices.post_id";
197
-					break;
198
-				case 'invoice_item':
199
-					$prepared['invoice_items'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoice_items AS invoice_items ON posts.ID = invoice_items.post_id";
200
-					break;
201
-			}
202
-		}
203
-
204
-		if ( $with_parent ) {
205
-			$prepared['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
206
-		}
207
-
208
-		return $prepared;
209
-
210
-	}
211
-
212
-	/**
213
-	 * Retrieves the appropriate table key to use.
214
-	 *
215
-	 *
216
-	 * @param  string $key
217
-	 * @param  string $table
218
-	 * @return string|false
219
-	 */
220
-	public static function get_invoice_table_key( $key, $table ) {
221
-
222
-		$keys = array(
223
-			'meta'         => "meta_{$key}.meta_value",
224
-			'parent_meta'  => "parent_meta_{$key}.meta_value",
225
-			'post_data'    => "posts.{$key}",
226
-			'invoice_data' => "invoices.{$key}",
227
-			'invoice_item' => "invoice_items.{$key}",
228
-		);
229
-
230
-		return isset( $keys[ $table ] ) ? $keys[ $table ] : false;
231
-
232
-	}
233
-
234
-	/**
235
-	 * Executes a query and caches the result for a minute.
236
-	 *
237
-	 *
238
-	 * @param  string $query_type
239
-	 * @param  string $query
240
-	 * @return mixed depending on query_type
241
-	 */
242
-	public static function execute( $query_type, $query ) {
243
-		global $wpdb;
244
-
245
-		$query_hash = md5( $query_type . $query );
246
-		$result     = self::get_cached_query( $query_hash );
247
-		if ( $result === false ) {
248
-			self::enable_big_selects();
249
-
250
-			$result = $wpdb->$query_type( $query );
251
-			self::set_cached_query( $query_hash, $result );
252
-		}
253
-
254
-		return $result;
255
-
256
-	}
257
-
258
-	/**
259
-	 * Enables big mysql selects for reports, just once for this session.
260
-	 */
261
-	protected static function enable_big_selects() {
262
-		static $big_selects = false;
263
-
264
-		global $wpdb;
265
-
266
-		if ( ! $big_selects ) {
267
-			$wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
268
-			$big_selects = true;
269
-		}
270
-	}
271
-
272
-	/**
273
-	 * Get the cached query result or null if it's not in the cache.
274
-	 *
275
-	 * @param string $query_hash The query hash.
276
-	 *
277
-	 * @return mixed|false The cache contents on success, false on failure to retrieve contents.
278
-	 */
279
-	protected static function get_cached_query( $query_hash ) {
280
-
281
-		return wp_cache_get(
282
-			$query_hash,
283
-			strtolower( __CLASS__ )
284
-		);
285
-
286
-	}
287
-
288
-	/**
289
-	 * Set the cached query result.
290
-	 *
291
-	 * @param string $query_hash The query hash.
292
-	 * @param mixed  $data The data to cache.
293
-	 */
294
-	protected static function set_cached_query( $query_hash, $data ) {
295
-
296
-		wp_cache_set(
297
-			$query_hash,
298
-			$data,
299
-			strtolower( __CLASS__ ),
300
-			MINUTE_IN_SECONDS
301
-		);
302
-
303
-	}
93
+                if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
94
+
95
+                    if ( is_array( $value['value'] ) ) {
96
+                        $value['value'] = implode( "','", $value['value'] );
97
+                    }
98
+
99
+                    if ( ! empty( $value['value'] ) ) {
100
+                        $where_value = "{$value['operator']} ('{$value['value']}')";
101
+                    }
102
+                } else {
103
+                    $where_value = "{$value['operator']} '{$value['value']}'";
104
+                }
105
+
106
+                if ( ! empty( $where_value ) ) {
107
+                    $query['where'] .= " AND {$value['key']} {$where_value}";
108
+                }
109
+            }
110
+        }
111
+
112
+        if ( $group_by ) {
113
+            $query['group_by'] = "GROUP BY {$group_by}";
114
+        }
115
+
116
+        if ( $order_by ) {
117
+            $query['order_by'] = "ORDER BY {$order_by}";
118
+        }
119
+
120
+        if ( $limit ) {
121
+            $query['limit'] = "LIMIT {$limit}";
122
+        }
123
+
124
+        $query = apply_filters( 'getpaid_reports_get_invoice_report_query', $query, $data );
125
+        $query = implode( ' ', $query );
126
+
127
+        return self::execute( $query_type, $query );
128
+
129
+    }
130
+
131
+    /**
132
+     * Prepares the data to select.
133
+     *
134
+     *
135
+     * @param  array $data
136
+     * @return array
137
+     */
138
+    public static function prepare_invoice_data( $data ) {
139
+
140
+        $prepared = array();
141
+
142
+        foreach ( $data as $raw_key => $value ) {
143
+            $key      = sanitize_key( $raw_key );
144
+            $distinct = '';
145
+
146
+            if ( isset( $value['distinct'] ) ) {
147
+                $distinct = 'DISTINCT';
148
+            }
149
+
150
+            $get_key = self::get_invoice_table_key( $key, $value['type'] );
151
+
152
+            if ( false === $get_key ) {
153
+                // Skip to the next foreach iteration else the query will be invalid.
154
+                continue;
155
+            }
156
+
157
+            if ( ! empty( $value['function'] ) ) {
158
+                $get = "{$value['function']}({$distinct} {$get_key})";
159
+            } else {
160
+                $get = "{$distinct} {$get_key}";
161
+            }
162
+
163
+            $prepared[] = "{$get} as {$value['name']}";
164
+        }
165
+
166
+        return $prepared;
167
+
168
+    }
169
+
170
+    /**
171
+     * Prepares the joins to use.
172
+     *
173
+     *
174
+     * @param  array $data
175
+     * @param  bool $with_parent
176
+     * @return array
177
+     */
178
+    public static function prepare_invoice_joins( $data, $with_parent ) {
179
+        global $wpdb;
180
+
181
+        $prepared = array();
182
+
183
+        foreach ( $data as $raw_key => $value ) {
184
+            $join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
185
+            $type      = isset( $value['type'] ) ? $value['type'] : false;
186
+            $key       = sanitize_key( $raw_key );
187
+
188
+            switch ( $type ) {
189
+                case 'meta':
190
+                    $prepared[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
191
+                    break;
192
+                case 'parent_meta':
193
+                    $prepared[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$raw_key}')";
194
+                    break;
195
+                case 'invoice_data':
196
+                    $prepared['invoices'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoices AS invoices ON posts.ID = invoices.post_id";
197
+                    break;
198
+                case 'invoice_item':
199
+                    $prepared['invoice_items'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoice_items AS invoice_items ON posts.ID = invoice_items.post_id";
200
+                    break;
201
+            }
202
+        }
203
+
204
+        if ( $with_parent ) {
205
+            $prepared['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
206
+        }
207
+
208
+        return $prepared;
209
+
210
+    }
211
+
212
+    /**
213
+     * Retrieves the appropriate table key to use.
214
+     *
215
+     *
216
+     * @param  string $key
217
+     * @param  string $table
218
+     * @return string|false
219
+     */
220
+    public static function get_invoice_table_key( $key, $table ) {
221
+
222
+        $keys = array(
223
+            'meta'         => "meta_{$key}.meta_value",
224
+            'parent_meta'  => "parent_meta_{$key}.meta_value",
225
+            'post_data'    => "posts.{$key}",
226
+            'invoice_data' => "invoices.{$key}",
227
+            'invoice_item' => "invoice_items.{$key}",
228
+        );
229
+
230
+        return isset( $keys[ $table ] ) ? $keys[ $table ] : false;
231
+
232
+    }
233
+
234
+    /**
235
+     * Executes a query and caches the result for a minute.
236
+     *
237
+     *
238
+     * @param  string $query_type
239
+     * @param  string $query
240
+     * @return mixed depending on query_type
241
+     */
242
+    public static function execute( $query_type, $query ) {
243
+        global $wpdb;
244
+
245
+        $query_hash = md5( $query_type . $query );
246
+        $result     = self::get_cached_query( $query_hash );
247
+        if ( $result === false ) {
248
+            self::enable_big_selects();
249
+
250
+            $result = $wpdb->$query_type( $query );
251
+            self::set_cached_query( $query_hash, $result );
252
+        }
253
+
254
+        return $result;
255
+
256
+    }
257
+
258
+    /**
259
+     * Enables big mysql selects for reports, just once for this session.
260
+     */
261
+    protected static function enable_big_selects() {
262
+        static $big_selects = false;
263
+
264
+        global $wpdb;
265
+
266
+        if ( ! $big_selects ) {
267
+            $wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
268
+            $big_selects = true;
269
+        }
270
+    }
271
+
272
+    /**
273
+     * Get the cached query result or null if it's not in the cache.
274
+     *
275
+     * @param string $query_hash The query hash.
276
+     *
277
+     * @return mixed|false The cache contents on success, false on failure to retrieve contents.
278
+     */
279
+    protected static function get_cached_query( $query_hash ) {
280
+
281
+        return wp_cache_get(
282
+            $query_hash,
283
+            strtolower( __CLASS__ )
284
+        );
285
+
286
+    }
287
+
288
+    /**
289
+     * Set the cached query result.
290
+     *
291
+     * @param string $query_hash The query hash.
292
+     * @param mixed  $data The data to cache.
293
+     */
294
+    protected static function set_cached_query( $query_hash, $data ) {
295
+
296
+        wp_cache_set(
297
+            $query_hash,
298
+            $data,
299
+            strtolower( __CLASS__ ),
300
+            MINUTE_IN_SECONDS
301
+        );
302
+
303
+    }
304 304
 
305 305
 }
Please login to merge, or discard this patch.
includes/class-wpinv-notes.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -12,202 +12,202 @@
 block discarded – undo
12 12
  */
13 13
 class WPInv_Notes {
14 14
 
15
-	/**
16
-	 * Class constructor.
17
-	 */
18
-	public function __construct() {
19
-
20
-		// Filter inovice notes.
21
-		add_action( 'pre_get_comments', array( $this, 'set_invoice_note_type' ), 11, 1 );
22
-		add_action( 'comment_feed_where', array( $this, 'wpinv_comment_feed_where' ), 10, 1 );
23
-
24
-		// Delete comments count cache whenever there is a new comment or a comment status changes.
25
-		add_action( 'wp_insert_comment', array( $this, 'delete_comments_count_cache' ) );
26
-		add_action( 'wp_set_comment_status', array( $this, 'delete_comments_count_cache' ) );
27
-
28
-		// Count comments.
29
-		add_filter( 'wp_count_comments', array( $this, 'wp_count_comments' ), 100, 2 );
30
-
31
-		// Fires after notes are loaded.
32
-		do_action( 'wpinv_notes_init', $this );
33
-	}
34
-
35
-	/**
36
-	 * Filters invoice notes query to only include our notes.
37
-	 *
38
-	 * @param WP_Comment_Query $query
39
-	 */
40
-	public function set_invoice_note_type( $query ) {
41
-		$post_id = ! empty( $query->query_vars['post_ID'] ) ? $query->query_vars['post_ID'] : $query->query_vars['post_id'];
42
-
43
-		if ( $post_id && getpaid_is_invoice_post_type( get_post_type( $post_id ) ) ) {
44
-			$query->query_vars['type'] = 'wpinv_note';
45
-		} else {
46
-
47
-			if ( empty( $query->query_vars['type__not_in'] ) ) {
48
-				$query->query_vars['type__not_in'] = array();
49
-			}
50
-
51
-			$query->query_vars['type__not_in'] = wpinv_parse_list( $query->query_vars['type__not_in'] );
52
-			$query->query_vars['type__not_in'] = array_merge( array( 'wpinv_note' ), $query->query_vars['type__not_in'] );
53
-		}
54
-
55
-		return $query;
56
-	}
57
-
58
-	/**
59
-	 * Exclude notes from the comments feed.
60
-	 */
61
-	function wpinv_comment_feed_where( $where ){
62
-		return $where . ( $where ? ' AND ' : '' ) . " comment_type != 'wpinv_note' ";
63
-	}
64
-
65
-	/**
66
-	 * Delete comments count cache whenever there is
67
-	 * new comment or the status of a comment changes. Cache
68
-	 * will be regenerated next time WPInv_Notes::wp_count_comments()
69
-	 * is called.
70
-	 */
71
-	public function delete_comments_count_cache() {
72
-		delete_transient( 'getpaid_count_comments' );
73
-	}
74
-
75
-	/**
76
-	 * Remove invoice notes from wp_count_comments().
77
-	 *
78
-	 * @since  2.2
79
-	 * @param  object $stats   Comment stats.
80
-	 * @param  int    $post_id Post ID.
81
-	 * @return object
82
-	 */
83
-	public function wp_count_comments( $stats, $post_id ) {
84
-		global $wpdb;
85
-
86
-		if ( empty( $post_id ) ) {
87
-			$stats = get_transient( 'getpaid_count_comments' );
88
-
89
-			if ( ! $stats ) {
90
-				$stats = array(
91
-					'total_comments' => 0,
92
-					'all'            => 0,
93
-				);
94
-
95
-				$count = $wpdb->get_results(
96
-					"
15
+    /**
16
+     * Class constructor.
17
+     */
18
+    public function __construct() {
19
+
20
+        // Filter inovice notes.
21
+        add_action( 'pre_get_comments', array( $this, 'set_invoice_note_type' ), 11, 1 );
22
+        add_action( 'comment_feed_where', array( $this, 'wpinv_comment_feed_where' ), 10, 1 );
23
+
24
+        // Delete comments count cache whenever there is a new comment or a comment status changes.
25
+        add_action( 'wp_insert_comment', array( $this, 'delete_comments_count_cache' ) );
26
+        add_action( 'wp_set_comment_status', array( $this, 'delete_comments_count_cache' ) );
27
+
28
+        // Count comments.
29
+        add_filter( 'wp_count_comments', array( $this, 'wp_count_comments' ), 100, 2 );
30
+
31
+        // Fires after notes are loaded.
32
+        do_action( 'wpinv_notes_init', $this );
33
+    }
34
+
35
+    /**
36
+     * Filters invoice notes query to only include our notes.
37
+     *
38
+     * @param WP_Comment_Query $query
39
+     */
40
+    public function set_invoice_note_type( $query ) {
41
+        $post_id = ! empty( $query->query_vars['post_ID'] ) ? $query->query_vars['post_ID'] : $query->query_vars['post_id'];
42
+
43
+        if ( $post_id && getpaid_is_invoice_post_type( get_post_type( $post_id ) ) ) {
44
+            $query->query_vars['type'] = 'wpinv_note';
45
+        } else {
46
+
47
+            if ( empty( $query->query_vars['type__not_in'] ) ) {
48
+                $query->query_vars['type__not_in'] = array();
49
+            }
50
+
51
+            $query->query_vars['type__not_in'] = wpinv_parse_list( $query->query_vars['type__not_in'] );
52
+            $query->query_vars['type__not_in'] = array_merge( array( 'wpinv_note' ), $query->query_vars['type__not_in'] );
53
+        }
54
+
55
+        return $query;
56
+    }
57
+
58
+    /**
59
+     * Exclude notes from the comments feed.
60
+     */
61
+    function wpinv_comment_feed_where( $where ){
62
+        return $where . ( $where ? ' AND ' : '' ) . " comment_type != 'wpinv_note' ";
63
+    }
64
+
65
+    /**
66
+     * Delete comments count cache whenever there is
67
+     * new comment or the status of a comment changes. Cache
68
+     * will be regenerated next time WPInv_Notes::wp_count_comments()
69
+     * is called.
70
+     */
71
+    public function delete_comments_count_cache() {
72
+        delete_transient( 'getpaid_count_comments' );
73
+    }
74
+
75
+    /**
76
+     * Remove invoice notes from wp_count_comments().
77
+     *
78
+     * @since  2.2
79
+     * @param  object $stats   Comment stats.
80
+     * @param  int    $post_id Post ID.
81
+     * @return object
82
+     */
83
+    public function wp_count_comments( $stats, $post_id ) {
84
+        global $wpdb;
85
+
86
+        if ( empty( $post_id ) ) {
87
+            $stats = get_transient( 'getpaid_count_comments' );
88
+
89
+            if ( ! $stats ) {
90
+                $stats = array(
91
+                    'total_comments' => 0,
92
+                    'all'            => 0,
93
+                );
94
+
95
+                $count = $wpdb->get_results(
96
+                    "
97 97
 					SELECT comment_approved, COUNT(*) AS num_comments
98 98
 					FROM {$wpdb->comments}
99 99
 					WHERE comment_type NOT IN ('action_log', 'order_note', 'webhook_delivery', 'wpinv_note')
100 100
 					GROUP BY comment_approved
101 101
 					",
102
-					ARRAY_A
103
-				);
104
-
105
-				$approved = array(
106
-					'0'            => 'moderated',
107
-					'1'            => 'approved',
108
-					'spam'         => 'spam',
109
-					'trash'        => 'trash',
110
-					'post-trashed' => 'post-trashed',
111
-				);
112
-
113
-				foreach ( (array) $count as $row ) {
114
-					// Don't count post-trashed toward totals.
115
-					if ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash', 'spam' ), true ) ) {
116
-						$stats['all']            += $row['num_comments'];
117
-						$stats['total_comments'] += $row['num_comments'];
118
-					} elseif ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash' ), true ) ) {
119
-						$stats['total_comments'] += $row['num_comments'];
120
-					}
121
-					if ( isset( $approved[ $row['comment_approved'] ] ) ) {
122
-						$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
123
-					}
124
-				}
125
-
126
-				foreach ( $approved as $key ) {
127
-					if ( empty( $stats[ $key ] ) ) {
128
-						$stats[ $key ] = 0;
129
-					}
130
-				}
131
-
132
-				$stats = (object) $stats;
133
-				set_transient( 'getpaid_count_comments', $stats );
134
-			}
135
-
136
-		}
137
-
138
-		return $stats;
139
-	}
140
-
141
-	/**
142
-	 * Returns an array of invoice notes.
143
-	 *
144
-	 * @param int $invoice_id The invoice ID whose notes to retrieve.
145
-	 * @param string $type Optional. Pass in customer to only return customer notes.
146
-	 * @return WP_Comment[]
147
-	 */
148
-	public function get_invoice_notes( $invoice_id = 0, $type = 'all' ) {
149
-
150
-		// Default comment args.
151
-		$args = array(
152
-			'post_id'   => $invoice_id,
153
-			'orderby'   => 'comment_ID',
154
-			'order'     => 'ASC',
155
-		);
156
-
157
-		// Maybe only show customer comments.
158
-		if ( $type == 'customer' ) {
159
-			$args['meta_key']   = '_wpi_customer_note';
160
-			$args['meta_value'] = 1;
161
-		}
162
-
163
-		$args = apply_filters( 'wpinv_invoice_notes_args', $args, $this, $invoice_id, $type );
164
-
165
-		return get_comments( $args );
166
-	}
167
-
168
-	/**
169
-	 * Saves an invoice comment.
170
-	 * 
171
-	 * @param WPInv_Invoice $invoice The invoice to add the comment to.
172
-	 * @param string $note The note content.
173
-	 * @param string $note_author The name of the author of the note.
174
-	 * @param bool $for_customer Whether or not this comment is meant to be sent to the customer.
175
-	 * @return int|false The new note's ID on success, false on failure.
176
-	 */
177
-	function add_invoice_note( $invoice, $note, $note_author, $author_email, $for_customer = false ){
178
-
179
-		do_action( 'wpinv_pre_insert_invoice_note', $invoice->get_id(), $note, $for_customer );
180
-
181
-		/**
182
-		 * Insert the comment.
183
-		 */
184
-		$note_id = wp_insert_comment(
185
-			wp_filter_comment(
186
-				array(
187
-					'comment_post_ID'      => $invoice->get_id(),
188
-					'comment_content'      => $note,
189
-					'comment_agent'        => 'Invoicing',
190
-					'user_id'              => get_current_user_id(),
191
-					'comment_author'       => $note_author,
192
-					'comment_author_IP'    => wpinv_get_ip(),
193
-					'comment_author_email' => $author_email,
194
-					'comment_author_url'   => $invoice->get_view_url(),
195
-					'comment_type'         => 'wpinv_note',
196
-				)
197
-			)
198
-		);
199
-
200
-		do_action( 'wpinv_insert_payment_note', $note_id, $invoice->get_id(), $note, $for_customer );
201
-
202
-		// Are we notifying the customer?
203
-		if ( empty( $note_id ) || empty( $for_customer ) ) {
204
-			return $note_id;
205
-		}
206
-
207
-		add_comment_meta( $note_id, '_wpi_customer_note', 1 );
208
-		do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $invoice->get_id(), 'user_note' => $note ) );
209
-		do_action( 'getpaid_new_customer_note', $invoice, $note );
210
-		return $note_id;
211
-	}
102
+                    ARRAY_A
103
+                );
104
+
105
+                $approved = array(
106
+                    '0'            => 'moderated',
107
+                    '1'            => 'approved',
108
+                    'spam'         => 'spam',
109
+                    'trash'        => 'trash',
110
+                    'post-trashed' => 'post-trashed',
111
+                );
112
+
113
+                foreach ( (array) $count as $row ) {
114
+                    // Don't count post-trashed toward totals.
115
+                    if ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash', 'spam' ), true ) ) {
116
+                        $stats['all']            += $row['num_comments'];
117
+                        $stats['total_comments'] += $row['num_comments'];
118
+                    } elseif ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash' ), true ) ) {
119
+                        $stats['total_comments'] += $row['num_comments'];
120
+                    }
121
+                    if ( isset( $approved[ $row['comment_approved'] ] ) ) {
122
+                        $stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
123
+                    }
124
+                }
125
+
126
+                foreach ( $approved as $key ) {
127
+                    if ( empty( $stats[ $key ] ) ) {
128
+                        $stats[ $key ] = 0;
129
+                    }
130
+                }
131
+
132
+                $stats = (object) $stats;
133
+                set_transient( 'getpaid_count_comments', $stats );
134
+            }
135
+
136
+        }
137
+
138
+        return $stats;
139
+    }
140
+
141
+    /**
142
+     * Returns an array of invoice notes.
143
+     *
144
+     * @param int $invoice_id The invoice ID whose notes to retrieve.
145
+     * @param string $type Optional. Pass in customer to only return customer notes.
146
+     * @return WP_Comment[]
147
+     */
148
+    public function get_invoice_notes( $invoice_id = 0, $type = 'all' ) {
149
+
150
+        // Default comment args.
151
+        $args = array(
152
+            'post_id'   => $invoice_id,
153
+            'orderby'   => 'comment_ID',
154
+            'order'     => 'ASC',
155
+        );
156
+
157
+        // Maybe only show customer comments.
158
+        if ( $type == 'customer' ) {
159
+            $args['meta_key']   = '_wpi_customer_note';
160
+            $args['meta_value'] = 1;
161
+        }
162
+
163
+        $args = apply_filters( 'wpinv_invoice_notes_args', $args, $this, $invoice_id, $type );
164
+
165
+        return get_comments( $args );
166
+    }
167
+
168
+    /**
169
+     * Saves an invoice comment.
170
+     * 
171
+     * @param WPInv_Invoice $invoice The invoice to add the comment to.
172
+     * @param string $note The note content.
173
+     * @param string $note_author The name of the author of the note.
174
+     * @param bool $for_customer Whether or not this comment is meant to be sent to the customer.
175
+     * @return int|false The new note's ID on success, false on failure.
176
+     */
177
+    function add_invoice_note( $invoice, $note, $note_author, $author_email, $for_customer = false ){
178
+
179
+        do_action( 'wpinv_pre_insert_invoice_note', $invoice->get_id(), $note, $for_customer );
180
+
181
+        /**
182
+         * Insert the comment.
183
+         */
184
+        $note_id = wp_insert_comment(
185
+            wp_filter_comment(
186
+                array(
187
+                    'comment_post_ID'      => $invoice->get_id(),
188
+                    'comment_content'      => $note,
189
+                    'comment_agent'        => 'Invoicing',
190
+                    'user_id'              => get_current_user_id(),
191
+                    'comment_author'       => $note_author,
192
+                    'comment_author_IP'    => wpinv_get_ip(),
193
+                    'comment_author_email' => $author_email,
194
+                    'comment_author_url'   => $invoice->get_view_url(),
195
+                    'comment_type'         => 'wpinv_note',
196
+                )
197
+            )
198
+        );
199
+
200
+        do_action( 'wpinv_insert_payment_note', $note_id, $invoice->get_id(), $note, $for_customer );
201
+
202
+        // Are we notifying the customer?
203
+        if ( empty( $note_id ) || empty( $for_customer ) ) {
204
+            return $note_id;
205
+        }
206
+
207
+        add_comment_meta( $note_id, '_wpi_customer_note', 1 );
208
+        do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $invoice->get_id(), 'user_note' => $note ) );
209
+        do_action( 'getpaid_new_customer_note', $invoice, $note );
210
+        return $note_id;
211
+    }
212 212
 
213 213
 }
Please login to merge, or discard this patch.