Passed
Push — master ( 3d88bf...f3309e )
by Brian
05:31
created

GetPaid_Invoice_Data_Store::get_post_status()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * GetPaid_Invoice_Data_Store class file.
5
 *
6
 */
7
if ( ! defined( 'ABSPATH' ) ) {
8
	exit;
9
}
10
11
/**
12
 * Invoice Data Store: Stored in CPT.
13
 *
14
 * @version  1.0.19
15
 */
16
class GetPaid_Invoice_Data_Store extends GetPaid_Data_Store_WP {
17
18
	/**
19
	 * Data stored in meta keys, but not considered "meta" for a discount.
20
	 *
21
	 * @since 1.0.19
22
	 * @var array
23
	 */
24
	protected $internal_meta_keys = array(
25
		'_wpinv_subscr_profile_id',
26
		'_wpinv_subscription_id',
27
		'_wpinv_taxes',
28
		'_wpinv_fees',
29
		'_wpinv_discounts',
30
		'_wpinv_submission_id',
31
		'_wpinv_payment_form',
32
		'_wpinv_is_viewed',
33
		'wpinv_email_cc',
34
		'wpinv_template',
35
		'wpinv_created_via'
36
	);
37
38
	/**
39
	 * A map of meta keys to data props.
40
	 *
41
	 * @since 1.0.19
42
	 *
43
	 * @var array
44
	 */
45
	protected $meta_key_to_props = array(
46
		'_wpinv_subscr_profile_id' => 'remote_subscription_id',
47
		'_wpinv_subscription_id'   => 'subscription_id',
48
		'_wpinv_taxes'             => 'taxes',
49
		'_wpinv_fees'              => 'fees',
50
		'_wpinv_discounts'         => 'discounts',
51
		'_wpinv_submission_id'     => 'submission_id',
52
		'_wpinv_payment_form'      => 'payment_form',
53
		'_wpinv_is_viewed'         => 'is_viewed',
54
		'wpinv_email_cc'           => 'email_cc',
55
		'wpinv_template'           => 'template',
56
		'wpinv_created_via'        => 'created_via',
57
	);
58
59
	/**
60
	 * A map of database fields to data props.
61
	 *
62
	 * @since 1.0.19
63
	 *
64
	 * @var array
65
	 */
66
	protected $database_fields_to_props = array(
67
		'post_id'            => 'id',
68
		'number'             => 'number',
69
		'currency'           => 'currency',
70
		'key'                => 'key',
71
		'type'               => 'type',
72
		'mode'               => 'mode',
73
		'user_ip'            => 'user_ip',
74
		'first_name'         => 'first_name',
75
		'last_name'          => 'last_name',
76
		'address'            => 'address',
77
		'city'               => 'city',
78
		'state'              => 'state',
79
		'country'            => 'country',
80
		'zip'                => 'zip',
81
		'zip'                => 'zip',
82
		'adddress_confirmed' => 'address_confirmed',
83
		'gateway'            => 'gateway',
84
		'transaction_id'     => 'transaction_id',
85
		'currency'           => 'currency',
86
		'subtotal'           => 'subtotal',
87
		'tax'                => 'total_tax',
88
		'fees_total'         => 'total_fees',
89
		'discount'           => 'total_discount',
90
		'total'              => 'total',
91
		'discount_code'      => 'discount_code',
92
		'disable_taxes'      => 'disable_taxes',
93
		'due_date'           => 'due_date',
94
		'completed_date'     => 'completed_date',
95
		'company'            => 'company',
96
		'vat_number'         => 'vat_number',
97
		'vat_rate'           => 'vat_rate',
98
	);
99
100
	/*
101
	|--------------------------------------------------------------------------
102
	| CRUD Methods
103
	|--------------------------------------------------------------------------
104
	*/
105
106
	/**
107
	 * Method to create a new invoice in the database.
108
	 *
109
	 * @param WPInv_Invoice $invoice Invoice object.
110
	 */
111
	public function create( &$invoice ) {
112
		$invoice->set_version( WPINV_VERSION );
113
		$invoice->set_date_created( current_time('mysql') );
114
115
		// Create a new post.
116
		$id = wp_insert_post(
117
			apply_filters(
118
				'getpaid_new_invoice_data',
119
				array(
120
					'post_date'     => $invoice->get_date_created( 'edit' ),
121
					'post_type'     => $invoice->get_post_type( 'edit' ),
122
					'post_status'   => $this->get_post_status( $invoice ),
123
					'ping_status'   => 'closed',
124
					'post_author'   => $invoice->get_user_id( 'edit' ),
125
					'post_title'    => $invoice->get_title( 'edit' ),
126
					'post_excerpt'  => $invoice->get_description( 'edit' ),
127
					'post_parent'   => $invoice->get_parent_id( 'edit' ),
128
				)
129
			),
130
			true
131
		);
132
133
		if ( $id && ! is_wp_error( $id ) ) {
134
135
			// Update the new id and regenerate a title.
136
			$invoice->set_id( $id );
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type WP_Error; however, parameter $id of GetPaid_Data::set_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
			$invoice->set_id( /** @scrutinizer ignore-type */ $id );
Loading history...
137
138
			$invoice->maybe_set_number();
139
140
			wp_update_post(
141
				array(
142
					'ID'         => $invoice->get_id(),
143
					'post_title' => $invoice->get_number( 'edit' ),
144
					'post_name'  => $invoice->get_path( 'edit' )
145
				)
146
			);
147
148
			// Save special fields and items.
149
			$this->save_special_fields( $invoice );
150
			$this->save_items( $invoice );
151
152
			// Update meta data.
153
			$this->update_post_meta( $invoice );
154
			$invoice->save_meta_data();
155
156
			// Apply changes.
157
			$invoice->apply_changes();
158
			$this->clear_caches( $invoice );
159
160
			// Fires after a new invoice is created.
161
			do_action( 'getpaid_new_invoice', $invoice );
162
			return true;
163
		}
164
165
		if ( is_wp_error( $id ) ) {
166
			$invoice->last_error = $id->get_error_message();
167
		}
168
169
		return false;
170
	}
171
172
	/**
173
	 * Method to read an invoice from the database.
174
	 *
175
	 * @param WPInv_Invoice $invoice Invoice object.
176
	 *
177
	 */
178
	public function read( &$invoice ) {
179
180
		$invoice->set_defaults();
181
		$invoice_object = get_post( $invoice->get_id() );
182
183
		if ( ! $invoice->get_id() || ! $invoice_object || ! getpaid_is_invoice_post_type( $invoice_object->post_type ) ) {
184
			$invoice->last_error = __( 'Invalid invoice.', 'invoicing' );
185
			$invoice->set_id( 0 );
186
			return false;
187
		}
188
189
		$invoice->set_props(
190
			array(
191
				'date_created'  => 0 < $invoice_object->post_date ? $invoice_object->post_date : null,
192
				'date_modified' => 0 < $invoice_object->post_modified ? $invoice_object->post_modified : null,
193
				'status'        => $invoice_object->post_status,
194
				'author'        => $invoice_object->post_author,
195
				'description'   => $invoice_object->post_excerpt,
196
				'parent_id'     => $invoice_object->post_parent,
197
				'name'          => $invoice_object->post_title,
198
				'path'          => $invoice_object->post_name,
199
				'post_type'     => $invoice_object->post_type,
200
			)
201
		);
202
203
		$invoice->set_type( $invoice_object->post_type );
204
205
		$this->read_object_data( $invoice, $invoice_object );
206
		$this->add_special_fields( $invoice );
207
		$this->add_items( $invoice );
208
		$invoice->read_meta_data();
209
		$invoice->set_object_read( true );
210
		do_action( 'getpaid_read_invoice', $invoice );
211
212
	}
213
214
	/**
215
	 * Method to update an invoice in the database.
216
	 *
217
	 * @param WPInv_Invoice $invoice Invoice object.
218
	 */
219
	public function update( &$invoice ) {
220
		$invoice->save_meta_data();
221
		$invoice->set_version( WPINV_VERSION );
222
223
		if ( null === $invoice->get_date_created( 'edit' ) ) {
0 ignored issues
show
introduced by
The condition null === $invoice->get_date_created('edit') is always false.
Loading history...
224
			$invoice->set_date_created(  current_time('mysql') );
225
		}
226
227
		// Ensure both the key and number are set.
228
		$invoice->get_path();
229
230
		// Grab the current status so we can compare.
231
		$previous_status = get_post_status( $invoice->get_id() );
232
233
		$changes = $invoice->get_changes();
234
235
		// Only update the post when the post data changes.
236
		if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'name', 'author', 'description', 'parent_id', 'post_excerpt', 'path' ), array_keys( $changes ) ) ) {
237
			$post_data = array(
238
				'post_date'         => $invoice->get_date_created( 'edit' ),
239
				'post_date_gmt'     => $invoice->get_date_created_gmt( 'edit' ),
240
				'post_status'       => $invoice->get_status( 'edit' ),
241
				'post_title'        => $invoice->get_name( 'edit' ),
242
				'post_author'       => $invoice->get_user_id( 'edit' ),
243
				'post_modified'     => $invoice->get_date_modified( 'edit' ),
244
				'post_excerpt'      => $invoice->get_description( 'edit' ),
245
				'post_parent'       => $invoice->get_parent_id( 'edit' ),
246
				'post_name'         => $invoice->get_path( 'edit' ),
247
				'post_type'         => $invoice->get_post_type( 'edit' ),
248
			);
249
250
			/**
251
			 * When updating this object, to prevent infinite loops, use $wpdb
252
			 * to update data, since wp_update_post spawns more calls to the
253
			 * save_post action.
254
			 *
255
			 * This ensures hooks are fired by either WP itself (admin screen save),
256
			 * or an update purely from CRUD.
257
			 */
258
			if ( doing_action( 'save_post' ) ) {
259
				$GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $invoice->get_id() ) );
