Passed
Push — master ( 039fc1...a932b5 )
by Brian
05:54
created
includes/payments/class-getpaid-payment-form.php 1 patch
Indentation   +579 added lines, -579 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,55 +10,55 @@  discard block
 block discarded – undo
10 10
 class GetPaid_Payment_Form extends GetPaid_Data {
11 11
 
12 12
     /**
13
-	 * Which data store to load.
14
-	 *
15
-	 * @var string
16
-	 */
13
+     * Which data store to load.
14
+     *
15
+     * @var string
16
+     */
17 17
     protected $data_store_name = 'payment_form';
18 18
 
19 19
     /**
20
-	 * This is the name of this object type.
21
-	 *
22
-	 * @var string
23
-	 */
24
-	protected $object_type = 'payment_form';
20
+     * This is the name of this object type.
21
+     *
22
+     * @var string
23
+     */
24
+    protected $object_type = 'payment_form';
25 25
 
26 26
     /**
27
-	 * Form Data array. This is the core form data exposed in APIs.
28
-	 *
29
-	 * @since 1.0.19
30
-	 * @var array
31
-	 */
32
-	protected $data = array(
33
-		'status'        => 'draft',
34
-		'version'       => '',
35
-		'date_created'  => null,
27
+     * Form Data array. This is the core form data exposed in APIs.
28
+     *
29
+     * @since 1.0.19
30
+     * @var array
31
+     */
32
+    protected $data = array(
33
+        'status'        => 'draft',
34
+        'version'       => '',
35
+        'date_created'  => null,
36 36
         'date_modified' => null,
37 37
         'name'          => '',
38 38
         'author'        => 1,
39 39
         'elements'      => null,
40
-		'items'         => null,
41
-		'earned'        => 0,
42
-		'refunded'      => 0,
43
-		'cancelled'     => 0,
44
-		'failed'        => 0,
45
-	);
46
-
47
-    /**
48
-	 * Stores meta in cache for future reads.
49
-	 *
50
-	 * A group must be set to to enable caching.
51
-	 *
52
-	 * @var string
53
-	 */
54
-	protected $cache_group = 'getpaid_forms';
55
-
56
-	/**
57
-	 * Stores a reference to the invoice if the form is for an invoice..
58
-	 *
59
-	 * @var WPInv_Invoice
60
-	 */
61
-	public $invoice = 0;
40
+        'items'         => null,
41
+        'earned'        => 0,
42
+        'refunded'      => 0,
43
+        'cancelled'     => 0,
44
+        'failed'        => 0,
45
+    );
46
+
47
+    /**
48
+     * Stores meta in cache for future reads.
49
+     *
50
+     * A group must be set to to enable caching.
51
+     *
52
+     * @var string
53
+     */
54
+    protected $cache_group = 'getpaid_forms';
55
+
56
+    /**
57
+     * Stores a reference to the invoice if the form is for an invoice..
58
+     *
59
+     * @var WPInv_Invoice
60
+     */
61
+    public $invoice = 0;
62 62
 
63 63
     /**
64 64
      * Stores a reference to the original WP_Post object
@@ -68,35 +68,35 @@  discard block
 block discarded – undo
68 68
     protected $post = null;
69 69
 
70 70
     /**
71
-	 * Get the form if ID is passed, otherwise the form is new and empty.
72
-	 *
73
-	 * @param  int|object|GetPaid_Payment_Form|WP_Post $form Form to read.
74
-	 */
75
-	public function __construct( $form = 0 ) {
76
-		parent::__construct( $form );
71
+     * Get the form if ID is passed, otherwise the form is new and empty.
72
+     *
73
+     * @param  int|object|GetPaid_Payment_Form|WP_Post $form Form to read.
74
+     */
75
+    public function __construct( $form = 0 ) {
76
+        parent::__construct( $form );
77 77
 
78
-		if ( is_numeric( $form ) && $form > 0 ) {
79
-			$this->set_id( $form );
80
-		} elseif ( $form instanceof self ) {
78
+        if ( is_numeric( $form ) && $form > 0 ) {
79
+            $this->set_id( $form );
80
+        } elseif ( $form instanceof self ) {
81 81
 
82
-			$this->set_id( $form->get_id() );
83
-			$this->invoice = $form->invoice;
82
+            $this->set_id( $form->get_id() );
83
+            $this->invoice = $form->invoice;
84 84
 
85
-		} elseif ( ! empty( $form->ID ) ) {
86
-			$this->set_id( $form->ID );
87
-		} else {
88
-			$this->set_object_read( true );
89
-		}
85
+        } elseif ( ! empty( $form->ID ) ) {
86
+            $this->set_id( $form->ID );
87
+        } else {
88
+            $this->set_object_read( true );
89
+        }
90 90
 
91 91
         // Load the datastore.
92
-		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
92
+        $this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
93 93
 
94
-		if ( $this->get_id() > 0 ) {
94
+        if ( $this->get_id() > 0 ) {
95 95
             $this->post = get_post( $this->get_id() );
96
-			$this->data_store->read( $this );
96
+            $this->data_store->read( $this );
97 97
         }
98 98
 
99
-	}
99
+    }
100 100
 
101 101
     /*
102 102
 	|--------------------------------------------------------------------------
@@ -114,356 +114,356 @@  discard block
 block discarded – undo
114 114
     */
115 115
 
116 116
     /**
117
-	 * Get plugin version when the form was created.
118
-	 *
119
-	 * @since 1.0.19
120
-	 * @param  string $context View or edit context.
121
-	 * @return string
122
-	 */
123
-	public function get_version( $context = 'view' ) {
124
-		return $this->get_prop( 'version', $context );
117
+     * Get plugin version when the form was created.
118
+     *
119
+     * @since 1.0.19
120
+     * @param  string $context View or edit context.
121
+     * @return string
122
+     */
123
+    public function get_version( $context = 'view' ) {
124
+        return $this->get_prop( 'version', $context );
125 125
     }
126 126
 
127 127
     /**
128
-	 * Get date when the form was created.
129
-	 *
130
-	 * @since 1.0.19
131
-	 * @param  string $context View or edit context.
132
-	 * @return string
133
-	 */
134
-	public function get_date_created( $context = 'view' ) {
135
-		return $this->get_prop( 'date_created', $context );
128
+     * Get date when the form was created.
129
+     *
130
+     * @since 1.0.19
131
+     * @param  string $context View or edit context.
132
+     * @return string
133
+     */
134
+    public function get_date_created( $context = 'view' ) {
135
+        return $this->get_prop( 'date_created', $context );
136 136
     }
137 137
 
138 138
     /**
139
-	 * Get GMT date when the form was created.
140
-	 *
141
-	 * @since 1.0.19
142
-	 * @param  string $context View or edit context.
143
-	 * @return string
144
-	 */
145
-	public function get_date_created_gmt( $context = 'view' ) {
139
+     * Get GMT date when the form was created.
140
+     *
141
+     * @since 1.0.19
142
+     * @param  string $context View or edit context.
143
+     * @return string
144
+     */
145
+    public function get_date_created_gmt( $context = 'view' ) {
146 146
         $date = $this->get_date_created( $context );
147 147
 
148 148
         if ( $date ) {
149 149
             $date = get_gmt_from_date( $date );
150 150
         }
151
-		return $date;
151
+        return $date;
152 152
     }
153 153
 
154 154
     /**
155
-	 * Get date when the form was last modified.
156
-	 *
157
-	 * @since 1.0.19
158
-	 * @param  string $context View or edit context.
159
-	 * @return string
160
-	 */
161
-	public function get_date_modified( $context = 'view' ) {
162
-		return $this->get_prop( 'date_modified', $context );
155
+     * Get date when the form was last modified.
156
+     *
157
+     * @since 1.0.19
158
+     * @param  string $context View or edit context.
159
+     * @return string
160
+     */
161
+    public function get_date_modified( $context = 'view' ) {
162
+        return $this->get_prop( 'date_modified', $context );
163 163
     }
164 164
 
165 165
     /**
166
-	 * Get GMT date when the form was last modified.
167
-	 *
168
-	 * @since 1.0.19
169
-	 * @param  string $context View or edit context.
170
-	 * @return string
171
-	 */
172
-	public function get_date_modified_gmt( $context = 'view' ) {
166
+     * Get GMT date when the form was last modified.
167
+     *
168
+     * @since 1.0.19
169
+     * @param  string $context View or edit context.
170
+     * @return string
171
+     */
172
+    public function get_date_modified_gmt( $context = 'view' ) {
173 173
         $date = $this->get_date_modified( $context );
174 174
 
175 175
         if ( $date ) {
176 176
             $date = get_gmt_from_date( $date );
177 177
         }
178
-		return $date;
178
+        return $date;
179 179
     }
180 180
 
181 181
     /**
182
-	 * Get the form name.
183
-	 *
184
-	 * @since 1.0.19
185
-	 * @param  string $context View or edit context.
186
-	 * @return string
187
-	 */
188
-	public function get_name( $context = 'view' ) {
189
-		return $this->get_prop( 'name', $context );
182
+     * Get the form name.
183
+     *
184
+     * @since 1.0.19
185
+     * @param  string $context View or edit context.
186
+     * @return string
187
+     */
188
+    public function get_name( $context = 'view' ) {
189
+        return $this->get_prop( 'name', $context );
190 190
     }
191 191
 
192 192
     /**
193
-	 * Alias of self::get_name().
194
-	 *
195
-	 * @since 1.0.19
196
-	 * @param  string $context View or edit context.
197
-	 * @return string
198
-	 */
199
-	public function get_title( $context = 'view' ) {
200
-		return $this->get_name( $context );
201
-	}
193
+     * Alias of self::get_name().
194
+     *
195
+     * @since 1.0.19
196
+     * @param  string $context View or edit context.
197
+     * @return string
198
+     */
199
+    public function get_title( $context = 'view' ) {
200
+        return $this->get_name( $context );
201
+    }
202 202
 
203 203
     /**
204
-	 * Get the owner of the form.
205
-	 *
206
-	 * @since 1.0.19
207
-	 * @param  string $context View or edit context.
208
-	 * @return int
209
-	 */
210
-	public function get_author( $context = 'view' ) {
211
-		return (int) $this->get_prop( 'author', $context );
204
+     * Get the owner of the form.
205
+     *
206
+     * @since 1.0.19
207
+     * @param  string $context View or edit context.
208
+     * @return int
209
+     */
210
+    public function get_author( $context = 'view' ) {
211
+        return (int) $this->get_prop( 'author', $context );
212 212
     }
213 213
 
214 214
     /**
215
-	 * Get the elements that make up the form.
216
-	 *
217
-	 * @since 1.0.19
218
-	 * @param  string $context View or edit context.
219
-	 * @return array
220
-	 */
221
-	public function get_elements( $context = 'view' ) {
222
-		$elements = $this->get_prop( 'elements', $context );
215
+     * Get the elements that make up the form.
216
+     *
217
+     * @since 1.0.19
218
+     * @param  string $context View or edit context.
219
+     * @return array
220
+     */
221
+    public function get_elements( $context = 'view' ) {
222
+        $elements = $this->get_prop( 'elements', $context );
223 223
 
224
-		if ( empty( $elements ) || ! is_array( $elements ) ) {
224
+        if ( empty( $elements ) || ! is_array( $elements ) ) {
225 225
             return wpinv_get_data( 'sample-payment-form' );
226
-		}
226
+        }
227 227
 
228
-		// Ensure that all required elements exist.
229
-		$_elements = array();
230
-		foreach ( $elements as $element ) {
228
+        // Ensure that all required elements exist.
229
+        $_elements = array();
230
+        foreach ( $elements as $element ) {
231 231
 
232
-			if ( $element['type'] == 'pay_button' && ! $this->has_element_type( 'gateway_select' ) ) {
232
+            if ( $element['type'] == 'pay_button' && ! $this->has_element_type( 'gateway_select' ) ) {
233 233
 
234
-				$_elements[] = array(
235
-					'text'    => __( 'Select Payment Method', 'invoicing' ),
236
-					'id'      => 'gtscicd',
237
-					'name'    => 'gtscicd',
238
-					'type'    => 'gateway_select',
239
-					'premade' => true,
234
+                $_elements[] = array(
235
+                    'text'    => __( 'Select Payment Method', 'invoicing' ),
236
+                    'id'      => 'gtscicd',
237
+                    'name'    => 'gtscicd',
238
+                    'type'    => 'gateway_select',
239
+                    'premade' => true,
240 240
 
241
-				);
241
+                );
242 242
 
243
-			}
243
+            }
244 244
 
245
-			$_elements[] = $element;
245
+            $_elements[] = $element;
246 246
 
247
-		}
247
+        }
248 248
 
249 249
         return $_elements;
250
-	}
251
-
252
-	/**
253
-	 * Get the items sold via the form.
254
-	 *
255
-	 * @since 1.0.19
256
-	 * @param  string $context View or edit context.
257
-	 * @param  string $return objects or arrays.
258
-	 * @return GetPaid_Form_Item[]
259
-	 */
260
-	public function get_items( $context = 'view', $return = 'objects' ) {
261
-		$items = $this->get_prop( 'items', $context );
262
-
263
-		if ( empty( $items ) || ! is_array( $items ) ) {
250
+    }
251
+
252
+    /**
253
+     * Get the items sold via the form.
254
+     *
255
+     * @since 1.0.19
256
+     * @param  string $context View or edit context.
257
+     * @param  string $return objects or arrays.
258
+     * @return GetPaid_Form_Item[]
259
+     */
260
+    public function get_items( $context = 'view', $return = 'objects' ) {
261
+        $items = $this->get_prop( 'items', $context );
262
+
263
+        if ( empty( $items ) || ! is_array( $items ) ) {
264 264
             $items = wpinv_get_data( 'sample-payment-form-items' );
265
-		}
265
+        }
266
+
267
+        // Convert the items.
268
+        $prepared = array();
269
+
270
+        foreach ( $items as $key => $value ) {
271
+
272
+            // Form items.
273
+            if ( $value instanceof GetPaid_Form_Item ) {
274
+
275
+                if ( $value->can_purchase() ) {
276
+                    $prepared[] = $value;
277
+                }
266 278
 
267
-		// Convert the items.
268
-		$prepared = array();
279
+                continue;
269 280
 
270
-		foreach ( $items as $key => $value ) {
281
+            }
271 282
 
272
-			// Form items.
273
-			if ( $value instanceof GetPaid_Form_Item ) {
283
+            // $item_id => $quantity (buy buttons)
284
+            if ( is_numeric( $key ) && is_numeric( $value ) ) {
285
+                $item = new GetPaid_Form_Item( $key );
274 286
 
275
-				if ( $value->can_purchase() ) {
276
-					$prepared[] = $value;
277
-				}
287
+                if ( $item->can_purchase() ) {
278 288
 
279
-				continue;
289
+                    $value = (float) $value;
290
+                    $item->set_quantity( $value );
291
+                    if ( 0 == $value ) {
292
+                        $item->set_quantity( 1 );
293
+                        $item->set_allow_quantities( true );
294
+                    }
280 295
 
281
-			}
296
+                    $prepared[] = $item;
297
+                }
282 298
 
283
-			// $item_id => $quantity (buy buttons)
284
-			if ( is_numeric( $key ) && is_numeric( $value ) ) {
285
-				$item = new GetPaid_Form_Item( $key );
299
+                continue;
300
+            }
286 301
 
287
-				if ( $item->can_purchase() ) {
302
+            // Items saved via payment forms editor.
303
+            if ( is_array( $value ) && isset( $value['id'] ) ) {
288 304
 
289
-					$value = (float) $value;
290
-					$item->set_quantity( $value );
291
-					if ( 0 == $value ) {
292
-						$item->set_quantity( 1 );
293
-						$item->set_allow_quantities( true );
294
-					}
305
+                $item = new GetPaid_Form_Item( $value['id'] );
295 306
 
296
-					$prepared[] = $item;
297
-				}
307
+                if ( ! $item->can_purchase() ) {
308
+                    continue;
309
+                }
298 310
 
299
-				continue;
300
-			}
311
+                // Sub-total (Cart items).
312
+                if ( isset( $value['subtotal'] ) ) {
313
+                    $item->set_price( $value['subtotal'] );
314
+                }
301 315
 
302
-			// Items saved via payment forms editor.
303
-			if ( is_array( $value ) && isset( $value['id'] ) ) {
316
+                if ( isset( $value['quantity'] ) ) {
317
+                    $item->set_quantity( $value['quantity'] );
318
+                }
304 319
 
305
-				$item = new GetPaid_Form_Item( $value['id'] );
320
+                if ( isset( $value['allow_quantities'] ) ) {
321
+                    $item->set_allow_quantities( $value['allow_quantities'] );
322
+                }
306 323
 
307
-				if ( ! $item->can_purchase() ) {
308
-					continue;
309
-				}
324
+                if ( isset( $value['required'] ) ) {
325
+                    $item->set_is_required( $value['required'] );
326
+                }
310 327
 
311
-				// Sub-total (Cart items).
312
-				if ( isset( $value['subtotal'] ) ) {
313
-					$item->set_price( $value['subtotal'] );
314
-				}
328
+                if ( isset( $value['description'] ) ) {
329
+                    $item->set_custom_description( $value['description'] );
330
+                }
315 331
 
316
-				if ( isset( $value['quantity'] ) ) {
317
-					$item->set_quantity( $value['quantity'] );
318
-				}
332
+                $prepared[] = $item;
333
+                continue;
319 334
 
320
-				if ( isset( $value['allow_quantities'] ) ) {
321
-					$item->set_allow_quantities( $value['allow_quantities'] );
322
-				}
335
+            }
323 336
 
324
-				if ( isset( $value['required'] ) ) {
325
-					$item->set_is_required( $value['required'] );
326
-				}
337
+            // $item_id => array( 'price' => 10 ) (item variations)
338
+            if ( is_numeric( $key ) && is_array( $value ) ) {
339
+                $item = new GetPaid_Form_Item( $key );
327 340
 
328
-				if ( isset( $value['description'] ) ) {
329
-					$item->set_custom_description( $value['description'] );
330
-				}
341
+                if ( isset( $value['price'] ) && $item->user_can_set_their_price() ) {
342
+                    $item->set_price( $value['price'] );
343
+                }
331 344
 
332
-				$prepared[] = $item;
333
-				continue;
345
+                if ( $item->can_purchase() ) {
346
+                    $prepared[] = $item;
347
+                }
334 348
 
335
-			}
336
-
337
-			// $item_id => array( 'price' => 10 ) (item variations)
338
-			if ( is_numeric( $key ) && is_array( $value ) ) {
339
-				$item = new GetPaid_Form_Item( $key );
340
-
341
-				if ( isset( $value['price'] ) && $item->user_can_set_their_price() ) {
342
-					$item->set_price( $value['price'] );
343
-				}
344
-
345
-				if ( $item->can_purchase() ) {
346
-					$prepared[] = $item;
347
-				}
348
-
349
-				continue;
350
-			}
351
-		}
352
-
353
-		if ( 'objects' == $return && 'view' == $context ) {
354
-			return $prepared;
355
-		}
356
-
357
-		$items = array();
358
-		foreach ( $prepared as $item ) {
359
-			$items[] = $item->prepare_data_for_use();
360
-		}
361
-
362
-		return $items;
363
-	}
364
-
365
-	/**
366
-	 * Get a single item belonging to the form.
367
-	 *
368
-	 * @since 1.0.19
369
-	 * @param  int $item_id The item id to return.
370
-	 * @return GetPaid_Form_Item|bool
371
-	 */
372
-	public function get_item( $item_id ) {
373
-
374
-		if ( empty( $item_id ) || ! is_numeric( $item_id ) ) {
375
-			return false;
376
-		}
377
-
378
-		foreach ( $this->get_items() as $item ) {
379
-			if ( $item->get_id() == (int) $item_id ) {
380
-				return $item;
381
-			}
382
-		}
383
-
384
-		return false;
385
-
386
-	}
387
-
388
-	/**
389
-	 * Gets a single element.
390
-	 *
391
-	 * @since 1.0.19
392
-	 * @param  string $element_type The element type to return.
393
-	 * @return array|bool
394
-	 */
395
-	public function get_element_type( $element_type ) {
396
-
397
-		if ( empty( $element_type ) || ! is_scalar( $element_type ) ) {
398
-			return false;
399
-		}
400
-
401
-		foreach ( $this->get_prop( 'elements' ) as $element ) {
402
-
403
-			if ( $element['type'] === $element_type ) {
404
-				return $element;
405
-			}
406
-		}
407
-
408
-		return false;
409
-
410
-	}
411
-
412
-	/**
413
-	 * Get the total amount earned via this form.
414
-	 *
415
-	 * @since 1.0.19
416
-	 * @param  string $context View or edit context.
417
-	 * @return float
418
-	 */
419
-	public function get_earned( $context = 'view' ) {
420
-		return $this->get_prop( 'earned', $context );
421
-	}
422
-
423
-	/**
424
-	 * Get the total amount refunded via this form.
425
-	 *
426
-	 * @since 1.0.19
427
-	 * @param  string $context View or edit context.
428
-	 * @return float
429
-	 */
430
-	public function get_refunded( $context = 'view' ) {
431
-		return $this->get_prop( 'refunded', $context );
432
-	}
433
-
434
-	/**
435
-	 * Get the total amount cancelled via this form.
436
-	 *
437
-	 * @since 1.0.19
438
-	 * @param  string $context View or edit context.
439
-	 * @return float
440
-	 */
441
-	public function get_cancelled( $context = 'view' ) {
442
-		return $this->get_prop( 'cancelled', $context );
443
-	}
444
-
445
-	/**
446
-	 * Get the total amount failed via this form.
447
-	 *
448
-	 * @since 1.0.19
449
-	 * @param  string $context View or edit context.
450
-	 * @return float
451
-	 */
452
-	public function get_failed( $context = 'view' ) {
453
-		return $this->get_prop( 'failed', $context );
454
-	}
455
-
456
-	/**
457
-	 * Get the currency.
458
-	 *
459
-	 * @since 1.0.19
460
-	 * @param  string $context View or edit context.
461
-	 * @return string
462
-	 */
463
-	public function get_currency() {
464
-		$currency = empty( $this->invoice ) ? wpinv_get_currency() : $this->invoice->get_currency();
465
-		return apply_filters( 'getpaid-payment-form-currency', $currency, $this );
466
-	}
349
+                continue;
350
+            }
351
+        }
352
+
353
+        if ( 'objects' == $return && 'view' == $context ) {
354
+            return $prepared;
355
+        }
356
+
357
+        $items = array();
358
+        foreach ( $prepared as $item ) {
359
+            $items[] = $item->prepare_data_for_use();
360
+        }
361
+
362
+        return $items;
363
+    }
364
+
365
+    /**
366
+     * Get a single item belonging to the form.
367
+     *
368
+     * @since 1.0.19
369
+     * @param  int $item_id The item id to return.
370
+     * @return GetPaid_Form_Item|bool
371
+     */
372
+    public function get_item( $item_id ) {
373
+
374
+        if ( empty( $item_id ) || ! is_numeric( $item_id ) ) {
375
+            return false;
376
+        }
377
+
378
+        foreach ( $this->get_items() as $item ) {
379
+            if ( $item->get_id() == (int) $item_id ) {
380
+                return $item;
381
+            }
382
+        }
383
+
384
+        return false;
385
+
386
+    }
387
+
388
+    /**
389
+     * Gets a single element.
390
+     *
391
+     * @since 1.0.19
392
+     * @param  string $element_type The element type to return.
393
+     * @return array|bool
394
+     */
395
+    public function get_element_type( $element_type ) {
396
+
397
+        if ( empty( $element_type ) || ! is_scalar( $element_type ) ) {
398
+            return false;
399
+        }
400
+
401
+        foreach ( $this->get_prop( 'elements' ) as $element ) {
402
+
403
+            if ( $element['type'] === $element_type ) {
404
+                return $element;
405
+            }
406
+        }
407
+
408
+        return false;
409
+
410
+    }
411
+
412
+    /**
413
+     * Get the total amount earned via this form.
414
+     *
415
+     * @since 1.0.19
416
+     * @param  string $context View or edit context.
417
+     * @return float
418
+     */
419
+    public function get_earned( $context = 'view' ) {
420
+        return $this->get_prop( 'earned', $context );
421
+    }
422
+
423
+    /**
424
+     * Get the total amount refunded via this form.
425
+     *
426
+     * @since 1.0.19
427
+     * @param  string $context View or edit context.
428
+     * @return float
429
+     */
430
+    public function get_refunded( $context = 'view' ) {
431
+        return $this->get_prop( 'refunded', $context );
432
+    }
433
+
434
+    /**
435
+     * Get the total amount cancelled via this form.
436
+     *
437
+     * @since 1.0.19
438
+     * @param  string $context View or edit context.
439
+     * @return float
440
+     */
441
+    public function get_cancelled( $context = 'view' ) {
442
+        return $this->get_prop( 'cancelled', $context );
443
+    }
444
+
445
+    /**
446
+     * Get the total amount failed via this form.
447
+     *
448
+     * @since 1.0.19
449
+     * @param  string $context View or edit context.
450
+     * @return float
451
+     */
452
+    public function get_failed( $context = 'view' ) {
453
+        return $this->get_prop( 'failed', $context );
454
+    }
455
+
456
+    /**
457
+     * Get the currency.
458
+     *
459
+     * @since 1.0.19
460
+     * @param  string $context View or edit context.
461
+     * @return string
462
+     */
463
+    public function get_currency() {
464
+        $currency = empty( $this->invoice ) ? wpinv_get_currency() : $this->invoice->get_currency();
465
+        return apply_filters( 'getpaid-payment-form-currency', $currency, $this );
466
+    }
467 467
 
468 468
     /*
469 469
 	|--------------------------------------------------------------------------
@@ -476,22 +476,22 @@  discard block
 block discarded – undo
476 476
     */
477 477
 
478 478
     /**
479
-	 * Set plugin version when the item was created.
480
-	 *
481
-	 * @since 1.0.19
482
-	 */
483
-	public function set_version( $value ) {
484
-		$this->set_prop( 'version', $value );
479
+     * Set plugin version when the item was created.
480
+     *
481
+     * @since 1.0.19
482
+     */
483
+    public function set_version( $value ) {
484
+        $this->set_prop( 'version', $value );
485 485
     }
486 486
 
487 487
     /**
488
-	 * Set date when the item was created.
489
-	 *
490
-	 * @since 1.0.19
491
-	 * @param string $value Value to set.
488
+     * Set date when the item was created.
489
+     *
490
+     * @since 1.0.19
491
+     * @param string $value Value to set.
492 492
      * @return bool Whether or not the date was set.
493
-	 */
494
-	public function set_date_created( $value ) {
493
+     */
494
+    public function set_date_created( $value ) {
495 495
         $date = strtotime( $value );
496 496
 
497 497
         if ( $date ) {
@@ -504,13 +504,13 @@  discard block
 block discarded – undo
504 504
     }
505 505
 
506 506
     /**
507
-	 * Set date when the item was last modified.
508
-	 *
509
-	 * @since 1.0.19
510
-	 * @param string $value Value to set.
507
+     * Set date when the item was last modified.
508
+     *
509
+     * @since 1.0.19
510
+     * @param string $value Value to set.
511 511
      * @return bool Whether or not the date was set.
512
-	 */
513
-	public function set_date_modified( $value ) {
512
+     */
513
+    public function set_date_modified( $value ) {
514 514
         $date = strtotime( $value );
515 515
 
516 516
         if ( $date ) {
@@ -523,164 +523,164 @@  discard block
 block discarded – undo
523 523
     }
524 524
 
525 525
     /**
526
-	 * Set the item name.
527
-	 *
528
-	 * @since 1.0.19
529
-	 * @param  string $value New name.
530
-	 */
531
-	public function set_name( $value ) {
532
-		$this->set_prop( 'name', sanitize_text_field( $value ) );
533
-    }
534
-
535
-    /**
536
-	 * Alias of self::set_name().
537
-	 *
538
-	 * @since 1.0.19
539
-	 * @param  string $value New name.
540
-	 */
541
-	public function set_title( $value ) {
542
-		$this->set_name( $value );
543
-    }
544
-
545
-    /**
546
-	 * Set the owner of the item.
547
-	 *
548
-	 * @since 1.0.19
549
-	 * @param  int $value New author.
550
-	 */
551
-	public function set_author( $value ) {
552
-		$this->set_prop( 'author', (int) $value );
553
-	}
554
-
555
-	/**
556
-	 * Set the form elements.
557
-	 *
558
-	 * @since 1.0.19
559
-	 * @sinve 2.3.4 Array values sanitized.
560
-	 * @param  array $value Form elements.
561
-	 */
562
-	public function set_elements( $value ) {
563
-		if ( is_array( $value ) ) {
564
-			$this->set_prop( 'elements', wp_kses_post_deep( $value ) );
565
-		}
566
-	}
567
-
568
-	/**
569
-	 * Sanitize array values.
570
-	 *
571
-	 * @param $value
572
-	 *
573
-	 * @return mixed
574
-	 */
575
-	public function sanitize_array_values( $value ) {
576
-
577
-		// sanitize
578
-		if ( ! empty( $value ) ) {
579
-
580
-			foreach ( $value as $key => $val_arr ) {
581
-
582
-				if ( is_array( $val_arr ) ) {
583
-					// check if we have sub array items.
584
-					$sub_arr = array();
585
-					foreach ( $val_arr as $key2 => $val2 ) {
586
-						if ( is_array( $val2 ) ) {
587
-							$sub_arr[ $key2 ] = $this->sanitize_array_values( $val2 );
588
-							unset( $val_arr[ $key ][ $key2 ] );
589
-						}
590
-					}
591
-
592
-					// we allow some html in description so we sanitize it separately.
593
-					$help_text = ! empty( $val_arr['description'] ) ? wp_kses_post( $val_arr['description'] ) : '';
594
-
595
-					// sanitize array elements
596
-					$value[ $key ] = array_map( 'sanitize_text_field', $val_arr );
597
-
598
-					// add back the description if set
599
-					if ( isset( $val_arr['description'] ) ) {
526
+     * Set the item name.
527
+     *
528
+     * @since 1.0.19
529
+     * @param  string $value New name.
530
+     */
531
+    public function set_name( $value ) {
532
+        $this->set_prop( 'name', sanitize_text_field( $value ) );
533
+    }
534
+
535
+    /**
536
+     * Alias of self::set_name().
537
+     *
538
+     * @since 1.0.19
539
+     * @param  string $value New name.
540
+     */
541
+    public function set_title( $value ) {
542
+        $this->set_name( $value );
543
+    }
544
+
545
+    /**
546
+     * Set the owner of the item.
547
+     *
548
+     * @since 1.0.19
549
+     * @param  int $value New author.
550
+     */
551
+    public function set_author( $value ) {
552
+        $this->set_prop( 'author', (int) $value );
553
+    }
554
+
555
+    /**
556
+     * Set the form elements.
557
+     *
558
+     * @since 1.0.19
559
+     * @sinve 2.3.4 Array values sanitized.
560
+     * @param  array $value Form elements.
561
+     */
562
+    public function set_elements( $value ) {
563
+        if ( is_array( $value ) ) {
564
+            $this->set_prop( 'elements', wp_kses_post_deep( $value ) );
565
+        }
566
+    }
567
+
568
+    /**
569
+     * Sanitize array values.
570
+     *
571
+     * @param $value
572
+     *
573
+     * @return mixed
574
+     */
575
+    public function sanitize_array_values( $value ) {
576
+
577
+        // sanitize
578
+        if ( ! empty( $value ) ) {
579
+
580
+            foreach ( $value as $key => $val_arr ) {
581
+
582
+                if ( is_array( $val_arr ) ) {
583
+                    // check if we have sub array items.
584
+                    $sub_arr = array();
585
+                    foreach ( $val_arr as $key2 => $val2 ) {
586
+                        if ( is_array( $val2 ) ) {
587
+                            $sub_arr[ $key2 ] = $this->sanitize_array_values( $val2 );
588
+                            unset( $val_arr[ $key ][ $key2 ] );
589
+                        }
590
+                    }
591
+
592
+                    // we allow some html in description so we sanitize it separately.
593
+                    $help_text = ! empty( $val_arr['description'] ) ? wp_kses_post( $val_arr['description'] ) : '';
594
+
595
+                    // sanitize array elements
596
+                    $value[ $key ] = array_map( 'sanitize_text_field', $val_arr );
597
+
598
+                    // add back the description if set
599
+                    if ( isset( $val_arr['description'] ) ) {
600 600
 $value[ $key ]['description'] = $help_text;}
601 601
 
602
-					// add back sub array items after its been sanitized.
603
-					if ( ! empty( $sub_arr ) ) {
604
-						$value[ $key ] = array_merge( $value[ $key ], $sub_arr );
605
-					}
606
-				}
602
+                    // add back sub array items after its been sanitized.
603
+                    if ( ! empty( $sub_arr ) ) {
604
+                        $value[ $key ] = array_merge( $value[ $key ], $sub_arr );
605
+                    }
606
+                }
607 607
 }
608 608
 }
609 609
 
610
-		return $value;
611
-	}
612
-
613
-	/**
614
-	 * Set the form items.
615
-	 *
616
-	 * @since 1.0.19
617
-	 * @param  array $value Form elements.
618
-	 */
619
-	public function set_items( $value ) {
620
-		if ( is_array( $value ) ) {
621
-			$this->set_prop( 'items', $value );
622
-		}
623
-	}
624
-
625
-	/**
626
-	 * Set the total amount earned via this form.
627
-	 *
628
-	 * @since 1.0.19
629
-	 * @param  float $value Amount earned.
630
-	 */
631
-	public function set_earned( $value ) {
632
-		$value = max( (float) $value, 0 );
633
-		$this->set_prop( 'earned', $value );
634
-	}
635
-
636
-	/**
637
-	 * Set the total amount refunded via this form.
638
-	 *
639
-	 * @since 1.0.19
640
-	 * @param  float $value Amount refunded.
641
-	 */
642
-	public function set_refunded( $value ) {
643
-		$value = max( (float) $value, 0 );
644
-		$this->set_prop( 'refunded', $value );
645
-	}
646
-
647
-	/**
648
-	 * Set the total amount cancelled via this form.
649
-	 *
650
-	 * @since 1.0.19
651
-	 * @param  float $value Amount cancelled.
652
-	 */
653
-	public function set_cancelled( $value ) {
654
-		$value = max( (float) $value, 0 );
655
-		$this->set_prop( 'cancelled', $value );
656
-	}
657
-
658
-	/**
659
-	 * Set the total amount failed via this form.
660
-	 *
661
-	 * @since 1.0.19
662
-	 * @param  float $value Amount cancelled.
663
-	 */
664
-	public function set_failed( $value ) {
665
-		$value = max( (float) $value, 0 );
666
-		$this->set_prop( 'failed', $value );
667
-	}
610
+        return $value;
611
+    }
612
+
613
+    /**
614
+     * Set the form items.
615
+     *
616
+     * @since 1.0.19
617
+     * @param  array $value Form elements.
618
+     */
619
+    public function set_items( $value ) {
620
+        if ( is_array( $value ) ) {
621
+            $this->set_prop( 'items', $value );
622
+        }
623
+    }
624
+
625
+    /**
626
+     * Set the total amount earned via this form.
627
+     *
628
+     * @since 1.0.19
629
+     * @param  float $value Amount earned.
630
+     */
631
+    public function set_earned( $value ) {
632
+        $value = max( (float) $value, 0 );
633
+        $this->set_prop( 'earned', $value );
634
+    }
635
+
636
+    /**
637
+     * Set the total amount refunded via this form.
638
+     *
639
+     * @since 1.0.19
640
+     * @param  float $value Amount refunded.
641
+     */
642
+    public function set_refunded( $value ) {
643
+        $value = max( (float) $value, 0 );
644
+        $this->set_prop( 'refunded', $value );
645
+    }
646
+
647
+    /**
648
+     * Set the total amount cancelled via this form.
649
+     *
650
+     * @since 1.0.19
651
+     * @param  float $value Amount cancelled.
652
+     */
653
+    public function set_cancelled( $value ) {
654
+        $value = max( (float) $value, 0 );
655
+        $this->set_prop( 'cancelled', $value );
656
+    }
657
+
658
+    /**
659
+     * Set the total amount failed via this form.
660
+     *
661
+     * @since 1.0.19
662
+     * @param  float $value Amount cancelled.
663
+     */
664
+    public function set_failed( $value ) {
665
+        $value = max( (float) $value, 0 );
666
+        $this->set_prop( 'failed', $value );
667
+    }
668 668
 
669 669
     /**
670 670
      * Create an item. For backwards compatibilty.
671 671
      *
672 672
      * @deprecated
673
-	 * @return int item id
673
+     * @return int item id
674 674
      */
675 675
     public function create( $data = array() ) {
676 676
 
677
-		// Set the properties.
678
-		if ( is_array( $data ) ) {
679
-			$this->set_props( $data );
680
-		}
677
+        // Set the properties.
678
+        if ( is_array( $data ) ) {
679
+            $this->set_props( $data );
680
+        }
681 681
 
682
-		// Save the item.
683
-		return $this->save();
682
+        // Save the item.
683
+        return $this->save();
684 684
 
685 685
     }
686 686
 
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
      * Updates an item. For backwards compatibilty.
689 689
      *
690 690
      * @deprecated
691
-	 * @return int item id
691
+     * @return int item id
692 692
      */
693 693
     public function update( $data = array() ) {
694 694
         return $this->create( $data );
@@ -704,22 +704,22 @@  discard block
 block discarded – undo
704 704
 	*/
705 705
 
706 706
     /**
707
-	 * Checks whether this is the default payment form.
708
-	 *
709
-	 * @since 1.0.19
710
-	 * @return bool
711
-	 */
707
+     * Checks whether this is the default payment form.
708
+     *
709
+     * @since 1.0.19
710
+     * @return bool
711
+     */
712 712
     public function is_default() {
713 713
         $is_default = $this->get_id() == wpinv_get_default_payment_form();
714 714
         return (bool) apply_filters( 'wpinv_is_default_payment_form', $is_default, $this->get_id(), $this );
715
-	}
715
+    }
716 716
 
717 717
     /**
718
-	 * Checks whether the form is active.
719
-	 *
720
-	 * @since 1.0.19
721
-	 * @return bool
722
-	 */
718
+     * Checks whether the form is active.
719
+     *
720
+     * @since 1.0.19
721
+     * @return bool
722
+     */
723 723
     public function is_active() {
724 724
         $is_active = 0 !== (int) $this->get_id();
725 725
 
@@ -728,81 +728,81 @@  discard block
 block discarded – undo
728 728
         }
729 729
 
730 730
         return (bool) apply_filters( 'wpinv_is_payment_form_active', $is_active, $this );
731
-	}
732
-
733
-	/**
734
-	 * Checks whether the form has a given item.
735
-	 *
736
-	 * @since 1.0.19
737
-	 * @return bool
738
-	 */
731
+    }
732
+
733
+    /**
734
+     * Checks whether the form has a given item.
735
+     *
736
+     * @since 1.0.19
737
+     * @return bool
738
+     */
739 739
     public function has_item( $item_id ) {
740 740
         return false !== $this->get_item( $item_id );
741
-	}
742
-
743
-	/**
744
-	 * Checks whether the form has a given element.
745
-	 *
746
-	 * @since 1.0.19
747
-	 * @return bool
748
-	 */
741
+    }
742
+
743
+    /**
744
+     * Checks whether the form has a given element.
745
+     *
746
+     * @since 1.0.19
747
+     * @return bool
748
+     */
749 749
     public function has_element_type( $element_type ) {
750 750
         return false !== $this->get_element_type( $element_type );
751
-	}
752
-
753
-	/**
754
-	 * Checks whether this form is recurring or not.
755
-	 *
756
-	 * @since 1.0.19
757
-	 * @return bool
758
-	 */
751
+    }
752
+
753
+    /**
754
+     * Checks whether this form is recurring or not.
755
+     *
756
+     * @since 1.0.19
757
+     * @return bool
758
+     */
759 759
     public function is_recurring() {
760 760
 
761
-		if ( ! empty( $this->invoice ) ) {
762
-			return $this->invoice->is_recurring();
763
-		}
761
+        if ( ! empty( $this->invoice ) ) {
762
+            return $this->invoice->is_recurring();
763
+        }
764 764
 
765
-		foreach ( $this->get_items() as $item ) {
765
+        foreach ( $this->get_items() as $item ) {
766 766
 
767
-			if ( $item->is_recurring() ) {
768
-				return true;
769
-			}
767
+            if ( $item->is_recurring() ) {
768
+                return true;
769
+            }
770 770
 }
771 771
 
772 772
         return false;
773
-	}
773
+    }
774 774
 
775
-	/**
776
-	 * Retrieves the form's html.
777
-	 *
778
-	 * @since 1.0.19
779
-	 */
775
+    /**
776
+     * Retrieves the form's html.
777
+     *
778
+     * @since 1.0.19
779
+     */
780 780
     public function get_html( $extra_markup = '' ) {
781 781
 
782
-		// Return the HTML.
783
-		return wpinv_get_template_html(
784
-			'payment-forms/form.php',
785
-			array(
786
-				'form'         => $this,
787
-				'extra_markup' => $extra_markup,
788
-			)
789
-		);
790
-
791
-	}
792
-
793
-	/**
794
-	 * Displays the payment form.
795
-	 *
796
-	 * @since 1.0.19
797
-	 */
782
+        // Return the HTML.
783
+        return wpinv_get_template_html(
784
+            'payment-forms/form.php',
785
+            array(
786
+                'form'         => $this,
787
+                'extra_markup' => $extra_markup,
788
+            )
789
+        );
790
+
791
+    }
792
+
793
+    /**
794
+     * Displays the payment form.
795
+     *
796
+     * @since 1.0.19
797
+     */
798 798
     public function display( $extra_markup = '' ) {
799
-		wpinv_get_template(
800
-			'payment-forms/form.php',
801
-			array(
802
-				'form'         => $this,
803
-				'extra_markup' => $extra_markup,
804
-			)
805
-		);
799
+        wpinv_get_template(
800
+            'payment-forms/form.php',
801
+            array(
802
+                'form'         => $this,
803
+                'extra_markup' => $extra_markup,
804
+            )
805
+        );
806 806
     }
807 807
 
808 808
 }
Please login to merge, or discard this patch.
includes/wpinv-address-functions.php 1 patch
Indentation   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -13,9 +13,9 @@  discard block
 block discarded – undo
13 13
 
14 14
 
15 15
 function wpinv_get_default_country() {
16
-	$country = wpinv_get_option( 'default_country', 'UK' );
16
+    $country = wpinv_get_option( 'default_country', 'UK' );
17 17
 
18
-	return apply_filters( 'wpinv_default_country', $country );
18
+    return apply_filters( 'wpinv_default_country', $country );
19 19
 }
20 20
 
21 21
 /**
@@ -36,7 +36,7 @@  discard block
 block discarded – undo
36 36
  */
37 37
 function wpinv_sanitize_country( $country ) {
38 38
 
39
-	// Enure the country is specified
39
+    // Enure the country is specified
40 40
     if ( empty( $country ) ) {
41 41
         $country = wpinv_get_default_country();
42 42
     }
@@ -66,9 +66,9 @@  discard block
 block discarded – undo
66 66
 }
67 67
 
68 68
 function wpinv_get_default_state() {
69
-	$state = wpinv_get_option( 'default_state', '' );
69
+    $state = wpinv_get_option( 'default_state', '' );
70 70
 
71
-	return apply_filters( 'wpinv_default_state', $state );
71
+    return apply_filters( 'wpinv_default_state', $state );
72 72
 }
73 73
 
74 74
 function wpinv_state_name( $state_code = '', $country_code = '' ) {
@@ -299,11 +299,11 @@  discard block
 block discarded – undo
299 299
 
300 300
     $country = wpinv_sanitize_country( $country );
301 301
 
302
-	foreach ( wpinv_get_continents( 'countries' ) as $continent_code => $countries ) {
303
-		if ( false !== array_search( $country, $countries, true ) ) {
304
-			return $continent_code;
305
-		}
306
-	}
302
+    foreach ( wpinv_get_continents( 'countries' ) as $continent_code => $countries ) {
303
+        if ( false !== array_search( $country, $countries, true ) ) {
304
+            return $continent_code;
305
+        }
306
+    }
307 307
 
308 308
     return '';
309 309
 
@@ -595,31 +595,31 @@  discard block
 block discarded – undo
595 595
 }
596 596
 
597 597
 function wpinv_get_states_field() {
598
-	if ( empty( $_POST['country'] ) ) {
599
-		$_POST['country'] = wpinv_get_default_country();
600
-	}
601
-	$states = wpinv_get_country_states( sanitize_text_field( $_POST['country'] ) );
598
+    if ( empty( $_POST['country'] ) ) {
599
+        $_POST['country'] = wpinv_get_default_country();
600
+    }
601
+    $states = wpinv_get_country_states( sanitize_text_field( $_POST['country'] ) );
602 602
 
603
-	if ( ! empty( $states ) ) {
604
-		$sanitized_field_name = sanitize_text_field( $_POST['field_name'] );
603
+    if ( ! empty( $states ) ) {
604
+        $sanitized_field_name = sanitize_text_field( $_POST['field_name'] );
605 605
 
606 606
         $class  = isset( $_POST['class'] ) ? esc_attr( sanitize_text_field( $_POST['class'] ) ) : '';
607 607
         $class .= " $sanitized_field_name getpaid_js_field-state custom-select wpinv-select wpi_select2";
608 608
 
609 609
         $args  = array(
610
-			'name'             => $sanitized_field_name,
611
-			'id'               => $sanitized_field_name,
612
-			'class'            => implode( ' ', array_unique( explode( ' ', $class ) ) ),
613
-			'options'          => array_merge( array( '' => '' ), $states ),
614
-			'show_option_all'  => false,
615
-			'show_option_none' => false,
616
-		);
617
-
618
-		wpinv_html_select( $args );
619
-
620
-	} else {
621
-		echo 'nostates';
622
-	}
610
+            'name'             => $sanitized_field_name,
611
+            'id'               => $sanitized_field_name,
612
+            'class'            => implode( ' ', array_unique( explode( ' ', $class ) ) ),
613
+            'options'          => array_merge( array( '' => '' ), $states ),
614
+            'show_option_all'  => false,
615
+            'show_option_none' => false,
616
+        );
617
+
618
+        wpinv_html_select( $args );
619
+
620
+    } else {
621
+        echo 'nostates';
622
+    }
623 623
 
624 624
 }
625 625
 
@@ -638,47 +638,47 @@  discard block
 block discarded – undo
638 638
  */
639 639
 function wpinv_get_address_formats() {
640 640
 
641
-		return apply_filters(
641
+        return apply_filters(
642 642
             'wpinv_localisation_address_formats',
643
-			array(
644
-				'default' => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}\n{{zip}}\n{{country}}",
645
-				'AU'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}} {{zip}}\n{{country}}",
646
-				'AT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
647
-				'BE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
648
-				'CA'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{state_code}}&nbsp;&nbsp;{{zip}}\n{{country}}",
649
-				'CH'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
650
-				'CL'      => "{{company}}\n{{name}}\n{{address}}\n{{state}}\n{{zip}} {{city}}\n{{country}}",
651
-				'CN'      => "{{country}} {{zip}}\n{{state}}, {{city}}, {{address}}\n{{company}}\n{{name}}",
652
-				'CZ'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
653
-				'DE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
654
-				'EE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
655
-				'FI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
656
-				'DK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
657
-				'FR'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city_upper}}\n{{country}}",
658
-				'HK'      => "{{company}}\n{{first_name}} {{last_name_upper}}\n{{address}}\n{{city_upper}}\n{{state_upper}}\n{{country}}",
659
-				'HU'      => "{{name}}\n{{company}}\n{{city}}\n{{address}}\n{{zip}}\n{{country}}",
660
-				'IN'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{zip}}\n{{state}}, {{country}}",
661
-				'IS'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
662
-				'IT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}}\n{{city}}\n{{state_upper}}\n{{country}}",
663
-				'JP'      => "{{zip}}\n{{state}} {{city}} {{address}}\n{{company}}\n{{last_name}} {{first_name}}\n{{country}}",
664
-				'TW'      => "{{company}}\n{{last_name}} {{first_name}}\n{{address}}\n{{state}}, {{city}} {{zip}}\n{{country}}",
665
-				'LI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
666
-				'NL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
667
-				'NZ'      => "{{name}}\n{{company}}\n{{address}}\n{{city}} {{zip}}\n{{country}}",
668
-				'NO'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
669
-				'PL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
670
-				'PT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
671
-				'SK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
672
-				'RS'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
673
-				'SI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
674
-				'ES'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{state}}\n{{country}}",
675
-				'SE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
676
-				'TR'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}} {{state}}\n{{country}}",
677
-				'UG'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}, {{country}}",
678
-				'US'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}, {{state_code}} {{zip}}\n{{country}}",
679
-				'VN'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{country}}",
680
-			)
681
-		);
643
+            array(
644
+                'default' => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}\n{{zip}}\n{{country}}",
645
+                'AU'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}} {{zip}}\n{{country}}",
646
+                'AT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
647
+                'BE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
648
+                'CA'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{state_code}}&nbsp;&nbsp;{{zip}}\n{{country}}",
649
+                'CH'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
650
+                'CL'      => "{{company}}\n{{name}}\n{{address}}\n{{state}}\n{{zip}} {{city}}\n{{country}}",
651
+                'CN'      => "{{country}} {{zip}}\n{{state}}, {{city}}, {{address}}\n{{company}}\n{{name}}",
652
+                'CZ'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
653
+                'DE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
654
+                'EE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
655
+                'FI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
656
+                'DK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
657
+                'FR'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city_upper}}\n{{country}}",
658
+                'HK'      => "{{company}}\n{{first_name}} {{last_name_upper}}\n{{address}}\n{{city_upper}}\n{{state_upper}}\n{{country}}",
659
+                'HU'      => "{{name}}\n{{company}}\n{{city}}\n{{address}}\n{{zip}}\n{{country}}",
660
+                'IN'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{zip}}\n{{state}}, {{country}}",
661
+                'IS'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
662
+                'IT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}}\n{{city}}\n{{state_upper}}\n{{country}}",
663
+                'JP'      => "{{zip}}\n{{state}} {{city}} {{address}}\n{{company}}\n{{last_name}} {{first_name}}\n{{country}}",
664
+                'TW'      => "{{company}}\n{{last_name}} {{first_name}}\n{{address}}\n{{state}}, {{city}} {{zip}}\n{{country}}",
665
+                'LI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
666
+                'NL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
667
+                'NZ'      => "{{name}}\n{{company}}\n{{address}}\n{{city}} {{zip}}\n{{country}}",
668
+                'NO'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
669
+                'PL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
670
+                'PT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
671
+                'SK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
672
+                'RS'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
673
+                'SI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
674
+                'ES'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{state}}\n{{country}}",
675
+                'SE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
676
+                'TR'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}} {{state}}\n{{country}}",
677
+                'UG'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}, {{country}}",
678
+                'US'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}, {{state_code}} {{zip}}\n{{country}}",
679
+                'VN'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{country}}",
680
+            )
681
+        );
682 682
 }
