Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/paid-memberships-pro/adminpages/login-csv.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
3
+
// only admins can get this
4
+
if ( ! function_exists( 'current_user_can' ) || ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'pmpro_loginscsv' ) ) ) {
5
+
die( esc_html__( 'You do not have permissions to perform this action.', 'paid-memberships-pro' ) );
6
+
}
7
+
8
+
if ( ! defined( 'PMPRO_BENCHMARK' ) ) {
9
+
define( 'PMPRO_BENCHMARK', false );
10
+
}
11
+
12
+
$start_memory = memory_get_usage( true );
13
+
$start_time = microtime( true );
14
+
15
+
if ( true === PMPRO_BENCHMARK ) {
16
+
error_log( str_repeat( '-', 10 ) . date_i18n( 'Y-m-d H:i:s' ) . str_repeat( '-', 10 ) );
17
+
}
18
+
19
+
/**
20
+
* Filter to set max number records to process at a time
21
+
* for the export (helps manage memory footprint)
22
+
*
23
+
* NOTE: Use the pmpro_before_visits_views_logins_csv_export hook to increase memory "on-the-fly"
24
+
* Can reset with the pmpro_after_visits_views_logins_csv_export hook
25
+
*
26
+
* @since 2.9
27
+
*/
28
+
// set the number of records we'll load to try and protect ourselves from OOM errors
29
+
$max_record_loops = apply_filters( 'pmpro_set_max_visits_views_logins_records_per_export_loop', 2000 );
30
+
global $wpdb;
31
+
32
+
// vars
33
+
if ( ! empty( $_REQUEST['s'] ) ) {
34
+
$s = sanitize_text_field( $_REQUEST['s'] );
35
+
} else {
36
+
$s = '';
37
+
}
38
+
39
+
if ( ! empty( $_REQUEST['l'] ) ) {
40
+
if ( $_REQUEST['l'] == 'all' ) {
41
+
$l = 'all';
42
+
} else {
43
+
$l = intval( $_REQUEST['l'] );
44
+
}
45
+
} else {
46
+
$l = '';
47
+
}
48
+
49
+
// some vars for the search
50
+
if ( isset( $_REQUEST['pn'] ) ) {
51
+
$pn = intval( $_REQUEST['pn'] );
52
+
} else {
53
+
$pn = 1;
54
+
}
55
+
56
+
if ( isset( $_REQUEST['limit'] ) ) {
57
+
$limit = intval( $_REQUEST['limit'] );
58
+
} else {
59
+
$limit = false;
60
+
}
61
+
62
+
if ( $limit ) {
63
+
$end = $pn * $limit;
64
+
$start = $end - $limit;
65
+
} else {
66
+
$end = null;
67
+
$start = null;
68
+
}
69
+
70
+
if ( $s ) {
71
+
$sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(CONVERT_TZ(u.user_registered, '+00:00', @@global.time_zone)) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(CONVERT_TZ(mu.startdate, '+00:00', @@global.time_zone)) as startdate, UNIX_TIMESTAMP(CONVERT_TZ(mu.enddate, '+00:00', @@global.time_zone)) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE (u.user_login LIKE '%" . esc_sql( $s ) . "%' OR u.user_email LIKE '%" . esc_sql( $s ) . "%' OR um.meta_value LIKE '%" . esc_sql( $s ) . "%') ";
72
+
73
+
if ( $l == 'all' ) {
74
+
$sqlQuery .= " AND mu.status = 'active' AND mu.membership_id > 0 ";
75
+
} elseif ( $l ) {
76
+
$sqlQuery .= " AND mu.membership_id = '" . esc_sql( $l ) . "' ";
77
+
}
78
+
79
+
$sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC";
80
+
} else {
81
+
$sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(CONVERT_TZ(u.user_registered, '+00:00', @@global.time_zone)) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(CONVERT_TZ(mu.startdate, '+00:00', @@global.time_zone)) as startdate, UNIX_TIMESTAMP(CONVERT_TZ(mu.enddate, '+00:00', @@global.time_zone)) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id";
82
+
$sqlQuery .= ' WHERE 1=1 ';
83
+
84
+
if ( $l == 'all' ) {
85
+
$sqlQuery .= " AND mu.membership_id > 0 AND mu.status = 'active' ";
86
+
} elseif ( $l ) {
87
+
$sqlQuery .= " AND mu.membership_id = '" . esc_sql( $l ) . "' ";
88
+
}
89
+
$sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC";
90
+
}
91
+
92
+
if ( ! empty( $start ) && ! empty( $limit ) ) {
93
+
$sqlQuery .= "LIMIT " . (int) $start . "," . (int) $limit;
94
+
}
95
+
96
+
$sqlQuery = apply_filters( 'pmpro_visits_views_logins_csv_sql', $sqlQuery );
97
+
98
+
$theusers = $wpdb->get_results( $sqlQuery );
99
+
100
+
$headers = array();
101
+
$headers[] = 'Content-Type: text/csv';
102
+
$headers[] = 'Cache-Control: max-age=0, no-cache, no-store';
103
+
$headers[] = 'Pragma: no-cache';
104
+
$headers[] = 'Connection: close';
105
+
106
+
$filename = 'views-logins-visits.csv';
107
+
/*
108
+
Insert logic here for building filename from $filter and other values.
109
+
*/
110
+
$filename = apply_filters( 'pmpro_visits_views_logins_csv_export_filename', $filename );
111
+
$headers[] = "Content-Disposition: attachment; filename={$filename};";
112
+
113
+
// Default CSV file headers.
114
+
$csv_file_header_array = array(
115
+
'ID',
116
+
'username',
117
+
'level',
118
+
'last_visit',
119
+
'visits_this_week',
120
+
'visits_this_month',
121
+
'visits_this_year',
122
+
'visits_all_time',
123
+
'views_this_week',
124
+
'views_this_month',
125
+
'views_this_year',
126
+
'views_all_time',
127
+
'last_login',
128
+
'logins_this_week',
129
+
'logins_this_month',
130
+
'logins_this_year',
131
+
'logins_all_time',
132
+
'joined',
133
+
'expires',
134
+
);
135
+
136
+
// These are the meta_keys for the fields (arrays are object, property. so e.g. $theuser->ID) - Date items are manually handled further down.
137
+
$default_columns = array(
138
+
array( 'user', 'ID' ),
139
+
array( 'user', 'user_login' ),
140
+
array( 'user', 'membership' ),
141
+
array( 'visits', 'last' ),
142
+
array( 'visits', 'week' ),
143
+
array( 'visits', 'month' ),
144
+
array( 'visits', 'ytd' ),
145
+
array( 'visits', 'alltime' ),
146
+
array( 'views', 'week' ),
147
+
array( 'views', 'month' ),
148
+
array( 'views', 'ytd' ),
149
+
array( 'views', 'alltime' ),
150
+
array( 'logins', 'last' ),
151
+
array( 'logins', 'week' ),
152
+
array( 'logins', 'month' ),
153
+
array( 'logins', 'ytd' ),
154
+
array( 'logins', 'alltime' ),
155
+
);
156
+
157
+
$dateformat = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
158
+
159
+
$csv_file_header = implode( ',', $csv_file_header_array ) . "\n";
160
+
161
+
// Generate a temporary file to store the data in.
162
+
$tmp_dir = apply_filters( 'pmpro_visits_views_logins_csv_export_tmp_dir', sys_get_temp_dir() );
163
+
$filename = tempnam( $tmp_dir, 'pmpro_olcsv_' );
164
+
165
+
// open in append mode
166
+
$csv_fh = fopen( $filename, 'a' );
167
+
168
+
// write the CSV header to the file
169
+
fprintf( $csv_fh, '%s', $csv_file_header );
170
+
171
+
$user_ids = $wpdb->get_col( $sqlQuery );
172
+
$users_found = count( $user_ids );
173
+
174
+
if ( empty( $user_ids ) ) {
175
+
// send data to remote browser
176
+
pmpro_transmit_report_data( $csv_fh, $filename, $headers );
177
+
}
178
+
179
+
if ( PMPRO_BENCHMARK ) {
180
+
$pre_action_time = microtime( true );
181
+
$pre_action_memory = memory_get_usage( true );
182
+
}
183
+
184
+
do_action( 'pmpro_before_visits_views_logins_csv_export', $user_ids );
185
+
186
+
$i_start = 0;
187
+
$i_limit = 0;
188
+
$iterations = 1;
189
+
190
+
if ( $users_found >= $max_record_loops ) {
191
+
$iterations = ceil( $users_found / $max_record_loops );
192
+
$i_limit = $max_record_loops;
193
+
}
194
+
195
+
$end = 0;
196
+
$time_limit = ini_get( 'max_execution_time' );
197
+
198
+
if ( PMPRO_BENCHMARK ) {
199
+
error_log( "PMPRO_BENCHMARK - Total records to process: {$users_found}" );
200
+
error_log( "PMPRO_BENCHMARK - Will process {$iterations} iterations of max {$max_record_loops} records per iteration." );
201
+
$pre_iteration_time = microtime( true );
202
+
$pre_iteration_memory = memory_get_usage( true );
203
+
}
204
+
205
+
for ( $ic = 1; $ic <= $iterations; $ic ++ ) {
206
+
207
+
if ( PMPRO_BENCHMARK ) {
208
+
$start_iteration_time = microtime( true );
209
+
$start_iteration_memory = memory_get_usage( true );
210
+
}
211
+
212
+
// avoiding timeouts (modify max run-time for export)
213
+
if ( $end != 0 ) {
214
+
215
+
$iteration_diff = $end - $start;
216
+
$new_time_limit = ceil( $iteration_diff * $iterations * 1.2 );
217
+
218
+
if ( $time_limit < $new_time_limit ) {
219
+
$time_limit = $new_time_limit;
220
+
set_time_limit( $time_limit );
221
+
}
222
+
}
223
+
224
+
225
+
// get the user list we should process
226
+
$user_list = array_slice( $user_ids, $i_start, $max_record_loops );
227
+
228
+
if ( PMPRO_BENCHMARK ) {
229
+
$pre_data_time = microtime( true );
230
+
$pre_data_memory = memory_get_usage( true );
231
+
}
232
+
233
+
foreach ( $theusers as $user ) {
234
+
$csvoutput = array();
235
+
236
+
// Get the visits, views and logins arrays. Set it to an object.
237
+
$visits = (object) pmpro_reports_get_values_for_user( 'visits', $user->ID );
238
+
$views = (object) pmpro_reports_get_values_for_user( 'views', $user->ID );
239
+
$logins = (object) pmpro_reports_get_values_for_user( 'logins', $user->ID );
240
+
241
+
if ( ! empty( $default_columns ) ) {
242
+
$count = 0;
243
+
foreach ( $default_columns as $col ) {
244
+
245
+
// checking $object->property. note the double $$
246
+
switch ( count( $col ) ) {
247
+
case 3:
248
+
$val = isset( ${$col[0]}->{$col[1]}->{$col[2]} ) ? ${$col[0]}->{$col[1]}->{$col[2]} : null;
249
+
break;
250
+
251
+
case 2:
252
+
$val = isset( ${$col[0]}->{$col[1]} ) ? ${$col[0]}->{$col[1]} : null;
253
+
break;
254
+
255
+
default:
256
+
$val = null;
257
+
}
258
+
259
+
array_push( $csvoutput, pmpro_enclose( $val ) );
260
+
}
261
+
}
262
+
263
+
// Check if the user has an enddate or not.
264
+
if ( $user->enddate ) {
265
+
$enddate = pmpro_enclose( date_i18n( $dateformat, $user->enddate ) );
266
+
} else {
267
+
$enddate = __( 'Never', 'paid-memberships-pro' );
268
+
}
269
+
270
+
// Add joindate and enddate to the CSV export.
271
+
array_push( $csvoutput, pmpro_enclose( date_i18n( $dateformat, $user->joindate ) ) );
272
+
array_push( $csvoutput, $enddate ); // Don't pmpro_enclose, handled further up for date and not needed for strings.
273
+
274
+
$line = implode( ',', $csvoutput ) . "\n";
275
+
276
+
// output
277
+
fprintf( $csv_fh, '%s', $line );
278
+
279
+
$line = null;
280
+
$csvoutput = null;
281
+
282
+
$end = current_time( 'timestamp' );
283
+
284
+
285
+
286
+
} // end of foreach users.
287
+
288
+
if ( PMPRO_BENCHMARK ) {
289
+
$after_data_time = microtime( true );
290
+
$after_data_memory = memory_get_peak_usage( true );
291
+
292
+
$time_processing_data = $after_data_time - $start_time;
293
+
$memory_processing_data = $after_data_memory - $start_memory;
294
+
295
+
list($sec, $usec) = explode( '.', $time_processing_data );
296
+
297
+
error_log( "PMPRO_BENCHMARK - Time processing data: {$sec}.{$usec} seconds" );
298
+
error_log( 'PMPRO_BENCHMARK - Peak memory usage: ' . number_format( $memory_processing_data, false, '.', ',' ) . ' bytes' );
299
+
}
300
+
$user_list = null;
301
+
wp_cache_flush();
302
+
}
303
+
// If this was run via Toolkit API, we don't have to output the CSV file.
304
+
if ( empty( $_REQUEST['pmpro_no_download'] ) ) {
305
+
pmpro_transmit_report_data( $csv_fh, $filename, $headers );
306
+
}
307
+
308
+
/**
309
+
* Enclose items passed through to ensure data structure is valid for export CSV.
310
+
*
311
+
* @param mixed $string|$date Enclose and return a given string, required for CSV files.
312
+
* @return string
313
+
*/
314
+
function pmpro_enclose( $s ) {
315
+
return '"' . str_replace( '"', '\\"', $s ) . '"';
316
+
}
317
+
318
+
/**
319
+
* Write the data to the CSV and create the CSV file.
320
+
*
321
+
* @param mixed $csv_fh The temp file we opened and write to.
322
+
* @param string $filename The name of the CSV file.
323
+
* @param array $headers The headers for the CSV file.
324
+
* @return void
325
+
*/
326
+
function pmpro_transmit_report_data( $csv_fh, $filename, $headers = array() ) {
327
+
328
+
// close the temp file
329
+
fclose( $csv_fh );
330
+
331
+
if ( version_compare( phpversion(), '5.3.0', '>' ) ) {
332
+
333
+
// make sure we get the right file size
334
+
clearstatcache( true, $filename );
335
+
} else {
336
+
// for any PHP version prior to v5.3.0
337
+
clearstatcache();
338
+
}
339
+
340
+
// did we accidentally send errors/warnings to browser?
341
+
if ( headers_sent() ) {
342
+
echo esc_html( str_repeat( '-', 75 ) ) . "<br/>\n";
343
+
echo 'Please open a support case and paste in the warnings/errors you see above this text to\n ';
344
+
echo 'the <a href="http://paidmembershipspro.com/support/?utm_source=plugin&utm_medium=pmpro-visits-views-logins-csv&utm_campaign=support" target="_blank">Paid Memberships Pro support forum</a><br/>\n';
345
+
echo esc_html( str_repeat( '-', 75 ) ) . "<br/>\n";
346
+
echo wp_kses_post( file_get_contents( $filename ) );
347
+
echo esc_html( str_repeat( '-', 75 ) ) . "<br/>\n";
348
+
}
349
+
350
+
// transmission
351
+
if ( ! empty( $headers ) ) {
352
+
// set the download size
353
+
$headers[] = 'Content-Length: ' . filesize( $filename );
354
+
355
+
// set headers
356
+
foreach ( $headers as $header ) {
357
+
header( $header . "\r\n" );
358
+
}
359
+
360
+
// disable compression for the duration of file download
361
+
if ( ini_get( 'zlib.output_compression' ) ) {
362
+
ini_set( 'zlib.output_compression', 'Off' );
363
+
}
364
+
365
+
if ( function_exists( 'fpassthru' ) ) {
366
+
// use fpassthru to output the csv
367
+
$csv_fh = fopen( $filename, 'rb' );
368
+
fpassthru( $csv_fh );
369
+
fclose( $csv_fh );
370
+
} else {
371
+
// use readfile() if fpassthru() is disabled (like on Flywheel Hosted)
372
+
readfile( $filename );
373
+
}
374
+
375
+
// remove the temp file
376
+
unlink( $filename );
377
+
}
378
+
379
+
// allow user to clean up after themselves
380
+
do_action( 'pmpro_after_visits_views_logins_csv_export' );
381
+
exit;
382
+
}
383
+