260
				clean_post_cache( $invoice->get_id() );
261
			} else {
262
				wp_update_post( array_merge( array( 'ID' => $invoice->get_id() ), $post_data ) );
263
			}
264
			$invoice->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
265
		}
266
267
		// Update meta data.
268
		$this->update_post_meta( $invoice );
269
270
		// Save special fields and items.
271
		$this->save_special_fields( $invoice );
272
		$this->save_items( $invoice );
273
274
		// Apply the changes.
275
		$invoice->apply_changes();
276
277
		// Clear caches.
278
		$this->clear_caches( $invoice );
279
280
		// Fire a hook depending on the status - this should be considered a creation if it was previously draft status.
281
		$new_status = $invoice->get_status( 'edit' );
282
283
		if ( $new_status !== $previous_status && in_array( $previous_status, array( 'new', 'auto-draft', 'draft' ), true ) ) {
284
			do_action( 'getpaid_new_invoice', $invoice );
285
		} else {
286
			do_action( 'getpaid_update_invoice', $invoice );
287
		}
288
289
	}
290
291
	/*
292
	|--------------------------------------------------------------------------
293
	| Additional Methods
294
	|--------------------------------------------------------------------------
295
	*/
296
297
	/**
298
     * Retrieves special fields and adds to the invoice.
299
	 *
300
	 * @param WPInv_Invoice $invoice Invoice object.
301
     */