683 683
 
684 684
 /**
@@ -695,21 +695,21 @@  discard block
 block discarded – undo
695 695
     }
696 696
 
697 697
     // Get all formats.
698
-	$formats = wpinv_get_address_formats();
698
+    $formats = wpinv_get_address_formats();
699 699
 
700
-	// Get format for the specified country.
701
-	$format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
700
+    // Get format for the specified country.
701
+    $format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
702 702
 
703 703
     /**
704
-	 * Filters the address format to use on Invoices.
704
+     * Filters the address format to use on Invoices.
705 705
      *
706 706
      * New lines will be replaced by a `br` element. Double new lines will be replaced by a paragraph. HTML tags are allowed.
707
-	 *
708
-	 * @since 1.0.13
709
-	 *
710
-	 * @param string $format  The address format to use.
707
+     *
708
+     * @since 1.0.13
709
+     *
710
+     * @param string $format  The address format to use.
711 711
      * @param string $country The country who's address format is being retrieved.
712
-	 */
712
+     */
713 713
     return apply_filters( 'wpinv_get_full_address_format', $format, $country );
714 714
 }
715 715
 
@@ -730,8 +730,8 @@  discard block
 block discarded – undo
730 730
         'country'    => '',
731 731
         'zip'        => '',
732 732
         'first_name' => '',
733
-		'last_name'  => '',
734
-		'company'    => '',
733
+        'last_name'  => '',
734
+        'company'    => '',
735 735
     );
736 736
 
737 737
     $args    = map_deep( wp_parse_args( array_filter( $billing_details ), $default_args ), 'trim' );
@@ -752,14 +752,14 @@  discard block
 block discarded – undo
752 752
     $args['country_code'] = $country;
753 753
 
754 754
     /**
755
-	 * Filters the address format replacements to use on Invoices.
755
+     * Filters the address format replacements to use on Invoices.
756
+     *
757
+     *
758
+     * @since 1.0.13
756 759
      *
757
-	 *
758
-	 * @since 1.0.13
759
-	 *
760
-	 * @param array $replacements  The address replacements to use.
760
+     * @param array $replacements  The address replacements to use.
761 761
      * @param array $billing_details  The billing details to use.
762
-	 */
762
+     */
763 763
     $replacements = apply_filters( 'wpinv_get_invoice_address_replacements', $args, $billing_details );
764 764
 
765 765
     $return = array();
@@ -782,5 +782,5 @@  discard block
 block discarded – undo
782 782
  * @return string
783 783
  */
784 784
 function wpinv_trim_formatted_address_line( $line ) {
785
-	return trim( $line, ', ' );
785
+    return trim( $line, ', ' );
786 786
 }
Please login to merge, or discard this patch.
includes/class-getpaid-invoice-notification-emails.php 1 patch
Indentation   +470 added lines, -470 removed lines patch added patch discarded remove patch
@@ -12,493 +12,493 @@
 block discarded – undo
12 12
  */
