Completed
Push — issues/1817 ( 12f6f1...27df7d )
by Ravinder
19:58
created

Give_Tools_Recount_Form_Stats::get_data()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 56
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 31
nc 20
nop 0
dl 0
loc 56
rs 7.7489
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 23 and the first side effect is on line 15.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Recount donation form income and donations
4
 *
5
 * This class handles batch processing of recounting earnings and stats
6
 *
7
 * @subpackage  Admin/Tools/Give_Tools_Recount_Stats
8
 * @copyright   Copyright (c) 2016, WordImpress
9
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
10
 * @since       1.5
11
 */
12
13
// Exit if accessed directly.
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
/**
19
 * Give_Tools_Recount_Form_Stats Class
20
 *
21
 * @since 1.5
22
 */
23
class Give_Tools_Recount_Form_Stats extends Give_Batch_Export {
24
25
	/**
26
	 * Our export type. Used for export-type specific filters/actions
27
	 * @var string
28
	 * @since 1.5
29
	 */
30
	public $export_type = '';
31
32
	/**
33
	 * Allows for a non-form batch processing to be run.
34
	 * @since  1.5
35
	 * @var boolean
36
	 */
37
	public $is_void = true;
38
39
	/**
40
	 * Sets the number of items to pull on each step
41
	 * @since  1.5
42
	 * @var integer
43
	 */
44
	public $per_step = 30;
45
46
	/**
47
	 * Sets the donation form ID to recalculate
48
	 * @since  1.5
49
	 * @var integer
50
	 */
51
	protected $form_id = null;
52
53
	/**
54
	 * Get the Export Data
55
	 *
56
	 * @access public
57
	 * @since 1.5
58
	 *
59
	 * @return bool
60
	 */
61
	public function get_data() {
62
		$accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
63
64
		if ( $this->step == 1 ) {
65
			$this->delete_data( 'give_temp_recount_form_stats' );
66
		}
67
68
		$totals = $this->get_stored_data( 'give_temp_recount_form_stats' );
69
70
		if ( false === $totals ) {
71
			$totals = array(
72
				'earnings' => (float) 0,
73
				'sales'    => 0,
74
			);
75
			$this->store_data( 'give_temp_recount_form_stats', $totals );
76
		}
77
78
		$args = apply_filters( 'give_recount_form_stats_args', array(
79
			'give_forms' => $this->form_id,
80
			'number'     => $this->per_step,
81
			'status'     => $accepted_statuses,
82
			'paged'      => $this->step,
83
			'fields'     => 'ids',
84
		) );
85
86
		$payments = new Give_Payments_Query( $args );
87
		$payments = $payments->get_payments();
88
89
		if ( $payments ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
90
			foreach ( $payments as $payment ) {
91
				//Ensure acceptible status only
92
				if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
93
					continue;
94
				}
95
96
				//Ensure only payments for this form are counted
97
				if ( $payment->form_id != $this->form_id ) {
98
					continue;
99
				}
100
101
				$totals['sales'] ++;
102
				$totals['earnings'] += $payment->total;
103
104
			}
105
106
			$this->store_data( 'give_temp_recount_form_stats', $totals );
107
108
			return true;
109
		}
110
111
112
		give_update_meta( $this->form_id, '_give_form_sales', $totals['sales'] );
113
		give_update_meta( $this->form_id, '_give_form_earnings', $totals['earnings'] );
114
115
		return false;
116
	}
117
118
	/**
119
	 * Return the calculated completion percentage
120
	 *
121
	 * @since 1.5
122
	 * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
123
	 */