302
    public function add_special_fields( &$invoice ) {
303
		global $wpdb;
304
305
		// Maybe retrieve from the cache.
306
		$data   = wp_cache_get( $invoice->get_id(), 'getpaid_invoice_special_fields' );
307
308
		// If not found, retrieve from the db.
309
		if ( false === $data ) {
310
			$table =  $wpdb->prefix . 'getpaid_invoices';
311
312
			$data  = $wpdb->get_row(
313
				$wpdb->prepare( "SELECT * FROM $table WHERE `post_id`=%d LIMIT 1", $invoice->get_id() ),
314
				ARRAY_A
315
			);
316
317
			// Update the cache with our data
318
			wp_cache_set( $invoice->get_id(), $data, 'getpaid_invoice_special_fields' );
319
320
		}
321
322
		// Abort if the data does not exist.
323
		if ( empty( $data ) ) {
324
			$invoice->set_object_read( true );
325
			$invoice->set_props( wpinv_get_user_address( $invoice->get_user_id() ) );
326
			return;
327
		}
328
329
		$props = array();
330
331
		foreach ( $this->database_fields_to_props as $db_field => $prop ) {
332
			
333
			if ( $db_field == 'post_id' ) {
334
				continue;
335
			}
336
337
			$props[ $prop ] = $data[ $db_field ];
338
		}
339
340
		$invoice->set_props( $props );
341
342
	}