13 13
 class GetPaid_Invoice_Notification_Emails {
14 14
 
15
-	/**
16
-	 * The array of invoice email actions.
17
-	 *
18
-	 * @param array
19
-	 */
20
-	public $invoice_actions;
21
-
22
-	/**
23
-	 * Class constructor
24
-	 *
25
-	 */
26
-	public function __construct() {
27
-
28
-		$this->invoice_actions = apply_filters(
29
-			'getpaid_notification_email_invoice_triggers',
30
-			array(
31
-				'getpaid_new_invoice'                   => array( 'new_invoice', 'user_invoice' ),
32
-				'getpaid_invoice_status_wpi-cancelled'  => 'cancelled_invoice',
33
-				'getpaid_invoice_status_wpi-failed'     => 'failed_invoice',
34
-				'getpaid_invoice_status_wpi-onhold'     => 'onhold_invoice',
35
-				'getpaid_invoice_status_wpi-processing' => 'processing_invoice',
36
-				'getpaid_invoice_status_publish'        => 'completed_invoice',
37
-				'getpaid_invoice_status_wpi-renewal'    => 'completed_invoice',
38
-				'getpaid_invoice_status_wpi-refunded'   => 'refunded_invoice',
39
-				'getpaid_new_customer_note'             => 'user_note',
40
-				'getpaid_daily_maintenance'             => 'overdue',
41
-			)
42
-		);
43
-
44
-		$this->init_hooks();
45
-
46
-	}
47
-
48
-	/**
49
-	 * Registers email hooks.
50
-	 */
51
-	public function init_hooks() {
52
-
53
-		add_filter( 'getpaid_get_email_merge_tags', array( $this, 'invoice_merge_tags' ), 10, 2 );
54
-		add_filter( 'getpaid_invoice_email_recipients', array( $this, 'filter_email_recipients' ), 10, 2 );
55
-
56
-		foreach ( $this->invoice_actions as $hook => $email_type ) {
57
-			$this->init_email_type_hook( $hook, $email_type );
58
-		}
59
-	}
60
-
61
-	/**
62
-	 * Registers an email hook for an invoice action.
63
-	 *
64
-	 * @param string $hook
65
-	 * @param string|array $email_type
66
-	 */
67
-	public function init_email_type_hook( $hook, $email_type ) {
68
-
69
-		$email_type = wpinv_parse_list( $email_type );
70
-
71
-		foreach ( $email_type as $type ) {
72
-
73
-			$email = new GetPaid_Notification_Email( $type );
74
-
75
-			// Abort if it is not active.
76
-			if ( ! $email->is_active() ) {
77
-				continue;
78
-			}
79
-
80
-			if ( method_exists( $this, $type ) ) {
81
-				add_action( $hook, array( $this, $type ), 100, 2 );
82
-				continue;
83
-			}
84
-
85
-			do_action( 'getpaid_invoice_init_email_type_hook', $type, $hook );
86
-		}
87
-
88
-	}
89
-
90
-	/**
91
-	 * Filters invoice merge tags.
92
-	 *
93
-	 * @param array $merge_tags
94
-	 * @param mixed|WPInv_Invoice|WPInv_Subscription $object
95
-	 */
96
-	public function invoice_merge_tags( $merge_tags, $object ) {
97
-
98
-		if ( is_a( $object, 'WPInv_Invoice' ) ) {
99
-			return array_merge(
100
-				$merge_tags,
101
-				$this->get_invoice_merge_tags( $object )
102
-			);
103
-		}
104
-
105
-		if ( is_a( $object, 'WPInv_Subscription' ) ) {
106
-			return array_merge(
107
-				$merge_tags,
108
-				$this->get_invoice_merge_tags( $object->get_parent_payment() )
109
-			);
110
-		}
111
-
112
-		return $merge_tags;
113
-
114
-	}
115
-
116
-	/**
117
-	 * Generates invoice merge tags.
118
-	 *
119
-	 * @param WPInv_Invoice $invoice
120
-	 * @return array
121
-	 */
122
-	public function get_invoice_merge_tags( $invoice ) {
123
-
124
-		// Abort if it does not exist.
125
-		if ( ! $invoice->get_id() ) {
126
-			return array();
127
-		}
128
-
129
-		$due_date   = $invoice->get_due_date();
130
-		$due_date   = empty( $due_date ) ? time() + MINUTE_IN_SECONDS : strtotime( $due_date ) + ( (int) get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
131
-		$merge_tags = array(
132
-			'{name}'                 => sanitize_text_field( $invoice->get_user_full_name() ),
133
-			'{full_name}'            => sanitize_text_field( $invoice->get_user_full_name() ),
134
-			'{first_name}'           => sanitize_text_field( $invoice->get_first_name() ),
135
-			'{last_name}'            => sanitize_text_field( $invoice->get_last_name() ),
136
-			'{email}'                => sanitize_email( $invoice->get_email() ),
137
-			'{invoice_number}'       => sanitize_text_field( $invoice->get_number() ),
138
-			'{invoice_currency}'     => sanitize_text_field( $invoice->get_currency() ),
139
-			'{invoice_total}'        => sanitize_text_field( wpinv_price( $invoice->get_total(), $invoice->get_currency() ) ),
140
-			'{invoice_link}'         => esc_url( $invoice->get_view_url() ),
141
-			'{invoice_pay_link}'     => esc_url( $invoice->get_checkout_payment_url() ),
142
-			'{invoice_receipt_link}' => esc_url( $invoice->get_receipt_url() ),
143
-			'{invoice_date}'         => getpaid_format_date_value( $invoice->get_date_created() ),
144
-			'{invoice_due_date}'     => getpaid_format_date_value( $invoice->get_due_date(), __( 'on receipt', 'invoicing' ) ),
145
-			'{invoice_quote}'        => sanitize_text_field( strtolower( $invoice->get_label() ) ),
146
-			'{invoice_label}'        => sanitize_text_field( ucfirst( $invoice->get_label() ) ),
147
-			'{invoice_description}'  => wp_kses_post( $invoice->get_description() ),
148
-			'{subscription_name}'    => wp_kses_post( $invoice->get_subscription_name() ),
149
-			'{is_was}'               => $due_date < time() ? __( 'was', 'invoicing' ) : __( 'is', 'invoicing' ),
150
-		);
151
-
152
-		$payment_form_data = $invoice->get_meta( 'payment_form_data', true );
153
-
154
-		if ( is_array( $payment_form_data ) ) {
155
-
156
-			foreach ( $payment_form_data as $label => $value ) {
157
-
158
-				$label = preg_replace( '/[^a-z0-9]+/', '_', strtolower( $label ) );
159
-				$value = is_array( $value ) ? implode( ', ', $value ) : $value;
160
-
161
-				if ( is_scalar( $value ) ) {
162
-					$merge_tags[ "{{$label}}" ] = wp_kses_post( $value );
163
-				}
164
-			}
165
-		}
166
-
167
-		return apply_filters( 'getpaid_invoice_email_merge_tags', $merge_tags, $invoice );
168
-	}
169
-
170
-	/**
171
-	 * Helper function to send an email.
172
-	 *
173
-	 * @param WPInv_Invoice $invoice
174
-	 * @param GetPaid_Notification_Email $email
175
-	 * @param string $type
176
-	 * @param string|array $recipients
177
-	 * @param array $extra_args Extra template args.
178
-	 */
179
-	public function send_email( $invoice, $email, $type, $recipients, $extra_args = array() ) {
180
-
181
-		do_action( 'getpaid_before_send_invoice_notification', $type, $invoice, $email );
182
-
183
-		$skip = $invoice->is_free() && wpinv_get_option( 'skip_email_free_invoice' );
184
-		if ( apply_filters( 'getpaid_skip_invoice_email', $skip, $type, $invoice ) ) {
185
-			return;
186
-		}
187
-
188
-		$mailer     = new GetPaid_Notification_Email_Sender();
189
-		$merge_tags = $email->get_merge_tags();
190
-
191
-		$result = $mailer->send(
192
-			apply_filters( 'getpaid_invoice_email_recipients', wpinv_parse_list( $recipients ), $email ),
193
-			$email->add_merge_tags( $email->get_subject(), $merge_tags ),
194
-			$email->get_content( $merge_tags, $extra_args ),
195
-			$email->get_attachments()
196
-		);
197
-
198
-		// Maybe send a copy to the admin.
199
-		if ( $email->include_admin_bcc() ) {
200
-			$mailer->send(
201
-				wpinv_get_admin_email(),
202
-				$email->add_merge_tags( $email->get_subject() . __( ' - ADMIN BCC COPY', 'invoicing' ), $merge_tags ),
203
-				$email->get_content( $merge_tags ),
204
-				$email->get_attachments()
205
-			);
206
-		}
207
-
208
-		if ( $result ) {
209
-			$invoice->add_system_note(
210
-				sprintf(
211
-					// translators: %1 is the email type, %2 is the invoice recipient.
212
-					__( 'Successfully sent %1$s notification email to %2$s.', 'invoicing' ),
213
-					sanitize_key( $type ),
214
-					$email->is_admin_email() ? __( 'admin', 'invoicing' ) : __( 'the customer', 'invoicing' )
215
-				)
216
-			);
217
-		} else {
218
-			$invoice->add_system_note(
219
-				sprintf(
220
-					// translators: %1 is the email type, %2 is the invoice recipient.
221
-					__( 'Failed sending %1$s notification email to %2$s.', 'invoicing' ),
222
-					sanitize_key( $type ),
223
-					$email->is_admin_email() ? __( 'admin', 'invoicing' ) : __( 'the customer', 'invoicing' )
224
-				)
225
-			);
226
-		}
227
-
228
-		do_action( 'getpaid_after_send_invoice_notification', $type, $invoice, $email );
229
-
230
-		return $result;
231
-	}
232
-
233
-	/**
234
-	 * Also send emails to any cc users.
235
-	 *
236
-	 * @param array $recipients
237
-	 * @param GetPaid_Notification_Email $email
238
-	 */
239
-	public function filter_email_recipients( $recipients, $email ) {
240
-
241
-		if ( ! $email->is_admin_email() ) {
242
-			$cc   = $email->object->get_email_cc();
243
-			$cc_2 = get_user_meta( $email->object->get_user_id(), '_wpinv_email_cc', true );
244
-
245
-			if ( ! empty( $cc ) ) {
246
-				$cc = array_map( 'sanitize_email', wpinv_parse_list( $cc ) );
247
-				$recipients = array_filter( array_unique( array_merge( $recipients, $cc ) ) );
248
-			}
249
-
250
-			if ( ! empty( $cc_2 ) ) {
251
-				$cc_2 = array_map( 'sanitize_email', wpinv_parse_list( $cc_2 ) );
252
-				$recipients = array_filter( array_unique( array_merge( $recipients, $cc_2 ) ) );
253
-			}
254
-		}
255
-
256
-		return $recipients;
257
-
258
-	}
259
-
260
-	/**
261
-	 * Sends a new invoice notification.
262
-	 *
263
-	 * @param WPInv_Invoice $invoice
264
-	 */
265
-	public function new_invoice( $invoice ) {
266
-
267
-		// Only send this email for invoices created via the admin page.
268
-		if ( ! $invoice->is_type( 'invoice' ) || $invoice->is_paid() || $this->is_payment_form_invoice( $invoice->get_id() ) ) {
269
-			return;
270
-		}
271
-
272
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
273
-		$recipient = wpinv_get_admin_email();
274
-
275
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
276
-
277
-	}
278
-
279
-	/**
280
-	 * Sends a cancelled invoice notification.
281
-	 *
282
-	 * @param WPInv_Invoice $invoice
283
-	 */
284
-	public function cancelled_invoice( $invoice ) {
285
-
286
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
287
-		$recipient = $invoice->get_email();
288
-
289
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
290
-	}
291
-
292
-	/**
293
-	 * Sends a failed invoice notification.
294
-	 *
295
-	 * @param WPInv_Invoice $invoice
296
-	 */
297
-	public function failed_invoice( $invoice ) {
298
-
299
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
300
-		$recipient = wpinv_get_admin_email();
301
-
302
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
303
-
304
-	}
305
-
306
-	/**
307
-	 * Sends a notification whenever an invoice is put on hold.
308
-	 *
309
-	 * @param WPInv_Invoice $invoice
310
-	 */
311
-	public function onhold_invoice( $invoice ) {
312
-
313
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
314
-		$recipient = $invoice->get_email();
315
-
316
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
317
-
318
-	}
319
-
320
-	/**
321
-	 * Sends a notification whenever an invoice is marked as processing payment.
322
-	 *
323
-	 * @param WPInv_Invoice $invoice
324
-	 */
325
-	public function processing_invoice( $invoice ) {
326
-
327
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
328
-		$recipient = $invoice->get_email();
329
-
330
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
331
-
332
-	}
333
-
334
-	/**
335
-	 * Sends a notification whenever an invoice is paid.
336
-	 *
337
-	 * @param WPInv_Invoice $invoice
338
-	 */
339
-	public function completed_invoice( $invoice ) {
340
-
341
-		// (Maybe) abort if it is a renewal invoice.
342
-		if ( $invoice->is_renewal() && ! wpinv_get_option( 'email_completed_invoice_renewal_active', false ) ) {
343
-			return;
344
-		}
345
-
346
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
347
-		$recipient = $invoice->get_email();
348
-
349
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
350
-
351
-	}
15
+    /**
16
+     * The array of invoice email actions.
17
+     *
18
+     * @param array
19
+     */
20
+    public $invoice_actions;
21
+
22
+    /**
23
+     * Class constructor
24
+     *
25
+     */
26
+    public function __construct() {
27
+
28
+        $this->invoice_actions = apply_filters(
29
+            'getpaid_notification_email_invoice_triggers',
30
+            array(
31
+                'getpaid_new_invoice'                   => array( 'new_invoice', 'user_invoice' ),
32
+                'getpaid_invoice_status_wpi-cancelled'  => 'cancelled_invoice',
33
+                'getpaid_invoice_status_wpi-failed'     => 'failed_invoice',
34
+                'getpaid_invoice_status_wpi-onhold'     => 'onhold_invoice',
35
+                'getpaid_invoice_status_wpi-processing' => 'processing_invoice',
36
+                'getpaid_invoice_status_publish'        => 'completed_invoice',
37
+                'getpaid_invoice_status_wpi-renewal'    => 'completed_invoice',
38
+                'getpaid_invoice_status_wpi-refunded'   => 'refunded_invoice',
39
+                'getpaid_new_customer_note'             => 'user_note',
40
+                'getpaid_daily_maintenance'             => 'overdue',
41
+            )
42
+        );
43
+
44
+        $this->init_hooks();
45
+
46
+    }
47
+
48
+    /**
49
+     * Registers email hooks.
50
+     */
51
+    public function init_hooks() {
52
+
53
+        add_filter( 'getpaid_get_email_merge_tags', array( $this, 'invoice_merge_tags' ), 10, 2 );
54
+        add_filter( 'getpaid_invoice_email_recipients', array( $this, 'filter_email_recipients' ), 10, 2 );
55
+
56
+        foreach ( $this->invoice_actions as $hook => $email_type ) {
57
+            $this->init_email_type_hook( $hook, $email_type );
58
+        }
59
+    }
60
+
61
+    /**
62
+     * Registers an email hook for an invoice action.
63
+     *
64
+     * @param string $hook
65
+     * @param string|array $email_type
66
+     */
67
+    public function init_email_type_hook( $hook, $email_type ) {
68
+
69
+        $email_type = wpinv_parse_list( $email_type );
70
+
71
+        foreach ( $email_type as $type ) {
72
+
73
+            $email = new GetPaid_Notification_Email( $type );
74
+
75
+            // Abort if it is not active.
76
+            if ( ! $email->is_active() ) {
77
+                continue;
78
+            }
79
+
80
+            if ( method_exists( $this, $type ) ) {
81
+                add_action( $hook, array( $this, $type ), 100, 2 );
82
+                continue;
83
+            }
84
+
85
+            do_action( 'getpaid_invoice_init_email_type_hook', $type, $hook );
86
+        }
87
+
88
+    }
89
+
90
+    /**
91
+     * Filters invoice merge tags.
92
+     *
93
+     * @param array $merge_tags
94
+     * @param mixed|WPInv_Invoice|WPInv_Subscription $object
95
+     */
96
+    public function invoice_merge_tags( $merge_tags, $object ) {
97
+
98
+        if ( is_a( $object, 'WPInv_Invoice' ) ) {
99
+            return array_merge(
100
+                $merge_tags,
101
+                $this->get_invoice_merge_tags( $object )
102
+            );
103
+        }
104
+
105
+        if ( is_a( $object, 'WPInv_Subscription' ) ) {
106
+            return array_merge(
107
+                $merge_tags,
108
+                $this->get_invoice_merge_tags( $object->get_parent_payment() )
109
+            );
110
+        }
111
+
112
+        return $merge_tags;
113
+
114
+    }
115
+
116
+    /**
117
+     * Generates invoice merge tags.
118
+     *
119
+     * @param WPInv_Invoice $invoice
120
+     * @return array
121
+     */
122
+    public function get_invoice_merge_tags( $invoice ) {
123
+
124
+        // Abort if it does not exist.
125
+        if ( ! $invoice->get_id() ) {
126
+            return array();
127
+        }
128
+
129
+        $due_date   = $invoice->get_due_date();
130
+        $due_date   = empty( $due_date ) ? time() + MINUTE_IN_SECONDS : strtotime( $due_date ) + ( (int) get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
131
+        $merge_tags = array(
132
+            '{name}'                 => sanitize_text_field( $invoice->get_user_full_name() ),
133
+            '{full_name}'            => sanitize_text_field( $invoice->get_user_full_name() ),
134
+            '{first_name}'           => sanitize_text_field( $invoice->get_first_name() ),
135
+            '{last_name}'            => sanitize_text_field( $invoice->get_last_name() ),
136
+            '{email}'                => sanitize_email( $invoice->get_email() ),
137
+            '{invoice_number}'       => sanitize_text_field( $invoice->get_number() ),
138
+            '{invoice_currency}'     => sanitize_text_field( $invoice->get_currency() ),
139
+            '{invoice_total}'        => sanitize_text_field( wpinv_price( $invoice->get_total(), $invoice->get_currency() ) ),
140
+            '{invoice_link}'         => esc_url( $invoice->get_view_url() ),
141
+            '{invoice_pay_link}'     => esc_url( $invoice->get_checkout_payment_url() ),
142
+            '{invoice_receipt_link}' => esc_url( $invoice->get_receipt_url() ),
143
+            '{invoice_date}'         => getpaid_format_date_value( $invoice->get_date_created() ),
144
+            '{invoice_due_date}'     => getpaid_format_date_value( $invoice->get_due_date(), __( 'on receipt', 'invoicing' ) ),
145
+            '{invoice_quote}'        => sanitize_text_field( strtolower( $invoice->get_label() ) ),
146
+            '{invoice_label}'        => sanitize_text_field( ucfirst( $invoice->get_label() ) ),
147
+            '{invoice_description}'  => wp_kses_post( $invoice->get_description() ),
148
+            '{subscription_name}'    => wp_kses_post( $invoice->get_subscription_name() ),
149
+            '{is_was}'               => $due_date < time() ? __( 'was', 'invoicing' ) : __( 'is', 'invoicing' ),
150
+        );
151
+
152
+        $payment_form_data = $invoice->get_meta( 'payment_form_data', true );
153
+
154
+        if ( is_array( $payment_form_data ) ) {
155
+
156
+            foreach ( $payment_form_data as $label => $value ) {
157
+
158
+                $label = preg_replace( '/[^a-z0-9]+/', '_', strtolower( $label ) );
159
+                $value = is_array( $value ) ? implode( ', ', $value ) : $value;
160
+
161
+                if ( is_scalar( $value ) ) {
162
+                    $merge_tags[ "{{$label}}" ] = wp_kses_post( $value );
163
+                }
164
+            }
165
+        }
166
+
167
+        return apply_filters( 'getpaid_invoice_email_merge_tags', $merge_tags, $invoice );
168
+    }
352 169
 
353
-	/**
354
-	 * Sends a notification whenever an invoice is refunded.
355
-	 *
356
-	 * @param WPInv_Invoice $invoice
357
-	 */
358
-	public function refunded_invoice( $invoice ) {
359
-
360
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
361
-		$recipient = $invoice->get_email();
362
-
363
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
364
-
365
-	}
170
+    /**
171
+     * Helper function to send an email.
172
+     *
173
+     * @param WPInv_Invoice $invoice
174
+     * @param GetPaid_Notification_Email $email
175
+     * @param string $type
176
+     * @param string|array $recipients
177
+     * @param array $extra_args Extra template args.
178
+     */
179
+    public function send_email( $invoice, $email, $type, $recipients, $extra_args = array() ) {
366 180
 
367
-	/**
368
-	 * Notifies a user about new invoices
369
-	 *
370
-	 * @param WPInv_Invoice $invoice
371
-	 * @param bool $force
372
-	 */
373
-	public function user_invoice( $invoice, $force = false ) {
181
+        do_action( 'getpaid_before_send_invoice_notification', $type, $invoice, $email );
374 182
 
375
-		if ( ! $force && ! empty( $GLOBALS['wpinv_skip_invoice_notification'] ) ) {
376
-			return;
377
-		}
378
-
379
-		// Only send this email for invoices created via the admin page.
380
-		if ( ! $invoice->is_type( 'invoice' ) || ( empty( $force ) && $invoice->is_paid() ) || ( empty( $force ) && $this->is_payment_form_invoice( $invoice->get_id() ) ) ) {
381
-			return;
382
-		}
383
-
384
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
385
-		$recipient = $invoice->get_email();
386
-
387
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
388
-
389
-	}
390
-
391
-	/**
392
-	 * Checks if an invoice is a payment form invoice.
393
-	 *
394
-	 * @param int $invoice
395
-	 * @return bool
396
-	 */
397
-	public function is_payment_form_invoice( $invoice ) {
398
-		$created_via             = get_post_meta( $invoice, 'wpinv_created_via', true );
399
-		$is_payment_form_invoice = 'payment_form' === $created_via || 'geodirectory' === $created_via;
400
-		$is_payment_form_invoice = apply_filters( 'getpaid_invoice_notifications_is_payment_form_invoice', $is_payment_form_invoice, $invoice );
401
-		return empty( $_GET['getpaid-admin-action'] ) && $is_payment_form_invoice;
402
-	}
403
-
404
-	/**
405
-	 * Notifies admin about new invoice notes
406
-	 *
407
-	 * @param WPInv_Invoice $invoice
408
-	 * @param string $note
409
-	 */
410
-	public function user_note( $invoice, $note ) {
411
-
412
-		$email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
413
-		$recipient = $invoice->get_email();
414
-
415
-		return $this->send_email( $invoice, $email, __FUNCTION__, $recipient, array( 'customer_note' => $note ) );
416
-
417
-	}
418
-
419
-	/**
420
-	 * (Force) Sends overdue notices.
421
-	 *
422
-	 * @param WPInv_Invoice $invoice
423
-	 */
424
-	public function force_send_overdue_notice( $invoice ) {
425
-		$email = new GetPaid_Notification_Email( 'overdue', $invoice );
426
-		return $this->send_email( $invoice, $email, 'overdue', $invoice->get_email() );
427
-	}
428
-
429
-	/**
430
-	 * Sends overdue notices.
431
-	 *
432
-	 * @TODO: Create an invoices query class.
433
-	 */
434
-	public function overdue() {
435
-		global $wpdb;
436
-
437
-		$email = new GetPaid_Notification_Email( __FUNCTION__ );
438
-
439
-		// Fetch reminder days.
440
-		$reminder_days = array_unique( wp_parse_id_list( $email->get_option( 'days' ) ) );
441
-
442
-		// Abort if non is set.
443
-		if ( empty( $reminder_days ) ) {
444
-			return;
445
-		}
446
-
447
-		// Retrieve date query.
448
-		$date_query = $this->get_date_query( $reminder_days );
449
-
450
-		// Invoices table.
451
-		$table = $wpdb->prefix . 'getpaid_invoices';
452
-
453
-		// Fetch invoices.
454
-		$invoices  = $wpdb->get_col(
455
-			"SELECT posts.ID FROM $wpdb->posts as posts
183
+        $skip = $invoice->is_free() && wpinv_get_option( 'skip_email_free_invoice' );
184
+        if ( apply_filters( 'getpaid_skip_invoice_email', $skip, $type, $invoice ) ) {
185
+            return;
186
+        }
187
+
188
+        $mailer     = new GetPaid_Notification_Email_Sender();
189
+        $merge_tags = $email->get_merge_tags();
190
+
191
+        $result = $mailer->send(
192
+            apply_filters( 'getpaid_invoice_email_recipients', wpinv_parse_list( $recipients ), $email ),
193
+            $email->add_merge_tags( $email->get_subject(), $merge_tags ),
194
+            $email->get_content( $merge_tags, $extra_args ),
195
+            $email->get_attachments()
196
+        );
197
+
198
+        // Maybe send a copy to the admin.
199
+        if ( $email->include_admin_bcc() ) {
200
+            $mailer->send(
201
+                wpinv_get_admin_email(),
202
+                $email->add_merge_tags( $email->get_subject() . __( ' - ADMIN BCC COPY', 'invoicing' ), $merge_tags ),
203
+                $email->get_content( $merge_tags ),
204
+                $email->get_attachments()
205
+            );
206
+        }
207
+
208
+        if ( $result ) {
209
+            $invoice->add_system_note(
210
+                sprintf(
211
+                    // translators: %1 is the email type, %2 is the invoice recipient.
212
+                    __( 'Successfully sent %1$s notification email to %2$s.', 'invoicing' ),
213
+                    sanitize_key( $type ),
214
+                    $email->is_admin_email() ? __( 'admin', 'invoicing' ) : __( 'the customer', 'invoicing' )
215
+                )
216
+            );
217
+        } else {
218
+            $invoice->add_system_note(
219
+                sprintf(
220
+                    // translators: %1 is the email type, %2 is the invoice recipient.
221
+                    __( 'Failed sending %1$s notification email to %2$s.', 'invoicing' ),
222
+                    sanitize_key( $type ),
223
+                    $email->is_admin_email() ? __( 'admin', 'invoicing' ) : __( 'the customer', 'invoicing' )
224
+                )
225
+            );
226
+        }
227
+
228
+        do_action( 'getpaid_after_send_invoice_notification', $type, $invoice, $email );
229
+
230
+        return $result;
231
+    }
232
+
233
+    /**
234
+     * Also send emails to any cc users.
235
+     *
236
+     * @param array $recipients
237
+     * @param GetPaid_Notification_Email $email
238
+     */
239
+    public function filter_email_recipients( $recipients, $email ) {
240
+
241
+        if ( ! $email->is_admin_email() ) {
242
+            $cc   = $email->object->get_email_cc();
243
+            $cc_2 = get_user_meta( $email->object->get_user_id(), '_wpinv_email_cc', true );
244
+
245
+            if ( ! empty( $cc ) ) {
246
+                $cc = array_map( 'sanitize_email', wpinv_parse_list( $cc ) );
247
+                $recipients = array_filter( array_unique( array_merge( $recipients, $cc ) ) );
248
+            }
249
+
250
+            if ( ! empty( $cc_2 ) ) {
251
+                $cc_2 = array_map( 'sanitize_email', wpinv_parse_list( $cc_2 ) );
252
+                $recipients = array_filter( array_unique( array_merge( $recipients, $cc_2 ) ) );
253
+            }
254
+        }
255
+
256
+        return $recipients;
257
+
258
+    }
259
+
260
+    /**
261
+     * Sends a new invoice notification.
262
+     *
263
+     * @param WPInv_Invoice $invoice
264
+     */
265
+    public function new_invoice( $invoice ) {
266
+
267
+        // Only send this email for invoices created via the admin page.
268
+        if ( ! $invoice->is_type( 'invoice' ) || $invoice->is_paid() || $this->is_payment_form_invoice( $invoice->get_id() ) ) {
269
+            return;
270
+        }
271
+
272
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
273
+        $recipient = wpinv_get_admin_email();
274
+
275
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
276
+
277
+    }
278
+
279
+    /**
280
+     * Sends a cancelled invoice notification.
281
+     *
282
+     * @param WPInv_Invoice $invoice
283
+     */
284
+    public function cancelled_invoice( $invoice ) {
285
+
286
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
287
+        $recipient = $invoice->get_email();
288
+
289
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
290
+    }
291
+
292
+    /**
293
+     * Sends a failed invoice notification.
294
+     *
295
+     * @param WPInv_Invoice $invoice
296
+     */
297
+    public function failed_invoice( $invoice ) {
298
+
299
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
300
+        $recipient = wpinv_get_admin_email();
301
+
302
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
303
+
304
+    }
305
+
306
+    /**
307
+     * Sends a notification whenever an invoice is put on hold.
308
+     *
309
+     * @param WPInv_Invoice $invoice
310
+     */
311
+    public function onhold_invoice( $invoice ) {
312
+
313
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
314
+        $recipient = $invoice->get_email();
315
+
316
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
317
+
318
+    }
319
+
320
+    /**
321
+     * Sends a notification whenever an invoice is marked as processing payment.
322
+     *
323
+     * @param WPInv_Invoice $invoice
324
+     */
325
+    public function processing_invoice( $invoice ) {
326
+
327
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
328
+        $recipient = $invoice->get_email();
329
+
330
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
331
+
332
+    }
333
+
334
+    /**
335
+     * Sends a notification whenever an invoice is paid.
336
+     *
337
+     * @param WPInv_Invoice $invoice
338
+     */
339
+    public function completed_invoice( $invoice ) {
340
+
341
+        // (Maybe) abort if it is a renewal invoice.
342
+        if ( $invoice->is_renewal() && ! wpinv_get_option( 'email_completed_invoice_renewal_active', false ) ) {
343
+            return;
344
+        }
345
+
346
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
347
+        $recipient = $invoice->get_email();
348
+
349
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
350
+
351
+    }
352
+
353
+    /**
354
+     * Sends a notification whenever an invoice is refunded.
355
+     *
356
+     * @param WPInv_Invoice $invoice
357
+     */
358
+    public function refunded_invoice( $invoice ) {
359
+
360
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
361
+        $recipient = $invoice->get_email();
362
+
363
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
364
+
365
+    }
366
+
367
+    /**
368
+     * Notifies a user about new invoices
369
+     *
370
+     * @param WPInv_Invoice $invoice
371
+     * @param bool $force
372
+     */
373
+    public function user_invoice( $invoice, $force = false ) {
374
+
375
+        if ( ! $force && ! empty( $GLOBALS['wpinv_skip_invoice_notification'] ) ) {
376
+            return;
377
+        }
378
+
379
+        // Only send this email for invoices created via the admin page.
380
+        if ( ! $invoice->is_type( 'invoice' ) || ( empty( $force ) && $invoice->is_paid() ) || ( empty( $force ) && $this->is_payment_form_invoice( $invoice->get_id() ) ) ) {
381
+            return;
382
+        }
383
+
384
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
385
+        $recipient = $invoice->get_email();
386
+
387
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient );
388
+
389
+    }
390
+
391
+    /**
392
+     * Checks if an invoice is a payment form invoice.
393
+     *
394
+     * @param int $invoice
395
+     * @return bool
396
+     */
397
+    public function is_payment_form_invoice( $invoice ) {
398
+        $created_via             = get_post_meta( $invoice, 'wpinv_created_via', true );
399
+        $is_payment_form_invoice = 'payment_form' === $created_via || 'geodirectory' === $created_via;
400
+        $is_payment_form_invoice = apply_filters( 'getpaid_invoice_notifications_is_payment_form_invoice', $is_payment_form_invoice, $invoice );
401
+        return empty( $_GET['getpaid-admin-action'] ) && $is_payment_form_invoice;
402
+    }
403
+
404
+    /**
405
+     * Notifies admin about new invoice notes
406
+     *
407
+     * @param WPInv_Invoice $invoice
408
+     * @param string $note
409
+     */
410
+    public function user_note( $invoice, $note ) {
411
+
412
+        $email     = new GetPaid_Notification_Email( __FUNCTION__, $invoice );
413
+        $recipient = $invoice->get_email();
414
+
415
+        return $this->send_email( $invoice, $email, __FUNCTION__, $recipient, array( 'customer_note' => $note ) );
416
+
417
+    }
418
+
419
+    /**
420
+     * (Force) Sends overdue notices.
421
+     *
422
+     * @param WPInv_Invoice $invoice
423
+     */
424
+    public function force_send_overdue_notice( $invoice ) {
425
+        $email = new GetPaid_Notification_Email( 'overdue', $invoice );
426
+        return $this->send_email( $invoice, $email, 'overdue', $invoice->get_email() );
427
+    }
428
+
429
+    /**
430
+     * Sends overdue notices.
431
+     *
432
+     * @TODO: Create an invoices query class.
433
+     */
434
+    public function overdue() {
435
+        global $wpdb;
436
+
437
+        $email = new GetPaid_Notification_Email( __FUNCTION__ );
438
+
439
+        // Fetch reminder days.
440
+        $reminder_days = array_unique( wp_parse_id_list( $email->get_option( 'days' ) ) );
441
+
442
+        // Abort if non is set.
443
+        if ( empty( $reminder_days ) ) {
444
+            return;
445
+        }
446
+
447
+        // Retrieve date query.
448
+        $date_query = $this->get_date_query( $reminder_days );
449
+
450
+        // Invoices table.
451
+        $table = $wpdb->prefix . 'getpaid_invoices';
452
+
453
+        // Fetch invoices.
454
+        $invoices  = $wpdb->get_col(
455
+            "SELECT posts.ID FROM $wpdb->posts as posts
456 456
 			LEFT JOIN $table as invoices ON invoices.post_id = posts.ID
457 457
 			WHERE posts.post_type = 'wpi_invoice' AND posts.post_status = 'wpi-pending' $date_query"
458 458
         );
459 459
 
460
-		foreach ( $invoices as $invoice ) {
460
+        foreach ( $invoices as $invoice ) {
461 461
 
462
-			// Only send this email for invoices created via the admin page.
463
-			if ( ! $this->is_payment_form_invoice( $invoice ) ) {
464
-				$invoice       = new WPInv_Invoice( $invoice );
465
-				$email->object = $invoice;
462
+            // Only send this email for invoices created via the admin page.
463
+            if ( ! $this->is_payment_form_invoice( $invoice ) ) {
464
+                $invoice       = new WPInv_Invoice( $invoice );
465
+                $email->object = $invoice;
466 466
 
467
-				if ( $invoice->needs_payment() && ! $invoice->is_renewal() ) {
468
-					$this->send_email( $invoice, $email, __FUNCTION__, $invoice->get_email() );
469
-				}
470
-			}
471
-		}
467
+                if ( $invoice->needs_payment() && ! $invoice->is_renewal() ) {
468
+                    $this->send_email( $invoice, $email, __FUNCTION__, $invoice->get_email() );
469
+                }
470
+            }
471
+        }
472 472
 
473
-	}
473
+    }
474 474
 
475
-	/**
476
-	 * Calculates the date query for an invoices query
477
-	 *
478
-	 * @param array $reminder_days
479
-	 * @return string
480
-	 */
481
-	public function get_date_query( $reminder_days ) {
475
+    /**
476
+     * Calculates the date query for an invoices query
477
+     *
478
+     * @param array $reminder_days
479
+     * @return string
480
+     */
481
+    public function get_date_query( $reminder_days ) {
482 482
 
483
-		$date_query = array(
484
-			'relation' => 'OR',
485
-		);
483
+        $date_query = array(
484
+            'relation' => 'OR',
485
+        );
486 486
 
487
-		foreach ( $reminder_days as $days ) {
488
-			$date = date_parse( date( 'Y-m-d', strtotime( "-$days days", current_time( 'timestamp' ) ) ) );
487
+        foreach ( $reminder_days as $days ) {
488
+            $date = date_parse( date( 'Y-m-d', strtotime( "-$days days", current_time( 'timestamp' ) ) ) );
489 489
 
490
-			$date_query[] = array(
491
-				'year'  => $date['year'],
492
-				'month' => $date['month'],
493
-				'day'   => $date['day'],
494
-			);
490
+            $date_query[] = array(
491
+                'year'  => $date['year'],
492
+                'month' => $date['month'],
493
+                'day'   => $date['day'],
494
+            );
495 495
 
496
-		}
496
+        }
497 497
 
498
-		$date_query = new WP_Date_Query( $date_query, 'invoices.due_date' );
498
+        $date_query = new WP_Date_Query( $date_query, 'invoices.due_date' );
499 499
 
500
-		return $date_query->get_sql();
500
+        return $date_query->get_sql();
501 501
 
502
-	}
502
+    }
503 503
 
504 504
 }
Please login to merge, or discard this patch.
includes/data-stores/class-getpaid-item-data-store.php 1 patch
Indentation   +210 added lines, -210 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
  *
5 5
  */
6 6
 if ( ! defined( 'ABSPATH' ) ) {
7
-	exit;
7
+    exit;
8 8
 }
9 9
 
10 10
 /**
@@ -14,228 +14,228 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class GetPaid_Item_Data_Store extends GetPaid_Data_Store_WP {
16 16
 
17
-	/**
18
-	 * Data stored in meta keys, but not considered "meta" for an item.
19
-	 *
20
-	 * @since 1.0.19
21
-	 * @var array
22
-	 */
23
-	protected $internal_meta_keys = array(
24
-		'_wpinv_price',
25
-		'_wpinv_vat_rule',
26
-		'_wpinv_vat_class',
27
-		'_wpinv_type',
28
-		'_wpinv_custom_id',
29
-		'_wpinv_custom_name',
30
-		'_wpinv_custom_singular_name',
31
-		'_wpinv_editable',
32
-		'_wpinv_dynamic_pricing',
33
-		'_minimum_price',
34
-		'_wpinv_is_recurring',
35
-		'_wpinv_recurring_period',
36
-		'_wpinv_recurring_interval',
37
-		'_wpinv_recurring_limit',
38
-		'_wpinv_free_trial',
39
-		'_wpinv_trial_period',
40
-		'_wpinv_trial_interval',
41
-	);
42
-
43
-	/**
44
-	 * A map of meta keys to data props.
45
-	 *
46
-	 * @since 1.0.19
47
-	 *
48
-	 * @var array
49
-	 */
50
-	protected $meta_key_to_props = array(
51
-		'_wpinv_price'                => 'price',
52
-		'_wpinv_vat_rule'             => 'vat_rule',
53
-		'_wpinv_vat_class'            => 'vat_class',
54
-		'_wpinv_type'                 => 'type',
55
-		'_wpinv_custom_id'            => 'custom_id',
56
-		'_wpinv_custom_name'          => 'custom_name',
57
-		'_wpinv_custom_singular_name' => 'custom_singular_name',
58
-		'_wpinv_editable'             => 'is_editable',
59
-		'_wpinv_dynamic_pricing'      => 'is_dynamic_pricing',
60
-		'_minimum_price'              => 'minimum_price',
61
-		'_wpinv_custom_name'          => 'custom_name',
62
-		'_wpinv_is_recurring'         => 'is_recurring',
63
-		'_wpinv_recurring_period'     => 'recurring_period',
64
-		'_wpinv_recurring_interval'   => 'recurring_interval',
65
-		'_wpinv_recurring_limit'      => 'recurring_limit',
66
-		'_wpinv_free_trial'           => 'is_free_trial',
67
-		'_wpinv_trial_period'         => 'trial_period',
68
-		'_wpinv_trial_interval'       => 'trial_interval',
69
-		'_wpinv_version'              => 'version',
70
-	);
71
-
72
-	/*
17
+    /**
18
+     * Data stored in meta keys, but not considered "meta" for an item.
19
+     *
20
+     * @since 1.0.19
21
+     * @var array
22
+     */
23
+    protected $internal_meta_keys = array(
24
+        '_wpinv_price',
25
+        '_wpinv_vat_rule',
26
+        '_wpinv_vat_class',
27
+        '_wpinv_type',
28
+        '_wpinv_custom_id',
29
+        '_wpinv_custom_name',
30
+        '_wpinv_custom_singular_name',
31
+        '_wpinv_editable',
32
+        '_wpinv_dynamic_pricing',
33
+        '_minimum_price',
34
+        '_wpinv_is_recurring',
35
+        '_wpinv_recurring_period',
36
+        '_wpinv_recurring_interval',
37
+        '_wpinv_recurring_limit',
38
+        '_wpinv_free_trial',
39
+        '_wpinv_trial_period',
40
+        '_wpinv_trial_interval',
41
+    );
42
+
43
+    /**
44
+     * A map of meta keys to data props.
45
+     *
46
+     * @since 1.0.19
47
+     *
48
+     * @var array
49
+     */
50
+    protected $meta_key_to_props = array(
51
+        '_wpinv_price'                => 'price',
52
+        '_wpinv_vat_rule'             => 'vat_rule',
53
+        '_wpinv_vat_class'            => 'vat_class',
54
+        '_wpinv_type'                 => 'type',
55
+        '_wpinv_custom_id'            => 'custom_id',
56
+        '_wpinv_custom_name'          => 'custom_name',
57
+        '_wpinv_custom_singular_name' => 'custom_singular_name',
58
+        '_wpinv_editable'             => 'is_editable',
59
+        '_wpinv_dynamic_pricing'      => 'is_dynamic_pricing',
60
+        '_minimum_price'              => 'minimum_price',
61
+        '_wpinv_custom_name'          => 'custom_name',
62
+        '_wpinv_is_recurring'         => 'is_recurring',
63
+        '_wpinv_recurring_period'     => 'recurring_period',
64
+        '_wpinv_recurring_interval'   => 'recurring_interval',
65
+        '_wpinv_recurring_limit'      => 'recurring_limit',
66
+        '_wpinv_free_trial'           => 'is_free_trial',
67
+        '_wpinv_trial_period'         => 'trial_period',
68
+        '_wpinv_trial_interval'       => 'trial_interval',
69
+        '_wpinv_version'              => 'version',
70
+    );
71
+
72
+    /*
73 73
 	|--------------------------------------------------------------------------
74 74
 	| CRUD Methods
75 75
 	|--------------------------------------------------------------------------
76 76
 	*/
77 77
 
78
-	/**
79
-	 * Method to create a new item in the database.
80
-	 *
81
-	 * @param WPInv_Item $item Item object.
82
-	 */
83
-	public function create( &$item ) {
84
-		$item->set_version( WPINV_VERSION );
85
-		$item->set_date_created( current_time( 'mysql' ) );
86
-
87
-		// Create a new post.
88
-		$id = wp_insert_post(
89
-			apply_filters(
90
-				'getpaid_new_item_data',
91
-				array(
92
-					'post_date'    => $item->get_date_created( 'edit' ),
93
-					'post_type'    => 'wpi_item',
94
-					'post_status'  => $this->get_post_status( $item ),
95
-					'ping_status'  => 'closed',
96
-					'post_author'  => $item->get_author( 'edit' ),
97
-					'post_title'   => $item->get_name( 'edit' ),
98
-					'post_parent'  => $item->get_parent_id(),
99
-					'post_excerpt' => $item->get_description( 'edit' ),
100
-				)
101
-			),
102
-			true
103
-		);
104
-
105
-		if ( $id && ! is_wp_error( $id ) ) {
106
-			$item->set_id( $id );
107
-			$this->update_post_meta( $item );
108
-			$item->save_meta_data();
109
-			$item->apply_changes();
110
-			$this->clear_caches( $item );
111
-			do_action( 'getpaid_new_item', $item );
112
-			return true;
113
-		}
114
-
115
-		if ( is_wp_error( $id ) ) {
116
-			$item->last_error = $id->get_error_message();
117
-		}
118
-
119
-		return false;
120
-	}
121
-
122
-	/**
123
-	 * Method to read an item from the database.
124
-	 *
125
-	 * @param WPInv_Item $item Item object.
126
-	 *
127
-	 */
128
-	public function read( &$item ) {
129
-
130
-		$item->set_defaults();
131
-		$item_object = get_post( $item->get_id() );
132
-
133
-		if ( ! $item->get_id() || ! $item_object || $item_object->post_type != 'wpi_item' ) {
134
-			$item->last_error = __( 'Invalid item.', 'invoicing' );
135
-			$item->set_id( 0 );
136
-			return false;
137
-		}
138
-
139
-		$item->set_props(
140
-			array(
141
-				'parent_id'     => $item_object->post_parent,
142
-				'date_created'  => 0 < $item_object->post_date ? $item_object->post_date : null,
143
-				'date_modified' => 0 < $item_object->post_modified ? $item_object->post_modified : null,
144
-				'status'        => $item_object->post_status,
145
-				'name'          => $item_object->post_title,
146
-				'description'   => $item_object->post_excerpt,
147
-				'author'        => $item_object->post_author,
148
-			)
149
-		);
150
-
151
-		$this->read_object_data( $item, $item_object );
152
-		$item->read_meta_data();
153
-		$item->set_object_read( true );
154
-		do_action( 'getpaid_read_item', $item );
155
-
156
-	}
157
-
158
-	/**
159
-	 * Method to update an item in the database.
160
-	 *
161
-	 * @param WPInv_Item $item Item object.
162
-	 */
163
-	public function update( &$item ) {
164
-		$item->save_meta_data();
165
-		$item->set_version( WPINV_VERSION );
166
-
167
-		if ( null === $item->get_date_created( 'edit' ) ) {
168
-			$item->set_date_created( current_time( 'mysql' ) );
169
-		}
170
-
171
-		// Grab the current status so we can compare.
172
-		$previous_status = get_post_status( $item->get_id() );
173
-
174
-		$changes = $item->get_changes();
175
-
176
-		// Only update the post when the post data changes.
177
-		if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'description', 'name', 'author' ), array_keys( $changes ) ) ) {
178
-			$post_data = array(
179
-				'post_date'     => $item->get_date_created( 'edit' ),
180
-				'post_status'   => $item->get_status( 'edit' ),
181
-				'post_parent'   => $item->get_parent_id( 'edit' ),
182
-				'post_excerpt'  => $item->get_description( 'edit' ),
183
-				'post_modified' => $item->get_date_modified( 'edit' ),
184
-				'post_title'    => $item->get_name( 'edit' ),
185
-				'post_author'   => $item->get_author( 'edit' ),
186
-			);
187
-
188
-			/**
189
-			 * When updating this object, to prevent infinite loops, use $wpdb
190
-			 * to update data, since wp_update_post spawns more calls to the
191
-			 * save_post action.
192
-			 *
193
-			 * This ensures hooks are fired by either WP itself (admin screen save),
194
-			 * or an update purely from CRUD.
195
-			 */
196
-			if ( doing_action( 'save_post' ) ) {
197
-				$GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $item->get_id() ) );
198
-				clean_post_cache( $item->get_id() );
199
-			} else {
200
-				wp_update_post( array_merge( array( 'ID' => $item->get_id() ), $post_data ) );
201
-			}
202
-			$item->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
203
-		}
204
-		$this->update_post_meta( $item );
205
-		$item->apply_changes();
206
-		$this->clear_caches( $item );
207
-
208
-		// Fire a hook depending on the status - this should be considered a creation if it was previously draft status.
209
-		$new_status = $item->get_status( 'edit' );
210
-
211
-		if ( $new_status !== $previous_status && in_array( $previous_status, array( 'new', 'auto-draft', 'draft' ), true ) ) {
212
-			do_action( 'getpaid_new_item', $item );
213
-		} else {
214
-			do_action( 'getpaid_update_item', $item );
215
-		}
216
-
217
-	}
218
-
219
-	/*
78
+    /**
79
+     * Method to create a new item in the database.
80
+     *
81
+     * @param WPInv_Item $item Item object.
82
+     */
83
+    public function create( &$item ) {
84
+        $item->set_version( WPINV_VERSION );
85
+        $item->set_date_created( current_time( 'mysql' ) );
86
+
87
+        // Create a new post.
88
+        $id = wp_insert_post(
89
+            apply_filters(
90
+                'getpaid_new_item_data',
91
+                array(
92
+                    'post_date'    => $item->get_date_created( 'edit' ),
93
+                    'post_type'    => 'wpi_item',
94
+                    'post_status'  => $this->get_post_status( $item ),
95
+                    'ping_status'  => 'closed',
96
+                    'post_author'  => $item->get_author( 'edit' ),
97
+                    'post_title'   => $item->get_name( 'edit' ),
98
+                    'post_parent'  => $item->get_parent_id(),
99
+                    'post_excerpt' => $item->get_description( 'edit' ),
100
+                )
101
+            ),
102
+            true
103
+        );
104
+
105
+        if ( $id && ! is_wp_error( $id ) ) {
106
+            $item->set_id( $id );
107
+            $this->update_post_meta( $item );
108
+            $item->save_meta_data();
109
+            $item->apply_changes();
110
+            $this->clear_caches( $item );
111
+            do_action( 'getpaid_new_item', $item );
112
+            return true;
113
+        }
114
+
115
+        if ( is_wp_error( $id ) ) {
116
+            $item->last_error = $id->get_error_message();
117
+        }
118
+
119
+        return false;
120
+    }
121
+
122
+    /**
123
+     * Method to read an item from the database.
124
+     *
125
+     * @param WPInv_Item $item Item object.
126
+     *
127
+     */
128
+    public function read( &$item ) {
129
+
130
+        $item->set_defaults();
131
+        $item_object = get_post( $item->get_id() );
132
+
133
+        if ( ! $item->get_id() || ! $item_object || $item_object->post_type != 'wpi_item' ) {
134
+            $item->last_error = __( 'Invalid item.', 'invoicing' );
135
+            $item->set_id( 0 );
136
+            return false;
137
+        }
138
+
139
+        $item->set_props(
140
+            array(
141
+                'parent_id'     => $item_object->post_parent,
142
+                'date_created'  => 0 < $item_object->post_date ? $item_object->post_date : null,
143
+                'date_modified' => 0 < $item_object->post_modified ? $item_object->post_modified : null,
144
+                'status'        => $item_object->post_status,
145
+                'name'          => $item_object->post_title,
146
+                'description'   => $item_object->post_excerpt,
147
+                'author'        => $item_object->post_author,
148
+            )
149
+        );
150
+
151
+        $this->read_object_data( $item, $item_object );
152
+        $item->read_meta_data();
153
+        $item->set_object_read( true );
154
+        do_action( 'getpaid_read_item', $item );
155
+
156
+    }
157
+
158
+    /**
159
+     * Method to update an item in the database.
160
+     *
161
+     * @param WPInv_Item $item Item object.
162
+     */
163
+    public function update( &$item ) {
164
+        $item->save_meta_data();
165
+        $item->set_version( WPINV_VERSION );
166
+
167
+        if ( null === $item->get_date_created( 'edit' ) ) {
168
+            $item->set_date_created( current_time( 'mysql' ) );
169
+        }
170
+
171
+        // Grab the current status so we can compare.
172
+        $previous_status = get_post_status( $item->get_id() );
173
+
174
+        $changes = $item->get_changes();
175
+
176
+        // Only update the post when the post data changes.
177
+        if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'description', 'name', 'author' ), array_keys( $changes ) ) ) {
178
+            $post_data = array(
179
+                'post_date'     => $item->get_date_created( 'edit' ),
180
+                'post_status'   => $item->get_status( 'edit' ),
181
+                'post_parent'   => $item->get_parent_id( 'edit' ),
182
+                'post_excerpt'  => $item->get_description( 'edit' ),
183
+                'post_modified' => $item->get_date_modified( 'edit' ),
184
+                'post_title'    => $item->get_name( 'edit' ),
185
+                'post_author'   => $item->get_author( 'edit' ),
186
+            );
187
+
188
+            /**
189
+             * When updating this object, to prevent infinite loops, use $wpdb
190
+             * to update data, since wp_update_post spawns more calls to the
191
+             * save_post action.
192
+             *
193
+             * This ensures hooks are fired by either WP itself (admin screen save),
194
+             * or an update purely from CRUD.
195
+             */
196
+            if ( doing_action( 'save_post' ) ) {
197
+                $GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $item->get_id() ) );
198
+                clean_post_cache( $item->get_id() );
199
+            } else {
200
+                wp_update_post( array_merge( array( 'ID' => $item->get_id() ), $post_data ) );
201
+            }
202
+            $item->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
203
+        }
204
+        $this->update_post_meta( $item );
205
+        $item->apply_changes();
206
+        $this->clear_caches( $item );
207
+
208
+        // Fire a hook depending on the status - this should be considered a creation if it was previously draft status.
209
+        $new_status = $item->get_status( 'edit' );
210
+
211
+        if ( $new_status !== $previous_status && in_array( $previous_status, array( 'new', 'auto-draft', 'draft' ), true ) ) {
212
+            do_action( 'getpaid_new_item', $item );
213
+        } else {
214
+            do_action( 'getpaid_update_item', $item );
215
+        }
216
+
217
+    }
218
+
219
+    /*
220 220
 	|--------------------------------------------------------------------------
221 221
 	| Additional Methods
222 222
 	|--------------------------------------------------------------------------
223 223
 	*/
