Test Failed
Push — feature/background-processing ( ddf6d7 )
by Ravinder
06:04
created

Give_Tools_Delete_Donors   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 432
Duplicated Lines 6.71 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 29
loc 432
rs 9.2
c 0
b 0
f 0
wmc 34
lcom 1
cbo 4

11 Methods

Rating   Name   Duplication   Size   Complexity  
B pre_fetch() 0 33 3
B count() 0 66 4
A get_percentage_complete() 0 3 1
B process_step() 29 29 4
C get_data() 0 104 11
A get_delete_ids() 0 19 3
A get_option() 0 3 1
A update_option() 0 3 1
A delete_option() 0 3 1
A get_step() 0 12 4
A get_step_page() 0 3 1

How to fix   Duplicated Code   

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:

1
<?php
2
/**
3
 * Delete Donors.
4
 *
5
 * This class handles batch processing of deleting donor data.
6
 *
7
 * @subpackage  Admin/Tools/Give_Tools_Delete_Donors
8
 * @copyright   Copyright (c) 2016, WordImpress
9
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
10
 * @since       1.8.12
11
 */
12
13
// Exit if accessed directly.
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
19
/**
20
 * Give_Tools_Delete_Donors Class
21
 *
22
 * @since 1.8.12
23
 */
24
class Give_Tools_Delete_Donors extends Give_Batch_Export {
25
26
	var $request;
27
28
	/**
29
	 * Used to store donation id's that are going to get deleted.
30
	 * @var string
31
	 * @since 1.8.12
32
	 */
33
	var $donation_key = 'give_temp_delete_donation_ids';
34
35
	/**
36
	 * Used to store donors id's that are going to get deleted.
37
	 * @var string
38
	 * @since 1.8.12
39
	 */
40
	var $donor_key = 'give_temp_delete_donor_ids';
41
42
	/**
43
	 * Used to store the step where the step will be. ( 'count', 'donations', 'donors' ).
44
	 * @var string
45
	 * @since 1.8.12
46
	 */
47
	var $step_key = 'give_temp_delete_step';
48
49
	/**
50
	 * Used to store to get the page count in the loop.
51
	 * @var string
52
	 * @since 1.8.12
53
	 */
54
	var $step_on_key = 'give_temp_delete_step_on';
55
56
	/**
57
	 * Contain total number of step .
58
	 * @var string
59
	 * @since 1.8.12
60
	 */
61
	var $total_step;
62
63
	/**
64
	 * Counting contain total number of step that completed.
65
	 * @var int
66
	 * @since 1.8.12
67
	 */
68
	var $step_completed;
69
70
	/**
71
	 * Our export type. Used for export-type specific filters/actions
72
	 * @var string
73
	 * @since 1.8.12
74
	 */
75
	public $export_type = '';
76
77
	/**
78
	 * Allows for a non-form batch processing to be run.
79
	 * @since  1.8.12
80
	 * @var boolean
81
	 */
82
	public $is_void = true;
83
84
	/**
85
	 * Sets the number of items to pull on each step
86
	 * @since  1.8.12
87
	 * @var int
88
	 */
89
	public $per_step = 10;
90
91
	/**
92
	 * Set's all the donors id's
93
	 * @since  1.8.12
94
	 * @var array
95
	 */
96
	public $donor_ids = array();
97
98
	/**
99
	 * Get the Export Data
100
	 *
101
	 * @access public
102
	 * @since  1.8.12
103
	 * @global object $wpdb Used to query the database using the WordPress Database API
104
	 *
105
	 * @return array|bool $data The data for the CSV file
106
	 */
107
	public function pre_fetch() {
108
		$donation_ids = array();
109
		$donor_ids    = array();
110
111
		// Check if the ajax request if running for the first time.
112
		if ( 1 === (int) $this->step ) {
113
			// Delete all the donation ids.
114
			$this->delete_option( $this->donation_key );
115
			// Delete all the donor ids.
116
			$this->delete_option( $this->donor_key );
117
118
			// Delete all the step and set to 'count' which if the first step in the process of deleting the donors.
119
			$this->update_option( $this->step_key, 'count' );
120
121
			// Delete tha page count of the step.
122
			$this->update_option( $this->step_on_key, '0' );
123
		} else {
124
			// Get the old donors list.
125
			$donor_ids = $this->get_option( $this->donor_key );
126
127
			// Get the old donation list.
128
			$donation_ids = $this->get_option( $this->donation_key );
129
		}
130
131
		// Get the step and check for it if it's on the first step( 'count' ) or not.
132
		$step = (int) $this->get_step();
133
		if ( 1 === $step ) {
134
			/**
135
			 * Will add or update the donation and donor data by running wp query.
136
			 */
137
			$this->count( $step, $donation_ids, $donor_ids );
138
		}
139
	}
140
141
	/**
142
	 * Will Update or Add the donation and donors ids in the with option table for there respected key.
143
	 *
144
	 * @param string $step         On which the current ajax is running.
145
	 * @param array  $donation_ids Contain the list of all the donation id's that has being add before this
146
	 * @param array  $donor_ids    Contain the list of all the donors id's that has being add before this
147
	 */
148
	private function count( $step, $donation_ids = array(), $donor_ids = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $step is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
149
150
		// Get the Page count by default it's zero.
151
		$paged = (int) $this->get_step_page();
152
		// Incresed the page count by one.
153
		++ $paged;
154
155
		/**
156
		 * Filter add to alter the argument before the wp quest run
157
		 */
158
		$args = apply_filters( 'give_tools_reset_stats_total_args', array(
159
			'post_type'      => 'give_payment',
160
			'post_status'    => 'any',
161
			'posts_per_page' => $this->per_step,
162
			'paged'          => $paged,
163
			// ONLY TEST MODE TRANSACTIONS!!!
164
			'meta_key'       => '_give_payment_mode',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
165
			'meta_value'     => 'test',
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
166
		) );
167
168
		// Reset the post data.
169
		wp_reset_postdata();
170
		// Getting the new donation.
171
		$donation_posts = new WP_Query( $args );
172
173
		// The Loop.
174
		if ( $donation_posts->have_posts() ) {
175
			while ( $donation_posts->have_posts() ) {
176
				$donation_posts->the_post();
177
				global $post;
178
				// Add the donation id in side the array.
179
				$donation_ids[] = $post->ID;
180
181
				// Add the donor id in side the array.
182
				$donor_ids[] = (int) $post->post_author;
183
			}
184
			/* Restore original Post Data */
185
		}
186
187
		// Get the total number of post found.
188
		$total_donation = (int) $donation_posts->found_posts;
189
190
		// Maximum number of page can be display
191
		$max_num_pages = (int) $donation_posts->max_num_pages;
192
193
		// Check current page is less then max number of page or not
194
		if ( $paged < $max_num_pages ) {
195
			// Update the curretn page virable for the next step
196
			$this->update_option( $this->step_on_key, $paged );
197
198
			// Calculating percentage.
199
			$page_remain          = $max_num_pages - $paged;
200
			$this->total_step     = (int) $max_num_pages + ( $total_donation / $this->per_step ) + ( ( $page_remain * 2 ) * count( $donor_ids ) );
0 ignored issues
show
Documentation Bug introduced by
The property $total_step was declared of type string, but (int) $max_num_pages + $...* 2 * count($donor_ids) is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
201
			$this->step_completed = $paged;
202
		} else {
203
			$donation_ids_count = count( $donor_ids );
0 ignored issues
show
Unused Code introduced by
$donation_ids_count is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
204
			$this->update_option( $this->step_key, 'donation' );
205
			$this->update_option( $this->step_on_key, '0' );
206
		}
207
208
		$donor_ids = array_unique( $donor_ids );
209
		$this->update_option( $this->donor_key, $donor_ids );
210
		$this->update_option( $this->donation_key, $donation_ids );
211
212
		wp_reset_postdata();
213
	}
214
215
	/**
216
	 * Return the calculated completion percentage.
217
	 *
218
	 * @since 1.8.12
219
	 * @return int
220
	 */
221
	public function get_percentage_complete() {
222
		return ceil( ( 100 * $this->step_completed ) / $this->total_step );
223
	}
224
225 View Code Duplication
	public function process_step() {
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...
226
227
		if ( ! $this->can_export() ) {
228
			wp_die( __( 'You do not have permission to delete test transactions.', 'give' ), __( 'Error', 'give' ), array( 'response' => 403 ) );
229
		}
230
231
		$had_data = $this->get_data();
232
233
		if ( $had_data ) {
234
			$this->done = false;
235
236
			return true;
237
		} else {
238
			update_option( 'give_earnings_total', give_get_total_earnings( true ) );
239
			Give_Cache::delete( Give_Cache::get_key( 'give_estimated_monthly_stats' ) );
240
241
			$this->delete_option( $this->donation_key );
242
243
			// Reset the sequential order numbers
244
			if ( give_get_option( 'enable_sequential' ) ) {
245
				delete_option( 'give_last_payment_number' );
246
			}
247
248
			$this->done    = true;
249
			$this->message = __( 'Test donor and transactions successfully deleted.', 'give' );
250
251
			return false;
252
		}
253
	}
254
255
	/**
256
	 * Get the Export Data
257
	 *
258
	 * @access public
259
	 * @since  1.8.12
260
	 * @global object $wpdb Used to query the database using the WordPress Database API
261
	 *
262
	 * @return array|bool $data The data for the CSV file
263
	 */
264
	public function get_data() {
265
266
		// Get the donation id's.
267
		$donation_ids = $this->get_option( $this->donation_key );
268
269
		/**
270
		 * Return false id not test donation is found.
271
		 */
272
		if ( empty( $donation_ids ) ) {
273
			$this->is_empty   = true;
274
			$this->total_step = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $total_step was declared of type string, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
275
276
			return false;
277
		}
278
279
		// Get the current step.
280
		$step = (int) $this->get_step();
281
282
		// get teh donor ids.
283
		$donor_ids = $this->get_option( $this->donor_key );
284
285
		// In step to we delete all the donation in loop.
286
		if ( 2 === $step ) {
287
			$pass_to_donor = false;
288
			$page          = (int) $this->get_step_page();
289
			$page ++;
290
			$count = count( $donation_ids );
291
292
			$this->total_step     = ( ( count( $donation_ids ) / $this->per_step ) * 2 ) + count( $donor_ids );
0 ignored issues
show
Documentation Bug introduced by
The property $total_step was declared of type string, but count($donation_ids) / $...* 2 + count($donor_ids) is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
293
			$this->step_completed = $page;
294
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
295
296
			if ( $count > $this->per_step ) {
297
298
				$this->update_option( $this->step_on_key, $page );
299
				$donation_ids = $this->get_delete_ids( $donation_ids, $page );
300
				$current_page = (int) ceil( $count / $this->per_step );
301
302
				if ( $page === $current_page ) {
303
					$pass_to_donor = true;
304
				}
305
			} else {
306
				$pass_to_donor = true;
307
			}
308
309
			if ( true === $pass_to_donor ) {
310
				$this->update_option( $this->step_key, 'donor' );
311
				$this->update_option( $this->step_on_key, '0' );
312
			}
313
314
			global $wpdb;
315
			foreach ( $donation_ids as $item ) {
316
317
				// will delete the payment log first.
318
				$parent_query = $wpdb->prepare( "SELECT post_id as id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %d", '_give_log_payment_id', (int) $item );
319
				$log_id       = $wpdb->get_row( $parent_query, ARRAY_A );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
320
				// Check if payment has it log or not if yes then delete it.
321
				if ( ! empty( $log_id['id'] ) ) {
322
					// Deleting the payment log.
323
					wp_delete_post( $log_id['id'], true );
324
				}
325
326
				// Delete the main payment.
327
				wp_delete_post( $item, true );
328
			}
329
			do_action( 'give_delete_log_cache' );
330
		}
331
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
332
333
		// Here we delete all the donor
334
		if ( 3 === $step ) {
335
			$page  = (int) $this->get_step_page();
336
			$count = count( $donor_ids );
337
338
			$this->total_step     = ( ( count( $donation_ids ) / $this->per_step ) * 2 ) + count( $donor_ids );
339
			$this->step_completed = $page + ( count( $donation_ids ) / $this->per_step );
340
341
			$args = apply_filters( 'give_tools_reset_stats_total_args', array(
342
				'post_type'      => 'give_payment',
343
				'post_status'    => 'any',
344
				'posts_per_page' => 1,
345
				'meta_key'       => '_give_payment_mode',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
346
				'meta_value'     => 'live',
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
347
				'author'         => $donor_ids[ $page ],
348
			) );
349
350
			$donation_posts = get_posts( $args );
351
			if ( empty( $donation_posts ) ) {
352
				Give()->donors->delete_by_user_id( $donor_ids[ $page ] );
353
			}
354
355
			$page ++;
356
			$this->update_option( $this->step_on_key, $page );
357
			if ( $count === $page ) {
358
				$this->is_empty = false;
359
360
				return false;
361
			}
362
363
			return true;
364
		}
365
366
		return true;
367
	}
368
369
	public function get_delete_ids( $donation_ids, $page ) {
370
		$index            = $page --;
0 ignored issues
show
Unused Code introduced by
$index is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
371
		$count            = count( $donation_ids );
0 ignored issues
show
Unused Code introduced by
$count is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
372
		$temp             = 0;
373
		$current_page     = 0;
374
		$post_delete      = $this->per_step;
375
		$page_donation_id = array();
376
377
		foreach ( $donation_ids as $item ) {
378
			$temp ++;
379
			$page_donation_id[ $current_page ][] = $item;
380
			if ( $temp === $post_delete ) {
381
				$current_page ++;
382
				$temp = 0;
383
			}
384
		}
385
386
		return $page_donation_id[ $page ];
387
	}
388
389
	/**
390
	 * Given a key, get the information from the Database Directly
391
	 *
392
	 * @since  1.8.12
393
	 *
394
	 * @param  string $key The option_name
395
	 *
396
	 * @return mixed       Returns the data from the database
397
	 */
398
	public function get_option( $key, $defalut_value = false ) {
399
		return get_option( $key, $defalut_value );
400
	}
401
402
	/**
403
	 * Give a key, store the value
404
	 *
405
	 * @since  1.8.12s
406
	 *
407
	 * @param  string $key   The option_name
408
	 * @param  mixed  $value The value to store
409
	 *
410
	 * @return void
411
	 */
412
	public function update_option( $key, $value ) {
413
		update_option( $key, $value, false );
414
	}
415
416
	/**
417
	 * Delete an option
418
	 *
419
	 * @since  1.8.12
420
	 *
421
	 * @param  string $key The option_name to delete
422
	 *
423
	 * @return void
424
	 */
425
	public function delete_option( $key ) {
426
		delete_option( $key );
427
	}
428
429
	/**
430
	 * Get the current step in number.
431
	 *
432
	 * There are three step to delete the total donor first counting, second deleting donotion and third deleting donors.
433
	 *
434
	 * @return int|string
435
	 */
436
	private function get_step() {
437
		$step_key = (string) $this->get_option( $this->step_key, false );
438
		if ( 'count' === $step_key ) {
439
			return 1;
440
		} elseif ( 'donation' === $step_key ) {
441
			return 2;
442
		} elseif ( 'donor' === $step_key ) {
443
			return 3;
444
		} else {
445
			return $step_key;
446
		}
447
	}
448
449
	/**
450
	 * Get the current $page value in the ajax.
451
	 */
452
	private function get_step_page() {
453
		return $this->get_option( $this->step_on_key, false );
454
	}
455
}
456