Passed
Pull Request — master (#371)
by Brian
104:46
created

GetPaid_Item_Data_Store::update()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 21
nc 6
nop 1
dl 0
loc 39
rs 9.584
c 0
b 0
f 0
1
<?php
2
/**
3
 * GetPaid_Item_Data_Store class file.
4
 *
5
 */
6
if ( ! defined( 'ABSPATH' ) ) {
7
	exit;
8
}
9
10
/**
11
 * Abstract item Data Store: Stored in CPT.
12
 *
13
 * @version  1.0.19
14
 */
15
class GetPaid_Item_Data_Store extends GetPaid_Data_Store_WP {
16
17
	/**
18
	 * Internal meta type used to store order data.
19
	 *
20
	 * @since 1.0.19
21
	 * @var string
22
	 */
23
	protected $meta_type = 'post';
24
25
	/**
26
	 * Data stored in meta keys, but not considered "meta" for an item.
27
	 *
28
	 * @since 1.0.19
29
	 * @var array
30
	 */
31
	protected $internal_meta_keys = array(
32
		'_wpinv_price',
33
		'_wpinv_vat_rule',
34
		'_wpinv_vat_class',
35
		'_wpinv_type',
36
		'_wpinv_custom_id',
37
		'_wpinv_custom_name',
38
		'_wpinv_custom_singular_name',
39
		'_wpinv_editable',
40
		'_wpinv_dynamic_pricing',
41
		'_minimum_price',
42
		'_wpinv_is_recurring',
43
		'_wpinv_recurring_period',
44
		'_wpinv_recurring_interval',
45
		'_wpinv_recurring_limit',
46
		'_wpinv_free_trial',
47
		'_wpinv_trial_period',
48
		'_wpinv_signup_fee',
49
		'_wpinv_trial_interval'
50
	);
51
52
	/*
53
	|--------------------------------------------------------------------------
54
	| CRUD Methods
55
	|--------------------------------------------------------------------------
56
	*/
57
58
	/**
59
	 * Method to create a new item in the database.
60
	 *
61
	 * @param WPInv_Item $item Item object.
62
	 */
63
	public function create( &$item ) {
64
		$item->set_version( WPINV_VERSION );
65
		$item->set_date_created( current_time('mysql') );
66
67
		// Create a new post.
68
		$id = wp_insert_post(
69
			apply_filters(
70
				'getpaid_new_item_data',
71
				array(
72
					'post_date'     => $item->get_date_created( 'edit' ),
73
					'post_type'     => 'wpi_item',
74
					'post_status'   => $this->get_post_status( $item ),
75
					'ping_status'   => 'closed',
76
					'post_author'   => $item->get_author( 'edit' ),
77
					'post_title'    => $item->get_name( 'edit' ),
78
					'post_parent'   => 0,
79
					'post_excerpt'  => $item->get_description( 'edit' ),
80
				)
81
			),
82
			true
83
		);
84
85
		if ( $id && ! is_wp_error( $id ) ) {
86
			$item->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

86
			$item->set_id( /** @scrutinizer ignore-type */ $id );
Loading history...
87
			$this->update_post_meta( $item );
88
			$item->save_meta_data();
89
			$item->apply_changes();
90
			$this->clear_caches( $item );
91
			return true;
92
		}
93
94
		if ( is_wp_error( $id ) ) {
95
			$item->last_error = $id->get_error_message();
96
		}
97
		
98
		return false;
99
	}
100
101
	/**
102
	 * Method to read an item from the database.
103
	 *
104
	 * @param WPInv_Item $item Item object.
105
	 *
106
	 */
107
	public function read( &$item ) {
108
109
		$item->set_defaults();
110
		$item_object = get_post( $item->get_id() );
111
112
		if ( ! $item->get_id() || ! $item_object || $item_object->post_type != 'wpi_item' ) {
113
			$item->last_error = __( 'Invalid item.', 'invoicing' );
114
			return false;
115
		}
116
117
		$item->set_props(
118
			array(
119
				'parent_id'     => $item_object->post_parent,
120
				'date_created'  => 0 < $item_object->post_date_gmt ? $item_object->post_date_gmt : null,
121
				'date_modified' => 0 < $item_object->post_modified_gmt ? $item_object->post_modified_gmt : null,
122
				'status'        => $item_object->post_status,
123
				'name'          => $item_object->post_title,
124
				'description'   => $item_object->post_excerpt,
125
				'author'        => $item_object->post_author,
126
			)
127
		);
128
129
		$this->read_item_data( $item, $item_object );
130
		$item->read_meta_data();
131
		$item->set_object_read( true );
132
133
	}
134
135
	/**
136
	 * Method to update an item in the database.
137
	 *
138
	 * @param WPInv_Item $item Order object.
139
	 */
140
	public function update( &$item ) {
141
		$item->save_meta_data();
142
		$item->set_version( WPINV_VERSION );
143
144
		if ( null === $item->get_date_created( 'edit' ) ) {
0 ignored issues
show
introduced by
The condition null === $item->get_date_created('edit') is always false.
Loading history...
145
			$item->set_date_created(  current_time('mysql') );
146
		}
147
148
		$changes = $item->get_changes();
149
150
		// Only update the post when the post data changes.
151
		if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'post_excerpt' ), array_keys( $changes ) ) ) {
152
			$post_data = array(
153
				'post_date'         => $item->get_date_created( 'edit' ),
154
				'post_status'       => $item->get_status( $item ),
155
				'post_parent'       => $item->get_parent_id(),
156
				'post_excerpt'      => $item->get_description(),
157
				'post_modified'     => $item->get_date_modified( 'edit' ),
158
			);
159
160
			/**
161
			 * When updating this object, to prevent infinite loops, use $wpdb
162
			 * to update data, since wp_update_post spawns more calls to the
163
			 * save_post action.
164
			 *
165
			 * This ensures hooks are fired by either WP itself (admin screen save),
166
			 * or an update purely from CRUD.
167
			 */
168
			if ( doing_action( 'save_post' ) ) {
169
				$GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $item->get_id() ) );
