|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
/** |
|
3
|
|
|
* Batch Export Class |
|
4
|
|
|
* |
|
5
|
|
|
* This is the base class for all batch export methods. Each data export type (customers, payments, etc) extend this class |
|
6
|
|
|
* |
|
7
|
|
|
* @package Give |
|
8
|
|
|
* @subpackage Admin/Export |
|
9
|
|
|
* @copyright Copyright (c) 2016, WordImpress |
|
10
|
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
|
11
|
|
|
* @since 1.5 |
|
12
|
|
|
*/ |
|
13
|
|
|
|
|
14
|
|
|
// Exit if accessed directly |
|
15
|
|
|
if ( ! defined( 'ABSPATH' ) ) exit; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* Give_Batch_Export Class |
|
19
|
|
|
* |
|
20
|
|
|
* @since 1.5 |
|
21
|
|
|
*/ |
|
22
|
|
|
class Give_Batch_Export extends Give_Export { |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* The file the data is stored in |
|
26
|
|
|
* |
|
27
|
|
|
* @since 1.5 |
|
28
|
|
|
*/ |
|
29
|
|
|
private $file; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* The name of the file the data is stored in |
|
33
|
|
|
* |
|
34
|
|
|
* @since 1.5 |
|
35
|
|
|
*/ |
|
36
|
|
|
public $filename; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* The file type, typically .csv |
|
40
|
|
|
* |
|
41
|
|
|
* @since 1.5 |
|
42
|
|
|
*/ |
|
43
|
|
|
public $filetype; |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* The current step being processed |
|
47
|
|
|
* |
|
48
|
|
|
* @since 1.5 |
|
49
|
|
|
*/ |
|
50
|
|
|
public $step; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* Start date, Y-m-d H:i:s |
|
54
|
|
|
* |
|
55
|
|
|
* @since 1.5 |
|
56
|
|
|
*/ |
|
57
|
|
|
public $start; |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* End date, Y-m-d H:i:s |
|
61
|
|
|
* |
|
62
|
|
|
* @since 1.5 |
|
63
|
|
|
*/ |
|
64
|
|
|
public $end; |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* Status to export |
|
68
|
|
|
* |
|
69
|
|
|
* @since 1.5 |
|
70
|
|
|
*/ |
|
71
|
|
|
public $status; |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* Form to export data for |
|
75
|
|
|
* |
|
76
|
|
|
* @since 1.5 |
|
77
|
|
|
*/ |
|
78
|
|
|
public $form = null; |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* Form Price ID to export data for |
|
82
|
|
|
* |
|
83
|
|
|
* @since 1.5 |
|
84
|
|
|
*/ |
|
85
|
|
|
public $price_id = null; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* Is the export file writable |
|
89
|
|
|
* |
|
90
|
|
|
* @since 1.5 |
|
91
|
|
|
*/ |
|
92
|
|
|
public $is_writable = true; |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Is the export file empty |
|
96
|
|
|
* |
|
97
|
|
|
* @since 1.5 |
|
98
|
|
|
*/ |
|
99
|
|
|
public $is_empty = false; |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Get things started |
|
103
|
|
|
* |
|
104
|
|
|
* @param $_step int The step to process |
|
105
|
|
|
* @since 1.5 |
|
106
|
|
|
*/ |
|
107
|
|
|
public function __construct( $_step = 1 ) { |
|
108
|
|
|
|
|
109
|
|
|
$upload_dir = wp_upload_dir(); |
|
110
|
|
|
$this->filetype = '.csv'; |
|
111
|
|
|
$this->filename = 'give-' . $this->export_type . $this->filetype; |
|
112
|
|
|
$this->file = trailingslashit( $upload_dir['basedir'] ) . $this->filename; |
|
113
|
|
|
|
|
114
|
|
|
if ( ! is_writeable( $upload_dir['basedir'] ) ) { |
|
115
|
|
|
$this->is_writable = false; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
$this->step = $_step; |
|
119
|
|
|
$this->done = false; |
|
|
|
|
|
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Process a step |
|
124
|
|
|
* |
|
125
|
|
|
* @since 1.5 |
|
126
|
|
|
* @return bool |
|
127
|
|
|
*/ |
|
128
|
|
|
public function process_step() { |
|
129
|
|
|
|
|
130
|
|
|
if ( ! $this->can_export() ) { |
|
131
|
|
|
wp_die( __( 'You do not have permission to export data.', 'give' ), __( 'Error', 'give' ), array( 'response' => 403 ) ); |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
if( $this->step < 2 ) { |
|
135
|
|
|
|
|
136
|
|
|
// Make sure we start with a fresh file on step 1 |
|
137
|
|
|
@unlink( $this->file ); |
|
138
|
|
|
$this->print_csv_cols(); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
$rows = $this->print_csv_rows(); |
|
142
|
|
|
|
|
143
|
|
|
if( $rows ) { |
|
|
|
|
|
|
144
|
|
|
return true; |
|
145
|
|
|
} else { |
|
146
|
|
|
return false; |
|
147
|
|
|
} |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Output the CSV columns |
|
152
|
|
|
* |
|
153
|
|
|
* @access public |
|
154
|
|
|
* @since 1.5 |
|
155
|
|
|
* @uses Give_Export::get_csv_cols() |
|
156
|
|
|
* @return string |
|
157
|
|
|
*/ |
|
158
|
|
|
public function print_csv_cols() { |
|
159
|
|
|
|
|
160
|
|
|
$col_data = ''; |
|
161
|
|
|
$cols = $this->get_csv_cols(); |
|
162
|
|
|
$i = 1; |
|
163
|
|
|
foreach( $cols as $col_id => $column ) { |
|
164
|
|
|
$col_data .= '"' . addslashes( $column ) . '"'; |
|
165
|
|
|
$col_data .= $i == count( $cols ) ? '' : ','; |
|
166
|
|
|
$i++; |
|
167
|
|
|
} |
|
168
|
|
|
$col_data .= "\r\n"; |
|
169
|
|
|
|
|
170
|
|
|
$this->stash_step_data( $col_data ); |
|
171
|
|
|
|
|
172
|
|
|
return $col_data; |
|
173
|
|
|
|
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* Print the CSV rows for the current step |
|
178
|
|
|
* |
|
179
|
|
|
* @access public |
|
180
|
|
|
* @since 1.5 |
|
181
|
|
|
* @return string|false |
|
182
|
|
|
*/ |
|
183
|
|
|
public function print_csv_rows() { |
|
184
|
|
|
|
|
185
|
|
|
$row_data = ''; |
|
186
|
|
|
$data = $this->get_data(); |
|
187
|
|
|
$cols = $this->get_csv_cols(); |
|
188
|
|
|
|
|
189
|
|
|
if( $data ) { |
|
|
|
|
|
|
190
|
|
|
|
|
191
|
|
|
// Output each row |
|
192
|
|
|
foreach ( $data as $row ) { |
|
193
|
|
|
$i = 1; |
|
194
|
|
|
foreach ( $row as $col_id => $column ) { |
|
195
|
|
|
// Make sure the column is valid |
|
196
|
|
|
if ( array_key_exists( $col_id, $cols ) ) { |
|
197
|
|
|
$row_data .= '"' . addslashes( preg_replace( "/\"/","'", $column ) ) . '"'; |
|
198
|
|
|
$row_data .= $i == count( $cols ) ? '' : ','; |
|
199
|
|
|
$i++; |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
$row_data .= "\r\n"; |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
$this->stash_step_data( $row_data ); |
|
206
|
|
|
|
|
207
|
|
|
return $row_data; |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
return false; |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
/** |
|
214
|
|
|
* Return the calculated completion percentage |
|
215
|
|
|
* |
|
216
|
|
|
* @since 1.5 |
|
217
|
|
|
* @return int |
|
218
|
|
|
*/ |
|
219
|
|
|
public function get_percentage_complete() { |
|
220
|
|
|
return 100; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
/** |
|
224
|
|
|
* Retrieve the file data is written to |
|
225
|
|
|
* |
|
226
|
|
|
* @since 1.5 |
|
227
|
|
|
* @return string |
|
228
|
|
|
*/ |
|
229
|
|
|
protected function get_file() { |
|
230
|
|
|
|
|
231
|
|
|
$file = ''; |
|
232
|
|
|
|
|
233
|
|
|
if ( @file_exists( $this->file ) ) { |
|
234
|
|
|
|
|
235
|
|
|
if ( ! is_writeable( $this->file ) ) { |
|
236
|
|
|
$this->is_writable = false; |
|
237
|
|
|
} |
|
238
|
|
|
|
|
239
|
|
|
$file = @file_get_contents( $this->file ); |
|
240
|
|
|
|
|
241
|
|
|
} else { |
|
242
|
|
|
|
|
243
|
|
|
@file_put_contents( $this->file, '' ); |
|
244
|
|
|
@chmod( $this->file, 0664 ); |
|
245
|
|
|
|
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
return $file; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
/** |
|
252
|
|
|
* Append data to export file |
|
253
|
|
|
* |
|
254
|
|
|
* @since 1.5 |
|
255
|
|
|
* @param $data string The data to add to the file |
|
256
|
|
|
* @return void |
|
257
|
|
|
*/ |
|
258
|
|
|
protected function stash_step_data( $data = '' ) { |
|
259
|
|
|
|
|
260
|
|
|
$file = $this->get_file(); |
|
261
|
|
|
$file .= $data; |
|
262
|
|
|
@file_put_contents( $this->file, $file ); |
|
263
|
|
|
|
|
264
|
|
|
// If we have no rows after this step, mark it as an empty export |
|
265
|
|
|
$file_rows = file( $this->file, FILE_SKIP_EMPTY_LINES); |
|
266
|
|
|
$default_cols = $this->get_csv_cols(); |
|
267
|
|
|
$default_cols = empty( $default_cols ) ? 0 : 1; |
|
268
|
|
|
|
|
269
|
|
|
$this->is_empty = count( $file_rows ) == $default_cols ? true : false; |
|
270
|
|
|
|
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Perform the export |
|
275
|
|
|
* |
|
276
|
|
|
* @access public |
|
277
|
|
|
* @since 1.5 |
|
278
|
|
|
* @return void |
|
279
|
|
|
*/ |
|
280
|
|
|
public function export() { |
|
281
|
|
|
|
|
282
|
|
|
// Set headers |
|
283
|
|
|
$this->headers(); |
|
284
|
|
|
|
|
285
|
|
|
$file = $this->get_file(); |
|
286
|
|
|
|
|
287
|
|
|
@unlink( $this->file ); |
|
288
|
|
|
|
|
289
|
|
|
echo $file; |
|
290
|
|
|
|
|
291
|
|
|
give_die(); |
|
292
|
|
|
} |
|
293
|
|
|
|
|
294
|
|
|
/* |
|
295
|
|
|
* Set the properties specific to the export |
|
296
|
|
|
* |
|
297
|
|
|
* @since 1.5 |
|
298
|
|
|
* @param array $request The Form Data passed into the batch processing |
|
299
|
|
|
*/ |
|
300
|
|
|
public function set_properties( $request ) {} |
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* Allow for prefetching of data for the remainder of the exporter |
|
304
|
|
|
* |
|
305
|
|
|
* @access public |
|
306
|
|
|
* @since 1.5 |
|
307
|
|
|
* @return void |
|
308
|
|
|
*/ |
|
309
|
|
|
public function pre_fetch() {} |
|
310
|
|
|
|
|
311
|
|
|
} |
|
312
|
|
|
|
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.