124
	public function get_percentage_complete() {
125
		if ( $this->step == 1 ) {
126
			$this->delete_data( 'give_recount_total_' . $this->form_id );
127
		}
128
129
		$accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
130
		$total             = $this->get_stored_data( 'give_recount_total_' . $this->form_id );
131
132
		if ( false === $total ) {
133
			$total = 0;
134
			$args  = apply_filters( 'give_recount_form_stats_total_args', array(
135
				'give_forms' => $this->form_id,
136
				'number'     => - 1,
137
				'status'     => $accepted_statuses,
138
				'fields'     => 'ids',
139
			) );
140
141
			$payments = new Give_Payments_Query( $args );
142
			$total    = count( $payments->get_payments() );
143
			$this->store_data( 'give_recount_total_' . $this->form_id, $total );
144
145
		}
146
147
		$percentage = 100;
148
149
		if ( $total > 0 ) {
150
			$percentage = ( ( $this->per_step * $this->step ) / $total ) * 100;
151
		}
152
153
		if ( $percentage > 100 ) {
154
			$percentage = 100;
155
		}
156
157
		return $percentage;
158
	}
159
160
	/**
161
	 * Set the properties specific to the payments export
162
	 *
163
	 * @since 1.5
164
	 *
165
	 * @param array $request The Form Data passed into the batch processing
166
	 */
167
	public function set_properties( $request ) {
168
		$this->form_id = isset( $request['form_id'] ) ? sanitize_text_field( $request['form_id'] ) : false;
169
	}
170
171
	/**
172
	 * Process a step
173
	 *
174
	 * @since 1.5
175
	 * @return bool
176
	 */
177
	public function process_step() {
178
179
		if ( ! $this->can_export() ) {
180
			wp_die( esc_html__( 'You do not have permission to recount stats.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
181
		}
182
183
		$had_data = $this->get_data();
184
185
		if ( $had_data ) {
186
			$this->done = false;
187
188
			return true;
189
		} else {
190
			$this->delete_data( 'give_recount_total_' . $this->form_id );
191
			$this->delete_data( 'give_temp_recount_form_stats' );
192
			$this->done    = true;
193
			$this->message = sprintf( esc_html__( 'Donation counts and income amount statistics successfully recounted for "%s".', 'give' ), get_the_title( $this->form_id ) );
0 ignored issues
show
Bug introduced by
The property message does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
194
195
			return false;
196
		}
197
	}
198
199
	public function headers() {
200
		ignore_user_abort( true );
201
202
		if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
203
			set_time_limit( 0 );
204
		}
205
	}
206
207
	/**
208
	 * Perform the export
209
	 *
210
	 * @access public
211
	 * @since 1.5
212
	 * @return void
213
	 */
214
	public function export() {
215
216
		// Set headers
217
		$this->headers();
218
219
		give_die();
220
	}
221
222
	/**
223
	 * Given a key, get the information from the Database Directly
224
	 *
225
	 * @since  1.5
226
	 *
227
	 * @param  string $key The option_name
228
	 *
229
	 * @return mixed       Returns the data from the database
230
	 */
231
	private function get_stored_data( $key ) {
232
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
233
		$value = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = '%s'", $key ) );
234
235
		return empty( $value ) ? false : maybe_unserialize( $value );
236
	}
237
238
	/**
239
	 * Give a key, store the value
240
	 *
241
	 * @since  1.5
242
	 *
243
	 * @param  string $key The option_name
244
	 * @param  mixed $value The value to store
245
	 *
246
	 * @return void
247
	 */
248
	private function store_data( $key, $value ) {
249
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
250
251
		$value = maybe_serialize( $value );
252
253
		$data = array(
254
			'option_name'  => $key,
255
			'option_value' => $value,
256
			'autoload'     => 'no',
257
		);
258
259
		$formats = array(
260
			'%s',
261
			'%s',
262
			'%s',
263
		);
264
265
		$wpdb->replace( $wpdb->options, $data, $formats );
266
	}
267
268
	/**
269
	 * Delete an option
270
	 *
271
	 * @since  1.5
272
	 *
273
	 * @param  string $key The option_name to delete
274
	 *
275
	 * @return void
276
	 */
277
	private function delete_data( $key ) {
278
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
279
		$wpdb->delete( $wpdb->options, array( 'option_name' => $key ) );
280
	}
281
282
}