224 224
 
225
-	/**
226
-	 * Helper method that updates all the post meta for an item based on it's settings in the WPInv_Item class.
227
-	 *
228
-	 * @param WPInv_Item $item WPInv_Item object.
229
-	 * @since 1.0.19
230
-	 */
231
-	protected function update_post_meta( &$item ) {
225
+    /**
226
+     * Helper method that updates all the post meta for an item based on it's settings in the WPInv_Item class.
227
+     *
228
+     * @param WPInv_Item $item WPInv_Item object.
229
+     * @since 1.0.19
230
+     */
231
+    protected function update_post_meta( &$item ) {
232 232
 
233
-		// Ensure that we have a custom id.
233
+        // Ensure that we have a custom id.
234 234
         if ( ! $item->get_custom_id() ) {
235 235
             $item->set_custom_id( $item->get_id() );
236
-		}
236
+        }
237 237
 
238
-		parent::update_post_meta( $item );
239
-	}
238
+        parent::update_post_meta( $item );
239
+    }
240 240
 
241 241
 }
Please login to merge, or discard this patch.
includes/payments/class-getpaid-payment-form-submission.php 1 patch
Indentation   +878 added lines, -878 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,199 +10,199 @@  discard block
 block discarded – undo
10 10
 class GetPaid_Payment_Form_Submission {
11 11
 
12 12
     /**
13
-	 * Submission ID
14
-	 *
15
-	 * @var string
16
-	 */
17
-	public $id = null;
18
-
19
-	/**
20
-	 * The raw submission data.
21
-	 *
22
-	 * @var array
23
-	 */
24
-	protected $data = null;
25
-
26
-	/**
27
-	 * Submission totals
28
-	 *
29
-	 * @var array
30
-	 */
31
-	protected $totals = array(
32
-
33
-		'subtotal' => array(
34
-			'initial'   => 0,
35
-			'recurring' => 0,
36
-		),
37
-
38
-		'discount' => array(
39
-			'initial'   => 0,
40
-			'recurring' => 0,
41
-		),
42
-
43
-		'fees'     => array(
44
-			'initial'   => 0,
45
-			'recurring' => 0,
46
-		),
47
-
48
-		'taxes'    => array(
49
-			'initial'   => 0,
50
-			'recurring' => 0,
51
-		),
52
-
53
-		'shipping' => array(
54
-			'initial'   => 0,
55
-			'recurring' => 0,
56
-		),
57
-
58
-	);
59
-
60
-	/**
61
-	 * Sets the associated payment form.
62
-	 *
63
-	 * @var GetPaid_Payment_Form
64
-	 */
13
+     * Submission ID
14
+     *
15
+     * @var string
16
+     */
17
+    public $id = null;
18
+
19
+    /**
20
+     * The raw submission data.
21
+     *
22
+     * @var array
23
+     */
24
+    protected $data = null;
25
+
26
+    /**
27
+     * Submission totals
28
+     *
29
+     * @var array
30
+     */
31
+    protected $totals = array(
32
+
33
+        'subtotal' => array(
34
+            'initial'   => 0,
35
+            'recurring' => 0,
36
+        ),
37
+
38
+        'discount' => array(
39
+            'initial'   => 0,
40
+            'recurring' => 0,
41
+        ),
42
+
43
+        'fees'     => array(
44
+            'initial'   => 0,
45
+            'recurring' => 0,
46
+        ),
47
+
48
+        'taxes'    => array(
49
+            'initial'   => 0,
50
+            'recurring' => 0,
51
+        ),
52
+
53
+        'shipping' => array(
54
+            'initial'   => 0,
55
+            'recurring' => 0,
56
+        ),
57
+
58
+    );
59
+
60
+    /**
61
+     * Sets the associated payment form.
62
+     *
63
+     * @var GetPaid_Payment_Form
64
+     */
65 65
     protected $payment_form = null;
66 66
 
67 67
     /**
68
-	 * The country for the submission.
69
-	 *
70
-	 * @var string
71
-	 */
72
-	public $country = null;
73
-
74
-    /**
75
-	 * The state for the submission.
76
-	 *
77
-	 * @since 1.0.19
78
-	 * @var string
79
-	 */
80
-	public $state = null;
81
-
82
-	/**
83
-	 * The invoice associated with the submission.
84
-	 *
85
-	 * @var WPInv_Invoice
86
-	 */
87
-	protected $invoice = null;
88
-
89
-	/**
90
-	 * The recurring item for the submission.
91
-	 *
92
-	 * @var int
93
-	 */
94
-	public $has_recurring = 0;
95
-
96
-	/**
97
-	 * An array of fees for the submission.
98
-	 *
99
-	 * @var array
100
-	 */
101
-	protected $fees = array();
102
-
103
-	/**
104
-	 * An array of discounts for the submission.
105
-	 *
106
-	 * @var array
107
-	 */
108
-	protected $discounts = array();
109
-
110
-	/**
111
-	 * An array of taxes for the submission.
112
-	 *
113
-	 * @var array
114
-	 */
115
-	protected $taxes = array();
116
-
117
-	/**
118
-	 * An array of items for the submission.
119
-	 *
120
-	 * @var GetPaid_Form_Item[]
121
-	 */
122
-	protected $items = array();
123
-
124
-	/**
125
-	 * The last error.
126
-	 *
127
-	 * @var string
128
-	 */
129
-	public $last_error = null;
130
-
131
-	/**
132
-	 * The last error code.
133
-	 *
134
-	 * @var string
135
-	 */
136
-	public $last_error_code = null;
137
-
138
-    /**
139
-	 * Class constructor.
140
-	 *
141
-	 */
142
-	public function __construct() {
143
-
144
-		// Set the state and country to the default state and country.
145
-		$this->country = wpinv_default_billing_country();
146
-		$this->state   = wpinv_get_default_state();
147
-
148
-		// Do we have an actual submission?
149
-		if ( isset( $_POST['getpaid_payment_form_submission'] ) ) {
150
-			$this->load_data( wp_kses_post_deep( wp_unslash( $_POST ) ) );
151
-		}
152
-
153
-	}
154
-
155
-	/**
156
-	 * Loads submission data.
157
-	 *
158
-	 * @param array $data
159
-	 */
160
-	public function load_data( $data ) {
161
-
162
-		// Allow plugins to filter the data.
163
-		$data       = apply_filters( 'getpaid_submission_data', $data, $this );
164
-
165
-		// Cache it...
166
-		$this->data = $data;
167
-
168
-		// Then generate a unique id from the data.
169
-		$this->id   = md5( wp_json_encode( $data ) );
170
-
171
-		// Finally, process the submission.
172
-		try {
173
-
174
-			// Each process is passed an instance of the class (with reference)
175
-			// and should throw an Exception whenever it encounters one.
176
-			$processors = apply_filters(
177
-				'getpaid_payment_form_submission_processors',
178
-				array(
179
-					array( $this, 'process_payment_form' ),
180
-					array( $this, 'process_invoice' ),
181
-					array( $this, 'process_fees' ),
182
-					array( $this, 'process_items' ),
183
-					array( $this, 'process_discount' ),
184
-					array( $this, 'process_taxes' ),
185
-				),
186
-				$this
187
-			);
188
-
189
-			foreach ( $processors as $processor ) {
190
-				call_user_func_array( $processor, array( &$this ) );
191
-			}
192
-		} catch ( GetPaid_Payment_Exception $e ) {
193
-			$this->last_error      = $e->getMessage();
194
-			$this->last_error_code = $e->getErrorCode();
195
-		} catch ( Exception $e ) {
196
-			$this->last_error      = $e->getMessage();
197
-			$this->last_error_code = $e->getCode();
198
-		}
199
-
200
-		// Fired when we are done processing a submission.
201
-		do_action_ref_array( 'getpaid_process_submission', array( &$this ) );
202
-
203
-	}
204
-
205
-	/*
68
+     * The country for the submission.
69
+     *
70
+     * @var string
71
+     */
72
+    public $country = null;
73
+
74
+    /**
75
+     * The state for the submission.
76
+     *
77
+     * @since 1.0.19
78
+     * @var string
79
+     */
80
+    public $state = null;
81
+
82
+    /**
83
+     * The invoice associated with the submission.
84
+     *
85
+     * @var WPInv_Invoice
86
+     */
87
+    protected $invoice = null;
88
+
89
+    /**
90
+     * The recurring item for the submission.
91
+     *
92
+     * @var int
93
+     */
94
+    public $has_recurring = 0;
95
+
96
+    /**
97
+     * An array of fees for the submission.
98
+     *
99
+     * @var array
100
+     */
101
+    protected $fees = array();
102
+
103
+    /**
104
+     * An array of discounts for the submission.
105
+     *
106
+     * @var array
107
+     */
108
+    protected $discounts = array();
109
+
110
+    /**
111
+     * An array of taxes for the submission.
112
+     *
113
+     * @var array
114
+     */
115
+    protected $taxes = array();
116
+
117
+    /**
118
+     * An array of items for the submission.
119
+     *
120
+     * @var GetPaid_Form_Item[]
121
+     */
122
+    protected $items = array();
123
+
124
+    /**
125
+     * The last error.
126
+     *
127
+     * @var string
128
+     */
129
+    public $last_error = null;
130
+
131
+    /**
132
+     * The last error code.
133
+     *
134
+     * @var string
135
+     */
136
+    public $last_error_code = null;
137
+
138
+    /**
139
+     * Class constructor.
140
+     *
141
+     */
142
+    public function __construct() {
143
+
144
+        // Set the state and country to the default state and country.
145
+        $this->country = wpinv_default_billing_country();
146
+        $this->state   = wpinv_get_default_state();
147
+
148
+        // Do we have an actual submission?
149
+        if ( isset( $_POST['getpaid_payment_form_submission'] ) ) {
150
+            $this->load_data( wp_kses_post_deep( wp_unslash( $_POST ) ) );
151
+        }
152
+
153
+    }
154
+
155
+    /**
156
+     * Loads submission data.
157
+     *
158
+     * @param array $data
159
+     */
160
+    public function load_data( $data ) {
161
+
162
+        // Allow plugins to filter the data.
163
+        $data       = apply_filters( 'getpaid_submission_data', $data, $this );
164
+
165
+        // Cache it...
166
+        $this->data = $data;
167
+
168
+        // Then generate a unique id from the data.
169
+        $this->id   = md5( wp_json_encode( $data ) );
170
+
171
+        // Finally, process the submission.
172
+        try {
173
+
174
+            // Each process is passed an instance of the class (with reference)
175
+            // and should throw an Exception whenever it encounters one.
176
+            $processors = apply_filters(
177
+                'getpaid_payment_form_submission_processors',
178
+                array(
179
+                    array( $this, 'process_payment_form' ),
180
+                    array( $this, 'process_invoice' ),
181
+                    array( $this, 'process_fees' ),
182
+                    array( $this, 'process_items' ),
183
+                    array( $this, 'process_discount' ),
184
+                    array( $this, 'process_taxes' ),
185
+                ),
186
+                $this
187
+            );
188
+
189
+            foreach ( $processors as $processor ) {
190
+                call_user_func_array( $processor, array( &$this ) );
191
+            }
192
+        } catch ( GetPaid_Payment_Exception $e ) {
193
+            $this->last_error      = $e->getMessage();
194
+            $this->last_error_code = $e->getErrorCode();
195
+        } catch ( Exception $e ) {
196
+            $this->last_error      = $e->getMessage();
197
+            $this->last_error_code = $e->getCode();
198
+        }
199
+
200
+        // Fired when we are done processing a submission.
201
+        do_action_ref_array( 'getpaid_process_submission', array( &$this ) );
202
+
203
+    }
204
+
205
+    /*
206 206
 	|--------------------------------------------------------------------------
207 207
 	| Payment Forms.
208 208
 	|--------------------------------------------------------------------------
@@ -211,39 +211,39 @@  discard block
 block discarded – undo
211 211
 	| submission has an active payment form etc.
212 212
     */
213 213
 
214
-	/**
215
-	 * Prepares the submission's payment form.
216
-	 *
217
-	 * @since 1.0.19
218
-	 */
219
-	public function process_payment_form() {
214
+    /**
215
+     * Prepares the submission's payment form.
216
+     *
217
+     * @since 1.0.19
218
+     */
219
+    public function process_payment_form() {
220 220
 
221
-		// Every submission needs an active payment form.
222
-		if ( empty( $this->data['form_id'] ) ) {
223
-			throw new Exception( __( 'Missing payment form', 'invoicing' ) );
224
-		}
221
+        // Every submission needs an active payment form.
222
+        if ( empty( $this->data['form_id'] ) ) {
223
+            throw new Exception( __( 'Missing payment form', 'invoicing' ) );
224
+        }
225 225
 
226
-		// Fetch the payment form.
227
-		$this->payment_form = new GetPaid_Payment_Form( $this->data['form_id'] );
226
+        // Fetch the payment form.
227
+        $this->payment_form = new GetPaid_Payment_Form( $this->data['form_id'] );
228 228
 
229
-		if ( ! $this->payment_form->is_active() ) {
230
-			throw new Exception( __( 'Payment form not active', 'invoicing' ) );
231
-		}
229
+        if ( ! $this->payment_form->is_active() ) {
230
+            throw new Exception( __( 'Payment form not active', 'invoicing' ) );
231
+        }
232 232
 
233
-		do_action_ref_array( 'getpaid_submissions_process_payment_form', array( &$this ) );
234
-	}
233
+        do_action_ref_array( 'getpaid_submissions_process_payment_form', array( &$this ) );
234
+    }
235 235
 
236 236
     /**
237
-	 * Returns the payment form.
238
-	 *
239
-	 * @since 1.0.19
240
-	 * @return GetPaid_Payment_Form
241
-	 */
242
-	public function get_payment_form() {
243
-		return $this->payment_form;
244
-	}
237
+     * Returns the payment form.
238
+     *
239
+     * @since 1.0.19
240
+     * @return GetPaid_Payment_Form
241
+     */
242
+    public function get_payment_form() {
243
+        return $this->payment_form;
244
+    }
245 245
 
246
-	/*
246
+    /*
247 247
 	|--------------------------------------------------------------------------
248 248
 	| Invoices.
249 249
 	|--------------------------------------------------------------------------
@@ -252,95 +252,95 @@  discard block
 block discarded – undo
252 252
 	| might be for an existing invoice.
253 253
 	*/
254 254
 
255
-	/**
256
-	 * Prepares the submission's invoice.
257
-	 *
258
-	 * @since 1.0.19
259
-	 */
260
-	public function process_invoice() {
261
-
262
-		// Abort if there is no invoice.
263
-		if ( empty( $this->data['invoice_id'] ) ) {
264
-
265
-			// Check if we are resuming a payment.
266
-			if ( empty( $this->data['maybe_use_invoice'] ) ) {
267
-				return;
268
-			}
269
-
270
-			$invoice = wpinv_get_invoice( $this->data['maybe_use_invoice'] );
271
-			if ( empty( $invoice ) || ! $invoice->has_status( 'draft, auto-draft, wpi-pending' ) ) {
272
-				return;
273
-			}
274
-		}
275
-
276
-		// If the submission is for an existing invoice, ensure that it exists
277
-		// and that it is not paid for.
278
-		if ( empty( $invoice ) ) {
279
-			$invoice = wpinv_get_invoice( $this->data['invoice_id'] );
280
-		}
255
+    /**
256
+     * Prepares the submission's invoice.
257
+     *
258
+     * @since 1.0.19
259
+     */
260
+    public function process_invoice() {
261
+
262
+        // Abort if there is no invoice.
263
+        if ( empty( $this->data['invoice_id'] ) ) {
264
+
265
+            // Check if we are resuming a payment.
266
+            if ( empty( $this->data['maybe_use_invoice'] ) ) {
267
+                return;
268
+            }
269
+
270
+            $invoice = wpinv_get_invoice( $this->data['maybe_use_invoice'] );
271
+            if ( empty( $invoice ) || ! $invoice->has_status( 'draft, auto-draft, wpi-pending' ) ) {
272
+                return;
273
+            }
274
+        }
275
+
276
+        // If the submission is for an existing invoice, ensure that it exists
277
+        // and that it is not paid for.
278
+        if ( empty( $invoice ) ) {
279
+            $invoice = wpinv_get_invoice( $this->data['invoice_id'] );
280
+        }
281 281
 
282 282
         if ( empty( $invoice ) ) {
283
-			throw new Exception( __( 'Invalid invoice', 'invoicing' ) );
284
-		}
285
-
286
-		if ( $invoice->is_paid() ) {
287
-			throw new Exception( __( 'This invoice is already paid for.', 'invoicing' ) );
288
-		}
289
-
290
-		$this->payment_form->invoice = $invoice;
291
-		if ( ! $this->payment_form->is_default() ) {
292
-
293
-			$items    = array();
294
-			$item_ids = array();
295
-
296
-			foreach ( $invoice->get_items() as $item ) {
297
-				if ( ! in_array( $item->get_id(), $item_ids ) ) {
298
-					$item_ids[] = $item->get_id();
299
-					$items[]    = $item;
300
-				}
301
-			}
302
-
303
-			foreach ( $this->payment_form->get_items() as $item ) {
304
-				if ( ! in_array( $item->get_id(), $item_ids ) ) {
305
-					$item_ids[] = $item->get_id();
306
-					$items[]    = $item;
307
-				}
308
-			}
309
-
310
-			$this->payment_form->set_items( $items );
311
-
312
-		} else {
313
-			$this->payment_form->set_items( $invoice->get_items() );
314
-		}
315
-
316
-		$this->country = $invoice->get_country();
317
-		$this->state   = $invoice->get_state();
318
-		$this->invoice = $invoice;
319
-
320
-		do_action_ref_array( 'getpaid_submissions_process_invoice', array( &$this ) );
321
-	}
322
-
323
-	/**
324
-	 * Returns the associated invoice.
325
-	 *
326
-	 * @since 1.0.19
327
-	 * @return WPInv_Invoice
328
-	 */
329
-	public function get_invoice() {
330
-		return $this->invoice;
331
-	}
332
-
333
-	/**
334
-	 * Checks whether there is an invoice associated with this submission.
335
-	 *
336
-	 * @since 1.0.19
337
-	 * @return bool
338
-	 */
339
-	public function has_invoice() {
340
-		return ! empty( $this->invoice );
341
-	}
342
-
343
-	/*
283
+            throw new Exception( __( 'Invalid invoice', 'invoicing' ) );
284
+        }
285
+
286
+        if ( $invoice->is_paid() ) {
287
+            throw new Exception( __( 'This invoice is already paid for.', 'invoicing' ) );
288
+        }
289
+
290
+        $this->payment_form->invoice = $invoice;
291
+        if ( ! $this->payment_form->is_default() ) {
292
+
293
+            $items    = array();
294
+            $item_ids = array();
295
+
296
+            foreach ( $invoice->get_items() as $item ) {
297
+                if ( ! in_array( $item->get_id(), $item_ids ) ) {
298
+                    $item_ids[] = $item->get_id();
299
+                    $items[]    = $item;
300
+                }
301
+            }
302
+
303
+            foreach ( $this->payment_form->get_items() as $item ) {
304
+                if ( ! in_array( $item->get_id(), $item_ids ) ) {
305
+                    $item_ids[] = $item->get_id();
306
+                    $items[]    = $item;
307
+                }
308
+            }
309
+
310
+            $this->payment_form->set_items( $items );
311
+
312
+        } else {
313
+            $this->payment_form->set_items( $invoice->get_items() );
314
+        }
315
+
316
+        $this->country = $invoice->get_country();
317
+        $this->state   = $invoice->get_state();
318
+        $this->invoice = $invoice;
319
+
320
+        do_action_ref_array( 'getpaid_submissions_process_invoice', array( &$this ) );
321
+    }
322
+
323
+    /**
324
+     * Returns the associated invoice.
325
+     *
326
+     * @since 1.0.19
327
+     * @return WPInv_Invoice
328
+     */
329
+    public function get_invoice() {
330
+        return $this->invoice;
331
+    }
332
+
333
+    /**
334
+     * Checks whether there is an invoice associated with this submission.
335
+     *
336
+     * @since 1.0.19
337
+     * @return bool
338
+     */
339
+    public function has_invoice() {
340
+        return ! empty( $this->invoice );
341
+    }
342
+
343
+    /*
344 344
 	|--------------------------------------------------------------------------
345 345
 	| Items.
346 346
 	|--------------------------------------------------------------------------
@@ -349,129 +349,129 @@  discard block
 block discarded – undo
349 349
 	| recurring item. But can have an unlimited number of non-recurring items.
350 350
 	*/
351 351
 
352
-	/**
353
-	 * Prepares the submission's items.
354
-	 *
355
-	 * @since 1.0.19
356
-	 */
357
-	public function process_items() {
358
-
359
-		$processor = new GetPaid_Payment_Form_Submission_Items( $this );
360
-
361
-		foreach ( $processor->items as $item ) {
362
-			$this->add_item( $item );
363
-		}
364
-
365
-		do_action_ref_array( 'getpaid_submissions_process_items', array( &$this ) );
366
-	}
367
-
368
-	/**
369
-	 * Adds an item to the submission.
370
-	 *
371
-	 * @since 1.0.19
372
-	 * @param GetPaid_Form_Item $item
373
-	 */
374
-	public function add_item( $item ) {
375
-
376
-		// Make sure that it is available for purchase.
377
-		if ( ! $item->can_purchase() || isset( $this->items[ $item->get_id() ] ) ) {
378
-			return;
379
-		}
380
-
381
-		// Each submission can only contain one recurring item.
382
-		if ( $item->is_recurring() ) {
383
-			$this->has_recurring = $item->get_id();
384
-		}
385
-
386
-		// Update the items and totals.
387
-		$this->items[ $item->get_id() ]         = $item;
388
-		$this->totals['subtotal']['initial']   += $item->get_sub_total();
389
-		$this->totals['subtotal']['recurring'] += $item->get_recurring_sub_total();
390
-
391
-	}
392
-
393
-	/**
394
-	 * Removes a specific item.
395
-	 *
396
-	 * You should not call this method after the discounts and taxes
397
-	 * have been calculated.
398
-	 *
399
-	 * @since 1.0.19
400
-	 */
401
-	public function remove_item( $item_id ) {
402
-
403
-		if ( isset( $this->items[ $item_id ] ) ) {
404
-			$this->totals['subtotal']['initial']   -= $this->items[ $item_id ]->get_sub_total();
405
-			$this->totals['subtotal']['recurring'] -= $this->items[ $item_id ]->get_recurring_sub_total();
406
-
407
-			if ( $this->items[ $item_id ]->is_recurring() ) {
408
-				$this->has_recurring = 0;
409
-			}
410
-
411
-			unset( $this->items[ $item_id ] );
412
-		}
413
-
414
-	}
415
-
416
-	/**
417
-	 * Returns the subtotal.
418
-	 *
419
-	 * @since 1.0.19
420
-	 */
421
-	public function get_subtotal() {
422
-
423
-		if ( wpinv_prices_include_tax() ) {
424
-			return $this->totals['subtotal']['initial'] - $this->totals['taxes']['initial'];
425
-		}
426
-
427
-		return $this->totals['subtotal']['initial'];
428
-	}
429
-
430
-	/**
431
-	 * Returns the recurring subtotal.
432
-	 *
433
-	 * @since 1.0.19
434
-	 */
435
-	public function get_recurring_subtotal() {
436
-
437
-		if ( wpinv_prices_include_tax() ) {
438
-			return $this->totals['subtotal']['recurring'] - $this->totals['taxes']['recurring'];
439
-		}
440
-
441
-		return $this->totals['subtotal']['recurring'];
442
-	}
443
-
444
-	/**
445
-	 * Returns all items.
446
-	 *
447
-	 * @since 1.0.19
448
-	 * @return GetPaid_Form_Item[]
449
-	 */
450
-	public function get_items() {
451
-		return $this->items;
452
-	}
453
-
454
-	/**
455
-	 * Checks if there's a single subscription group in the submission.
456
-	 *
457
-	 * @since 2.3.0
458
-	 * @return bool
459
-	 */
460
-	public function has_subscription_group() {
461
-		return $this->has_recurring && getpaid_should_group_subscriptions( $this ) && 1 == count( getpaid_get_subscription_groups( $this ) );
462
-	}
463
-
464
-	/**
465
-	 * Checks if there are multipe subscription groups in the submission.
466
-	 *
467
-	 * @since 2.3.0
468
-	 * @return bool
469
-	 */
470
-	public function has_multiple_subscription_groups() {
471
-		return $this->has_recurring && 1 < count( getpaid_get_subscription_groups( $this ) );
472
-	}
473
-
474
-	/*
352
+    /**
353
+     * Prepares the submission's items.
354
+     *
355
+     * @since 1.0.19
356
+     */
357
+    public function process_items() {
358
+
359
+        $processor = new GetPaid_Payment_Form_Submission_Items( $this );
360
+
361
+        foreach ( $processor->items as $item ) {
362
+            $this->add_item( $item );
363
+        }
364
+
365
+        do_action_ref_array( 'getpaid_submissions_process_items', array( &$this ) );
366
+    }
367
+
368
+    /**
369
+     * Adds an item to the submission.
370
+     *
371
+     * @since 1.0.19
372
+     * @param GetPaid_Form_Item $item
373
+     */
374
+    public function add_item( $item ) {
375
+
376
+        // Make sure that it is available for purchase.
377
+        if ( ! $item->can_purchase() || isset( $this->items[ $item->get_id() ] ) ) {
378
+            return;
379
+        }
380
+
381
+        // Each submission can only contain one recurring item.
382
+        if ( $item->is_recurring() ) {
383
+            $this->has_recurring = $item->get_id();
384
+        }
385
+
386
+        // Update the items and totals.
387
+        $this->items[ $item->get_id() ]         = $item;
388
+        $this->totals['subtotal']['initial']   += $item->get_sub_total();
389
+        $this->totals['subtotal']['recurring'] += $item->get_recurring_sub_total();
390
+
391
+    }
392
+
393
+    /**
394
+     * Removes a specific item.
395
+     *
396
+     * You should not call this method after the discounts and taxes
397
+     * have been calculated.
398
+     *
399
+     * @since 1.0.19
400
+     */
401
+    public function remove_item( $item_id ) {
402
+
403
+        if ( isset( $this->items[ $item_id ] ) ) {
404
+            $this->totals['subtotal']['initial']   -= $this->items[ $item_id ]->get_sub_total();
405
+            $this->totals['subtotal']['recurring'] -= $this->items[ $item_id ]->get_recurring_sub_total();
406
+
407
+            if ( $this->items[ $item_id ]->is_recurring() ) {
408
+                $this->has_recurring = 0;
409
+            }
410
+
411
+            unset( $this->items[ $item_id ] );
412
+        }
413
+
414
+    }
415
+
416
+    /**
417
+     * Returns the subtotal.
418
+     *
419
+     * @since 1.0.19
420
+     */
421
+    public function get_subtotal() {
422
+
423
+        if ( wpinv_prices_include_tax() ) {
424
+            return $this->totals['subtotal']['initial'] - $this->totals['taxes']['initial'];
425
+        }
426
+
427
+        return $this->totals['subtotal']['initial'];
428
+    }
429
+
430
+    /**
431
+     * Returns the recurring subtotal.
432
+     *
433
+     * @since 1.0.19
434
+     */
435
+    public function get_recurring_subtotal() {
436
+
437
+        if ( wpinv_prices_include_tax() ) {
438
+            return $this->totals['subtotal']['recurring'] - $this->totals['taxes']['recurring'];
439
+        }
440
+
441
+        return $this->totals['subtotal']['recurring'];
442
+    }
443
+
444
+    /**
445
+     * Returns all items.
446
+     *
447
+     * @since 1.0.19
448
+     * @return GetPaid_Form_Item[]
449
+     */
450
+    public function get_items() {
451
+        return $this->items;
452
+    }
453
+
454
+    /**
455
+     * Checks if there's a single subscription group in the submission.
456
+     *
457
+     * @since 2.3.0
458
+     * @return bool
459
+     */
460
+    public function has_subscription_group() {
461
+        return $this->has_recurring && getpaid_should_group_subscriptions( $this ) && 1 == count( getpaid_get_subscription_groups( $this ) );
462
+    }
463
+
464
+    /**
465
+     * Checks if there are multipe subscription groups in the submission.
466
+     *
467
+     * @since 2.3.0
468
+     * @return bool
469
+     */
470
+    public function has_multiple_subscription_groups() {
471
+        return $this->has_recurring && 1 < count( getpaid_get_subscription_groups( $this ) );
472
+    }
473
+
474
+    /*
475 475
 	|--------------------------------------------------------------------------
476 476
 	| Taxes
477 477
 	|--------------------------------------------------------------------------
@@ -480,128 +480,128 @@  discard block
 block discarded – undo
480 480
 	| or only one-time.
481 481
     */
482 482
 
483
-	/**
484
-	 * Prepares the submission's taxes.
485
-	 *
486
-	 * @since 1.0.19
487
-	 */
488
-	public function process_taxes() {
489
-
490
-		// Abort if we're not using taxes.
491
-		if ( ! $this->use_taxes() ) {
492
-			return;
493
-		}
494
-
495
-		// If a custom country && state has been passed in, use it to calculate taxes.
496
-		$country = $this->get_field( 'wpinv_country', 'billing' );
497
-		if ( ! empty( $country ) ) {
498
-			$this->country = $country;
499
-		}
500
-
501
-		$state = $this->get_field( 'wpinv_state', 'billing' );
502
-		if ( ! empty( $state ) ) {
503
-			$this->state = $state;
504
-		}
505
-
506
-		// Confirm if the provided country and the ip country are similar.
507
-		$address_confirmed = $this->get_field( 'confirm-address' );
508
-		if ( isset( $_POST['billing']['country'] ) && wpinv_should_validate_vat_number() && getpaid_get_ip_country() != $this->country && empty( $address_confirmed ) ) {
509
-			throw new Exception( __( 'The country of your current location must be the same as the country of your billing location or you must confirm the billing address is your home country.', 'invoicing' ) );
510
-		}
511
-
512
-		// Abort if the country is not taxable.
513
-		if ( ! wpinv_is_country_taxable( $this->country ) ) {
514
-			return;
515
-		}
516
-
517
-		$processor = new GetPaid_Payment_Form_Submission_Taxes( $this );
518
-
519
-		foreach ( $processor->taxes as $tax ) {
520
-			$this->add_tax( $tax );
521
-		}
522
-
523
-		do_action_ref_array( 'getpaid_submissions_process_taxes', array( &$this ) );
524
-	}
525
-
526
-	/**
527
-	 * Adds a tax to the submission.
528
-	 *
529
-	 * @param array $tax An array of tax details. name, initial_tax, and recurring_tax are required.
530
-	 * @since 1.0.19
531
-	 */
532
-	public function add_tax( $tax ) {
533
-
534
-		if ( wpinv_round_tax_per_tax_rate() ) {
535
-			$tax['initial_tax']   = wpinv_round_amount( $tax['initial_tax'] );
536
-			$tax['recurring_tax'] = wpinv_round_amount( $tax['recurring_tax'] );
537
-		}
538
-
539
-		$this->taxes[ $tax['name'] ]         = $tax;
540
-		$this->totals['taxes']['initial']   += wpinv_sanitize_amount( $tax['initial_tax'] );
541
-		$this->totals['taxes']['recurring'] += wpinv_sanitize_amount( $tax['recurring_tax'] );
542
-
543
-	}
544
-
545
-	/**
546
-	 * Removes a specific tax.
547
-	 *
548
-	 * @since 1.0.19
549
-	 */
550
-	public function remove_tax( $tax_name ) {
551
-
552
-		if ( isset( $this->taxes[ $tax_name ] ) ) {
553
-			$this->totals['taxes']['initial']   -= $this->taxes[ $tax_name ]['initial_tax'];
554
-			$this->totals['taxes']['recurring'] -= $this->taxes[ $tax_name ]['recurring_tax'];
555
-			unset( $this->taxes[ $tax_name ] );
556
-		}
557
-
558
-	}
559
-
560
-	/**
561
-	 * Whether or not we'll use taxes for the submission.
562
-	 *
563
-	 * @since 1.0.19
564
-	 */
565
-	public function use_taxes() {
566
-
567
-		$use_taxes = wpinv_use_taxes();
568
-
569
-		if ( $this->has_invoice() && ! $this->invoice->is_taxable() ) {
570
-			$use_taxes = false;
571
-		}
572
-
573
-		return apply_filters( 'getpaid_submission_use_taxes', $use_taxes, $this );
574
-
575
-	}
576
-
577
-	/**
578
-	 * Returns the tax.
579
-	 *
580
-	 * @since 1.0.19
581
-	 */
582
-	public function get_tax() {
583
-		return $this->totals['taxes']['initial'];
584
-	}
585
-
586
-	/**
587
-	 * Returns the recurring tax.
588
-	 *
589
-	 * @since 1.0.19
590
-	 */
591
-	public function get_recurring_tax() {
592
-		return $this->totals['taxes']['recurring'];
593
-	}
594
-
595
-	/**
596
-	 * Returns all taxes.
597
-	 *
598
-	 * @since 1.0.19
599
-	 */
600
-	public function get_taxes() {
601
-		return $this->taxes;
602
-	}
603
-
604
-	/*
483
+    /**
484
+     * Prepares the submission's taxes.
485
+     *
486
+     * @since 1.0.19
487
+     */
488
+    public function process_taxes() {
489
+
490
+        // Abort if we're not using taxes.
491
+        if ( ! $this->use_taxes() ) {
492
+            return;
493
+        }
494
+
495
+        // If a custom country && state has been passed in, use it to calculate taxes.
496
+        $country = $this->get_field( 'wpinv_country', 'billing' );
497
+        if ( ! empty( $country ) ) {
498
+            $this->country = $country;
499
+        }
500
+
501
+        $state = $this->get_field( 'wpinv_state', 'billing' );
502
+        if ( ! empty( $state ) ) {
503
+            $this->state = $state;
504
+        }
505
+
506
+        // Confirm if the provided country and the ip country are similar.
507
+        $address_confirmed = $this->get_field( 'confirm-address' );
508
+        if ( isset( $_POST['billing']['country'] ) && wpinv_should_validate_vat_number() && getpaid_get_ip_country() != $this->country && empty( $address_confirmed ) ) {
509
+            throw new Exception( __( 'The country of your current location must be the same as the country of your billing location or you must confirm the billing address is your home country.', 'invoicing' ) );
510
+        }
511
+
512
+        // Abort if the country is not taxable.
513
+        if ( ! wpinv_is_country_taxable( $this->country ) ) {
514
+            return;
515
+        }
516
+
517
+        $processor = new GetPaid_Payment_Form_Submission_Taxes( $this );
518
+
519
+        foreach ( $processor->taxes as $tax ) {
520
+            $this->add_tax( $tax );
521
+        }
522
+
523
+        do_action_ref_array( 'getpaid_submissions_process_taxes', array( &$this ) );
524
+    }
525
+
526
+    /**
527
+     * Adds a tax to the submission.
528
+     *
529
+     * @param array $tax An array of tax details. name, initial_tax, and recurring_tax are required.
530
+     * @since 1.0.19
531
+     */
532
+    public function add_tax( $tax ) {
533
+
534
+        if ( wpinv_round_tax_per_tax_rate() ) {
535
+            $tax['initial_tax']   = wpinv_round_amount( $tax['initial_tax'] );
536
+            $tax['recurring_tax'] = wpinv_round_amount( $tax['recurring_tax'] );
537
+        }
538
+
539
+        $this->taxes[ $tax['name'] ]         = $tax;
540
+        $this->totals['taxes']['initial']   += wpinv_sanitize_amount( $tax['initial_tax'] );
541
+        $this->totals['taxes']['recurring'] += wpinv_sanitize_amount( $tax['recurring_tax'] );
542
+
543
+    }
544
+
545
+    /**
546
+     * Removes a specific tax.
547
+     *
548
+     * @since 1.0.19
549
+     */
550
+    public function remove_tax( $tax_name ) {
551
+
552
+        if ( isset( $this->taxes[ $tax_name ] ) ) {
553
+            $this->totals['taxes']['initial']   -= $this->taxes[ $tax_name ]['initial_tax'];
554
+            $this->totals['taxes']['recurring'] -= $this->taxes[ $tax_name ]['recurring_tax'];
555
+            unset( $this->taxes[ $tax_name ] );
556
+        }
557
+
558
+    }
559
+
560
+    /**
561
+     * Whether or not we'll use taxes for the submission.
562
+     *
563
+     * @since 1.0.19
564
+     */
565
+    public function use_taxes() {
566
+
567
+        $use_taxes = wpinv_use_taxes();
568
+
569
+        if ( $this->has_invoice() && ! $this->invoice->is_taxable() ) {
570
+            $use_taxes = false;
571
+        }
572
+
573
+        return apply_filters( 'getpaid_submission_use_taxes', $use_taxes, $this );
574
+
575
+    }
576
+
577
+    /**
578
+     * Returns the tax.
579
+     *
580
+     * @since 1.0.19
581
+     */
582
+    public function get_tax() {
583
+        return $this->totals['taxes']['initial'];
584
+    }
585
+
586
+    /**
587
+     * Returns the recurring tax.
588
+     *
589
+     * @since 1.0.19
590
+     */
591
+    public function get_recurring_tax() {
592
+        return $this->totals['taxes']['recurring'];
593
+    }
594
+
595
+    /**
596
+     * Returns all taxes.
597
+     *
598
+     * @since 1.0.19
599
+     */
600
+    public function get_taxes() {
601
+        return $this->taxes;
602
+    }
603
+
604
+    /*
605 605
 	|--------------------------------------------------------------------------
606 606
 	| Discounts
607 607
 	|--------------------------------------------------------------------------
@@ -610,99 +610,99 @@  discard block
 block discarded – undo
610 610
 	| or only one-time. They also do not have to come from a discount code.
611 611
     */
612 612
 
613
-	/**
614
-	 * Prepares the submission's discount.
615
-	 *
616
-	 * @since 1.0.19
617
-	 */
618
-	public function process_discount() {
619
-
620
-		$initial_total    = $this->get_subtotal() + $this->get_fee() + $this->get_tax();
621
-		$recurring_total  = $this->get_recurring_subtotal() + $this->get_recurring_fee() + $this->get_recurring_tax();
622
-		$processor        = new GetPaid_Payment_Form_Submission_Discount( $this, $initial_total, $recurring_total );
623
-
624
-		foreach ( $processor->discounts as $discount ) {
625
-			$this->add_discount( $discount );
626
-		}
627
-
628
-		do_action_ref_array( 'getpaid_submissions_process_discounts', array( &$this ) );
629
-	}
630
-
631
-	/**
632
-	 * Adds a discount to the submission.
633
-	 *
634
-	 * @param array $discount An array of discount details. name, initial_discount, and recurring_discount are required. Include discount_code if the discount is from a discount code.
635
-	 * @since 1.0.19
636
-	 */
637
-	public function add_discount( $discount ) {
638
-		$this->discounts[ $discount['name'] ]   = $discount;
639
-		$this->totals['discount']['initial']   += wpinv_sanitize_amount( $discount['initial_discount'] );
640
-		$this->totals['discount']['recurring'] += wpinv_sanitize_amount( $discount['recurring_discount'] );
641
-	}
642
-
643
-	/**
644
-	 * Removes a discount from the submission.
645
-	 *
646
-	 * @since 1.0.19
647
-	 */
648
-	public function remove_discount( $name ) {
649
-
650
-		if ( isset( $this->discounts[ $name ] ) ) {
651
-			$this->totals['discount']['initial']   -= $this->discounts[ $name ]['initial_discount'];
652
-			$this->totals['discount']['recurring'] -= $this->discounts[ $name ]['recurring_discount'];
653
-			unset( $this->discounts[ $name ] );
654
-		}
655
-
656
-	}
657
-
658
-	/**
659
-	 * Checks whether there is a discount code associated with this submission.
660
-	 *
661
-	 * @since 1.0.19
662
-	 * @return bool
663
-	 */
664
-	public function has_discount_code() {
665
-		return ! empty( $this->discounts['discount_code'] );
666
-	}
667
-
668
-	/**
669
-	 * Returns the discount code.
670
-	 *
671
-	 * @since 1.0.19
672
-	 * @return string
673
-	 */
674
-	public function get_discount_code() {
675
-		return $this->has_discount_code() ? $this->discounts['discount_code']['discount_code'] : '';
676
-	}
677
-
678
-	/**
679
-	 * Returns the discount.
680
-	 *
681
-	 * @since 1.0.19
682
-	 */
683
-	public function get_discount() {
684
-		return $this->totals['discount']['initial'];
685
-	}
686
-
687
-	/**
688
-	 * Returns the recurring discount.
689
-	 *
690
-	 * @since 1.0.19
691
-	 */
692
-	public function get_recurring_discount() {
693
-		return $this->totals['discount']['recurring'];
694
-	}
695
-
696
-	/**
697
-	 * Returns all discounts.
698
-	 *
699
-	 * @since 1.0.19
700
-	 */
701
-	public function get_discounts() {
702
-		return $this->discounts;
703
-	}
704
-
705
-	/*
613
+    /**
614
+     * Prepares the submission's discount.
615
+     *
616
+     * @since 1.0.19
617
+     */
618
+    public function process_discount() {
619
+
620
+        $initial_total    = $this->get_subtotal() + $this->get_fee() + $this->get_tax();
621
+        $recurring_total  = $this->get_recurring_subtotal() + $this->get_recurring_fee() + $this->get_recurring_tax();
622
+        $processor        = new GetPaid_Payment_Form_Submission_Discount( $this, $initial_total, $recurring_total );
623
+
624
+        foreach ( $processor->discounts as $discount ) {
625
+            $this->add_discount( $discount );
626
+        }
627
+
628
+        do_action_ref_array( 'getpaid_submissions_process_discounts', array( &$this ) );
629
+    }
630
+
631
+    /**
632
+     * Adds a discount to the submission.
633
+     *
634
+     * @param array $discount An array of discount details. name, initial_discount, and recurring_discount are required. Include discount_code if the discount is from a discount code.
635
+     * @since 1.0.19
636
+     */
637
+    public function add_discount( $discount ) {
638
+        $this->discounts[ $discount['name'] ]   = $discount;
639
+        $this->totals['discount']['initial']   += wpinv_sanitize_amount( $discount['initial_discount'] );
640
+        $this->totals['discount']['recurring'] += wpinv_sanitize_amount( $discount['recurring_discount'] );
641
+    }
642
+
643
+    /**
644
+     * Removes a discount from the submission.
645
+     *
646
+     * @since 1.0.19
647
+     */
648
+    public function remove_discount( $name ) {
649
+
650
+        if ( isset( $this->discounts[ $name ] ) ) {
651
+            $this->totals['discount']['initial']   -= $this->discounts[ $name ]['initial_discount'];
652
+            $this->totals['discount']['recurring'] -= $this->discounts[ $name ]['recurring_discount'];
653
+            unset( $this->discounts[ $name ] );
654
+        }
655
+
656
+    }
657
+
658
+    /**
659
+     * Checks whether there is a discount code associated with this submission.
660
+     *
661
+     * @since 1.0.19
662
+     * @return bool
663
+     */
664
+    public function has_discount_code() {
665
+        return ! empty( $this->discounts['discount_code'] );
666
+    }
667
+
668
+    /**
669
+     * Returns the discount code.
670
+     *
671
+     * @since 1.0.19
672
+     * @return string
673
+     */
674
+    public function get_discount_code() {
675
+        return $this->has_discount_code() ? $this->discounts['discount_code']['discount_code'] : '';
676
+    }
677
+
678
+    /**
679
+     * Returns the discount.
680
+     *
681
+     * @since 1.0.19
682
+     */
683
+    public function get_discount() {
684
+        return $this->totals['discount']['initial'];
685
+    }
686
+
687
+    /**
688
+     * Returns the recurring discount.
689
+     *
690
+     * @since 1.0.19
691
+     */
692
+    public function get_recurring_discount() {
693
+        return $this->totals['discount']['recurring'];
694
+    }
695
+
696
+    /**
697
+     * Returns all discounts.
698
+     *
699
+     * @since 1.0.19
700
+     */
701
+    public function get_discounts() {
702
+        return $this->discounts;
703
+    }
704
+
705
+    /*
706 706
 	|--------------------------------------------------------------------------
707 707
 	| Fees
708 708
 	|--------------------------------------------------------------------------
@@ -712,100 +712,100 @@  discard block
 block discarded – undo
712 712
 	| fees.
713 713
     */
714 714
 
715
-	/**
716
-	 * Prepares the submission's fees.
717
-	 *
718
-	 * @since 1.0.19
719
-	 */
720
-	public function process_fees() {
721
-
722
-		$fees_processor = new GetPaid_Payment_Form_Submission_Fees( $this );
723
-
724
-		foreach ( $fees_processor->fees as $fee ) {
725
-			$this->add_fee( $fee );
726
-		}
727
-
728
-		do_action_ref_array( 'getpaid_submissions_process_fees', array( &$this ) );
729
-	}
730
-
731
-	/**
732
-	 * Adds a fee to the submission.
733
-	 *
734
-	 * @param array $fee An array of fee details. name, initial_fee, and recurring_fee are required.
735
-	 * @since 1.0.19
736
-	 */
737
-	public function add_fee( $fee ) {
738
-
739
-		if ( $fee['name'] == 'shipping' ) {
740
-			$this->totals['shipping']['initial']   += wpinv_sanitize_amount( $fee['initial_fee'] );
741
-			$this->totals['shipping']['recurring'] += wpinv_sanitize_amount( $fee['recurring_fee'] );
742
-			return;
743
-		}
744
-
745
-		$this->fees[ $fee['name'] ]         = $fee;
746
-		$this->totals['fees']['initial']   += wpinv_sanitize_amount( $fee['initial_fee'] );
747
-		$this->totals['fees']['recurring'] += wpinv_sanitize_amount( $fee['recurring_fee'] );
748
-
749
-	}
750
-
751
-	/**
752
-	 * Removes a fee from the submission.
753
-	 *
754
-	 * @since 1.0.19
755
-	 */
756
-	public function remove_fee( $name ) {
757
-
758
-		if ( isset( $this->fees[ $name ] ) ) {
759
-			$this->totals['fees']['initial']   -= $this->fees[ $name ]['initial_fee'];
760
-			$this->totals['fees']['recurring'] -= $this->fees[ $name ]['recurring_fee'];
761
-			unset( $this->fees[ $name ] );
762
-		}
763
-
764
-		if ( 'shipping' == $name ) {
765
-			$this->totals['shipping']['initial']   = 0;
766
-			$this->totals['shipping']['recurring'] = 0;
767
-		}
768
-
769
-	}
770
-
771
-	/**
772
-	 * Returns the fees.
773
-	 *
774
-	 * @since 1.0.19
775
-	 */
776
-	public function get_fee() {
777
-		return $this->totals['fees']['initial'];
778
-	}
779
-
780
-	/**
781
-	 * Returns the recurring fees.
782
-	 *
783
-	 * @since 1.0.19
784
-	 */
785
-	public function get_recurring_fee() {
786
-		return $this->totals['fees']['recurring'];
787
-	}
788
-
789
-	/**
790
-	 * Returns all fees.
791
-	 *
792
-	 * @since 1.0.19
793
-	 */
794
-	public function get_fees() {
795
-		return $this->fees;
796
-	}
797
-
798
-	/**
799
-	 * Checks if there are any fees for the form.
800
-	 *
801
-	 * @return bool
802
-	 * @since 1.0.19
803
-	 */
804
-	public function has_fees() {
805
-		return count( $this->fees ) !== 0;
806
-	}
807
-
808
-	/*
715
+    /**
716
+     * Prepares the submission's fees.
717
+     *
718
+     * @since 1.0.19
719
+     */
720
+    public function process_fees() {
721
+
722
+        $fees_processor = new GetPaid_Payment_Form_Submission_Fees( $this );
723
+
724
+        foreach ( $fees_processor->fees as $fee ) {
725
+            $this->add_fee( $fee );
726
+        }
727
+
728
+        do_action_ref_array( 'getpaid_submissions_process_fees', array( &$this ) );
729
+    }
730
+
731
+    /**
732
+     * Adds a fee to the submission.
733
+     *
734
+     * @param array $fee An array of fee details. name, initial_fee, and recurring_fee are required.
735
+     * @since 1.0.19
736
+     */
737
+    public function add_fee( $fee ) {
738
+
739
+        if ( $fee['name'] == 'shipping' ) {
740
+            $this->totals['shipping']['initial']   += wpinv_sanitize_amount( $fee['initial_fee'] );
741
+            $this->totals['shipping']['recurring'] += wpinv_sanitize_amount( $fee['recurring_fee'] );
742
+            return;
743
+        }
744
+
745
+        $this->fees[ $fee['name'] ]         = $fee;
746
+        $this->totals['fees']['initial']   += wpinv_sanitize_amount( $fee['initial_fee'] );
747
+        $this->totals['fees']['recurring'] += wpinv_sanitize_amount( $fee['recurring_fee'] );
748
+
749
+    }
750
+
751
+    /**
752
+     * Removes a fee from the submission.
753
+     *
754
+     * @since 1.0.19
755
+     */
756
+    public function remove_fee( $name ) {
757
+
758
+        if ( isset( $this->fees[ $name ] ) ) {
759
+            $this->totals['fees']['initial']   -= $this->fees[ $name ]['initial_fee'];
760
+            $this->totals['fees']['recurring'] -= $this->fees[ $name ]['recurring_fee'];
761
+            unset( $this->fees[ $name ] );
762
+        }
763
+
764
+        if ( 'shipping' == $name ) {
765
+            $this->totals['shipping']['initial']   = 0;
766
+            $this->totals['shipping']['recurring'] = 0;
767
+        }
768
+
769
+    }
770
+
771
+    /**
772
+     * Returns the fees.
773
+     *
774
+     * @since 1.0.19
775
+     */
776
+    public function get_fee() {
777
+        return $this->totals['fees']['initial'];
778
+    }
779
+
780
+    /**
781
+     * Returns the recurring fees.
782
+     *
783
+     * @since 1.0.19
784
+     */
785
+    public function get_recurring_fee() {
786
+        return $this->totals['fees']['recurring'];
787
+    }
788
+
789
+    /**
790
+     * Returns all fees.
791
+     *
792
+     * @since 1.0.19
793
+     */
794
+    public function get_fees() {
795
+        return $this->fees;
796
+    }
797
+
798
+    /**
799
+     * Checks if there are any fees for the form.
800
+     *
801
+     * @return bool
802
+     * @since 1.0.19
803
+     */
804
+    public function has_fees() {
805
+        return count( $this->fees ) !== 0;
806
+    }
807
+
808
+    /*
809 809
 	|--------------------------------------------------------------------------
810 810
 	| MISC
811 811
 	|--------------------------------------------------------------------------
@@ -813,147 +813,147 @@  discard block
 block discarded – undo
813 813
 	| Extra submission functions.
814 814
     */
815 815
 
816
-	/**
817
-	 * Returns the shipping amount.
818
-	 *
819
-	 * @since 1.0.19
820
-	 */
821
-	public function get_shipping() {
822
-		return $this->totals['shipping']['initial'];
823
-	}
824
-
825
-	/**
826
-	 * Returns the recurring shipping.
827
-	 *
828
-	 * @since 1.0.19
829
-	 */
830
-	public function get_recurring_shipping() {
831
-		return $this->totals['shipping']['recurring'];
832
-	}
833
-
834
-	/**
835
-	 * Checks if there are any shipping fees for the form.
836
-	 *
837
-	 * @return bool
838
-	 * @since 1.0.19
839
-	 */
840
-	public function has_shipping() {
841
-		return apply_filters( 'getpaid_payment_form_has_shipping', false, $this );
842
-	}
843
-
844
-	/**
845
-	 * Checks if this is the initial fetch.
846
-	 *
847
-	 * @return bool
848
-	 * @since 1.0.19
849
-	 */
850
-	public function is_initial_fetch() {
851
-		return isset( $this->data['initial_state'] ) && empty( $this->data['initial_state'] );
852
-	}
853
-
854
-	/**
855
-	 * Returns the total amount to collect for this submission.
856
-	 *
857
-	 * @since 1.0.19
858
-	 */
859
-	public function get_total() {
860
-		$total = $this->get_subtotal() + $this->get_fee() + $this->get_tax() + $this->get_shipping() - $this->get_discount();
861
-		return max( $total, 0 );
862
-	}
863
-
864
-	/**
865
-	 * Returns the recurring total amount to collect for this submission.
866
-	 *
867
-	 * @since 1.0.19
868
-	 */
869
-	public function get_recurring_total() {
870
-		$total = $this->get_recurring_subtotal() + $this->get_recurring_fee() + $this->get_recurring_tax() + $this->get_recurring_shipping() - $this->get_recurring_discount();
871
-		return max( $total, 0 );
872
-	}
873
-
874
-	/**
875
-	 * Whether payment details should be collected for this submission.
876
-	 *
877
-	 * @since 1.0.19
878
-	 */
879
-	public function should_collect_payment_details() {
880
-		$initial   = $this->get_total();
881
-		$recurring = $this->get_recurring_total();
882
-
883
-		if ( $this->has_recurring == 0 ) {
884
-			$recurring = 0;
885
-		}
886
-
887
-		$collect = $initial > 0 || $recurring > 0;
888
-		return apply_filters( 'getpaid_submission_should_collect_payment_details', $collect, $this );
889
-	}
890
-
891
-	/**
892
-	 * Returns the billing email of the user.
893
-	 *
894
-	 * @since 1.0.19
895
-	 */
896
-	public function get_billing_email() {
897
-		return apply_filters( 'getpaid_get_submission_billing_email', $this->get_field( 'billing_email' ), $this );
898
-	}
899
-
900
-	/**
901
-	 * Checks if the submitter has a billing email.
902
-	 *
903
-	 * @since 1.0.19
904
-	 */
905
-	public function has_billing_email() {
906
-		$billing_email = $this->get_billing_email();
907
-		return ! empty( $billing_email ) && is_email( $billing_email );
908
-	}
909
-
910
-	/**
911
-	 * Returns the appropriate currency for the submission.
912
-	 *
913
-	 * @since 1.0.19
914
-	 * @return string
915
-	 */
916
-	public function get_currency() {
917
-		return $this->has_invoice() ? $this->invoice->get_currency() : wpinv_get_currency();
918
-    }
919
-
920
-    /**
921
-	 * Returns the raw submission data.
922
-	 *
923
-	 * @since 1.0.19
924
-	 * @return array
925
-	 */
926
-	public function get_data() {
927
-		return $this->data;
928
-	}
929
-
930
-	/**
931
-	 * Returns a field from the submission data
932
-	 *
933
-	 * @param string $field
934
-	 * @since 1.0.19
935
-	 * @return mixed|null
936
-	 */
937
-	public function get_field( $field, $sub_array_key = null ) {
938
-		return getpaid_get_array_field( $this->data, $field, $sub_array_key );
939
-	}
940
-
941
-	/**
942
-	 * Checks if a required field is set.
943
-	 *
944
-	 * @since 1.0.19
945
-	 */
946
-	public function is_required_field_set( $field ) {
947
-		return empty( $field['required'] ) || ! empty( $this->data[ $field['id'] ] );
948
-	}
949
-
950
-	/**
951
-	 * Formats an amount
952
-	 *
953
-	 * @since 1.0.19
954
-	 */
955
-	public function format_amount( $amount ) {
956
-		return wpinv_price( $amount, $this->get_currency() );
957
-	}
816
+    /**
817
+     * Returns the shipping amount.
818
+     *
819
+     * @since 1.0.19
820
+     */
821
+    public function get_shipping() {
822
+        return $this->totals['shipping']['initial'];
823
+    }
824
+
825
+    /**
826
+     * Returns the recurring shipping.
827
+     *
828
+     * @since 1.0.19
829
+     */
830
+    public function get_recurring_shipping() {
831
+        return $this->totals['shipping']['recurring'];
832
+    }
833
+
834
+    /**
835
+     * Checks if there are any shipping fees for the form.
836
+     *
837
+     * @return bool
838
+     * @since 1.0.19
839
+     */
840
+    public function has_shipping() {
841
+        return apply_filters( 'getpaid_payment_form_has_shipping', false, $this );
842
+    }
843
+
844
+    /**
845
+     * Checks if this is the initial fetch.
846
+     *
847
+     * @return bool
848
+     * @since 1.0.19
849
+     */
850
+    public function is_initial_fetch() {
851
+        return isset( $this->data['initial_state'] ) && empty( $this->data['initial_state'] );
852
+    }
853
+
854
+    /**
855
+     * Returns the total amount to collect for this submission.
856
+     *
857
+     * @since 1.0.19
858
+     */
859
+    public function get_total() {
860
+        $total = $this->get_subtotal() + $this->get_fee() + $this->get_tax() + $this->get_shipping() - $this->get_discount();
861
+        return max( $total, 0 );
862
+    }
863
+
864
+    /**
865
+     * Returns the recurring total amount to collect for this submission.
866
+     *
867
+     * @since 1.0.19
868
+     */
869
+    public function get_recurring_total() {
870
+        $total = $this->get_recurring_subtotal() + $this->get_recurring_fee() + $this->get_recurring_tax() + $this->get_recurring_shipping() - $this->get_recurring_discount();
871
+        return max( $total, 0 );
872
+    }
873
+
874
+    /**
875
+     * Whether payment details should be collected for this submission.
876
+     *
877
+     * @since 1.0.19
878
+     */
879
+    public function should_collect_payment_details() {
880
+        $initial   = $this->get_total();
881
+        $recurring = $this->get_recurring_total();
882
+
883
+        if ( $this->has_recurring == 0 ) {
884
+            $recurring = 0;
885
+        }
886
+
887
+        $collect = $initial > 0 || $recurring > 0;
888
+        return apply_filters( 'getpaid_submission_should_collect_payment_details', $collect, $this );
889
+    }
890
+
891
+    /**
892
+     * Returns the billing email of the user.
893
+     *
894
+     * @since 1.0.19
895
+     */
896
+    public function get_billing_email() {
897
+        return apply_filters( 'getpaid_get_submission_billing_email', $this->get_field( 'billing_email' ), $this );
898
+    }
899
+
900
+    /**
901
+     * Checks if the submitter has a billing email.
902
+     *
903
+     * @since 1.0.19
904
+     */
905
+    public function has_billing_email() {
906
+        $billing_email = $this->get_billing_email();
907
+        return ! empty( $billing_email ) && is_email( $billing_email );
908
+    }
909
+
910
+    /**
911
+     * Returns the appropriate currency for the submission.
912
+     *
913
+     * @since 1.0.19
914
+     * @return string
915
+     */
916
+    public function get_currency() {
917
+        return $this->has_invoice() ? $this->invoice->get_currency() : wpinv_get_currency();
918
+    }
919
+
920
+    /**
921
+     * Returns the raw submission data.
922
+     *
923
+     * @since 1.0.19
924
+     * @return array
925
+     */
926
+    public function get_data() {
927
+        return $this->data;
928
+    }
929
+
930
+    /**
931
+     * Returns a field from the submission data
932
+     *
933
+     * @param string $field
934
+     * @since 1.0.19
935
+     * @return mixed|null
936
+     */
937
+    public function get_field( $field, $sub_array_key = null ) {
938
+        return getpaid_get_array_field( $this->data, $field, $sub_array_key );
939
+    }
940
+
941
+    /**
942
+     * Checks if a required field is set.
943
+     *
944
+     * @since 1.0.19
945
+     */
946
+    public function is_required_field_set( $field ) {
947
+        return empty( $field['required'] ) || ! empty( $this->data[ $field['id'] ] );
948
+    }
949
+
950
+    /**
951
+     * Formats an amount
952
+     *
953
+     * @since 1.0.19
954
+     */
955
+    public function format_amount( $amount ) {
956
+        return wpinv_price( $amount, $this->get_currency() );
957
+    }
958 958
 
959 959
 }
Please login to merge, or discard this patch.
templates/invoice/line-totals.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -52,27 +52,27 @@
 block discarded – undo
52 52
 
53 53
                                 // Total Fee.
54 54
                                 if ( 'fee' === $key ) {
55
-								wpinv_the_price( $invoice->get_total_fees(), $invoice->get_currency() );
55
+                                wpinv_the_price( $invoice->get_total_fees(), $invoice->get_currency() );
56 56
                                 }
57 57
 
58 58
                                 // Total discount.
59 59
                                 if ( 'discount' === $key ) {
60
-								wpinv_the_price( $invoice->get_total_discount(), $invoice->get_currency() );
60
+                                wpinv_the_price( $invoice->get_total_discount(), $invoice->get_currency() );
61 61
                                 }
62 62
 
63 63
                                 // Shipping.
64 64
                                 if ( 'shipping' === $key ) {
65
-								wpinv_the_price( $invoice->get_shipping(), $invoice->get_currency() );
65
+                                wpinv_the_price( $invoice->get_shipping(), $invoice->get_currency() );
66 66
                                 }
67 67
 
68 68
                                 // Sub total.
69 69
                                 if ( 'subtotal' === $key ) {
70
-								wpinv_the_price( $invoice->get_subtotal(), $invoice->get_currency() );
70
+                                wpinv_the_price( $invoice->get_subtotal(), $invoice->get_currency() );
71 71
                                 }
72 72
 
73 73
                                 // Total.
74 74
                                 if ( 'total' === $key ) {
75
-								wpinv_the_price( $invoice->get_total(), $invoice->get_currency() );
75
+                                wpinv_the_price( $invoice->get_total(), $invoice->get_currency() );
76 76
                                 }
77 77
 
78 78
                                 // Fires when printing a cart total.
Please login to merge, or discard this patch.
includes/api/class-getpaid-rest-report-sales-controller.php 1 patch
Indentation   +679 added lines, -679 removed lines patch added patch discarded remove patch
@@ -18,688 +18,688 @@
 block discarded – undo
18 18
  */
19 19
 class GetPaid_REST_Report_Sales_Controller extends GetPaid_REST_Date_Based_Controller {
20 20
 
21
-	/**
22
-	 * Route base.
23
-	 *
24
-	 * @var string
25
-	 */
26
-	protected $rest_base = 'reports/sales';
27
-
28
-	/**
29
-	 * The report data.
30
-	 *
31
-	 * @var stdClass
32
-	 */
33
-	public $report_data;
34
-
35
-	/**
36
-	 * The report range.
37
-	 *
38
-	 * @var array
39
-	 */
40
-	public $report_range;
41
-
42
-	/**
43
-	 * Registers the routes for the objects of the controller.
44
-	 *
45
-	 * @since 2.0.0
46
-	 *
47
-	 * @see register_rest_route()
48
-	 */
49
-	public function register_namespace_routes( $namespace ) {
50
-
51
-		// Get sales report.
52
-		register_rest_route(
53
-			$namespace,
54
-			$this->rest_base,
55
-			array(
56
-				array(
57
-					'methods'             => WP_REST_Server::READABLE,
58
-					'callback'            => array( $this, 'get_items' ),
59
-					'permission_callback' => array( $this, 'get_items_permissions_check' ),
60
-					'args'                => $this->get_collection_params(),
61
-				),
62
-				'schema' => array( $this, 'get_public_item_schema' ),
63
-			)
64
-		);
65
-
66
-	}
67
-
68
-	/**
69
-	 * Makes sure the current user has access to READ the report APIs.
70
-	 *
71
-	 * @since  2.0.0
72
-	 * @param WP_REST_Request $request Full data about the request.
73
-	 * @return WP_Error|boolean
74
-	 */
75
-	public function get_items_permissions_check( $request ) {
76
-
77
-		if ( ! wpinv_current_user_can_manage_invoicing() ) {
78
-			return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot list resources.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) );
79
-		}
80
-
81
-		return true;
82
-	}
83
-
84
-	/**
85
-	 * Get sales reports.
86
-	 *
87
-	 * @param WP_REST_Request $request
88
-	 * @return array|WP_Error
89
-	 */
90
-	public function get_items( $request ) {
91
-		$data   = array();
92
-		$item   = $this->prepare_item_for_response( null, $request );
93
-		$data[] = $this->prepare_response_for_collection( $item );
94
-
95
-		return rest_ensure_response( $data );
96
-	}
97
-
98
-	/**
99
-	 * Prepare a report sales object for serialization.
100
-	 *
101
-	 * @param null $_
102
-	 * @param WP_REST_Request $request Request object.
103
-	 * @return WP_REST_Response $response Response data.
104
-	 */
105
-	public function prepare_item_for_response( $_, $request ) {
106
-
107
-		// Set report range.
108
-		$this->report_range = $this->get_date_range( $request );
109
-
110
-		$report_data     = $this->get_report_data();
111
-		$period_totals   = array();
112
-
113
-		// Setup period totals by ensuring each period in the interval has data.
114
-		$start_date      = strtotime( $this->report_range['after'] );
115
-
116
-		if ( 'month' === $this->groupby ) {
117
-			$start_date      = strtotime( gmdate( 'Y-m-01', $start_date ) );
118
-		}
119
-
120
-		for ( $i = 0; $i < $this->interval; $i++ ) {
121
-
122
-			switch ( $this->groupby ) {
123
-				case 'day':
124
-					$time = gmdate( 'Y-m-d', strtotime( "+{$i} DAY", $start_date ) );
125
-					break;
126
-				default:
127
-					$time = gmdate( 'Y-m', strtotime( "+{$i} MONTH", $start_date ) );
128
-					break;
129
-			}
130
-
131
-			// Set the defaults for each period.
132
-			$period_totals[ $time ] = array(
133
-				'invoices'          => 0,
134
-				'items'             => 0,
135
-				'refunded_items'    => 0,
136
-				'refunded_tax'      => wpinv_round_amount( 0.00 ),
137
-				'subtotal'          => wpinv_round_amount( 0.00 ),
138
-				'refunded_subtotal' => wpinv_round_amount( 0.00 ),
139
-				'refunded_fees'     => wpinv_round_amount( 0.00 ),
140
-				'discount'          => wpinv_round_amount( 0.00 ),
141
-			);
142
-
143
-			foreach ( array_keys( wpinv_get_report_graphs() ) as $key ) {
144
-				if ( ! isset( $period_totals[ $time ][ $key ] ) ) {
145
-					$period_totals[ $time ][ $key ] = wpinv_round_amount( 0.00 );
146
-				}
147
-			}
148
-		}
149
-
150
-		// add total sales, total invoice count, total tax for each period
151
-		$date_format = ( 'day' === $this->groupby ) ? 'Y-m-d' : 'Y-m';
152
-		foreach ( $report_data->invoices as $invoice ) {
153
-			$time = gmdate( $date_format, strtotime( $invoice->post_date ) );
154
-
155
-			if ( ! isset( $period_totals[ $time ] ) ) {
156
-				continue;
157
-			}
158
-
159
-			$period_totals[ $time ]['sales']    = wpinv_round_amount( $invoice->total_sales );
160
-			$period_totals[ $time ]['tax']      = wpinv_round_amount( $invoice->total_tax );
161
-			$period_totals[ $time ]['subtotal'] = wpinv_round_amount( $invoice->subtotal );
162
-			$period_totals[ $time ]['fees']     = wpinv_round_amount( $invoice->total_fees );
163
-
164
-		}
165
-
166
-		foreach ( $report_data->refunds as $invoice ) {
167
-			$time = gmdate( $date_format, strtotime( $invoice->post_date ) );
168
-
169
-			if ( ! isset( $period_totals[ $time ] ) ) {
170
-				continue;
171
-			}
172
-
173
-			$period_totals[ $time ]['refunds']           = wpinv_round_amount( $invoice->total_sales );
174
-			$period_totals[ $time ]['refunded_tax']      = wpinv_round_amount( $invoice->total_tax );
175
-			$period_totals[ $time ]['refunded_subtotal'] = wpinv_round_amount( $invoice->subtotal );
176
-			$period_totals[ $time ]['refunded_fees']     = wpinv_round_amount( $invoice->total_fees );
177
-
178
-		}
179
-
180
-		foreach ( $report_data->invoice_counts as $invoice ) {
181
-			$time = gmdate( $date_format, strtotime( $invoice->post_date ) );
182
-
183
-			if ( isset( $period_totals[ $time ] ) ) {
184
-				$period_totals[ $time ]['invoices']   = (int) $invoice->count;
185
-			}
186
-		}
187
-
188
-		// Add total invoice items for each period.
189
-		foreach ( $report_data->invoice_items as $invoice_item ) {
190
-			$time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $invoice_item->post_date ) ) : gmdate( 'Y-m', strtotime( $invoice_item->post_date ) );
191
-
192
-			if ( isset( $period_totals[ $time ] ) ) {
193
-				$period_totals[ $time ]['items'] = (int) $invoice_item->invoice_item_count;
194
-			}
195
-		}
196
-
197
-		// Add total discount for each period.
198
-		foreach ( $report_data->coupons as $discount ) {
199
-			$time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $discount->post_date ) ) : gmdate( 'Y-m', strtotime( $discount->post_date ) );
200
-
201
-			if ( isset( $period_totals[ $time ] ) ) {
202
-				$period_totals[ $time ]['discount'] = wpinv_round_amount( $discount->discount_amount );
203
-			}
204
-		}
205
-
206
-		// Extra fields.
207
-		foreach ( array_keys( wpinv_get_report_graphs() ) as $key ) {
208
-
209
-			// Abort unprepared.
210
-			if ( ! isset( $report_data->$key ) ) {
211
-				continue;
212
-			}
213
-
214
-			// Abort defaults.
215
-			if ( in_array( $key, array( 'sales', 'refunds', 'tax', 'fees', 'discount', 'invoices', 'items' ) ) ) {
216
-				continue;
217
-			}
218
-
219
-			// Set values.
220
-			foreach ( $report_data->$key as $item ) {
221
-				$time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $item->date ) ) : gmdate( 'Y-m', strtotime( $item->date ) );
222
-
223
-				if ( isset( $period_totals[ $time ] ) ) {
224
-					$period_totals[ $time ][ $key ] = wpinv_round_amount( $item->val );
225
-				}
226
-			}
227
-
228
-			unset( $report_data->$key );
229
-		}
230
-
231
-		$report_data->totals            = $period_totals;
232
-		$report_data->grouped_by        = $this->groupby;
233
-		$report_data->interval          = max( $this->interval, 1 );
234
-		$report_data->currency          = wpinv_get_currency();
235
-		$report_data->currency_symbol   = wpinv_currency_symbol();
236
-		$report_data->currency_position = wpinv_currency_position();
237
-		$report_data->decimal_places    = wpinv_decimals();
238
-		$report_data->thousands_sep     = wpinv_thousands_separator();
239
-		$report_data->decimals_sep      = wpinv_decimal_separator();
240
-		$report_data->start_date        = gmdate( 'Y-m-d', strtotime( $this->report_range['after'] ) );
241
-		$report_data->end_date          = gmdate( 'Y-m-d', strtotime( $this->report_range['before'] ) );
242
-		$report_data->start_date_locale = getpaid_format_date( gmdate( 'Y-m-d', strtotime( $this->report_range['after'] ) ) );
243
-		$report_data->end_date_locale   = getpaid_format_date( gmdate( 'Y-m-d', strtotime( $this->report_range['before'] ) ) );
244
-		$report_data->decimals_sep      = wpinv_decimal_separator();
245
-
246
-		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
247
-		$data    = $report_data;
248
-		unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
249
-		$data    = $this->add_additional_fields_to_object( (array) $data, $request );
250
-		$data    = $this->filter_response_by_context( $data, $context );
251
-
252
-		// Wrap the data in a response object.
253
-		$response = rest_ensure_response( $data );
254
-		$response->add_links(
21
+    /**
22
+     * Route base.
23
+     *
24
+     * @var string
25
+     */
26
+    protected $rest_base = 'reports/sales';
27
+
28
+    /**
29
+     * The report data.
30
+     *
31
+     * @var stdClass
32
+     */
33
+    public $report_data;
34
+
35
+    /**
36
+     * The report range.
37
+     *
38
+     * @var array
39
+     */
40
+    public $report_range;
41
+
42
+    /**
43
+     * Registers the routes for the objects of the controller.
44
+     *
45
+     * @since 2.0.0
46
+     *
47
+     * @see register_rest_route()
48
+     */
49
+    public function register_namespace_routes( $namespace ) {
50
+
51
+        // Get sales report.
52
+        register_rest_route(
53
+            $namespace,
54
+            $this->rest_base,
255 55
             array(
256
-				'about' => array(
257
-					'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
258
-				),
56
+                array(
57
+                    'methods'             => WP_REST_Server::READABLE,
58
+                    'callback'            => array( $this, 'get_items' ),
59
+                    'permission_callback' => array( $this, 'get_items_permissions_check' ),
60
+                    'args'                => $this->get_collection_params(),
61
+                ),
62
+                'schema' => array( $this, 'get_public_item_schema' ),
259 63
             )
260 64
         );
261 65
 
262
-		return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
263
-	}
264
-
265
-	/**
266
-	 * Get report data.
267
-	 *
268
-	 * @return stdClass
269
-	 */
270
-	public function get_report_data() {
271
-		if ( empty( $this->report_data ) ) {
272
-			$this->query_report_data();
273
-		}
274
-		return $this->report_data;
275
-	}
276
-
277
-	/**
278
-	 * Get all data needed for this report and store in the class.
279
-	 */
280
-	protected function query_report_data() {
281
-
282
-		// Prepare reports.
283
-		$this->report_data = (object) array(
284
-			'invoice_counts' => $this->query_invoice_counts(), //count, post_date
285
-			'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
286
-			'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
287
-			'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
288
-			'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
289
-			'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
290
-			'previous_range' => $this->previous_range,
291
-		);
292
-
293
-		// Calculated totals.
294
-		$this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
295
-		$this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
296
-		$this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
297
-		$this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
298
-		$this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
299
-		$this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
300
-		$this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
301
-		$this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
302
-		$this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
303
-		$this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
304
-		$this->report_data->refunded_subtotal  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
305
-		$this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
306
-
307
-		// Calculate average based on net.
308
-		$this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
309
-		$this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
310
-
311
-		// Total invoices in this period, even if refunded.
312
-		$this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
313
-
314
-		// Items invoiced in this period, even if refunded.
315
-		$this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
316
-
317
-		// 3rd party filtering of report data
318
-		$this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data, $this );
319
-	}
320
-
321
-	/**
322
-	 * Prepares invoice counts.
323
-	 *
324
-	 * @return array.
325
-	 */
326
-	protected function query_invoice_counts() {
327
-
328
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
329
-			array(
330
-				'data'           => array(
331
-					'ID'        => array(
332
-						'type'     => 'post_data',
333
-						'function' => 'COUNT',
334
-						'name'     => 'count',
335
-						'distinct' => true,
336
-					),
337
-					'post_date' => array(
338
-						'type'     => 'post_data',
339
-						'function' => 'MIN',
340
-						'name'     => 'post_date',
341
-					),
342
-				),
343
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
344
-				'order_by'       => 'post_date ASC',
345
-				'query_type'     => 'get_results',
346
-				'filter_range'   => $this->report_range,
347
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
348
-			)
349
-		);
350
-
351
-	}
352
-
353
-	/**
354
-	 * Prepares coupon counts.
355
-	 *
356
-	 * @return array.
357
-	 */
358
-	protected function query_coupon_counts() {
359
-
360
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
361
-			array(
362
-				'data'           => array(
363
-					'discount'  => array(
364
-						'type'     => 'invoice_data',
365
-						'function' => 'SUM',
366
-						'name'     => 'discount_amount',
367
-					),
368
-					'post_date' => array(
369
-						'type'     => 'post_data',
370
-						'function' => 'MIN',
371
-						'name'     => 'post_date',
372
-					),
373
-				),
374
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
375
-				'order_by'       => 'post_date ASC',
376
-				'query_type'     => 'get_results',
377
-				'filter_range'   => $this->report_range,
378
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
379
-			)
380
-		);
381
-
382
-	}
383
-
384
-	/**
385
-	 * Prepares item counts.
386
-	 *
387
-	 * @return array.
388
-	 */
389
-	protected function query_item_counts() {
390
-
391
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
392
-			array(
393
-				'data'           => array(
394
-					'quantity'  => array(
395
-						'type'     => 'invoice_item',
396
-						'function' => 'SUM',
397
-						'name'     => 'invoice_item_count',
398
-					),
399
-					'post_date' => array(
400
-						'type'     => 'post_data',
401
-						'function' => 'MIN',
402
-						'name'     => 'post_date',
403
-					),
404
-				),
405
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
406
-				'order_by'       => 'post_date ASC',
407
-				'query_type'     => 'get_results',
408
-				'filter_range'   => $this->report_range,
409
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
410
-			)
411
-		);
412
-
413
-	}
414
-
415
-	/**
416
-	 * Prepares refunded item counts.
417
-	 *
418
-	 * @return array.
419
-	 */
420
-	protected function count_refunded_items() {
421
-
422
-		return (int) GetPaid_Reports_Helper::get_invoice_report_data(
423
-			array(
424
-				'data'           => array(
425
-					'quantity' => array(
426
-						'type'     => 'invoice_item',
427
-						'function' => 'SUM',
428
-						'name'     => 'invoice_item_count',
429
-					),
430
-				),
431
-				'query_type'     => 'get_var',
432
-				'filter_range'   => $this->report_range,
433
-				'invoice_status' => array( 'wpi-refunded' ),
434
-			)
435
-		);
436
-
437
-	}
438
-
439
-	/**
440
-	 * Prepares daily invoice totals.
441
-	 *
442
-	 * @return array.
443
-	 */
444
-	protected function query_invoice_totals() {
445
-
446
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
447
-			array(
448
-				'data'           => array(
449
-					'total'      => array(
450
-						'type'     => 'invoice_data',
451
-						'function' => 'SUM',
452
-						'name'     => 'total_sales',
453
-					),
454
-					'tax'        => array(
455
-						'type'     => 'invoice_data',
456
-						'function' => 'SUM',
457
-						'name'     => 'total_tax',
458
-					),
459
-					'discount'   => array(
460
-						'type'     => 'invoice_data',
461
-						'function' => 'SUM',
462
-						'name'     => 'total_discount',
463
-					),
464
-					'fees_total' => array(
465
-						'type'     => 'invoice_data',
466
-						'function' => 'SUM',
467
-						'name'     => 'total_fees',
468
-					),
469
-					'subtotal'   => array(
470
-						'type'     => 'invoice_data',
471
-						'function' => 'SUM',
472
-						'name'     => 'subtotal',
473
-					),
474
-					'post_date'  => array(
475
-						'type'     => 'post_data',
476
-						'function' => '',
477
-						'name'     => 'post_date',
478
-					),
479
-				),
480
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
481
-				'order_by'       => 'post_date ASC',
482
-				'query_type'     => 'get_results',
483
-				'filter_range'   => $this->report_range,
484
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-renewal' ),
485
-			)
486
-		);
487
-
488
-	}
489
-
490
-	/**
491
-	 * Prepares daily invoice totals.
492
-	 *
493
-	 * @return array.
494
-	 */
495
-	protected function query_refunded_totals() {
496
-
497
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
498
-			array(
499
-				'data'           => array(
500
-					'total'      => array(
501
-						'type'     => 'invoice_data',
502
-						'function' => 'SUM',
503
-						'name'     => 'total_sales',
504
-					),
505
-					'tax'        => array(
506
-						'type'     => 'invoice_data',
507
-						'function' => 'SUM',
508
-						'name'     => 'total_tax',
509
-					),
510
-					'discount'   => array(
511
-						'type'     => 'invoice_data',
512
-						'function' => 'SUM',
513
-						'name'     => 'total_discount',
514
-					),
515
-					'fees_total' => array(
516
-						'type'     => 'invoice_data',
517
-						'function' => 'SUM',
518
-						'name'     => 'total_fees',
519
-					),
520
-					'subtotal'   => array(
521
-						'type'     => 'invoice_data',
522
-						'function' => 'SUM',
523
-						'name'     => 'subtotal',
524
-					),
525
-					'post_date'  => array(
526
-						'type'     => 'post_data',
527
-						'function' => '',
528
-						'name'     => 'post_date',
529
-					),
530
-				),
531
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
532
-				'order_by'       => 'post_date ASC',
533
-				'query_type'     => 'get_results',
534
-				'filter_range'   => $this->report_range,
535
-				'invoice_status' => array( 'wpi-refunded' ),
536
-			)
537
-		);
538
-
539
-	}
540
-
541
-	/**
542
-	 * Get the Report's schema, conforming to JSON Schema.
543
-	 *
544
-	 * @return array
545
-	 */
546
-	public function get_item_schema() {
547
-
548
-		$schema = array(
549
-			'$schema'    => 'http://json-schema.org/draft-04/schema#',
550
-			'title'      => 'sales_report',
551
-			'type'       => 'object',
552
-			'properties' => array(
553
-				'total_sales'         => array(
554
-					'description' => __( 'Gross sales in the period.', 'invoicing' ),
555
-					'type'        => 'string',
556
-					'context'     => array( 'view' ),
557
-					'readonly'    => true,
558
-				),
559
-				'net_sales'           => array(
560
-					'description' => __( 'Net sales in the period.', 'invoicing' ),
561
-					'type'        => 'string',
562
-					'context'     => array( 'view' ),
563
-					'readonly'    => true,
564
-				),
565
-				'average_sales'       => array(
566
-					'description' => __( 'Average net daily sales.', 'invoicing' ),
567
-					'type'        => 'string',
568
-					'context'     => array( 'view' ),
569
-					'readonly'    => true,
570
-				),
571
-				'average_total_sales' => array(
572
-					'description' => __( 'Average gross daily sales.', 'invoicing' ),
573
-					'type'        => 'string',
574
-					'context'     => array( 'view' ),
575
-					'readonly'    => true,
576
-				),
577
-				'total_invoices'      => array(
578
-					'description' => __( 'Number of paid invoices.', 'invoicing' ),
579
-					'type'        => 'integer',
580
-					'context'     => array( 'view' ),
581
-					'readonly'    => true,
582
-				),
583
-				'total_items'         => array(
584
-					'description' => __( 'Number of items purchased.', 'invoicing' ),
585
-					'type'        => 'integer',
586
-					'context'     => array( 'view' ),
587
-					'readonly'    => true,
588
-				),
589
-				'refunded_items'      => array(
590
-					'description' => __( 'Number of items refunded.', 'invoicing' ),
591
-					'type'        => 'integer',
592
-					'context'     => array( 'view' ),
593
-					'readonly'    => true,
594
-				),
595
-				'total_tax'           => array(
596
-					'description' => __( 'Total charged for taxes.', 'invoicing' ),
597
-					'type'        => 'string',
598
-					'context'     => array( 'view' ),
599
-					'readonly'    => true,
600
-				),
601
-				'total_refunded_tax'  => array(
602
-					'description' => __( 'Total refunded for taxes.', 'invoicing' ),
603
-					'type'        => 'string',
604
-					'context'     => array( 'view' ),
605
-					'readonly'    => true,
606
-				),
607
-				'total_fees'          => array(
608
-					'description' => __( 'Total fees charged.', 'invoicing' ),
609
-					'type'        => 'string',
610
-					'context'     => array( 'view' ),
611
-					'readonly'    => true,
612
-				),
613
-				'total_refunds'       => array(
614
-					'description' => __( 'Total of refunded invoices.', 'invoicing' ),
615
-					'type'        => 'integer',
616
-					'context'     => array( 'view' ),
617
-					'readonly'    => true,
618
-				),
619
-				'net_refunds'         => array(
620
-					'description' => __( 'Net of refunded invoices.', 'invoicing' ),
621
-					'type'        => 'integer',
622
-					'context'     => array( 'view' ),
623
-					'readonly'    => true,
624
-				),
625
-				'total_discount'      => array(
626
-					'description' => __( 'Total of discounts used.', 'invoicing' ),
627
-					'type'        => 'integer',
628
-					'context'     => array( 'view' ),
629
-					'readonly'    => true,
630
-				),
631
-				'totals'              => array(
632
-					'description' => __( 'Totals.', 'invoicing' ),
633
-					'type'        => 'array',
634
-					'items'       => array(
635
-						'type' => 'array',
636
-					),
637
-					'context'     => array( 'view' ),
638
-					'readonly'    => true,
639
-				),
640
-				'interval'            => array(
641
-					'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
642
-					'type'        => 'integer',
643
-					'context'     => array( 'view' ),
644
-					'readonly'    => true,
645
-				),
646
-				'previous_range'      => array(
647
-					'description' => __( 'The previous report period.', 'invoicing' ),
648
-					'type'        => 'array',
649
-					'items'       => array(
650
-						'type' => 'string',
651
-					),
652
-					'context'     => array( 'view' ),
653
-					'readonly'    => true,
654
-				),
655
-				'grouped_by'          => array(
656
-					'description' => __( 'The period used to group the totals.', 'invoicing' ),
657
-					'type'        => 'string',
658
-					'context'     => array( 'view' ),
659
-					'enum'        => array( 'day', 'month' ),
660
-					'readonly'    => true,
661
-				),
662
-				'currency'            => array(
663
-					'description' => __( 'The default store currency.', 'invoicing' ),
664
-					'type'        => 'string',
665
-					'context'     => array( 'view' ),
666
-					'readonly'    => true,
667
-				),
668
-				'currency_symbol'     => array(
669
-					'description' => __( 'The default store currency symbol.', 'invoicing' ),
670
-					'type'        => 'string',
671
-					'context'     => array( 'view' ),
672
-					'readonly'    => true,
673
-				),
674
-				'currency_position'   => array(
675
-					'description' => __( 'The default store currency position.', 'invoicing' ),
676
-					'type'        => 'string',
677
-					'context'     => array( 'view' ),
678
-					'readonly'    => true,
679
-				),
680
-				'decimal_places'      => array(
681
-					'description' => __( 'The default store decimal places.', 'invoicing' ),
682
-					'type'        => 'string',
683
-					'context'     => array( 'view' ),
684
-					'readonly'    => true,
685
-				),
686
-				'thousands_sep'       => array(
687
-					'description' => __( 'The default store thousands separator.', 'invoicing' ),
688
-					'type'        => 'string',
689
-					'context'     => array( 'view' ),
690
-					'readonly'    => true,
691
-				),
692
-				'decimals_sep'        => array(
693
-					'description' => __( 'The default store decimals separator.', 'invoicing' ),
694
-					'type'        => 'string',
695
-					'context'     => array( 'view' ),
696
-					'readonly'    => true,
697
-				),
698
-			),
699
-		);
700
-
701
-		return $this->add_additional_fields_schema( $schema );
702
-
703
-	}
66
+    }
67
+
68
+    /**
69
+     * Makes sure the current user has access to READ the report APIs.
70
+     *
71
+     * @since  2.0.0
72
+     * @param WP_REST_Request $request Full data about the request.
73
+     * @return WP_Error|boolean
74
+     */
75
+    public function get_items_permissions_check( $request ) {
76
+
77
+        if ( ! wpinv_current_user_can_manage_invoicing() ) {
78
+            return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot list resources.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) );
79
+        }
80
+
81
+        return true;
82
+    }
83
+
84
+    /**
85
+     * Get sales reports.
86
+     *
87
+     * @param WP_REST_Request $request
88
+     * @return array|WP_Error
89
+     */
90
+    public function get_items( $request ) {
91
+        $data   = array();
92
+        $item   = $this->prepare_item_for_response( null, $request );
93
+        $data[] = $this->prepare_response_for_collection( $item );
94
+
95
+        return rest_ensure_response( $data );
96
+    }
97
+
98
+    /**
99
+     * Prepare a report sales object for serialization.
100
+     *
101
+     * @param null $_
102
+     * @param WP_REST_Request $request Request object.
103
+     * @return WP_REST_Response $response Response data.
104
+     */
105
+    public function prepare_item_for_response( $_, $request ) {
106
+
107
+        // Set report range.
108
+        $this->report_range = $this->get_date_range( $request );
109
+
110
+        $report_data     = $this->get_report_data();
111
+        $period_totals   = array();
112
+
113
+        // Setup period totals by ensuring each period in the interval has data.
114
+        $start_date      = strtotime( $this->report_range['after'] );
115
+
116
+        if ( 'month' === $this->groupby ) {
117
+            $start_date      = strtotime( gmdate( 'Y-m-01', $start_date ) );
118
+        }
119
+
120
+        for ( $i = 0; $i < $this->interval; $i++ ) {
121
+
122
+            switch ( $this->groupby ) {
123
+                case 'day':
124
+                    $time = gmdate( 'Y-m-d', strtotime( "+{$i} DAY", $start_date ) );
125
+                    break;
126
+                default:
127
+                    $time = gmdate( 'Y-m', strtotime( "+{$i} MONTH", $start_date ) );
128
+                    break;
129
+            }
130
+
131
+            // Set the defaults for each period.
132
+            $period_totals[ $time ] = array(
133
+                'invoices'          => 0,
134
+                'items'             => 0,
135
+                'refunded_items'    => 0,
136
+                'refunded_tax'      => wpinv_round_amount( 0.00 ),
137
+                'subtotal'          => wpinv_round_amount( 0.00 ),
138
+                'refunded_subtotal' => wpinv_round_amount( 0.00 ),
139
+                'refunded_fees'     => wpinv_round_amount( 0.00 ),
140
+                'discount'          => wpinv_round_amount( 0.00 ),
141
+            );
142
+
143
+            foreach ( array_keys( wpinv_get_report_graphs() ) as $key ) {
144
+                if ( ! isset( $period_totals[ $time ][ $key ] ) ) {
145
+                    $period_totals[ $time ][ $key ] = wpinv_round_amount( 0.00 );
146
+                }
147
+            }
148
+        }
149
+
150
+        // add total sales, total invoice count, total tax for each period
151
+        $date_format = ( 'day' === $this->groupby ) ? 'Y-m-d' : 'Y-m';
152
+        foreach ( $report_data->invoices as $invoice ) {
153
+            $time = gmdate( $date_format, strtotime( $invoice->post_date ) );
154
+
155
+            if ( ! isset( $period_totals[ $time ] ) ) {
156
+                continue;
157
+            }
158
+
159
+            $period_totals[ $time ]['sales']    = wpinv_round_amount( $invoice->total_sales );
160
+            $period_totals[ $time ]['tax']      = wpinv_round_amount( $invoice->total_tax );
161
+            $period_totals[ $time ]['subtotal'] = wpinv_round_amount( $invoice->subtotal );
162
+            $period_totals[ $time ]['fees']     = wpinv_round_amount( $invoice->total_fees );
163
+
164
+        }
165
+
166
+        foreach ( $report_data->refunds as $invoice ) {
167
+            $time = gmdate( $date_format, strtotime( $invoice->post_date ) );
168
+
169
+            if ( ! isset( $period_totals[ $time ] ) ) {
170
+                continue;
171
+            }
172
+
173
+            $period_totals[ $time ]['refunds']           = wpinv_round_amount( $invoice->total_sales );
174
+            $period_totals[ $time ]['refunded_tax']      = wpinv_round_amount( $invoice->total_tax );
175
+            $period_totals[ $time ]['refunded_subtotal'] = wpinv_round_amount( $invoice->subtotal );
176
+            $period_totals[ $time ]['refunded_fees']     = wpinv_round_amount( $invoice->total_fees );
177
+
178
+        }
179
+
180
+        foreach ( $report_data->invoice_counts as $invoice ) {
181
+            $time = gmdate( $date_format, strtotime( $invoice->post_date ) );
182
+
183
+            if ( isset( $period_totals[ $time ] ) ) {
184
+                $period_totals[ $time ]['invoices']   = (int) $invoice->count;
185
+            }
186
+        }
187
+
188
+        // Add total invoice items for each period.
189
+        foreach ( $report_data->invoice_items as $invoice_item ) {
190
+            $time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $invoice_item->post_date ) ) : gmdate( 'Y-m', strtotime( $invoice_item->post_date ) );
191
+
192
+            if ( isset( $period_totals[ $time ] ) ) {
193
+                $period_totals[ $time ]['items'] = (int) $invoice_item->invoice_item_count;
194
+            }
195
+        }
196
+
197
+        // Add total discount for each period.
198
+        foreach ( $report_data->coupons as $discount ) {
199
+            $time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $discount->post_date ) ) : gmdate( 'Y-m', strtotime( $discount->post_date ) );
200
+
201
+            if ( isset( $period_totals[ $time ] ) ) {
202
+                $period_totals[ $time ]['discount'] = wpinv_round_amount( $discount->discount_amount );
203
+            }
204
+        }
205
+
206
+        // Extra fields.
207
+        foreach ( array_keys( wpinv_get_report_graphs() ) as $key ) {
208
+
209
+            // Abort unprepared.
210
+            if ( ! isset( $report_data->$key ) ) {
211
+                continue;
212
+            }
213
+
214
+            // Abort defaults.
215
+            if ( in_array( $key, array( 'sales', 'refunds', 'tax', 'fees', 'discount', 'invoices', 'items' ) ) ) {
216
+                continue;
217
+            }
218
+
219
+            // Set values.
220
+            foreach ( $report_data->$key as $item ) {
221
+                $time = ( 'day' === $this->groupby ) ? gmdate( 'Y-m-d', strtotime( $item->date ) ) : gmdate( 'Y-m', strtotime( $item->date ) );
222
+
223
+                if ( isset( $period_totals[ $time ] ) ) {
224
+                    $period_totals[ $time ][ $key ] = wpinv_round_amount( $item->val );
225
+                }
226
+            }
227
+
228
+            unset( $report_data->$key );
229
+        }
230
+
231
+        $report_data->totals            = $period_totals;
232
+        $report_data->grouped_by        = $this->groupby;
233
+        $report_data->interval          = max( $this->interval, 1 );
234
+        $report_data->currency          = wpinv_get_currency();
235
+        $report_data->currency_symbol   = wpinv_currency_symbol();
236
+        $report_data->currency_position = wpinv_currency_position();
237
+        $report_data->decimal_places    = wpinv_decimals();
238
+        $report_data->thousands_sep     = wpinv_thousands_separator();
239
+        $report_data->decimals_sep      = wpinv_decimal_separator();
240
+        $report_data->start_date        = gmdate( 'Y-m-d', strtotime( $this->report_range['after'] ) );
241
+        $report_data->end_date          = gmdate( 'Y-m-d', strtotime( $this->report_range['before'] ) );
242
+        $report_data->start_date_locale = getpaid_format_date( gmdate( 'Y-m-d', strtotime( $this->report_range['after'] ) ) );
243
+        $report_data->end_date_locale   = getpaid_format_date( gmdate( 'Y-m-d', strtotime( $this->report_range['before'] ) ) );
244
+        $report_data->decimals_sep      = wpinv_decimal_separator();
245
+
246
+        $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
247
+        $data    = $report_data;
248
+        unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
249
+        $data    = $this->add_additional_fields_to_object( (array) $data, $request );
250
+        $data    = $this->filter_response_by_context( $data, $context );
251
+
252
+        // Wrap the data in a response object.
253
+        $response = rest_ensure_response( $data );
254
+        $response->add_links(
255
+            array(
256
+                'about' => array(
257
+                    'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
258
+                ),
259
+            )
260
+        );
261
+
262
+        return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
263
+    }
264
+
265
+    /**
266
+     * Get report data.
267
+     *
268
+     * @return stdClass
269
+     */
270
+    public function get_report_data() {
271
+        if ( empty( $this->report_data ) ) {
272
+            $this->query_report_data();
273
+        }
274
+        return $this->report_data;
275
+    }
276
+
277
+    /**
278
+     * Get all data needed for this report and store in the class.
279
+     */
280
+    protected function query_report_data() {
281
+
282
+        // Prepare reports.
283
+        $this->report_data = (object) array(
284
+            'invoice_counts' => $this->query_invoice_counts(), //count, post_date
285
+            'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
286
+            'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
287
+            'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
288
+            'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
289
+            'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
290
+            'previous_range' => $this->previous_range,
291
+        );
292
+
293
+        // Calculated totals.
294
+        $this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
295
+        $this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
296
+        $this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
297
+        $this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
298
+        $this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
299
+        $this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
300
+        $this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
301
+        $this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
302
+        $this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
303
+        $this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
304
+        $this->report_data->refunded_subtotal  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
305
+        $this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
306
+
307
+        // Calculate average based on net.
308
+        $this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
309
+        $this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
310
+
311
+        // Total invoices in this period, even if refunded.
312
+        $this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
313
+
314
+        // Items invoiced in this period, even if refunded.
315
+        $this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
316
+
317
+        // 3rd party filtering of report data
318
+        $this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data, $this );
319
+    }
320
+
321
+    /**
322
+     * Prepares invoice counts.
323
+     *
324
+     * @return array.
325
+     */
326
+    protected function query_invoice_counts() {
327
+
328
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
329
+            array(
330
+                'data'           => array(
331
+                    'ID'        => array(
332
+                        'type'     => 'post_data',
333
+                        'function' => 'COUNT',
334
+                        'name'     => 'count',
335
+                        'distinct' => true,
336
+                    ),
337
+                    'post_date' => array(
338
+                        'type'     => 'post_data',
339
+                        'function' => 'MIN',
340
+                        'name'     => 'post_date',
341
+                    ),
342
+                ),
343
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
344
+                'order_by'       => 'post_date ASC',
345
+                'query_type'     => 'get_results',
346
+                'filter_range'   => $this->report_range,
347
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
348
+            )
349
+        );
350
+
351
+    }
352
+
353
+    /**
354
+     * Prepares coupon counts.
355
+     *
356
+     * @return array.
357
+     */
358
+    protected function query_coupon_counts() {
359
+
360
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
361
+            array(
362
+                'data'           => array(
363
+                    'discount'  => array(
364
+                        'type'     => 'invoice_data',
365
+                        'function' => 'SUM',
366
+                        'name'     => 'discount_amount',
367
+                    ),
368
+                    'post_date' => array(
369
+                        'type'     => 'post_data',
370
+                        'function' => 'MIN',
371
+                        'name'     => 'post_date',
372
+                    ),
373
+                ),
374
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
375
+                'order_by'       => 'post_date ASC',
376
+                'query_type'     => 'get_results',
377
+                'filter_range'   => $this->report_range,
378
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
379
+            )
380
+        );
381
+
382
+    }
383
+
384
+    /**
385
+     * Prepares item counts.
386
+     *
387
+     * @return array.
388
+     */
389
+    protected function query_item_counts() {
390
+
391
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
392
+            array(
393
+                'data'           => array(
394
+                    'quantity'  => array(
395
+                        'type'     => 'invoice_item',
396
+                        'function' => 'SUM',
397
+                        'name'     => 'invoice_item_count',
398
+                    ),
399
+                    'post_date' => array(
400
+                        'type'     => 'post_data',
401
+                        'function' => 'MIN',
402
+                        'name'     => 'post_date',
403
+                    ),
404
+                ),
405
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
406
+                'order_by'       => 'post_date ASC',
407
+                'query_type'     => 'get_results',
408
+                'filter_range'   => $this->report_range,
409
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
410
+            )
411
+        );
412
+
413
+    }
414
+
415
+    /**
416
+     * Prepares refunded item counts.
417
+     *
418
+     * @return array.
419
+     */
420
+    protected function count_refunded_items() {
421
+
422
+        return (int) GetPaid_Reports_Helper::get_invoice_report_data(
423
+            array(
424
+                'data'           => array(
425
+                    'quantity' => array(
426
+                        'type'     => 'invoice_item',
427
+                        'function' => 'SUM',
428
+                        'name'     => 'invoice_item_count',
429
+                    ),
430
+                ),
431
+                'query_type'     => 'get_var',
432
+                'filter_range'   => $this->report_range,
433
+                'invoice_status' => array( 'wpi-refunded' ),
434
+            )
435
+        );
436
+
437
+    }
438
+
439
+    /**
440
+     * Prepares daily invoice totals.
441
+     *
442
+     * @return array.
443
+     */
444
+    protected function query_invoice_totals() {
445
+
446
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
447
+            array(
448
+                'data'           => array(
449
+                    'total'      => array(
450
+                        'type'     => 'invoice_data',
451
+                        'function' => 'SUM',
452
+                        'name'     => 'total_sales',
453
+                    ),
454
+                    'tax'        => array(
455
+                        'type'     => 'invoice_data',
456
+                        'function' => 'SUM',
457
+                        'name'     => 'total_tax',
458
+                    ),
459
+                    'discount'   => array(
460
+                        'type'     => 'invoice_data',
461
+                        'function' => 'SUM',
462
+                        'name'     => 'total_discount',
463
+                    ),
464
+                    'fees_total' => array(
465
+                        'type'     => 'invoice_data',
466
+                        'function' => 'SUM',
467
+                        'name'     => 'total_fees',
468
+                    ),
469
+                    'subtotal'   => array(
470
+                        'type'     => 'invoice_data',
471
+                        'function' => 'SUM',
472
+                        'name'     => 'subtotal',
473
+                    ),
474
+                    'post_date'  => array(
475
+                        'type'     => 'post_data',
476
+                        'function' => '',
477
+                        'name'     => 'post_date',
478
+                    ),
479
+                ),
480
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
481
+                'order_by'       => 'post_date ASC',
482
+                'query_type'     => 'get_results',
483
+                'filter_range'   => $this->report_range,
484
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-renewal' ),
485
+            )
486
+        );
487
+
488
+    }
489
+
490
+    /**
491
+     * Prepares daily invoice totals.
492
+     *
493
+     * @return array.
494
+     */
495
+    protected function query_refunded_totals() {
496
+
497
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
498
+            array(
499
+                'data'           => array(
500
+                    'total'      => array(
501
+                        'type'     => 'invoice_data',
502
+                        'function' => 'SUM',
503
+                        'name'     => 'total_sales',
504
+                    ),
505
+                    'tax'        => array(
506
+                        'type'     => 'invoice_data',
507
+                        'function' => 'SUM',
508
+                        'name'     => 'total_tax',
509
+                    ),
510
+                    'discount'   => array(
511
+                        'type'     => 'invoice_data',
512
+                        'function' => 'SUM',
513
+                        'name'     => 'total_discount',
514
+                    ),
515
+                    'fees_total' => array(
516
+                        'type'     => 'invoice_data',
517
+                        'function' => 'SUM',
518
+                        'name'     => 'total_fees',
519
+                    ),
520
+                    'subtotal'   => array(
521
+                        'type'     => 'invoice_data',
522
+                        'function' => 'SUM',
523
+                        'name'     => 'subtotal',
524
+                    ),
525
+                    'post_date'  => array(
526
+                        'type'     => 'post_data',
527
+                        'function' => '',
528
+                        'name'     => 'post_date',
529
+                    ),
530
+                ),
531
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
532
+                'order_by'       => 'post_date ASC',
533
+                'query_type'     => 'get_results',
534
+                'filter_range'   => $this->report_range,
535
+                'invoice_status' => array( 'wpi-refunded' ),
536
+            )
537
+        );
538
+
539
+    }
540
+
541
+    /**
542
+     * Get the Report's schema, conforming to JSON Schema.
543
+     *
544
+     * @return array
545
+     */
546
+    public function get_item_schema() {
547
+
548
+        $schema = array(
549
+            '$schema'    => 'http://json-schema.org/draft-04/schema#',
550
+            'title'      => 'sales_report',
551
+            'type'       => 'object',
552
+            'properties' => array(
553
+                'total_sales'         => array(
554
+                    'description' => __( 'Gross sales in the period.', 'invoicing' ),
555
+                    'type'        => 'string',
556
+                    'context'     => array( 'view' ),
557
+                    'readonly'    => true,
558
+                ),
559
+                'net_sales'           => array(
560
+                    'description' => __( 'Net sales in the period.', 'invoicing' ),
561
+                    'type'        => 'string',
562
+                    'context'     => array( 'view' ),
563
+                    'readonly'    => true,
564
+                ),
565
+                'average_sales'       => array(
566
+                    'description' => __( 'Average net daily sales.', 'invoicing' ),
567
+                    'type'        => 'string',
568
+                    'context'     => array( 'view' ),
569
+                    'readonly'    => true,
570
+                ),
571
+                'average_total_sales' => array(
572
+                    'description' => __( 'Average gross daily sales.', 'invoicing' ),
573
+                    'type'        => 'string',
574
+                    'context'     => array( 'view' ),
575
+                    'readonly'    => true,
576
+                ),
577
+                'total_invoices'      => array(
578
+                    'description' => __( 'Number of paid invoices.', 'invoicing' ),
579
+                    'type'        => 'integer',
580
+                    'context'     => array( 'view' ),
581
+                    'readonly'    => true,
582
+                ),
583
+                'total_items'         => array(
584
+                    'description' => __( 'Number of items purchased.', 'invoicing' ),
585
+                    'type'        => 'integer',
586
+                    'context'     => array( 'view' ),
587
+                    'readonly'    => true,
588
+                ),
589
+                'refunded_items'      => array(
590
+                    'description' => __( 'Number of items refunded.', 'invoicing' ),
591
+                    'type'        => 'integer',
592
+                    'context'     => array( 'view' ),
593
+                    'readonly'    => true,
594
+                ),
595
+                'total_tax'           => array(
596
+                    'description' => __( 'Total charged for taxes.', 'invoicing' ),
597
+                    'type'        => 'string',
598
+                    'context'     => array( 'view' ),
599
+                    'readonly'    => true,
600
+                ),
601
+                'total_refunded_tax'  => array(
602
+                    'description' => __( 'Total refunded for taxes.', 'invoicing' ),
603
+                    'type'        => 'string',
604
+                    'context'     => array( 'view' ),
605
+                    'readonly'    => true,
606
+                ),
607
+                'total_fees'          => array(
608
+                    'description' => __( 'Total fees charged.', 'invoicing' ),
609
+                    'type'        => 'string',
610
+                    'context'     => array( 'view' ),
611
+                    'readonly'    => true,
612
+                ),
613
+                'total_refunds'       => array(
614
+                    'description' => __( 'Total of refunded invoices.', 'invoicing' ),
615
+                    'type'        => 'integer',
616
+                    'context'     => array( 'view' ),
617
+                    'readonly'    => true,
618
+                ),
619
+                'net_refunds'         => array(
620
+                    'description' => __( 'Net of refunded invoices.', 'invoicing' ),
621
+                    'type'        => 'integer',
622
+                    'context'     => array( 'view' ),
623
+                    'readonly'    => true,
624
+                ),
625
+                'total_discount'      => array(
626
+                    'description' => __( 'Total of discounts used.', 'invoicing' ),
627
+                    'type'        => 'integer',
628
+                    'context'     => array( 'view' ),
629
+                    'readonly'    => true,
630
+                ),
631
+                'totals'              => array(
632
+                    'description' => __( 'Totals.', 'invoicing' ),
633
+                    'type'        => 'array',
634
+                    'items'       => array(
635
+                        'type' => 'array',
636
+                    ),
637
+                    'context'     => array( 'view' ),
638
+                    'readonly'    => true,
639
+                ),
640
+                'interval'            => array(
641
+                    'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
642
+                    'type'        => 'integer',
643
+                    'context'     => array( 'view' ),
644
+                    'readonly'    => true,
645
+                ),
646
+                'previous_range'      => array(
647
+                    'description' => __( 'The previous report period.', 'invoicing' ),
648
+                    'type'        => 'array',
649
+                    'items'       => array(
650
+                        'type' => 'string',
651
+                    ),
652
+                    'context'     => array( 'view' ),
653
+                    'readonly'    => true,
654
+                ),
655
+                'grouped_by'          => array(
656
+                    'description' => __( 'The period used to group the totals.', 'invoicing' ),
657
+                    'type'        => 'string',
658
+                    'context'     => array( 'view' ),
659
+                    'enum'        => array( 'day', 'month' ),
660
+                    'readonly'    => true,
661
+                ),
662
+                'currency'            => array(
663
+                    'description' => __( 'The default store currency.', 'invoicing' ),
664
+                    'type'        => 'string',
665
+                    'context'     => array( 'view' ),
666
+                    'readonly'    => true,
667
+                ),
668
+                'currency_symbol'     => array(
669
+                    'description' => __( 'The default store currency symbol.', 'invoicing' ),
670
+                    'type'        => 'string',
671
+                    'context'     => array( 'view' ),
672
+                    'readonly'    => true,
673
+                ),
674
+                'currency_position'   => array(
675
+                    'description' => __( 'The default store currency position.', 'invoicing' ),
676
+                    'type'        => 'string',
677
+                    'context'     => array( 'view' ),
678
+                    'readonly'    => true,
679
+                ),
680
+                'decimal_places'      => array(
681
+                    'description' => __( 'The default store decimal places.', 'invoicing' ),
682
+                    'type'        => 'string',
683
+                    'context'     => array( 'view' ),
684
+                    'readonly'    => true,
685
+                ),
686
+                'thousands_sep'       => array(
687
+                    'description' => __( 'The default store thousands separator.', 'invoicing' ),
688
+                    'type'        => 'string',
689
+                    'context'     => array( 'view' ),
690
+                    'readonly'    => true,
691
+                ),
692
+                'decimals_sep'        => array(
693
+                    'description' => __( 'The default store decimals separator.', 'invoicing' ),
694
+                    'type'        => 'string',
695
+                    'context'     => array( 'view' ),
696
+                    'readonly'    => true,
697
+                ),
698
+            ),
699
+        );
700
+
701
+        return $this->add_additional_fields_schema( $schema );
702
+
703
+    }
704 704
 