170
				clean_post_cache( $item->get_id() );
171
			} else {
172
				wp_update_post( array_merge( array( 'ID' => $item->get_id() ), $post_data ) );
173
			}
174
			$item->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
175
		}
176
		$this->update_post_meta( $item );
177
		$item->apply_changes();
178
		$this->clear_caches( $item );
179
	}
180
181
	/**
182
	 * Method to delete an item from the database.
183
	 *
184
	 * @param WPInv_Item $item Item object.
185
	 * @param array    $args Array of args to pass to the delete method.
186
	 *
187
	 * @return void
188
	 */
189
	public function delete( &$item, $args = array() ) {
190
		$id   = $item->get_id();
191
		$args = wp_parse_args(
192
			$args,
193
			array(
194
				'force_delete' => false,
195
			)
196
		);
197
198
		if ( ! $id ) {
199
			return;
200
		}
201
202
		if ( $args['force_delete'] ) {
203
			wp_delete_post( $id );
204
			$item->set_id( 0 );
205
			do_action( 'getpaid_delete_item', $id );
206
		} else {
207
			wp_trash_post( $id );
208
			$item->set_status( 'trash' );
209
			do_action( 'getpaid_trash_item', $id );
210
		}
211
	}
212
213
	/*
214
	|--------------------------------------------------------------------------
215
	| Additional Methods
216
	|--------------------------------------------------------------------------
217
	*/
218
219
	/**
220
	 * Get the status to save to the post object.
221
	 *
222
	 *
223
	 * @since 1.0.19
224
	 * @param  WPInv_item $item Item object.
225
	 * @return string
226
	 */
227
	protected function get_post_status( $item ) {
228
		$item_status = $item->get_status( 'edit' );
229
230
		if ( ! $item_status ) {
231
			$item_status = apply_filters( 'getpaid_default_item_status', 'draft' );
232
		}
233
234
		return $item_status;
235
	}
236
237
	/**
238
	 * Read item data.
239
	 *
240
	 * @param WPInv_Item $item Item object.
241
	 * @param WP_Post   $post_object Post object.
242
	 * @since 1.0.19
243
	 */
