Completed
Push — release/2.0 ( 4d845f...d9fa8a )
by Ravinder
18:24
created

Give_Batch_Export::process_step()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 8
nop 0
dl 0
loc 23
rs 8.7972
c 0
b 0
f 0
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 24 and the first side effect is on line 16.

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
 * Batch Export Class
4
 *
5
 * This is the base class for all batch export methods. Each data export type (donors, payments, etc) extend this class.
6
 *
7
 * @package     Give
8
 * @subpackage  Admin/Export
9
 * @copyright   Copyright (c) 2016, WordImpress
10
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
11
 * @since       1.5
12
 */
13
14
// Exit if accessed directly.
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Give_Batch_Export Class
21
 *
22
 * @since 1.5
23
 */
24
class Give_Batch_Export extends Give_Export {
25
26
	/**
27
	 * The file the data is stored in.
28
	 *
29
	 * @since 1.5
30
	 */
31
	private $file;
32
33
	/**
34
	 * The name of the file the data is stored in.
35
	 *
36
	 * @since 1.5
37
	 */
38
	public $filename;
39
40
	/**
41
	 * The file type, typically .csv
42
	 *
43
	 * @since 1.5
44
	 */
45
	public $filetype;
46
47
	/**
48
	 * The current step being processed.
49
	 *
50
	 * @since 1.5
51
	 */
52
	public $step;
53
54
	/**
55
	 * Start date, Y-m-d H:i:s
56
	 *
57
	 * @since 1.5
58
	 */
59
	public $start;
60
61
	/**
62
	 * End date, Y-m-d H:i:s
63
	 *
64
	 * @since 1.5
65
	 */
66
	public $end;
67
68
	/**
69
	 * Status to export.
70
	 *
71
	 * @since 1.5
72
	 */
73
	public $status;
74
75
	/**
76
	 * Form to export data for.
77
	 *
78
	 * @since 1.5
79
	 */
80
	public $form = null;
81
82
	/**
83
	 * Form Price ID to export data for.
84
	 *
85
	 * @since 1.5
86
	 */
87
	public $price_id = null;
88
89
	/**
90
	 * Is the export file writable.
91
	 *
92
	 * @since 1.5
93
	 */
94
	public $is_writable = true;
95
96
	/**
97
	 *  Is the export file empty.
98
	 *
99
	 * @since 1.5
100
	 */
101
	public $is_empty = false;
102
103
	/**
104
	 * Give_Batch_Export constructor.
105
	 *
106
	 * @param int $_step
107
	 */
108
	public function __construct( $_step = 1 ) {
109
110
		$upload_dir       = wp_upload_dir();
111
		$this->filetype   = '.csv';
112
		$this->filename   = 'give-' . $this->export_type . $this->filetype;
113
		$this->file       = trailingslashit( $upload_dir['basedir'] ) . $this->filename;
114
115
		if ( ! is_writeable( $upload_dir['basedir'] ) ) {
116
			$this->is_writable = false;
117
		}
118
119
		$this->step       = $_step;
120
		$this->done       = false;
0 ignored issues
show
Bug introduced by
The property done 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...
121
	}
122
123
	/**
124
	 * Process a step.
125
	 *
126
	 * @since 1.5
127
	 * @return bool
128
	 */
129
	public function process_step() {
130
131
		if ( ! $this->can_export() ) {
132
			wp_die( esc_html__( 'You do not have permission to export data.', 'give' ), esc_html__( 'Error', 'give' ), array(
133
				'response' => 403,
134
			) );
135
		}
136
137
		if ( $this->step < 2 ) {
138
139
			// Make sure we start with a fresh file on step 1.
140
			@unlink( $this->file );
141
			$this->print_csv_cols();
142
		}
143
144
		$rows = $this->print_csv_rows();
145
146
		if ( $rows ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rows of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
147
			return true;
148
		} else {
149
			return false;
150
		}
151
	}
152
153
	/**
154
	 * Output the CSV columns.
155
	 *
156
	 * @access public
157
	 * @since 1.5
158
	 * @uses Give_Export::get_csv_cols()
159
	 * @return string
160
	 */
161
	public function print_csv_cols() {
162
163
		$col_data = '';
164
		$cols = $this->get_csv_cols();
165
		$i = 1;
166
		foreach ( $cols as $col_id => $column ) {
167
			$col_data .= '"' . addslashes( $column ) . '"';
168
			$col_data .= $i == count( $cols ) ? '' : ',';
169
			$i++;
170
		}
171
		$col_data .= "\r\n";
172
173
		$this->stash_step_data( $col_data );
174
175
		return $col_data;
176
177
	}
178
179
	/**
180
	 * Print the CSV rows for the current step.
181
	 *
182
	 * @access public
183
	 * @since 1.5
184
	 * @return string|false
185
	 */
186
	public function print_csv_rows() {
187
188
		$row_data = '';
189
		$data     = $this->get_data();
190
		$cols     = $this->get_csv_cols();
191
192
		if ( $data ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data 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...
193
194
			// Output each row
195
			foreach ( $data as $row ) {
196
				$i = 1;
197
				foreach ( $row as $col_id => $column ) {
198
					// Make sure the column is valid
199
					if ( array_key_exists( $col_id, $cols ) ) {
200
						$row_data .= '"' . addslashes( preg_replace( '/"/',"'", $column ) ) . '"';
201
						$row_data .= $i == count( $cols ) ? '' : ',';
202
						$i++;
203
					}
204
				}
205
				$row_data .= "\r\n";
206
			}
207
208
			$this->stash_step_data( $row_data );
209
210
			return $row_data;
211
		}
212
213
		return false;
214
	}
215
216
	/**
217
	 * Return the calculated completion percentage.
218
	 *
219
	 * @since 1.5
220
	 * @return int
221
	 */
222
	public function get_percentage_complete() {
223
		return 100;
224
	}
225
226
	/**
227
	 * Retrieve the file data is written to.
228
	 *
229
	 * @since 1.5
230
	 * @return string
231
	 */
232
	protected function get_file() {
233
234
		$file = '';
235
236
		if ( @file_exists( $this->file ) ) {
237
238
			if ( ! is_writeable( $this->file ) ) {
239
				$this->is_writable = false;
240
			}
241
242
			$file = @file_get_contents( $this->file );
243
244
		} else {
245
246
			@file_put_contents( $this->file, '' );
247
			@chmod( $this->file, 0664 );
248
249
		}
250
251
		return $file;
252
	}
253
254
	/**
255
	 * Append data to export file.
256
	 *
257
	 * @since 1.5
258
	 * @param $data string The data to add to the file.
259
	 * @return void
260
	 */
261
	protected function stash_step_data( $data = '' ) {
262
263
		$file = $this->get_file();
264
		$file .= $data;
265
		@file_put_contents( $this->file, $file );
266
267
		// If we have no rows after this step, mark it as an empty export.
268
		$file_rows    = file( $this->file, FILE_SKIP_EMPTY_LINES );
269
		$default_cols = $this->get_csv_cols();
270
		$default_cols = empty( $default_cols ) ? 0 : 1;
271
272
		$this->is_empty = count( $file_rows ) == $default_cols ? true : false;
273
274
	}
275
276
	/**
277
	 * Perform the export.
278
	 *
279
	 * @access public
280
	 * @since 1.5
281
	 * @return void
282
	 */
283
	public function export() {
284
285
		// Set headers
286
		$this->headers();
287
288
		$file = $this->get_file();
289
290
		@unlink( $this->file );
291
292
		echo $file;
293
294
		/**
295
		 * Fire action after file output.
296
		 *
297
		 * @since 1.8
298
		 */
299
		do_action( 'give_file_export_complete', $_REQUEST );
300
301
		give_die();
302
	}
303
304
	/**
305
	 * Set the properties specific to the export.
306
	 *
307
	 * @since 1.5
308
	 * @param array $request The Form Data passed into the batch processing.
309
	 */
310
	public function set_properties( $request ) {}
311
312
	/**
313
	 * Allow for pre-fetching of data for the remainder of the exporter.
314
	 *
315
	 * @access public
316
	 * @since  1.5
317
	 * @return void
318
	 */
319
	public function pre_fetch() {}
320
321
}
322