Completed
Pull Request — master (#2165)
by Justin
05:44
created

WPSC_Purchase_Log_Notes   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 445
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 445
rs 8.439
c 0
b 0
f 0
wmc 47
lcom 1
cbo 2

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 20 3
C fetch() 0 110 11
A prepare_get() 0 3 1
A prepare_get_data() 0 3 1
A add() 0 7 2
A remove() 0 6 1
A set() 0 21 4
C save() 0 53 10
A parse_args_for_db() 0 8 1
A parse_args() 0 8 1
A current() 0 4 1
A key() 0 4 1
A next() 0 4 1
A prev() 0 4 1
A rewind() 0 4 1
A valid() 0 4 1
A get_status_text() 0 11 3
A get_formatted_date() 0 15 3

How to fix   Complexity   

Complex Class

Complex classes like WPSC_Purchase_Log_Notes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WPSC_Purchase_Log_Notes, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class WPSC_Purchase_Log_Notes extends WPSC_Query_Base implements Iterator {
4
	const TYPE_DEFAULT   = 0;
5
	const TYPE_ERROR     = 1;
6
	const STATUS_PUBLIC  = 0;
7
	const STATUS_PRIVATE = 1;
8
	const KEY_CONTENT = 0;
9
	const KEY_STATUS  = 1;
10
	const KEY_TIME    = 2;
11
	const KEY_TYPE    = 3;
12
13
	protected static $map_types = array(
14
		self::TYPE_DEFAULT   => 'default',
15
		self::TYPE_ERROR     => 'error',
16
	);
17
18
	protected static $map_statuses = array(
19
		self::STATUS_PUBLIC  => 'public',
20
		self::STATUS_PRIVATE => 'private',
21
	);
22
23
	protected static $map_keys = array(
24
		self::KEY_TYPE       => 'type',
25
		self::KEY_STATUS     => 'status',
26
		self::KEY_TIME       => 'time',
27
		self::KEY_CONTENT    => 'content',
28
	);
29
30
	protected static $map_text = array();
31
	protected $log = null;
32
33
	public function __construct( $log ) {
34
		if ( $log instanceof WPSC_Purchase_Log ) {
35
			$this->log = $log;
36
		} else {
37
			$this->log = new WPSC_Purchase_Log( $log );
38
		}
39
40
		if ( empty( self::$map_text ) ) {
41
			self::$map_text = array(
42
				self::$map_types[ self::TYPE_DEFAULT ]      => __( 'Default', 'wp-e-commerce' ),
43
				self::$map_types[ self::TYPE_ERROR ]        => __( 'Error', 'wp-e-commerce' ),
44
				self::$map_statuses[ self::STATUS_PUBLIC ]  => __( 'Public', 'wp-e-commerce' ),
45
				self::$map_statuses[ self::STATUS_PRIVATE ] => __( 'Private', 'wp-e-commerce' ),
46
				self::$map_keys[ self::KEY_TYPE ]           => __( 'Note Type', 'wp-e-commerce' ),
47
				self::$map_keys[ self::KEY_STATUS ]         => __( 'Note Status', 'wp-e-commerce' ),
48
				self::$map_keys[ self::KEY_TIME ]           => __( 'Note Date', 'wp-e-commerce' ),
49
				self::$map_keys[ self::KEY_CONTENT ]        => __( 'Note Content', 'wp-e-commerce' ),
50
			);
51
		}
52
	}
53
54
	/**
55
	 * Fetches the actual record from the database
56
	 *
57
	 * @access protected
58
	 * @since 3.8.9
59
	 *
60
	 * @return WPSC_Purchase_Log
61
	 */
62
	protected function fetch() {
63
		if ( $this->fetched ) {
64
			return;
65
		}
66
67
		$this->fetched = true;
68
69
		$notes = array();
70
		$data = $this->log->get_data();
71
		$meta = $this->log->get_meta();
72
73
		if ( ! empty( $meta['notes'] ) ) {
74
			$notes = $meta['notes'];
75
		}
76
77
		if ( ! empty( $data['notes'] ) && ! is_array( $data['notes'] ) ) {
78
			$notes[] = array( self::KEY_CONTENT => $data['notes'] );
79
		}
80
81
		if ( ! empty( $notes ) ) {
82
83
			foreach ( $notes as $key => $args ) {
84
				// Ensure array is formatted properly
85
				$notes[ $key ] = self::parse_args_for_db( $args );
86
			}
87
88
			// Make keys and values human-readable.
89
			foreach ( $notes as $key => $args ) {
90
				foreach ( $args as $subkey => $value ) {
91
					$subkey = self::$map_keys[ $subkey ];
92
					switch ( $subkey ) {
93
						case 'type':
94
							$value = self::$map_types[ $value ];
95
							break;
96
97
						case 'status':
98
							$value = self::$map_statuses[ $value ];
99
							break;
100
					}
101
					$this->data[ $key ][ $subkey ] = $value;
102
				}
103
			}
104
		}
105
106
		// print( '<xmp>'. __LINE__ .') $this->data: '. print_r( $this->data, true ) .'</xmp>' );
107
		// $this->add( 'howdy' );
108
109
		// print( '<xmp>'. __LINE__ .') $this->data: '. print_r( $this->data, true ) .'</xmp>' );
110
111
		// $new_data = array( end( $this->data ) );
112
		// $new_data = $this->data;
113
// 		$new_data[] = array(
114
// 			'content' => 'slfjsfk fs;ajfg;sj agja;gj;sag j',
115
// 			'type'    => 'error',
116
// 			'status'  => 'private',
117
// 			'time'    => '1478637949',
118
// 		);
119
120
// 		$this->set( $new_data )->save();
121
122
// 		wp_die( '<xmp>'. __LINE__ .') $this->data: '. print_r( $this->data, true ) .'</xmp>' );
123
124
// 		$this->data[1] = array(
125
// 			'content' => 'Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Nullam quis risus eget urna mollis ornare vel eu leo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum.
126
127
// Cras mattis consectetur purus sit amet fermentum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.',
128
// 			'type'    => 'error',
129
// 			'status'  => 'private',
130
// 			'time'    => '1478637949',
131
// 		);
132
133
// 		$this->data[2] = array(
134
// 			'content' => 'slfjsfk fs;ajfg;sj agja;gj;sag j',
135
// 			'type'    => 'error',
136
// 			'status'  => 'private',
137
// 			'time'    => '1478637949',
138
// 		);
139
140
// 		$this->data[3] = array(
141
// 			'content' => 'slfjsfk fs;ajfg;sj agja;gj;sag j',
142
// 			'type'    => 'error',
143
// 			'status'  => 'private',
144
// 			'time'    => '1478637949',
145
// 		);
146
147
// 		$this->data[4] = array(
148
// 			'content' => 'Donec sed odio dui. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Nullam quis risus eget urna mollis ornare vel eu leo. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
149
150
// Curabitur blandit tempus porttitor. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Nullam quis risus eget urna mollis ornare vel eu leo.
151
152
// Sed posuere consectetur est at lobortis. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Aenean lacinia bibendum nulla sed consectetur. Cras mattis consectetur purus sit amet fermentum. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Curabitur blandit tempus porttitor. Donec ullamcorper nulla non metus auctor fringilla.
153
154
// Nullam quis risus eget urna mollis ornare vel eu leo. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec sed odio dui. Sed posuere consectetur est at lobortis. Maecenas sed diam eget risus varius blandit sit amet non magna. Etiam porta sem malesuada magna mollis euismod.',
155
// 			'type'    => 'error',
156
// 			'status'  => 'private',
157
// 			'time'    => '1478637949',
158
// 		);
159
160
// 		$this->data[5] = array(
161
// 			'content' => 'slfjsfk fs;ajfg;sj agja;gj;sag j',
162
// 			'type'    => 'error',
163
// 			'status'  => 'private',
164
// 			'time'    => '1478637949',
165
// 		);
166
167
		// $this->data = array();
168
		$this->exists = ! empty( $this->data );
169
170
		return $this;
171
	}
172
173
	/**
174
	 * Prepares the return value for get() (apply_filters, etc).
175
	 *
176
	 * @access protected
177
	 * @since  4.0
178
	 *
179
	 * @param  mixed  $value Value fetched
180
	 * @param  string $key   Key for $data.
181
	 *
182
	 * @return mixed
183
	 */
184
	protected function prepare_get( $value, $key ) {
185
		return apply_filters( 'wpsc_get_purchase_log_note', $value, $key, $this );
186
	}
187
188
	/**
189
	 * Prepares the return value for get_data() (apply_filters, etc).
190
	 *
191
	 * @access protected
192
	 * @since  4.0
193
	 *
194
	 * @return mixed
195
	 */
196
	protected function prepare_get_data() {
197
		return apply_filters( 'wpsc_get_purchase_log_notes', $this->data, $this );
198
	}
199
200
	public function add( $note_args ) {
201
		if ( ! is_array( $note_args ) ) {
202
			$note_args = self::parse_args( array( self::$map_keys[ self::KEY_CONTENT ] => $note_args ) );
203
		}
204
205
		return $this->set( false, $note_args );
206
	}
207
208
	public function remove( $note_id ) {
209
		$this->fetch();
210
		unset( $this->data[ $note_id ] );
211
212
		return $this;
213
	}
214
215
	/**
216
	 * Sets a property to a certain value. This function accepts a key and a value
217
	 * as arguments, or an associative array containing key value pairs.
218
	 *
219
	 * @access public
220
	 * @since  4.0
221
	 *
222
	 * @param mixed $key             Name of the property (column), or an array containing
223
	 *                               key value pairs
224
	 * @param string|int|null $value Optional. Defaults to null. In case $key is a string,
225
	 *                               this should be specified.
226
	 * @return WPSC_Query_Base       The current object (for method chaining)
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use WPSC_Purchase_Log_Notes.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
227
	 */
228
	public function set( $key, $value = null ) {
229
		$this->fetch();
230
231
		if ( is_array( $key ) ) {
232
			$this->data = array_map( array( __CLASS__, 'parse_args' ), $key );
233
		} else {
234
			if ( is_null( $value ) ) {
235
				return $this;
236
			}
237
238
			if ( is_numeric( $key ) ) {
239
				$this->data[ $key ] = self::parse_args( $value );
240
			} else {
241
				$this->data[] = self::parse_args( $value );
242
			}
243
		}
244
245
		$this->data = apply_filters( 'wpsc_set_purchase_log_notes', $this->data, $this );
246
247
		return $this;
248
	}
249
250
	/**
251
	 * Saves the object back to the database.
252
	 *
253
	 * @access public
254
	 * @since  4.0
255
	 *
256
	 * @return mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use WPSC_Purchase_Log_Notes.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
257
	 */
258
	public function save() {
259
		global $wpdb;
260
261
		$this->data = apply_filters( 'wpsc_purchase_log_notes_to_save', $this->data, $this );
262
263
		$meta = $this->log->get_meta();
264
265
		$deleted = array();
266
		if ( ! empty( $meta['notes'] ) ) {
267
			foreach ( $meta['notes'] as $key => $note ) {
268
				$deleted[] = wpsc_delete_purchase_meta( $this->log->get( 'id' ), 'notes', $note );
269
			}
270
		}
271
272
		$notes = array();
273
274
		$data = $this->log->get_data();
275
276
		if ( ! empty( $data['notes'] ) ) {
277
			$this->log->set( 'notes', '' )->save();
278
		}
279
280
		if ( ! empty( $this->data ) ) {
281
282
			foreach ( $this->data as $key => $args ) {
283
				foreach ( $args as $subkey => $value ) {
284
					switch ( $subkey ) {
285
						case 'type':
286
							$value = array_search( $value, self::$map_types );
287
							break;
288
289
						case 'status':
290
							$value = array_search( $value, self::$map_statuses );
291
							break;
292
					}
293
294
					$subkey = array_search( $subkey, self::$map_keys );
295
296
					$notes[ $key ][ $subkey ] = $value;
297
				}
298
			}
299
300
			foreach ( $notes as $note ) {
301
				wpsc_add_purchase_meta( $this->log->get( 'id' ), 'notes', $note );
302
			}
303
		}
304
305
		$this->log->set_meta( 'notes', $notes );
306
307
		do_action( 'wpsc_purchase_log_notes_save', $this );
308
309
		return $this;
310
	}
311
312
	/**
313
	 * Merge arguments into defaults array.
314
	 *
315
	 * @since 4.0
316
	 *
317
	 * @param array $args Value to merge with defaults.
318
	 * @return array Merged arguments with defaults.
319
	 */
320
	public static function parse_args_for_db( array $args ) {
321
		return $args + array(
322
			self::KEY_TYPE    => self::TYPE_DEFAULT,
323
			self::KEY_STATUS  => self::STATUS_PUBLIC,
324
			self::KEY_TIME    => time(),
325
			self::KEY_CONTENT => '',
326
		);
327
	}
328
329
	/**
330
	 * Merge arguments into defaults array.
331
	 *
332
	 * @since 4.0
333
	 *
334
	 * @param array $args Value to merge with defaults.
335
	 * @return array Merged arguments with defaults.
336
	 */
337
	public static function parse_args( array $args ) {
338
		return $args + array(
339
			self::$map_keys[ self::KEY_TYPE ]    => self::$map_types[ self::TYPE_DEFAULT ],
340
			self::$map_keys[ self::KEY_STATUS ]  => self::$map_statuses[ self::STATUS_PUBLIC ],
341
			self::$map_keys[ self::KEY_TIME ]    => time(),
342
			self::$map_keys[ self::KEY_CONTENT ] => '',
343
		);
344
	}
345
346
	/**
347
	 * Get current for Iterator.
348
	 *
349
	 * @since  4.0
350
	 *
351
	 * @return mixed
352
	 */
353
	public function current() {
354
		$this->fetch();
355
		return current( $this->data );
356
	}
357
358
	/**
359
	 * Get key for Iterator.
360
	 *
361
	 * @since  4.0
362
	 *
363
	 * @return scalar
364
	 */
365
	public function key() {
366
		$this->fetch();
367
		return key( $this->data );
368
	}
369
370
	/**
371
	 * Get next for Iterator.
372
	 *
373
	 * @since  4.0
374
	 *
375
	 * @return void
376
	 */
377
	public function next() {
378
		$this->fetch();
379
		return next( $this->data );
380
	}
381
382
	/**
383
	 * Get prev for Iterator.
384
	 *
385
	 * @since  4.0
386
	 *
387
	 * @return void
388
	 */
389
	public function prev() {
390
		$this->fetch();
391
		return prev( $this->data );
392
	}
393
394
	/**
395
	 * Get rewind for Iterator.
396
	 *
397
	 * @since  4.0
398
	 *
399
	 * @return void
400
	 */
401
	public function rewind() {
402
		$this->fetch();
403
		return reset( $this->data );
404
	}
405
406
	/**
407
	 * Get valid for Iterator.
408
	 *
409
	 * @since  4.0
410
	 *
411
	 * @return boolean
412
	 */
413
	public function valid() {
414
		$this->fetch();
415
		return isset( $this->data[ $this->key() ] );
416
	}
417
418
419
	public function get_status_text( $note = array() ) {
420
		if ( empty( $note ) ) {
421
			$note = $this->current();
422
		}
423
424
		if ( ! isset( self::$map_text[ $note['status'] ] ) ) {
425
			return '';
426
		}
427
428
		return sprintf( __( 'Status: <b>%1$s</b>', 'wp-e-commerce' ), self::$map_text[ $note['status'] ] );
429
	}
430
431
	public function get_formatted_date( $note = array() ) {
432
		if ( empty( $note ) ) {
433
			$note = $this->current();
434
		}
435
436
		if ( empty( $note['time'] ) ) {
437
			return '';
438
		}
439
440
		/* translators: Purchase log motes metabox date format, see https://secure.php.net/date */
441
		$date = date_i18n( __( 'M j, Y @ H:i', 'wp-e-commerce' ), $note['time'] );
442
443
		return $date;
444
		return sprintf( __( 'Posted: <b>%1$s</b>', 'wp-e-commerce' ), $date );
0 ignored issues
show
Unused Code introduced by
return sprintf(__('Poste...p-e-commerce'), $date); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
445
	}
446
447
}
448