343
344
	/**
345
	 * Gets a list of special fields that need updated based on change state
346
	 * or if they are present in the database or not.
347
	 *
348
	 * @param  WPInv_Invoice $invoice       The Invoice object.
349
	 * @return array                        A mapping of field keys => prop names, filtered by ones that should be updated.
350
	 */
351
	protected function get_special_fields_to_update( $invoice ) {
352
		$fields_to_update = array();
353
		$changed_props   = $invoice->get_changes();
354
355
		// Props should be updated if they are a part of the $changed array or don't exist yet.
356
		foreach ( $this->database_fields_to_props as $database_field => $prop ) {
357
			if ( array_key_exists( $prop, $changed_props ) ) {
358
				$fields_to_update[ $database_field ] = $prop;
359
			}
360
		}
361
362
		return $fields_to_update;
363
	}
364
365
	/**
366
	 * Helper method that updates all the database fields for an invoice based on it's settings in the WPInv_Invoice class.
367
	 *
368
	 * @param WPInv_Invoice $invoice WPInv_Invoice object.
369
	 * @since 1.0.19
370
	 */
371
	protected function update_special_fields( &$invoice ) {
372
		global $wpdb;
373
374
		$updated_props    = array();
375
		$fields_to_update = $this->get_special_fields_to_update( $invoice );
376
377
		foreach ( $fields_to_update as $database_field => $prop ) {
378
			$value = $invoice->{"get_$prop"}( 'edit' );
379
			$value = is_string( $value ) ? wp_slash( $value ) : $value;
380
			$value = is_bool( $value ) ? ( int ) $value : $value;
381
			$updated_props[ $database_field ] = maybe_serialize( $value );
382
		}
383
384
		if ( ! empty( $updated_props ) ) {
385
386
			$table = $wpdb->prefix . 'getpaid_invoices';
387
			$wpdb->update( $table, $updated_props, array( 'post_id' => $invoice->get_id() ) );
388
			wp_cache_delete( $invoice->get_id(), 'getpaid_invoice_special_fields' );
389
			do_action( "getpaid_invoice_update_database_fields", $invoice, $updated_props );
390
391
		}
392
393
	}
394
395
	/**
396
	 * Helper method that inserts special fields to the database.
397
	 *
398
	 * @param WPInv_Invoice $invoice WPInv_Invoice object.
399
	 * @since 1.0.19
400
	 */
401
	protected function insert_special_fields( &$invoice ) {
402
		global $wpdb;
403
404
		$updated_props   = array();
405
406
		foreach ( $this->database_fields_to_props as $database_field => $prop ) {
407
			$value = $invoice->{"get_$prop"}( 'edit' );
408
			$value = is_string( $value ) ? wp_slash( $value ) : $value;
409
			$value = is_bool( $value ) ? ( int ) $value : $value;
410
			$updated_props[ $database_field ] = maybe_serialize( $value );
411
		}
412
413
		$table = $wpdb->prefix . 'getpaid_invoices';
414
		$wpdb->insert( $table, $updated_props );
415
		wp_cache_delete( $invoice->get_id(), 'getpaid_invoice_special_fields' );
416
		do_action( "getpaid_invoice_insert_database_fields", $invoice, $updated_props );
417
418
	}
419
420
	/**
421
     * Saves all special fields.
422
	 *
423
	 * @param WPInv_Invoice $invoice Invoice object.
424
     */
425
    public function save_special_fields( & $invoice ) {
426
		global $wpdb;
427
428
		// The invoices table.
429
		$table = $wpdb->prefix . 'getpaid_invoices';
430
		$id    = (int) $invoice->get_id();
431
		$invoice->maybe_set_key();
432
433
		if ( $wpdb->get_var( "SELECT `post_id` FROM $table WHERE `post_id`= $id" ) ) {
434
435
			$this->update_special_fields( $invoice );
436
437
		} else {
438
439
			$this->insert_special_fields( $invoice );
440
441
		}
442
443
	}
