Give_DB_Meta   F
last analyzed

Complexity

Total Complexity 60

Size/Duplication

Total Lines 528
Duplicated Lines 16.29 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 86
loc 528
rs 3.6
c 0
b 0
f 0
wmc 60
lcom 1
cbo 2

15 Methods

Rating   Name   Duplication   Size   Complexity  
C __construct() 12 40 11
A get_meta() 0 22 4
A add_meta() 16 16 3
A update_meta() 16 16 3
A delete_meta() 16 16 3
A __rename_meta_table_name_in_query() 0 8 3
B __rename_meta_table_name() 0 41 8
B is_post_type_query() 0 20 6
A is_valid_post_type() 0 3 2
A is_custom_meta_table_active() 0 3 1
A delete_cache() 0 14 3
B __call() 26 59 9
A create_table() 0 20 1
A get_meta_type() 0 3 1
A delete_all_meta() 0 10 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Give_DB_Meta 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 Give_DB_Meta, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Give DB Meta
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_DB_Meta
7
 * @copyright   Copyright (c) 2017, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       2.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
class Give_DB_Meta extends Give_DB {
18
	/**
19
	 * Post type
20
	 *
21
	 * @since  2.0
22
	 * @access protected
23
	 * @var bool
24
	 */
25
	protected $post_type = '';
26
27
	/**
28
	 * Meta type
29
	 *
30
	 * @since  2.0
31
	 * @access protected
32
	 * @var bool
33
	 */
34
	protected $meta_type = '';
35
36
	/**
37
	 * Flag to handle result type
38
	 *
39
	 * @since  2.0
40
	 * @access protected
41
	 */
42
	protected $raw_result = false;
43
44
	/**
45
	 * Flag for short circuit of meta function
46
	 *
47
	 * @since  2.0
48
	 * @access protected
49
	 */
50
	protected $check = false;
51
52
53
	/**
54
	 * Meta supports.
55
	 *
56
	 * @since  2.0
57
	 * @access protected
58
	 * @var array
59
	 */
60
	protected $supports = array(
61
		'add_post_metadata',
62
		'get_post_metadata',
63
		'update_post_metadata',
64
		'delete_post_metadata',
65
		'posts_where',
66
		'posts_join',
67
		'posts_groupby',
68
		'posts_orderby'
69
	);
70
71
	/**
72
	 * Give_DB_Meta constructor.
73
	 *
74
	 * @since 2.0
75
	 */
76
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
77
		parent::__construct();
78
79
		// Bailout.
80
		if ( empty( $this->supports ) || ! $this->is_custom_meta_table_active() ) {
81
			return;
82
		}
83
84
		if ( in_array( 'add_post_metadata', $this->supports ) ) {
85
			add_filter( 'add_post_metadata', array( $this, '__add_meta' ), 0, 5 );
86
		}
87
88
		if ( in_array( 'get_post_metadata', $this->supports ) ) {
89
			add_filter( 'get_post_metadata', array( $this, '__get_meta' ), 10, 4 );
90
		}
91
92
		if ( in_array( 'update_post_metadata', $this->supports ) ) {
93
			add_filter( 'update_post_metadata', array( $this, '__update_meta' ), 0, 5 );
94
		}
95
96
		if ( in_array( 'delete_post_metadata', $this->supports ) ) {
97
			add_filter( 'delete_post_metadata', array( $this, '__delete_meta' ), 0, 5 );
98
		}
99
100 View Code Duplication
		if ( in_array( 'posts_where', $this->supports ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
			add_filter( 'posts_where', array( $this, '__rename_meta_table_name_in_query' ), 99999, 2 );
102
		}
103
104 View Code Duplication
		if ( in_array( 'posts_join', $this->supports ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105
			add_filter( 'posts_join', array( $this, '__rename_meta_table_name_in_query' ), 99999, 2 );
106
		}
107
108 View Code Duplication
		if ( in_array( 'posts_groupby', $this->supports ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109
			add_filter( 'posts_groupby', array( $this, '__rename_meta_table_name_in_query' ), 99999, 2 );
110
		}
111
112 View Code Duplication
		if ( in_array( 'posts_orderby', $this->supports ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
113
			add_filter( 'posts_orderby', array( $this, '__rename_meta_table_name_in_query' ), 99999, 2 );
114
		}
115
	}
116
117
118
	/**
119
	 * Retrieve payment meta field for a payment.
120
	 *
121
	 * @access  public
122
	 * @since   2.0
123
	 *
124
	 * @param   int    $id       Pst Type  ID.
125
	 * @param   string $meta_key The meta key to retrieve.
126
	 * @param   bool   $single   Whether to return a single value.
127
	 *
128
	 * @return  mixed                 Will be an array if $single is false. Will be value of meta data field if $single
129
	 *                                is true.
130
	 */
131
	public function get_meta( $id = 0, $meta_key = '', $single = false ) {
132
		$id = $this->sanitize_id( $id );
133
134
		// Bailout.
135
		if ( ! $this->is_valid_post_type( $id ) ) {
136
			return $this->check;
137
		}
138
139
		if ( $this->raw_result ) {
140
			if ( ! ( $value = get_metadata( $this->meta_type, $id, $meta_key, false ) ) ) {
141
				$value = '';
142
			}
143
144
			// Reset flag.
145
			$this->raw_result = false;
146
147
		} else {
148
			$value = get_metadata( $this->meta_type, $id, $meta_key, $single );
149
		}
150
151
		return $value;
152
	}
153
154
155
	/**
156
	 * Add meta data field to a payment.
157
	 *
158
	 * For internal use only. Use Give_Payment->add_meta() for public usage.
159
	 *
160
	 * @access  private
161
	 * @since   2.0
162
	 *
163
	 * @param   int    $id         Post Type ID.
164
	 * @param   string $meta_key   Metadata name.
165
	 * @param   mixed  $meta_value Metadata value.
166
	 * @param   bool   $unique     Optional, default is false. Whether the same key should not be added.
167
	 *
168
	 * @return  int|bool                  False for failure. True for success.
169
	 */
170 View Code Duplication
	public function add_meta( $id = 0, $meta_key = '', $meta_value, $unique = false ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
171
		$id = $this->sanitize_id( $id );
172
173
		// Bailout.
174
		if ( ! $this->is_valid_post_type( $id ) ) {
175
			return $this->check;
176
		}
177
178
		$meta_id = add_metadata( $this->meta_type, $id, $meta_key, $meta_value, $unique );
179
180
		if ( $meta_id ) {
181
			$this->delete_cache( $id );
0 ignored issues
show
Bug introduced by
It seems like $id defined by $this->sanitize_id($id) on line 171 can also be of type boolean; however, Give_DB_Meta::delete_cache() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
182
		}
183
184
		return $meta_id;
185
	}
186
187
	/**
188
	 * Update payment meta field based on Post Type ID.
189
	 *
190
	 * For internal use only. Use Give_Payment->update_meta() for public usage.
191
	 *
192
	 * Use the $prev_value parameter to differentiate between meta fields with the
193
	 * same key and Post Type ID.
194
	 *
195
	 * If the meta field for the payment does not exist, it will be added.
196
	 *
197
	 * @access  public
198
	 * @since   2.0
199
	 *
200
	 * @param   int    $id         Post Type ID.
201
	 * @param   string $meta_key   Metadata key.
202
	 * @param   mixed  $meta_value Metadata value.
203
	 * @param   mixed  $prev_value Optional. Previous value to check before removing.
204
	 *
205
	 * @return  int|bool                  False on failure, true if success.
206
	 */
207 View Code Duplication
	public function update_meta( $id = 0, $meta_key = '', $meta_value, $prev_value = '' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
		$id = $this->sanitize_id( $id );
209
210
		// Bailout.
211
		if ( ! $this->is_valid_post_type( $id ) ) {
212
			return $this->check;
213
		}
214
215
		$meta_id = update_metadata( $this->meta_type, $id, $meta_key, $meta_value, $prev_value );
216
217
		if ( $meta_id ) {
218
			$this->delete_cache( $id );
0 ignored issues
show
Bug introduced by
It seems like $id defined by $this->sanitize_id($id) on line 208 can also be of type boolean; however, Give_DB_Meta::delete_cache() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
219
		}
220
221
		return $meta_id;
222
	}
223
224
	/**
225
	 * Remove metadata matching criteria from a payment.
226
	 *
227
	 * You can match based on the key, or key and value. Removing based on key and
228
	 * value, will keep from removing duplicate metadata with the same key. It also
229
	 * allows removing all metadata matching key, if needed.
230
	 *
231
	 * @access  public
232
	 * @since   2.0
233
	 *
234
	 * @param   int    $id         Post Type ID.
235
	 * @param   string $meta_key   Metadata name.
236
	 * @param   mixed  $meta_value Optional. Metadata value.
237
	 * @param   mixed  $delete_all Optional.
238
	 *
239
	 * @return  bool                  False for failure. True for success.
240
	 */
241 View Code Duplication
	public function delete_meta( $id = 0, $meta_key = '', $meta_value = '', $delete_all = '' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242
		$id = $this->sanitize_id( $id );
243
244
		// Bailout.
245
		if ( ! $this->is_valid_post_type( $id ) ) {
246
			return $this->check;
247
		}
248
249
		$is_meta_deleted = delete_metadata( $this->meta_type, $id, $meta_key, $meta_value, $delete_all );
250
251
		if ( $is_meta_deleted ) {
252
			$this->delete_cache( $id );
0 ignored issues
show
Bug introduced by
It seems like $id defined by $this->sanitize_id($id) on line 242 can also be of type boolean; however, Give_DB_Meta::delete_cache() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
253
		}
254
255
		return $is_meta_deleted;
256
	}
257
258
	/**
259
	 * Rename query clauses of every query for new meta table
260
	 *
261
	 * @since  2.0
262
	 * @access public
263
	 *
264
	 * @param string   $clause
265
	 * @param WP_Query $wp_query
266
	 *
267
	 * @return string
268
	 */
269
	public function __rename_meta_table_name_in_query( $clause, $wp_query ) {
0 ignored issues
show
Coding Style introduced by
Method name "Give_DB_Meta::__rename_meta_table_name_in_query" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
270
		// Add new table to sql query.
271
		if ( $this->is_post_type_query( $wp_query ) && ! empty( $wp_query->meta_query->queries ) ) {
272
			$clause = $this->__rename_meta_table_name( $clause, current_filter() );
273
		}
274
275
		return $clause;
276
	}
277
278
279
	/**
280
	 * Rename query clauses for new meta table
281
	 *
282
	 * @param $clause
283
	 * @param $filter
284
	 *
285
	 * @return mixed
286
	 */
287
	public function __rename_meta_table_name( $clause, $filter ) {
0 ignored issues
show
Coding Style introduced by
Method name "Give_DB_Meta::__rename_meta_table_name" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
288
		global $wpdb;
289
290
		$clause = str_replace( "{$wpdb->postmeta}.post_id", "{$this->table_name}.{$this->meta_type}_id", $clause );
291
		$clause = str_replace( $wpdb->postmeta, $this->table_name, $clause );
292
293
		switch ( $filter ) {
294
			case 'posts_join':
295
				$joins = array( 'INNER JOIN', 'LEFT JOIN' );
296
297
				foreach ( $joins as $join ) {
298
					if ( false !== strpos( $clause, $join ) ) {
299
						$clause = explode( $join, $clause );
300
301
						foreach ( $clause as $key => $clause_part ) {
302
							if ( empty( $clause_part ) ) {
303
								continue;
304
							}
305
306
							preg_match( '/' . $wpdb->prefix . 'give_' . $this->meta_type . 'meta AS (.*) ON/', $clause_part, $alias_table_name );
307
308
							if ( isset( $alias_table_name[1] ) ) {
309
								$clause[ $key ] = str_replace( "{$alias_table_name[1]}.post_id", "{$alias_table_name[1]}.{$this->meta_type}_id", $clause_part );
310
							}
311
						}
312
313
						$clause = implode( "{$join} ", $clause );
314
					}
315
				}
316
				break;
317
318
			case 'posts_where':
319
				$clause = str_replace( array( 'mt2.post_id', 'mt1.post_id' ), array(
320
					"mt2.{$this->meta_type}_id",
321
					"mt1.{$this->meta_type}_id"
322
				), $clause );
323
				break;
324
		}
325
326
		return $clause;
327
	}
328
329
330
	/**
331
	 * Check if current query for post type or not.
332
	 *
333
	 * @since  2.0
334
	 * @access protected
335
	 *
336
	 * @param WP_Query $wp_query
337
	 *
338
	 * @return bool
339
	 */
340
	protected function is_post_type_query( $wp_query ) {
341
		$status = false;
342
343
		// Check if it is payment query.
344
		if ( ! empty( $wp_query->query['post_type'] ) ) {
345
			if (
346
				is_string( $wp_query->query['post_type'] ) &&
347
				$this->post_type === $wp_query->query['post_type']
348
			) {
349
				$status = true;
350
			} elseif (
351
				is_array( $wp_query->query['post_type'] ) &&
352
				in_array( $this->post_type, $wp_query->query['post_type'] )
353
			) {
354
				$status = true;
355
			}
356
		}
357
358
		return $status;
359
	}
360
361
	/**
362
	 * Check if current id of post type or not
363
	 *
364
	 * @since  2.0
365
	 * @access protected
366
	 *
367
	 * @param $ID
368
	 *
369
	 * @return bool
370
	 */
371
	protected function is_valid_post_type( $ID ) {
372
		return $ID && ( $this->post_type === get_post_type( $ID ) );
373
	}
374
375
	/**
376
	 * check if custom meta table enabled or not.
377
	 *
378
	 * @since  2.0
379
	 * @access protected
380
	 * @return bool
381
	 */
382
	protected function is_custom_meta_table_active() {
383
		return false;
384
	}
385
386
387
	/**
388
	 * Update last_changed key
389
	 *
390
	 * @since  2.0
391
	 * @access private
392
	 *
393
	 * @param int    $id
394
	 * @param string $meta_type
395
	 *
396
	 * @return void
397
	 */
398
	private function delete_cache( $id, $meta_type = '' ) {
399
		$meta_type = empty( $meta_type ) ? $this->meta_type : $meta_type;
400
401
		$group = array(
402
			'payment'  => 'give-donations', // Backward compatibility
403
			'donation' => 'give-donations',
404
			'donor'    => 'give-donors',
405
			'customer' => 'give-donors', // Backward compatibility for pre upgrade in 2.0
406
		);
407
408
		if ( array_key_exists( $meta_type, $group ) ) {
409
			Give_Cache::delete_group( $id, $group[ $meta_type ] );
410
		}
411
	}
412
413
	/**
414
	 * Add support for hidden functions.
415
	 *
416
	 * @since  2.0
417
	 * @access public
418
	 *
419
	 * @param $name
420
	 * @param $arguments
421
	 *
422
	 * @return mixed
423
	 */
424
	public function __call( $name, $arguments ) {
425
		switch ( $name ) {
426 View Code Duplication
			case '__add_meta':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
427
				$this->check = $arguments[0];
428
				$id          = $arguments[1];
429
				$meta_key    = $arguments[2];
430
				$meta_value  = $arguments[3];
431
				$unique      = $arguments[4];
432
433
				// Bailout.
434
				if ( ! $this->is_valid_post_type( $id ) ) {
435
					return $this->check;
436
				}
437
438
				return $this->add_meta( $id, $meta_key, $meta_value, $unique );
439
440
			case '__get_meta':
441
				$this->check = $arguments[0];
442
				$id          = $arguments[1];
443
				$meta_key    = $arguments[2];
444
				$single      = $arguments[3];
445
446
				// Bailout.
447
				if ( ! $this->is_valid_post_type( $id ) ) {
448
					return $this->check;
449
				}
450
451
				$this->raw_result = true;
452
453
				return $this->get_meta( $id, $meta_key, $single );
454
455
			case '__update_meta':
456
				$this->check = $arguments[0];
457
				$id          = $arguments[1];
458
				$meta_key    = $arguments[2];
459
				$meta_value  = $arguments[3];
460
461
				// Bailout.
462
				if ( ! $this->is_valid_post_type( $id ) ) {
463
					return $this->check;
464
				}
465
466
				return $this->update_meta( $id, $meta_key, $meta_value );
467
468 View Code Duplication
			case '__delete_meta':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
469
				$this->check = $arguments[0];
470
				$id          = $arguments[1];
471
				$meta_key    = $arguments[2];
472
				$meta_value  = $arguments[3];
473
				$delete_all  = $arguments[3];
474
475
				// Bailout.
476
				if ( ! $this->is_valid_post_type( $id ) ) {
477
					return $this->check;
478
				}
479
480
				return $this->delete_meta( $id, $meta_key, $meta_value, $delete_all );
481
		}
482
	}
483
484
	/**
485
	 * Create Meta Tables.
486
	 *
487
	 * @since  2.0.1
488
	 * @access public
489
	 */
490
	public function create_table() {
491
		global $wpdb;
492
493
		$charset_collate = $wpdb->get_charset_collate();
494
495
		$sql = "CREATE TABLE {$this->table_name} (
496
			meta_id bigint(20) NOT NULL AUTO_INCREMENT,
497
			{$this->meta_type}_id bigint(20) NOT NULL,
498
			meta_key varchar(255) DEFAULT NULL,
499
			meta_value longtext,
500
			PRIMARY KEY  (meta_id),
501
			KEY {$this->meta_type}_id ({$this->meta_type}_id),
502
			KEY meta_key (meta_key({$this->min_index_length}))
503
			) {$charset_collate};";
504
505
		require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
506
		dbDelta( $sql );
507
508
		update_option( $this->table_name . '_db_version', $this->version, false );
509
	}
510
511
512
	/**
513
	 * Get meta type
514
	 *
515
	 * @since  2.0.4
516
	 * @access public
517
	 *
518
	 * @return string
519
	 */
520
	public function get_meta_type() {
521
		return $this->meta_type;
522
	}
523
524
	/**
525
	 * Remove all meta data matching criteria from a meta table.
526
	 *
527
	 * @since   2.1.3
528
	 * @access  public
529
	 *
530
	 * @param   int $id ID.
531
	 *
532
	 * @return  bool  False for failure. True for success.
533
	 */
534
	public function delete_all_meta( $id = 0 ) {
535
		global $wpdb;
536
		$status = $wpdb->delete( $this->table_name, array( "{$this->meta_type}_id" => $id ), array( '%d' ) );
537
538
		if ( $status ) {
539
			$this->delete_cache( $id, $this->meta_type );
0 ignored issues
show
Documentation introduced by
$this->meta_type is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
540
		}
541
542
		return $status;
543
	}
544
}
545