244
	protected function read_item_data( &$item, $post_object ) {
245
		$id = $item->get_id();
246
247
		// Set item properties.
248
		$item->set_props(
249
			array(
250
				'price'                => get_post_meta( $id, '_wpinv_price', true ),
251
				'vat_rule'             => get_post_meta( $id, '_wpinv_vat_rule', true ),
252
				'vat_class'            => get_post_meta( $id, '_wpinv_vat_class', true ),
253
				'type'                 => get_post_meta( $id, '_wpinv_type', true ),
254
				'custom_id'            => get_post_meta( $id, '_wpinv_custom_id', true ),
255
				'custom_name'          => get_post_meta( $id, '_wpinv_custom_name', true ),
256
				'custom_singular_name' => get_post_meta( $id, '_wpinv_custom_singular_name', true ),
257
				'is_editable'          => get_post_meta( $id, '_wpinv_editable', true ),
258
				'is_dynamic_pricing'   => get_post_meta( $id, '_wpinv_dynamic_pricing', true ),
259
				'minimum_price'        => get_post_meta( $id, '_minimum_price', true ),
260
				'is_recurring'         => get_post_meta( $id, '_wpinv_is_recurring', true ),
261
				'recurring_period'     => get_post_meta( $id, '_wpinv_recurring_period', true ),
262
				'recurring_interval'   => get_post_meta( $id, '_wpinv_recurring_interval', true ),
263
				'recurring_limit'      => get_post_meta( $id, '_wpinv_recurring_limit', true ),
264
				'is_free_trial'        => get_post_meta( $id, '_wpinv_free_trial', true ),
265
				'trial_period'         => get_post_meta( $id, '_wpinv_trial_period', true ),
266
				'signup_fee'           => get_post_meta( $id, '_wpinv_signup_fee', true ),
267
				'trial_interval'       => get_post_meta( $id, '_wpinv_trial_interval', true ),
268
				'version'              => get_post_meta( $id, '_wpinv_version', true ),
269
			)
270
		);
271
272
		// Gets extra data associated with the item if needed.
273
		foreach ( $item->get_extra_data_keys() as $key ) {
274
			$function = 'set_' . $key;
275
			if ( is_callable( array( $item, $function ) ) ) {
276
				$item->{$function}( get_post_meta( $item->get_id(), '_' . $key, true ) );
277
			}
278
		}
279
	}
280
281
	/**
282
	 * Helper method that updates all the post meta for an item based on it's settings in the WPInv_Item class.
283
	 *
284
	 * @param WPInv_Item $item Item object.
285
	 * @since 1.0.19
286
	 */
287
	protected function update_post_meta( &$item ) {
288
		$updated_props     = array();
289
290
		$meta_key_to_props = array(
291
			'_wpinv_price'                => 'price',
292
			'_wpinv_vat_rule'             => 'vat_rule',
293
			'_wpinv_vat_class'            => 'vat_class',
294
			'_wpinv_type'                 => 'type',
295
			'_wpinv_custom_id'            => 'custom_id',
296
			'_wpinv_custom_name'          => 'custom_name',
297
			'_wpinv_custom_singular_name' => 'custom_singular_name',
298
			'_wpinv_editable'             => 'is_editable',
299
			'_wpinv_dynamic_pricing'      => 'is_dynamic_pricing',
300
			'_minimum_price'              => 'minimum_price',
301
			'_wpinv_custom_name'          => 'custom_name',
302
			'_wpinv_is_recurring'         => 'is_recurring',
303
			'_wpinv_recurring_period'     => 'recurring_period',
304
			'_wpinv_recurring_interval'   => 'recurring_interval',
305
			'_wpinv_recurring_limit'      => 'recurring_limit',
306
			'_wpinv_free_trial'           => 'is_free_trial',
307
			'_wpinv_trial_period'         => 'trial_period',
308
			'_wpinv_signup_fee'           => 'signup_fee',
309
			'_wpinv_trial_interval'       => 'trial_interval',
310
		);
311
312
		$props_to_update = $this->get_props_to_update( $item, $meta_key_to_props );
313
314
		// Ensure that we have a custom id.
315
        if ( ! $item->get_custom_id() ) {
316
            $item->set_custom_id( $item->get_id() );
317
        }
318
319
		foreach ( $props_to_update as $meta_key => $prop ) {
320
			$value = $item->{"get_$prop"}( 'edit' );
321
			$value = is_string( $value ) ? wp_slash( $value ) : $value;
322
323
			$updated = $this->update_or_delete_post_meta( $item, $meta_key, $value );
324
325
			if ( $updated ) {
326
				$updated_props[] = $prop;
327
			}
328
		}
329
330
		do_action( 'getpaid_item_object_updated_props', $item, $updated_props );
331
	}
332
333
	/**
334
	 * Clear any caches.
335
	 *
336
	 * @param WPInv_Item $item Item object.
337
	 * @since 1.0.19
338
	 */
339
	protected function clear_caches( &$item ) {
340
		clean_post_cache( $item->get_id() );
341
	}
342
343
}
344