705 705
 }
Please login to merge, or discard this patch.
includes/api/class-getpaid-rest-date-based-controller.php 1 patch
Indentation   +492 added lines, -492 removed lines patch added patch discarded remove patch
@@ -16,496 +16,496 @@
 block discarded – undo
16 16
  */
17 17
 class GetPaid_REST_Date_Based_Controller extends GetPaid_REST_Controller {
18 18
 
19
-	/**
20
-	 * Group response items by day or month.
21
-	 *
22
-	 * @var string
23
-	 */
24
-	public $groupby = 'day';
25
-
26
-	/**
27
-	 * Returns an array with arguments to request the previous report.
28
-	 *
29
-	 * @var array
30
-	 */
31
-	public $previous_range = array();
32
-
33
-	/**
34
-	 * The period interval.
35
-	 *
36
-	 * @var int
37
-	 */
38
-	public $interval;
39
-
40
-	/**
41
-	 * Retrieves the before and after dates.
42
-	 *
43
-	 * @param WP_REST_Request $request Request object.
44
-	 * @return array The appropriate date range.
45
-	 */
46
-	public function get_date_range( $request ) {
47
-
48
-		// Check if the period is x_days.
49
-		if ( preg_match( '/^(\d+)_days$/', $request['period'], $matches ) ) {
50
-			$date_range = $this->get_x_days_date_range( absint( $matches[1] ) );
51
-		} elseif ( is_callable( array( $this, 'get_' . $request['period'] . '_date_range' ) ) ) {
52
-			$date_range = call_user_func( array( $this, 'get_' . $request['period'] . '_date_range' ), $request );
53
-		} else {
54
-			$request['period'] = '7_days';
55
-			$date_range        = $this->get_x_days_date_range();
56
-		}
57
-
58
-		// 3 months max for day view.
59
-		$before = strtotime( $date_range['before'] );
60
-		$after  = strtotime( $date_range['after'] );
61
-		if ( floor( ( $before - $after ) / MONTH_IN_SECONDS ) > 2 ) {
62
-			$this->groupby = 'month';
63
-		}
64
-
65
-		$this->prepare_interval( $date_range );
66
-
67
-		return $date_range;
68
-
69
-	}
70
-
71
-	/**
72
-	 * Groups by month or days.
73
-	 *
74
-	 * @param array $range Date range.
75
-	 * @return array The appropriate date range.
76
-	 */
77
-	public function prepare_interval( $range ) {
78
-
79
-		$before = strtotime( $range['before'] );
80
-		$after  = strtotime( $range['after'] );
81
-		if ( 'day' === $this->groupby ) {
82
-			$difference     = max( DAY_IN_SECONDS, ( DAY_IN_SECONDS + $before - $after ) ); // Prevent division by 0;
83
-			$this->interval = absint( ceil( max( 1, $difference / DAY_IN_SECONDS ) ) );
84
-			return;
85
-		}
86
-
87
-		$this->interval = 0;
88
-		$min_date       = strtotime( gmdate( 'Y-m-01', $after ) );
89
-
90
-		while ( $min_date <= $before ) {
91
-			$this->interval ++;
92
-			$min_date = strtotime( '+1 MONTH', $min_date );
93
-		}
94
-
95
-		$this->interval = max( 1, $this->interval );
96
-
97
-	}
98
-
99
-	/**
100
-	 * Retrieves a custom date range.
101
-	 *
102
-	 * @param WP_REST_Request $request Request object.
103
-	 * @return array The appropriate date range.
104
-	 */
105
-	public function get_custom_date_range( $request ) {
106
-
107
-		$after  = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $request['after'] ) ) );
108
-		$before = gmdate( 'Y-m-d' );
109
-
110
-		if ( ! empty( $request['before'] ) ) {
111
-			$before  = min( $before, strtotime( sanitize_text_field( $request['before'] ) ) );
112
-		}
113
-
114
-		// Set the previous date range.
115
-		$difference           = $before - $after;
116
-		$this->previous_range = array(
117
-			'period' => 'custom',
118
-			'before' => gmdate( 'Y-m-d', $before - $difference - DAY_IN_SECONDS ),
119
-			'after'  => gmdate( 'Y-m-d', $after - $difference - DAY_IN_SECONDS ),
120
-		);
121
-
122
-		// Generate the report.
123
-		return array(
124
-			'before' => gmdate( 'Y-m-d', $before ),
125
-			'after'  => gmdate( 'Y-m-d', $after ),
126
-		);
127
-
128
-	}
129
-
130
-	/**
131
-	 * Retrieves todays date range.
132
-	 *
133
-	 * @return array The appropriate date range.
134
-	 */
135
-	public function get_today_date_range() {
136
-
137
-		// Set the previous date range.
138
-		$this->previous_range = array(
139
-			'period' => 'yesterday',
140
-		);
141
-
142
-		// Generate the report.
143
-		return array(
144
-			'before' => gmdate( 'Y-m-d' ),
145
-			'after'  => gmdate( 'Y-m-d' ),
146
-		);
147
-
148
-	}
149
-
150
-	/**
151
-	 * Retrieves yesterdays date range.
152
-	 *
153
-	 * @return array The appropriate date range.
154
-	 */
155
-	public function get_yesterday_date_range() {
156
-
157
-		// Set the previous date range.
158
-		$this->previous_range = array(
159
-			'period' => 'custom',
160
-			'before' => gmdate( 'Y-m-d', strtotime( '-2 days' ) ),
161
-			'after'  => gmdate( 'Y-m-d', strtotime( '-2 days' ) ),
162
-		);
163
-
164
-		// Generate the report.
165
-		return array(
166
-			'before' => gmdate( 'Y-m-d', strtotime( '-1 day' ) ),
167
-			'after'  => gmdate( 'Y-m-d', strtotime( '-1 day' ) ),
168
-		);
169
-
170
-	}
171
-
172
-	/**
173
-	 * Retrieves this week's date range.
174
-	 *
175
-	 * @return array The appropriate date range.
176
-	 */
177
-	public function get_week_date_range() {
178
-
179
-		// Set the previous date range.
180
-		$this->previous_range = array(
181
-			'period' => 'last_week',
182
-		);
183
-
184
-		// Generate the report.
185
-		$week_starts = absint( get_option( 'start_of_week' ) );
186
-		return array(
187
-			'before' => gmdate( 'Y-m-d' ),
188
-			'after'  => gmdate( 'Y-m-d', strtotime( 'next Sunday -' . ( 7 - $week_starts ) . ' days' ) ),
189
-		);
190
-	}
191
-
192
-	/**
193
-	 * Retrieves last week's date range.
194
-	 *
195
-	 * @return array The appropriate date range.
196
-	 */
197
-	public function get_last_week_date_range() {
198
-
199
-		$week_starts = absint( get_option( 'start_of_week' ) );
200
-		$week_starts = strtotime( 'last Sunday -' . ( 7 - $week_starts ) . ' days' );
201
-		$date_range  = array(
202
-			'before' => gmdate( 'Y-m-d', $week_starts + 6 * DAY_IN_SECONDS ),
203
-			'after'  => gmdate( 'Y-m-d', $week_starts ),
204
-		);
205
-
206
-		// Set the previous date range.
207
-		$week_starts          = $week_starts - 7 * DAY_IN_SECONDS;
208
-		$this->previous_range = array(
209
-			'period' => 'custom',
210
-			'before' => gmdate( 'Y-m-d', $week_starts + 6 * DAY_IN_SECONDS ),
211
-			'after'  => gmdate( 'Y-m-d', $week_starts ),
212
-		);
213
-
214
-		// Generate the report.
215
-		return $date_range;
216
-	}
217
-
218
-	/**
219
-	 * Retrieves last x days date range.
220
-	 *
221
-	 * @return array The appropriate date range.
222
-	 */
223
-	public function get_x_days_date_range( $days = 7 ) {
224
-
225
-		$days--;
226
-
227
-		$date_range  = array(
228
-			'before' => gmdate( 'Y-m-d' ),
229
-			'after'  => gmdate( 'Y-m-d', strtotime( "-$days days" ) ),
230
-		);
231
-
232
-		$days++;
233
-
234
-		// Set the previous date range.
235
-		$this->previous_range = array(
236
-			'period' => 'custom',
237
-			'before' => gmdate( 'Y-m-d', strtotime( $date_range['before'] ) - $days * DAY_IN_SECONDS ),
238
-			'after'  => gmdate( 'Y-m-d', strtotime( $date_range['after'] ) - $days * DAY_IN_SECONDS ),
239
-		);
240
-
241
-		// Generate the report.
242
-		return $date_range;
243
-	}
244
-
245
-	/**
246
-	 * Retrieves this month date range.
247
-	 *
248
-	 * @return array The appropriate date range.
249
-	 */
250
-	public function get_month_date_range() {
251
-
252
-		// Set the previous date range.
253
-		$this->previous_range = array(
254
-			'period' => 'last_month',
255
-		);
256
-
257
-		// Generate the report.
258
-		return array(
259
-			'after'  => gmdate( 'Y-m-01' ),
260
-			'before' => gmdate( 'Y-m-t' ),
261
-		);
262
-
263
-	}
264
-
265
-	/**
266
-	 * Retrieves last month's date range.
267
-	 *
268
-	 * @return array The appropriate date range.
269
-	 */
270
-	public function get_last_month_date_range() {
271
-
272
-		// Set the previous date range.
273
-		$this->previous_range = array(
274
-			'period' => 'custom',
275
-			'after'  => gmdate( 'Y-m-01', strtotime( '-2 months' ) ),
276
-			'before' => gmdate( 'Y-m-t', strtotime( '-2 months' ) ),
277
-		);
278
-
279
-		// Generate the report.
280
-		return array(
281
-			'after'  => gmdate( 'Y-m-01', strtotime( 'last month' ) ),
282
-			'before' => gmdate( 'Y-m-t', strtotime( 'last month' ) ),
283
-		);
284
-
285
-	}
286
-
287
-	/**
288
-	 * Retrieves this quarter date range.
289
-	 *
290
-	 * @return array The available quarters.
291
-	 */
292
-	public function get_quarters() {
293
-
294
-		$year      = (int) gmdate( 'Y' );
295
-		$last_year = (int) $year - 1;
296
-		return array(
297
-
298
-			// Third quarter of previous year: July 1st to September 30th
299
-			array(
300
-				'before' => "{$last_year}-09-30",
301
-				'after'  => "{$last_year}-07-01",
302
-			),
303
-
304
-			// Last quarter of previous year: October 1st to December 31st
305
-			array(
306
-				'before' => "{$last_year}-12-31",
307
-        		'after'  => "{$last_year}-10-01",
308
-			),
309
-
310
-			// First quarter: January 1st to March 31st
311
-			array(
312
-				'before' => "{$year}-03-31",
313
-				'after'  => "{$year}-01-01",
314
-			),
315
-
316
-			// Second quarter: April 1st to June 30th
317
-			array(
318
-				'before' => "{$year}-06-30",
319
-				'after'  => "{$year}-04-01",
320
-			),
321
-
322
-			// Third quarter: July 1st to September 30th
323
-			array(
324
-				'before' => "{$year}-09-30",
325
-				'after'  => "{$year}-07-01",
326
-			),
327
-
328
-			// Fourth quarter: October 1st to December 31st
329
-			array(
330
-				'before' => "{$year}-12-31",
331
-				'after'  => "{$year}-10-01",
332
-			),
333
-		);
334
-	}
335
-
336
-	/**
337
-	 * Retrieves the current quater.
338
-	 *
339
-	 * @return int The current quarter.
340
-	 */
341
-	public function get_quarter() {
342
-
343
-		$month    = (int) gmdate( 'n' );
344
-		$quarters = array( 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 );
345
-		return $quarters[ $month - 1 ];
346
-
347
-	}
348
-
349
-	/**
350
-	 * Retrieves this quarter date range.
351
-	 *
352
-	 * @return array The appropriate date range.
353
-	 */
354
-	public function get_quarter_date_range() {
355
-
356
-		// Set the previous date range.
357
-		$this->previous_range = array(
358
-			'period' => 'last_quarter',
359
-		);
360
-
361
-		// Generate the report.
362
-		$quarter  = $this->get_quarter();
363
-		$quarters = $this->get_quarters();
364
-		return $quarters[ $quarter + 1 ];
365
-
366
-	}
367
-
368
-	/**
369
-	 * Retrieves last quarter's date range.
370
-	 *
371
-	 * @return array The appropriate date range.
372
-	 */
373
-	public function get_last_quarter_date_range() {
374
-
375
-		$quarters = $this->get_quarters();
376
-		$quarter  = $this->get_quarter();
377
-
378
-		// Set the previous date range.
379
-		$this->previous_range = array_merge(
380
-			$quarters[ $quarter - 1 ],
381
-			array( 'period' => 'custom' )
382
-		);
383
-
384
-		// Generate the report.
385
-		return $quarters[ $quarter ];
386
-
387
-	}
388
-
389
-	/**
390
-	 * Retrieves this year date range.
391
-	 *
392
-	 * @return array The appropriate date range.
393
-	 */
394
-	public function get_year_date_range() {
395
-
396
-		// Set the previous date range.
397
-		$this->previous_range = array(
398
-			'period' => 'last_year',
399
-		);
400
-
401
-		// Generate the report.
402
-		return array(
403
-			'after'  => gmdate( 'Y-01-01' ),
404
-			'before' => gmdate( 'Y-12-31' ),
405
-		);
406
-
407
-	}
408
-
409
-	/**
410
-	 * Retrieves last year date range.
411
-	 *
412
-	 * @return array The appropriate date range.
413
-	 */
414
-	public function get_last_year_date_range() {
415
-
416
-		// Set the previous date range.
417
-		$this->previous_range = array(
418
-			'period' => 'custom',
419
-			'after'  => gmdate( 'Y-01-01', strtotime( '-2 years' ) ),
420
-			'before' => gmdate( 'Y-12-31', strtotime( '-2 years' ) ),
421
-		);
422
-
423
-		// Generate the report.
424
-		return array(
425
-			'after'  => gmdate( 'Y-01-01', strtotime( 'last year' ) ),
426
-			'before' => gmdate( 'Y-12-31', strtotime( 'last year' ) ),
427
-		);
428
-
429
-	}
430
-
431
-	/**
432
-	 * Prepare a the request date for SQL usage.
433
-	 *
434
-	 * @param WP_REST_Request $request Request object.
435
-	 * @param string $date_field The date field.
436
-	 * @return string The appropriate SQL.
437
-	 */
438
-	public function get_date_range_sql( $request, $date_field ) {
439
-		global $wpdb;
440
-
441
-		$sql = '1=1';
442
-		$range = $this->get_date_range( $request );
443
-
444
-		if ( ! empty( $range['after'] ) ) {
445
-			$sql .= ' AND ' . $wpdb->prepare(
446
-				"$date_field >= %s",
447
-				$range['after']
448
-			);
449
-		}
450
-
451
-		if ( ! empty( $range['before'] ) ) {
452
-			$sql .= ' AND ' . $wpdb->prepare(
453
-				"$date_field <= %s",
454
-				$range['before']
455
-			);
456
-		}
457
-
458
-		return $sql;
459
-
460
-	}
461
-
462
-	/**
463
-	 * Prepares a group by query.
464
-	 *
465
-	 * @param string $date_field The date field.
466
-	 * @return string The appropriate SQL.
467
-	 */
468
-	public function get_group_by_sql( $date_field ) {
469
-
470
-		if ( 'day' === $this->groupby ) {
471
-			return "YEAR($date_field), MONTH($date_field), DAY($date_field)";
472
-		}
473
-
474
-		return "YEAR($date_field), MONTH($date_field)";
475
-	}
476
-
477
-	/**
478
-	 * Get the query params for collections.
479
-	 *
480
-	 * @return array
481
-	 */
482
-	public function get_collection_params() {
483
-		return array(
484
-			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
485
-			'period'  => array(
486
-				'description'       => __( 'Limit to results of a specific period.', 'invoicing' ),
487
-				'type'              => 'string',
488
-				'enum'              => array( 'custom', 'today', 'yesterday', 'week', 'last_week', '7_days', '30_days', '60_days', '90_days', '180_days', 'month', 'last_month', 'quarter', 'last_quarter', 'year', 'last_year', 'quarter', 'last_quarter' ),
489
-				'validate_callback' => 'rest_validate_request_arg',
490
-				'sanitize_callback' => 'sanitize_text_field',
491
-				'default'           => '7_days',
492
-			),
493
-			'after'   => array(
494
-				/* translators: %s: date format */
495
-				'description'       => sprintf( __( 'Limit to results after a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
496
-				'type'              => 'string',
497
-				'validate_callback' => 'rest_validate_request_arg',
498
-				'sanitize_callback' => 'sanitize_text_field',
499
-				'default'           => gmdate( 'Y-m-d', strtotime( '-7 days' ) ),
500
-			),
501
-			'before'  => array(
502
-				/* translators: %s: date format */
503
-				'description'       => sprintf( __( 'Limit to results before a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
504
-				'type'              => 'string',
505
-				'validate_callback' => 'rest_validate_request_arg',
506
-				'sanitize_callback' => 'sanitize_text_field',
507
-				'default'           => gmdate( 'Y-m-d' ),
508
-			),
509
-		);
510
-	}
19
+    /**
20
+     * Group response items by day or month.
21
+     *
22
+     * @var string
23
+     */
24
+    public $groupby = 'day';
25
+
26
+    /**
27
+     * Returns an array with arguments to request the previous report.
28
+     *
29
+     * @var array
30
+     */
31
+    public $previous_range = array();
32
+
33
+    /**
34
+     * The period interval.
35
+     *
36
+     * @var int
37
+     */
38
+    public $interval;
39
+
40
+    /**
41
+     * Retrieves the before and after dates.
42
+     *
43
+     * @param WP_REST_Request $request Request object.
44
+     * @return array The appropriate date range.
45
+     */
46
+    public function get_date_range( $request ) {
47
+
48
+        // Check if the period is x_days.
49
+        if ( preg_match( '/^(\d+)_days$/', $request['period'], $matches ) ) {
50
+            $date_range = $this->get_x_days_date_range( absint( $matches[1] ) );
51
+        } elseif ( is_callable( array( $this, 'get_' . $request['period'] . '_date_range' ) ) ) {
52
+            $date_range = call_user_func( array( $this, 'get_' . $request['period'] . '_date_range' ), $request );
53
+        } else {
54
+            $request['period'] = '7_days';
55
+            $date_range        = $this->get_x_days_date_range();
56
+        }
57
+
58
+        // 3 months max for day view.
59
+        $before = strtotime( $date_range['before'] );
60
+        $after  = strtotime( $date_range['after'] );
61
+        if ( floor( ( $before - $after ) / MONTH_IN_SECONDS ) > 2 ) {
62
+            $this->groupby = 'month';
63
+        }
64
+
65
+        $this->prepare_interval( $date_range );
66
+
67
+        return $date_range;
68
+
69
+    }
70
+
71
+    /**
72
+     * Groups by month or days.
73
+     *
74
+     * @param array $range Date range.
75
+     * @return array The appropriate date range.
76
+     */
77
+    public function prepare_interval( $range ) {
78
+
79
+        $before = strtotime( $range['before'] );
80
+        $after  = strtotime( $range['after'] );
81
+        if ( 'day' === $this->groupby ) {
82
+            $difference     = max( DAY_IN_SECONDS, ( DAY_IN_SECONDS + $before - $after ) ); // Prevent division by 0;
83
+            $this->interval = absint( ceil( max( 1, $difference / DAY_IN_SECONDS ) ) );
84
+            return;
85
+        }
86
+
87
+        $this->interval = 0;
88
+        $min_date       = strtotime( gmdate( 'Y-m-01', $after ) );
89
+
90
+        while ( $min_date <= $before ) {
91
+            $this->interval ++;
92
+            $min_date = strtotime( '+1 MONTH', $min_date );
93
+        }
94
+
95
+        $this->interval = max( 1, $this->interval );
96
+
97
+    }
98
+
99
+    /**
100
+     * Retrieves a custom date range.
101
+     *
102
+     * @param WP_REST_Request $request Request object.
103
+     * @return array The appropriate date range.
104
+     */
105
+    public function get_custom_date_range( $request ) {
106
+
107
+        $after  = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $request['after'] ) ) );
108
+        $before = gmdate( 'Y-m-d' );
109
+
110
+        if ( ! empty( $request['before'] ) ) {
111
+            $before  = min( $before, strtotime( sanitize_text_field( $request['before'] ) ) );
112
+        }
113
+
114
+        // Set the previous date range.
115
+        $difference           = $before - $after;
116
+        $this->previous_range = array(
117
+            'period' => 'custom',
118
+            'before' => gmdate( 'Y-m-d', $before - $difference - DAY_IN_SECONDS ),
119
+            'after'  => gmdate( 'Y-m-d', $after - $difference - DAY_IN_SECONDS ),
120
+        );
121
+
122
+        // Generate the report.
123
+        return array(
124
+            'before' => gmdate( 'Y-m-d', $before ),
125
+            'after'  => gmdate( 'Y-m-d', $after ),
126
+        );
127
+
128
+    }
129
+
130
+    /**
131
+     * Retrieves todays date range.
132
+     *
133
+     * @return array The appropriate date range.
134
+     */
135
+    public function get_today_date_range() {
136
+
137
+        // Set the previous date range.
138
+        $this->previous_range = array(
139
+            'period' => 'yesterday',
140
+        );
141
+
142
+        // Generate the report.
143
+        return array(
144
+            'before' => gmdate( 'Y-m-d' ),
145
+            'after'  => gmdate( 'Y-m-d' ),
146
+        );
147
+
148
+    }
149
+
150
+    /**
151
+     * Retrieves yesterdays date range.
152
+     *
153
+     * @return array The appropriate date range.
154
+     */
155
+    public function get_yesterday_date_range() {
156
+
157
+        // Set the previous date range.
158
+        $this->previous_range = array(
159
+            'period' => 'custom',
160
+            'before' => gmdate( 'Y-m-d', strtotime( '-2 days' ) ),
161
+            'after'  => gmdate( 'Y-m-d', strtotime( '-2 days' ) ),
162
+        );
163
+
164
+        // Generate the report.
165
+        return array(
166
+            'before' => gmdate( 'Y-m-d', strtotime( '-1 day' ) ),
167
+            'after'  => gmdate( 'Y-m-d', strtotime( '-1 day' ) ),
168
+        );
169
+
170
+    }
171
+
172
+    /**
173
+     * Retrieves this week's date range.
174
+     *
175
+     * @return array The appropriate date range.
176
+     */
177
+    public function get_week_date_range() {
178
+
179
+        // Set the previous date range.
180
+        $this->previous_range = array(
181
+            'period' => 'last_week',
182
+        );
183
+
184
+        // Generate the report.
185
+        $week_starts = absint( get_option( 'start_of_week' ) );
186
+        return array(
187
+            'before' => gmdate( 'Y-m-d' ),
188
+            'after'  => gmdate( 'Y-m-d', strtotime( 'next Sunday -' . ( 7 - $week_starts ) . ' days' ) ),
189
+        );
190
+    }
191
+
192
+    /**
193
+     * Retrieves last week's date range.
194
+     *
195
+     * @return array The appropriate date range.
196
+     */
197
+    public function get_last_week_date_range() {
198
+
199
+        $week_starts = absint( get_option( 'start_of_week' ) );
200
+        $week_starts = strtotime( 'last Sunday -' . ( 7 - $week_starts ) . ' days' );
201
+        $date_range  = array(
202
+            'before' => gmdate( 'Y-m-d', $week_starts + 6 * DAY_IN_SECONDS ),
203
+            'after'  => gmdate( 'Y-m-d', $week_starts ),
204
+        );
205
+
206
+        // Set the previous date range.
207
+        $week_starts          = $week_starts - 7 * DAY_IN_SECONDS;
208
+        $this->previous_range = array(
209
+            'period' => 'custom',
210
+            'before' => gmdate( 'Y-m-d', $week_starts + 6 * DAY_IN_SECONDS ),
211
+            'after'  => gmdate( 'Y-m-d', $week_starts ),
212
+        );
213
+
214
+        // Generate the report.
215
+        return $date_range;
216
+    }
217
+
218
+    /**
219
+     * Retrieves last x days date range.
220
+     *
221
+     * @return array The appropriate date range.
222
+     */
223
+    public function get_x_days_date_range( $days = 7 ) {
224
+
225
+        $days--;
226
+
227
+        $date_range  = array(
228
+            'before' => gmdate( 'Y-m-d' ),
229
+            'after'  => gmdate( 'Y-m-d', strtotime( "-$days days" ) ),
230
+        );
231
+
232
+        $days++;
233
+
234
+        // Set the previous date range.
235
+        $this->previous_range = array(
236
+            'period' => 'custom',
237
+            'before' => gmdate( 'Y-m-d', strtotime( $date_range['before'] ) - $days * DAY_IN_SECONDS ),
238
+            'after'  => gmdate( 'Y-m-d', strtotime( $date_range['after'] ) - $days * DAY_IN_SECONDS ),
239
+        );
240
+
241
+        // Generate the report.
242
+        return $date_range;
243
+    }
244
+
245
+    /**
246
+     * Retrieves this month date range.
247
+     *
248
+     * @return array The appropriate date range.
249
+     */
250
+    public function get_month_date_range() {
251
+
252
+        // Set the previous date range.
253
+        $this->previous_range = array(
254
+            'period' => 'last_month',
255
+        );
256
+
257
+        // Generate the report.
258
+        return array(
259
+            'after'  => gmdate( 'Y-m-01' ),
260
+            'before' => gmdate( 'Y-m-t' ),
261
+        );
262
+
263
+    }
264
+
265
+    /**
266
+     * Retrieves last month's date range.
267
+     *
268
+     * @return array The appropriate date range.
269
+     */
270
+    public function get_last_month_date_range() {
271
+
272
+        // Set the previous date range.
273
+        $this->previous_range = array(
274
+            'period' => 'custom',
275
+            'after'  => gmdate( 'Y-m-01', strtotime( '-2 months' ) ),
276
+            'before' => gmdate( 'Y-m-t', strtotime( '-2 months' ) ),
277
+        );
278
+
279
+        // Generate the report.
280
+        return array(
281
+            'after'  => gmdate( 'Y-m-01', strtotime( 'last month' ) ),
282
+            'before' => gmdate( 'Y-m-t', strtotime( 'last month' ) ),
283
+        );
284
+
285
+    }
286
+
287
+    /**
288
+     * Retrieves this quarter date range.
289
+     *
290
+     * @return array The available quarters.
291
+     */
292
+    public function get_quarters() {
293
+
294
+        $year      = (int) gmdate( 'Y' );
295
+        $last_year = (int) $year - 1;
296
+        return array(
297
+
298
+            // Third quarter of previous year: July 1st to September 30th
299
+            array(
300
+                'before' => "{$last_year}-09-30",
301
+                'after'  => "{$last_year}-07-01",
302
+            ),
303
+
304
+            // Last quarter of previous year: October 1st to December 31st
305
+            array(
306
+                'before' => "{$last_year}-12-31",
307
+                'after'  => "{$last_year}-10-01",
308
+            ),
309
+
310
+            // First quarter: January 1st to March 31st
311
+            array(
312
+                'before' => "{$year}-03-31",
313
+                'after'  => "{$year}-01-01",
314
+            ),
315
+
316
+            // Second quarter: April 1st to June 30th
317
+            array(
318
+                'before' => "{$year}-06-30",
319
+                'after'  => "{$year}-04-01",
320
+            ),
321
+
322
+            // Third quarter: July 1st to September 30th
323
+            array(
324
+                'before' => "{$year}-09-30",
325
+                'after'  => "{$year}-07-01",
326
+            ),
327
+
328
+            // Fourth quarter: October 1st to December 31st
329
+            array(
330
+                'before' => "{$year}-12-31",
331
+                'after'  => "{$year}-10-01",
332
+            ),
333
+        );
334
+    }
335
+
336
+    /**
337
+     * Retrieves the current quater.
338
+     *
339
+     * @return int The current quarter.
340
+     */
341
+    public function get_quarter() {
342
+
343
+        $month    = (int) gmdate( 'n' );
344
+        $quarters = array( 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 );
345
+        return $quarters[ $month - 1 ];
346
+
347
+    }
348
+
349
+    /**
350
+     * Retrieves this quarter date range.
351
+     *
352
+     * @return array The appropriate date range.
353
+     */
354
+    public function get_quarter_date_range() {
355
+
356
+        // Set the previous date range.
357
+        $this->previous_range = array(
358
+            'period' => 'last_quarter',
359
+        );
360
+
361
+        // Generate the report.
362
+        $quarter  = $this->get_quarter();
363
+        $quarters = $this->get_quarters();
364
+        return $quarters[ $quarter + 1 ];
365
+
366
+    }
367
+
368
+    /**
369
+     * Retrieves last quarter's date range.
370
+     *
371
+     * @return array The appropriate date range.
372
+     */
373
+    public function get_last_quarter_date_range() {
374
+
375
+        $quarters = $this->get_quarters();
376
+        $quarter  = $this->get_quarter();
377
+
378
+        // Set the previous date range.
379
+        $this->previous_range = array_merge(
380
+            $quarters[ $quarter - 1 ],
381
+            array( 'period' => 'custom' )
382
+        );
383
+
384
+        // Generate the report.
385
+        return $quarters[ $quarter ];
386
+
387
+    }
388
+
389
+    /**
390
+     * Retrieves this year date range.
391
+     *
392
+     * @return array The appropriate date range.
393
+     */
394
+    public function get_year_date_range() {
395
+
396
+        // Set the previous date range.
397
+        $this->previous_range = array(
398
+            'period' => 'last_year',
399
+        );
400
+
401
+        // Generate the report.
402
+        return array(
403
+            'after'  => gmdate( 'Y-01-01' ),
404
+            'before' => gmdate( 'Y-12-31' ),
405
+        );
406
+
407
+    }
408
+
409
+    /**
410
+     * Retrieves last year date range.
411
+     *
412
+     * @return array The appropriate date range.
413
+     */
414
+    public function get_last_year_date_range() {
415
+
416
+        // Set the previous date range.
417
+        $this->previous_range = array(
418
+            'period' => 'custom',
419
+            'after'  => gmdate( 'Y-01-01', strtotime( '-2 years' ) ),
420
+            'before' => gmdate( 'Y-12-31', strtotime( '-2 years' ) ),
421
+        );
422
+
423
+        // Generate the report.
424
+        return array(
425
+            'after'  => gmdate( 'Y-01-01', strtotime( 'last year' ) ),
426
+            'before' => gmdate( 'Y-12-31', strtotime( 'last year' ) ),
427
+        );
428
+
429
+    }
430
+
431
+    /**
432
+     * Prepare a the request date for SQL usage.
433
+     *
434
+     * @param WP_REST_Request $request Request object.
435
+     * @param string $date_field The date field.
436
+     * @return string The appropriate SQL.
437
+     */
438
+    public function get_date_range_sql( $request, $date_field ) {
439
+        global $wpdb;
440
+
441
+        $sql = '1=1';
442
+        $range = $this->get_date_range( $request );
443
+
444
+        if ( ! empty( $range['after'] ) ) {
445
+            $sql .= ' AND ' . $wpdb->prepare(
446
+                "$date_field >= %s",
447
+                $range['after']
448
+            );
449
+        }
450
+
451
+        if ( ! empty( $range['before'] ) ) {
452
+            $sql .= ' AND ' . $wpdb->prepare(
453
+                "$date_field <= %s",
454
+                $range['before']
455
+            );
456
+        }
457
+
458
+        return $sql;
459
+
460
+    }
461
+
462
+    /**
463
+     * Prepares a group by query.
464
+     *
465
+     * @param string $date_field The date field.
466
+     * @return string The appropriate SQL.
467
+     */
468
+    public function get_group_by_sql( $date_field ) {
469
+
470
+        if ( 'day' === $this->groupby ) {
471
+            return "YEAR($date_field), MONTH($date_field), DAY($date_field)";
472
+        }
473
+
474
+        return "YEAR($date_field), MONTH($date_field)";
475
+    }
476
+
477
+    /**
478
+     * Get the query params for collections.
479
+     *
480
+     * @return array
481
+     */
482
+    public function get_collection_params() {
483
+        return array(
484
+            'context' => $this->get_context_param( array( 'default' => 'view' ) ),
485
+            'period'  => array(
486
+                'description'       => __( 'Limit to results of a specific period.', 'invoicing' ),
487
+                'type'              => 'string',
488
+                'enum'              => array( 'custom', 'today', 'yesterday', 'week', 'last_week', '7_days', '30_days', '60_days', '90_days', '180_days', 'month', 'last_month', 'quarter', 'last_quarter', 'year', 'last_year', 'quarter', 'last_quarter' ),
489
+                'validate_callback' => 'rest_validate_request_arg',
490
+                'sanitize_callback' => 'sanitize_text_field',
491
+                'default'           => '7_days',
492
+            ),
493
+            'after'   => array(
494
+                /* translators: %s: date format */
495
+                'description'       => sprintf( __( 'Limit to results after a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
496
+                'type'              => 'string',
497
+                'validate_callback' => 'rest_validate_request_arg',
498
+                'sanitize_callback' => 'sanitize_text_field',
499
+                'default'           => gmdate( 'Y-m-d', strtotime( '-7 days' ) ),
500
+            ),
501
+            'before'  => array(
502
+                /* translators: %s: date format */
503
+                'description'       => sprintf( __( 'Limit to results before a specific date, the date needs to be in the %s format.', 'invoicing' ), 'YYYY-MM-DD' ),
504
+                'type'              => 'string',
505
+                'validate_callback' => 'rest_validate_request_arg',
506
+                'sanitize_callback' => 'sanitize_text_field',
507
+                'default'           => gmdate( 'Y-m-d' ),
508
+            ),
509
+        );
510
+    }
511 511
 }
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 <= '" . gmdate( 'Y-m-d 23:59:59', 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 >= '" . gmdate( 'Y-m-d 00:00:00', 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.