444
445
	/**
446
     * Set's up cart details.
447
	 *
448
	 * @param WPInv_Invoice $invoice Invoice object.
449
     */
450
    public function add_items( &$invoice ) {
451
		global $wpdb;
452
453
		// Maybe retrieve from the cache.
454
		$items = wp_cache_get( $invoice->get_id(), 'getpaid_invoice_cart_details' );
455
456
		// If not found, retrieve from the db.
457
		if ( false === $items ) {
458
			$table =  $wpdb->prefix . 'getpaid_invoice_items';
459
460
			$items = $wpdb->get_results(
461
				$wpdb->prepare( "SELECT * FROM $table WHERE `post_id`=%d", $invoice->get_id() )
462
			);
463
464
			// Update the cache with our data
465
			wp_cache_set( $invoice->get_id(), $items, 'getpaid_invoice_cart_details' );
466
467
		}
468
469
		// Abort if no items found.
470
        if ( empty( $items ) ) {
471
            return;
472
		}
473
474
		foreach ( $items as $item_data ) {
475
			$item = new GetPaid_Form_Item( $item_data->item_id );
476
477
			// Set item data.
478
			$item->item_tax      = wpinv_sanitize_amount( $item_data->tax );
479
			$item->item_discount = wpinv_sanitize_amount( $item_data->discount );
480
			$item->set_name( $item_data->item_name );
481
			$item->set_description( $item_data->item_description );
482
			$item->set_price( $item_data->item_price );
483
			$item->set_quantity( $item_data->quantity );
484
			$item->set_item_meta( $item_data->meta );
485
486
			$invoice->add_item( $item );
487
		}
488
489
	}
490
491
	/**
492
     * Saves cart details.
493
	 *
494
	 * @param WPInv_Invoice $invoice Invoice object.
495
     */
496
    public function save_items( $invoice ) {
497
498
		// Delete previously existing items.
499
		$this->delete_items( $invoice );
500
501
		$table   =  $GLOBALS['wpdb']->prefix . 'getpaid_invoice_items';
502
503
		foreach ( $invoice->get_cart_details() as $item_data ) {
504
			$item_data = array_map( 'maybe_serialize', $item_data );
505
			$GLOBALS['wpdb']->insert( $table, $item_data );
506
		}
507
508
		wp_cache_delete( $invoice->get_id(), 'getpaid_invoice_cart_details' );
509
		do_action( "getpaid_invoice_save_items", $invoice );
510
511
	}
512
513
	/**
514
     * Deletes an invoice's cart details from the database.
515
	 *
516
	 * @param WPInv_Invoice $invoice Invoice object.
517
     */
518
    public function delete_items( $invoice ) {
519
		$table =  $GLOBALS['wpdb']->prefix . 'getpaid_invoice_items';
520
		return $GLOBALS['wpdb']->delete( $table, array( 'post_id' => $invoice->get_id() ) );
521
	}
522
523
	/**
524
     * Deletes an invoice's special fields from the database.
525
	 *
526
	 * @param WPInv_Invoice $invoice Invoice object.
527
     */
528
    public function delete_special_fields( $invoice ) {
529
		$table =  $GLOBALS['wpdb']->prefix . 'getpaid_invoices';
530
		return $GLOBALS['wpdb']->delete( $table, array( 'post_id' => $invoice->get_id() ) );
531
	}
532
	
533
	/**
534
	 * Get the status to save to the post object.
535
	 *
536
	 *
537
	 * @since 1.0.19
538
	 * @param  WPInv_Invoice $object GetPaid_Data object.
539
	 * @return string
540
	 */
541
	protected function get_post_status( $object ) {
542
		$object_status = $object->get_status( 'edit' );
543
544
		if ( ! $object_status ) {
545
			$object_status = $object->get_default_status();
546
		}
547
548
		return $object_status;
549
	}
550
551
}
552