Export User Data - Version 2.0.1

Version Description

Download this release

Release Info

Developer qlstudio
Plugin Icon wp plugin Export User Data
Version 2.0.1
Comparing to
See all releases

Code changes from version 1.3.1 to 2.0.1

CHANGELOG.md ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Changelog ##
2
+
3
+ *** 2.0.1 ***
4
+
5
+ * Deprecated BuddyPress support as untested in 4 years
6
+
7
+ *** 2.0.0 ***
8
+
9
+ * Fork to new name Q Report
10
+ * namespaced and moved to standard Q plugin setup model
11
+ * buddypress support might be flaky due to limited testing
12
+
13
+ *** 1.3.1 ***
14
+
15
+ * Moved all internal action hooks to admin_init to allow for internal function loading
16
+
17
+ *** 1.3.0 ***
18
+
19
+ * Added extra data sanitization before outputting to file - thanks to Hely Shah <helyhshah@gmail.com> for te heads-up
20
+
21
+ *** 1.2.8 ***
22
+
23
+ * New: Added load_buddypress() methods to test for buddypress and load up if missing
24
+ * New: move action hooks and priority to load later
25
+ * New: Plugin no longer uses singleton model to instatiate - instead called from action hook to public function
26
+ * New: added log() to debug.log file to help debugging issues
27
+ * Update: jQuery datepickers pull start_of_week value from WordPress
28
+ * Tested on 4.4.2
29
+
30
+ *** 1.2.7 ***
31
+
32
+ * Added: Spanish translation - thanks Elías Gómez Sainz ( elias@estudions.es )
33
+
34
+ *** 1.2.6 ***
35
+ * Update: WP 4.4.1
36
+
37
+ ### 1.2.3 ###
38
+ * Fix: to remove minor security loop hole
39
+ * New: Added option to remove standard wp_users data from export
40
+ * Fix: removed roles and groups columns from export when options hidden
41
+
42
+ ### 1.2.2 ###
43
+ * Minor FIxes
44
+
45
+ ### 1.2.1 ###
46
+ * Checked on WP 4.3.1
47
+ * Moved text-domain to string in preperation for addition to translate.wordpress.org
48
+ * Added Log() method to allow for debugging to WP Error Log
49
+ * Added Greek translation - Thanks @Leonidas Mi
50
+ * Added option to limit export by last_updated date of specific xprofile field - Thanks to @cwjordan
51
+
52
+ ### 1.2.0 ###
53
+ * Data stored in recursive and serialized arrays is now exported in a flat string format with safe delimiters ( ||, ||| - etc. )
54
+
55
+ ### 1.1.1 ###
56
+ * Removed accidently included .git files
57
+
58
+ ### 1.1.0 ###
59
+ * Version change to sync SVN on wordpress.org
60
+
61
+ ### 1.0.4 ###
62
+ * Added unserialize function with @ fallback
63
+ * Removed anonymous function to allow support for PHP < 5.2
64
+
65
+ ### 1.0.3 ###
66
+ * Tested as working on WordPress 4.1.0.
67
+
68
+ ### 1.0.2 ###
69
+ * Removed get_user_meta method, as not effective.
70
+ * Added registration date from and to pickers - to replace monthly <select> lists.
71
+
72
+ ### 1.0.1 ###
73
+ * Added recursive_implode() method to flatten data stored in arrays ( exported with keys and values divided by "|" )
74
+
75
+ ### 1.0.0 ###
76
+ * Reduced all get_user_meta queries to a single call to improve performance
77
+ * Serialized data is now returned in it's pure stored format - not imploded or unserialized to avoid data structure loss
78
+
79
+ ### 0.9.9 ###
80
+ * get_uermeta renamed get_user_meta to be more consistent with WP
81
+ * get_user_meta tidied up and tested on larger exports
82
+ * added option to export user BP Groups
83
+ * added option to export all user WP Roles
84
+
85
+ ### 0.9.8 ###
86
+ * added get_usermeta() to check if meta keys are unique and return an array if not
87
+ * removed known_arrays() filter to allow for array data to be returned correctly - too hacky
88
+
89
+ ### 0.9.7 ###
90
+ * Added known_arrays() filter to allow for array data to be returned correctly
91
+
92
+ ### 0.9.6 ###
93
+ * Save, load and delete stored export settings - thanks to @cwjordan
94
+ * Overcome memory outages on large exports - thanks to @grexican
95
+ * Tested on WP 4.0.0 & BP 2.1.0
96
+
97
+ ### 0.9.5 ###
98
+ * BP Serialized data fixes - thanks to @nicmare & @grexican
99
+ * Tested on WP 3.9.2 & BP 2.0.2
100
+
101
+ ### 0.9.4 ###
102
+ * BP X Profile Export Fix ( > version 2.0 )
103
+
104
+ ### 0.9.3 ###
105
+ * fix for hidden admin bar
106
+
107
+ ### 0.9.2 ###
108
+ * removed $key assignment casting to integer
109
+
110
+ ### 0.9.1 ###
111
+ * Tested with WP 3.9
112
+ * Fix for BuddyPress 2.0 bug
113
+
114
+ ### 0.9.0 ###
115
+ * Moved plugin class to singleton model
116
+ * Improved language handling
117
+ * French translation - thanks @bastho - http://wordpress.org/support/profile/bastho
118
+
119
+ ### 0.8.3 ###
120
+ * clarified export limit options
121
+
122
+ ### 0.8.2 ###
123
+ * corrected buddypress export option - broken in 0.8.1
124
+ * changed get_users arguments, in attempt to reduce memory usage
125
+
126
+ ### 0.8.1 ###
127
+ * Added experimental range limiter for exports
128
+ * Extra input data sanitizing
129
+
130
+ ### 0.8 ###
131
+ * moved plugin instatiation to the WP hook: init
132
+ * moved bp calls outside export loop
133
+ * added extra isset calls on values in export loop to clean up error log not sets
134
+
135
+ ### 0.7.8 ###
136
+ * added xml template for Excel exports - thanks to phil@fixitlab.com :)
137
+
138
+ ### 0.7.2 ###
139
+ * fixes to allow exports without selecting extra user date from usermeta or x-profile
140
+
141
+ ### 0.6.3 ###
142
+ * added multiselect to pick usermeta and xprofile fields
143
+
144
+ ### 0.5 ###
145
+ * First public release.
146
+
147
+ ## Upgrade Notice ##
148
+
149
+ ### 0.6.3 ###
150
+ Latest.
151
+
152
+ ### 0.5 ###
153
+ First release.
export-user-data.php CHANGED
@@ -1,2284 +1,206 @@
1
  <?php
2
 
3
  /*
4
- Plugin Name: Export User Data
5
- Plugin URI: http://qstudio.us/plugins/
6
- Description: Export User data, metadata and BuddyPress X-Profile data.
7
- Version: 1.3.1
8
- Author: Q Studio
9
- Author URI: http://qstudio.us
10
- License: GPL2
11
- Text Domain: export-user-data
 
12
  */
13
 
14
- // quick check :) ##
15
- defined( 'ABSPATH' ) OR exit;
16
-
17
- /* Check for Class */
18
- if ( ! class_exists( 'Q_Export_User_Data' ) )
19
- {
20
-
21
- // plugin version
22
- define( 'Q_EUD_HOOK', 'init' ); // wp action to hook to ##
23
- define( 'Q_EUD_HOOK_ADMIN', 'admin_init' ); // wp action to hook to ##
24
- define( 'Q_EUD_PRIORITY', '1000000' ); // priority ##
25
- define( 'Q_LOG_PREFIX', 'EUD' ); // wp action to hook to ##
26
-
27
- // plugin version
28
- define( 'Q_EUD', '1.3.0' ); // version ##
29
-
30
- // on activate ##
31
- #register_activation_hook( __FILE__, 'function' );
32
-
33
- // on deactivate ##
34
- #register_deactivation_hook( __FILE__, 'function' );
35
-
36
- /**
37
- * Main plugin class
38
- *
39
- * @since 0.1
40
- **/
41
- class Q_Export_User_Data {
42
 
 
 
 
 
43
 
44
- #private static $instance = null;
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /* properties */
47
- #protected $text_domain = 'export-user-data'; // for translation ##
48
- protected $debug = true; // debug ##
49
- protected $q_eud_exports = ''; // export settings ##
50
- protected $usermeta_saved_fields = array();
51
- protected $bp_fields_saved_fields = array();
52
- protected $bp_fields_update_time_saved_fields = array();
53
- protected $role = '';
54
- protected $roles = '0';
55
- protected $user_fields = '1';
56
- protected $groups = '0';
57
- protected $start_date = '';
58
- protected $end_date = '';
59
- protected $limit_offset = '';
60
- protected $limit_total = '';
61
- protected $updated_since_date = '';
62
- protected $field_updated_since = '';
63
- protected $format = '';
64
- protected $bp_data_available = false;
65
- protected $allowed_tags = '';
66
-
67
-
68
-
69
- /**
70
- * Class contructor
71
- *
72
- * @since 0.1
73
- **/
74
- public function __construct()
75
- {
76
-
77
- // silence is golden ##
78
-
79
- }
80
-
81
-
82
- /**
83
- * Load plugin text-domain
84
- *
85
- * @since 0.9.0
86
- * @return void
87
- **/
88
- public function load_plugin_textdomain()
89
- {
90
-
91
- // The "plugin_locale" filter is also used in load_plugin_textdomain()
92
- $locale = apply_filters( 'plugin_locale', get_locale(), 'export-user-data' );
93
-
94
- // try from global WP location first ##
95
- load_textdomain( 'export-user-data', WP_LANG_DIR.'/plugins/export-user-data-'.$locale.'.mo' );
96
-
97
- // try from plugin last ##
98
- load_plugin_textdomain( 'export-user-data', false, basename( dirname( __FILE__ ) ) . '/languages' );
99
-
100
- }
101
-
102
-
103
- /**
104
- * Hook intro WP filters and actions
105
- *
106
- * @since 1.2.8
107
- * @return void
108
- */
109
- public function run_hooks()
110
- {
111
-
112
- // set text domain ##
113
- add_action( 'init', array( $this, 'load_plugin_textdomain' ), 1 );
114
-
115
- if ( is_admin() ) {
116
-
117
- // load BP ##
118
- add_action( Q_EUD_HOOK_ADMIN, array( $this, 'load_buddypress' ), Q_EUD_PRIORITY+1 );
119
-
120
- // load user options ##
121
- add_action( Q_EUD_HOOK_ADMIN, array( $this, 'load_user_options' ), Q_EUD_PRIORITY+2 );
122
-
123
- // run export ##
124
- add_action( Q_EUD_HOOK_ADMIN, array( $this, 'generate_data' ), Q_EUD_PRIORITY+3 );
125
-
126
- // filter exported data - perhaps unused ##
127
- #add_filter( 'q_eud_exclude_data', array( $this, 'exclude_data' ) );
128
-
129
- // add export page inside admin ##
130
- add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
131
-
132
- // UI style and functionality ##
133
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 1 );
134
- add_action( 'admin_footer', array( $this, 'jquery' ), 100000 );
135
- add_action( 'admin_footer', array( $this, 'css' ), 100000 );
136
-
137
- }
138
-
139
- }
140
-
141
-
142
- /**
143
- * Write to WP Error Log
144
- *
145
- * @since 1.5.0
146
- * @return void
147
- */
148
- protected function log( $log )
149
- {
150
-
151
- if ( $this->debug && true === WP_DEBUG ) {
152
-
153
- $trace = debug_backtrace();
154
- $caller = $trace[1];
155
-
156
- $suffix = sprintf(
157
- __( ' - %s%s() %s:%d', 'Q_Scrape_Wordpress' )
158
- , isset($caller['class']) ? $caller['class'].'::' : ''
159
- , $caller['function']
160
- , isset( $caller['file'] ) ? $caller['file'] : 'n'
161
- , isset( $caller['line'] ) ? $caller['line'] : 'x'
162
- );
163
-
164
- $prefix = Q_LOG_PREFIX.' ';
165
-
166
- if ( is_array( $log ) || is_object( $log ) ) {
167
- error_log( $prefix.print_r( $log, true ).$suffix );
168
- } else {
169
- error_log( $prefix.$log.$suffix );
170
- }
171
-
172
- }
173
-
174
- }
175
-
176
-
177
- /**
178
- * Nicer var_dump
179
- *
180
- * @since 0.9.6
181
- */
182
- protected function pr ( $variable )
183
- {
184
-
185
- echo '<pre>';
186
- print_r ( $variable );
187
- echo '</pre>';
188
-
189
- }
190
 
 
 
191
 
192
  /**
193
- * Add administration menus
194
  *
195
- * @since 0.1
196
- **/
197
- public function add_admin_pages()
198
- {
199
-
200
- add_users_page( __( 'Export User Data', 'export-user-data' ), __( 'Export User Data', 'export-user-data' ), 'list_users', 'export-user-data', array( $this, 'users_page' ) );
201
-
202
- }
203
-
204
-
205
- /**
206
- * style and interaction
207
  */
208
- public function admin_enqueue_scripts( $hook )
209
  {
210
 
211
- // load the scripts on only the plugin admin page ##
212
- if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'export-user-data' ) ) {
213
-
214
- wp_register_style( 'css-q_export_user_data', plugins_url( 'css/export-user-data.css' ,__FILE__ ), '', Q_EUD );
215
- wp_enqueue_style( 'css-q_export_user_data' );
216
- wp_enqueue_script( 'q_eud_multi_select_js', plugins_url( 'js/jquery.multi-select.js', __FILE__ ), array('jquery'), '0.9.8', false );
217
-
218
- // add script ##
219
- wp_enqueue_script('jquery-ui-datepicker');
220
-
221
- // add style ##
222
- wp_enqueue_style( 'jquery-ui-datepicker' );
223
- wp_enqueue_style('jquery-ui-css', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
224
-
225
  }
226
 
227
- }
228
-
229
-
230
- /**
231
- * Return Byte count of $val
232
- *
233
- * @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue?replies=2
234
- * @since 0.9.6
235
- */
236
- protected function return_bytes( $val )
237
- {
238
-
239
- $val = trim( $val );
240
- $last = strtolower($val[strlen($val)-1]);
241
- switch( $last ) {
242
 
243
- // The 'G' modifier is available since PHP 5.1.0
244
- case 'g':
245
-
246
- $val *= 1024;
247
-
248
- case 'm':
249
-
250
- $val *= 1024;
251
-
252
- case 'k':
253
-
254
- $val *= 1024;
255
-
256
- }
257
-
258
- return $val;
259
  }
260
-
261
-
262
  /**
263
- * Sanitize data
264
- *
265
- * @since 1.2.8
266
- * @return string
267
  */
268
- protected function sanitize( $value )
269
  {
 
 
 
270
 
271
- // emove line breaks ##
272
- $value = str_replace("\r", '', $value);
273
- $value = str_replace("\n", '', $value);
274
- $value = str_replace("\t", '', $value);
275
 
276
- // with wp_kses ##
277
- $value = wp_kses( $value, $this->get_allowed_tags() );
278
-
279
- // with esc_html
280
- $value = esc_html( $value );
281
-
282
- // return value ##
283
- return $value;
284
 
285
  }
286
 
287
 
288
- /**
289
- * Get allowed tags for wp_kses
290
- *
291
- * @since 1.2.8
292
- * @return Array
293
- */
294
- protected function get_allowed_tags()
295
- {
296
 
297
- $allowed_tags = array(
298
- 'a' => array(
299
- 'href' => array(),
300
- 'title' => array()
301
- ),
302
- 'br' => array(),
303
- 'em' => array(),
304
- 'strong' => array(),
305
- );
306
 
307
- return apply_filters( 'export_user_data_allowed_tags', $allowed_tags );
 
 
308
 
309
  }
310
 
311
 
 
312
 
313
- /**
314
- * Load up saved exports for this user
315
- * Set to public as hooked into action
316
- *
317
- * @since 0.9.6
318
- * @return Array of saved exports
319
- */
320
- public function load_buddypress()
321
- {
322
-
323
- // do we have a bp object in the globals ##
324
- if (
325
- is_plugin_active( 'buddypress/bp-loader.php' ) // plugin active
326
- && function_exists ( 'buddypress' ) // loader function exists ##
327
- && ! isset( $GLOBALS['bp'] ) // but global unavailble ##
328
- ) {
329
-
330
- $this->log( 'BP not loaded - calling buddpress()' );
331
-
332
- // call BP
333
- buddypress();
334
-
335
- return true;
336
-
337
- }
338
-
339
- #$this->log( 'BP loaded' );
340
-
341
- return true;
342
 
343
  }
344
 
345
 
 
346
  /**
347
- * Load up saved exports for this user
348
- * Set to public as hooked into action
349
- *
350
- * @since 0.9.6
351
- * @return Array of saved exports
352
  */
353
- public function load_user_options()
354
  {
 
 
 
 
 
 
355
 
356
-
357
- $this->q_eud_exports =
358
- get_user_meta( get_current_user_id(), 'q_eud_exports' ) ?
359
- get_user_meta( get_current_user_id(), 'q_eud_exports', true ) :
360
- array() ;
361
- #var_dump( $this->q_eud_exports );
362
-
363
  }
364
-
365
-
 
366
  /**
367
- * Get list of saved exports for this user
368
- *
369
- * @since 0.9.4
370
- * @return Array of saved exports
 
371
  */
372
- protected function get_user_options()
373
  {
374
 
375
- // get the stored options - filter empty array items ##
376
- $q_eud_exports = array_filter( $this->q_eud_exports );
377
-
378
- // quick check if the array is empty ##
379
- if ( empty ( $q_eud_exports ) ) {
380
-
381
- return false;
382
-
383
- }
384
-
385
- // test the array of saved exports ##
386
- #$this->pr( $q_eud_exports );
387
-
388
- // start with an empty array ##
389
- $exports = array();
390
-
391
- // loop over each saved export and grab each key ##
392
- foreach ( $q_eud_exports as $key => $value ) {
393
-
394
- $exports[] = $key;
395
-
396
- }
397
-
398
- // kick back array ##
399
- return( $exports );
400
 
401
  }
402
-
403
-
404
  /**
405
- * Check for and load stored user options
406
- *
407
- * @since 0.9.3
408
- * @return void
 
409
  */
410
- protected function get_user_options_by_export( $export = null )
411
  {
412
 
413
- // sanity check ##
414
- if ( is_null ( $export ) ) { return false; }
415
-
416
- if ( isset( $this->q_eud_exports[$export] ) ) {
417
-
418
- $this->usermeta_saved_fields = $this->q_eud_exports[$export]['usermeta_saved_fields'];
419
- $this->bp_fields_saved_fields = $this->q_eud_exports[$export]['bp_fields_saved_fields'];
420
- $this->bp_fields_update_time_saved_fields = $this->q_eud_exports[$export]['bp_fields_update_time_saved_fields'];
421
- $this->updated_since_date = isset( $this->q_eud_exports[$export]['updated_since_date'] ) ? $this->q_eud_exports[$export]['updated_since_date'] : null ;
422
- $this->field_updated_since = isset( $this->q_eud_exports[$export]['field_updated_since'] ) ? $this->q_eud_exports[$export]['field_updated_since'] : null ;
423
- $this->role = $this->q_eud_exports[$export]['role'];
424
- $this->roles = $this->q_eud_exports[$export]['roles'];
425
- $this->groups = $this->q_eud_exports[$export]['groups'];
426
- $this->user_fields = isset( $this->q_eud_exports[$export]['user_fields'] ) ? $this->q_eud_exports[$export]['user_fields'] : null ;
427
- $this->start_date = $this->q_eud_exports[$export]['start_date'];
428
- $this->end_date = $this->q_eud_exports[$export]['end_date'];
429
- $this->limit_offset = $this->q_eud_exports[$export]['limit_offset'];
430
- $this->limit_total = $this->q_eud_exports[$export]['limit_total'];
431
- $this->format = $this->q_eud_exports[$export]['format'];
432
-
433
- } else {
434
-
435
- $this->usermeta_saved_fields = array();
436
- $this->bp_fields_saved_fields = array();
437
- $this->bp_fields_update_time_saved_fields = array();
438
- $this->updated_since_date = '';
439
- $this->field_updated_since = '';
440
- $this->role = '';
441
- $this->user_fields = '1';
442
- $this->roles = '1';
443
- $this->groups = '1';
444
- $this->start_date = '';
445
- $this->end_date = '';
446
- $this->limit_offset = '';
447
- $this->limit_total = '';
448
- $this->format = '';
449
-
450
- }
451
 
452
  }
453
-
454
-
455
- /**
456
- * Method to store user options
457
- *
458
- * @param string $save_export Export Key name
459
- * @param array $save_options Array of export options to save
460
- * @since 0.9.3
461
- * @return void
462
- */
463
- protected function set_user_options( $key = null, $options = null )
464
- {
465
-
466
- // sanity check ##
467
- if ( is_null ( $key ) || is_null ( $options ) ) {
468
-
469
- #$this->pr( 'missing save values' );
470
- return false;
471
-
472
- }
473
-
474
- #$this->pr( $key );
475
- #$this->pr( $options );
476
-
477
- // for now, I'm simply allowing keys to be resaved - but this is not so logical ##
478
- if ( array_key_exists( $key, $this->q_eud_exports ) ) {
479
-
480
- #$this->pr( 'key exists, skipping save' );
481
- #return false;
482
-
483
- }
484
-
485
- if ( isset( $options ) && is_array( $options ) ) {
486
-
487
- // update_option sanitizes the option name but not the option value ##
488
- foreach ( $options as $field_name => $field_value ) {
489
-
490
- // so do that here. ##
491
- if ( is_array( $field_value ) ) {
492
-
493
- foreach ( $field_value as $field_array_key => $field_array_value ) {
494
-
495
- $options[$field_name][$field_array_key] = sanitize_text_field( $field_array_value );
496
-
497
- }
498
-
499
- } else {
500
-
501
- $options[$field_name] = sanitize_text_field( $field_value );
502
-
503
- }
504
-
505
- }
506
-
507
- // assign the sanitized array of values to the class property $q_eud_exports as a new array with key $key ##
508
- $this->q_eud_exports[$key] = $options;
509
-
510
- // update stored user_meta values, if previous key found ##
511
- if ( get_user_meta( get_current_user_id(), 'q_eud_exports' ) !== false ) {
512
-
513
- #update_option( 'q_eud_exports', $this->q_eud_exports );
514
- update_user_meta( get_current_user_id(), 'q_eud_exports', $this->q_eud_exports );
515
-
516
- // create new user meta key ##
517
- } else {
518
-
519
- #add_option( 'q_eud_exports', $this->q_eud_exports, $deprecated, $autoload );
520
- add_user_meta( get_current_user_id(), 'q_eud_exports', $this->q_eud_exports );
521
-
522
- }
523
-
524
- }
525
-
526
- }
527
-
528
 
529
  /**
530
- * method to delete user options
531
- *
532
- * @param $key String Key name to drop from property
533
- * @since 0.9.3
534
- * @return void
535
- */
536
- protected function delete_user_options( $key = null )
537
  {
538
 
539
- // sanity check ##
540
- if ( is_null ( $key ) || ! array_key_exists( $key, $this->q_eud_exports ) ) { return false; }
541
-
542
- // clean it up ##
543
- $key = sanitize_text_field( $key );
544
-
545
- // check it out ##
546
- #$this->pr( $key );
547
-
548
- // drop the array by it's key name from the class property ##
549
- unset( $this->q_eud_exports[$key] );
550
-
551
- // update the saved data ##
552
- update_user_meta( get_current_user_id(), 'q_eud_exports', $this->q_eud_exports );
553
-
554
- }
555
-
556
-
557
- /**
558
- * Copy of BP_XProfile_ProfileData::get_all_for_user() from BP version 2.0?
559
- * Get all of the profile information for a specific user.
560
- *
561
- * @param $user_id Integer ID of specific user
562
- * @since 0.9.6
563
- * @return Array User profile fields
564
- * @deprecated since 1.2.1
565
- */
566
- protected function get_all_for_user( $user_id = null )
567
- {
568
-
569
- // sanity check ##
570
- if ( is_null( $user_id ) ) { return false; }
571
-
572
- global $wpdb, $bp;
573
-
574
- $bp = buddypress();
575
-
576
- $results = $wpdb->get_results(
577
- $wpdb->prepare(
578
- "
579
- SELECT g.id as field_group_id, g.name as field_group_name, f.id as field_id, f.name as field_name, f.type as field_type, d.value as field_data, u.user_login, u.user_nicename, u.user_email
580
- FROM {$bp->profile->table_name_groups} g
581
- LEFT JOIN {$bp->profile->table_name_fields} f ON g.id = f.group_id
582
- INNER JOIN {$bp->profile->table_name_data} d ON f.id = d.field_id LEFT JOIN {$wpdb->users} u ON d.user_id = u.ID
583
- WHERE d.user_id = %d AND d.value != ''
584
- "
585
- , $user_id
586
- )
587
- );
588
-
589
- $profile_data = array();
590
-
591
- if ( ! empty( $results ) ) {
592
 
593
- $profile_data['user_login'] = $results[0]->user_login;
594
- $profile_data['user_nicename'] = $results[0]->user_nicename;
595
- $profile_data['user_email'] = $results[0]->user_email;
596
-
597
- foreach( (array) $results as $field ) {
598
-
599
- $profile_data[$field->field_name] = array(
600
- 'field_group_id' => $field->field_group_id,
601
- 'field_group_name' => $field->field_group_name,
602
- 'field_id' => $field->field_id,
603
- 'field_type' => $field->field_type,
604
- 'field_data' => $field->field_data
605
- );
606
-
607
- }
608
-
609
- }
610
-
611
- return $profile_data;
612
 
 
 
 
613
  }
614
 
615
-
616
- /**
617
- * Attempt to generate the export file based on the passed arguements
618
- *
619
- * @since 0.1
620
- * @return Mixes
621
- **/
622
- public function generate_data()
623
- {
624
-
625
- // Check if the user clicked on the Save, Load, or Delete Settings buttons ##
626
- if (
627
- ! isset( $_POST['_wpnonce-q-eud-export-user-page_export'] )
628
- || isset( $_POST['load_export'] )
629
- || isset( $_POST['save_export'] )
630
- || isset( $_POST['delete_export'] ) )
631
- {
632
-
633
- return false;
634
-
635
- }
636
-
637
- // Increase maximum execution time to prevent "Maximum execution time exceeded" error ##
638
- ini_set( 'max_execution_time', -1 );
639
- ini_set( 'memory_limit', -1 ); // looks like a bad idea ##
640
-
641
- // check admin referer ##
642
- check_admin_referer( 'q-eud-export-user-page_export', '_wpnonce-q-eud-export-user-page_export' );
643
-
644
- // build argument array ##
645
- $args = array(
646
- 'fields' => ( isset( $_POST['user_fields'] ) && '1' == $_POST['user_fields'] ) ? 'all' : array( 'ID' ), // exclude standard wp_users fields from get_users query ##
647
- 'role' => sanitize_text_field( $_POST['role'] )
648
- );
649
-
650
- // did they request a specific program ? ##
651
- if ( isset( $_POST['program'] ) && $_POST['program'] != '' ) {
652
-
653
- $args['meta_key'] = 'member_of_club';
654
- $args['meta_value'] = (int)$_POST['program'];
655
- $args['meta_compare'] = '=';
656
-
657
- }
658
-
659
- // is there a range limit in place for the export ? ##
660
- if ( isset( $_POST['limit_total'] ) && $_POST['limit_total'] != '' ) {
661
-
662
- // let's just make sure they are integer values ##
663
- $limit_offset = isset( $_POST['limit_offset'] ) ? (int)$_POST['limit_offset'] : 0 ;
664
- $limit_total = (int)$_POST['limit_total'];
665
-
666
- if ( is_int( $limit_offset ) && is_int( $limit_total ) ) {
667
-
668
- $args['offset'] = $limit_offset;
669
- $args['number'] = $limit_total; // number - Limit the total number of users returned ##
670
-
671
- // test it ##
672
- #wp_die( $this->pr( $args ) );
673
-
674
- }
675
-
676
- }
677
-
678
- // pre_user query ##
679
- add_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
680
- $users = get_users( $args );
681
- remove_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
682
-
683
- // test args ##
684
- #wp_die( $this->pr ( $users ) );
685
-
686
- // no users found, so chuck an error into the args array and exit the export ##
687
- if ( ! $users ) {
688
-
689
- wp_redirect( add_query_arg( 'error', 'empty', wp_get_referer() ) );
690
- exit;
691
-
692
- }
693
-
694
- // get sitename and clean it up ##
695
- $sitename = sanitize_key( get_bloginfo( 'name' ) );
696
- if ( ! empty( $sitename ) ) {
697
- $sitename .= '.';
698
- }
699
-
700
- // export method ? ##
701
- $export_method = 'excel'; // default to Excel export ##
702
- if ( isset( $_POST['format'] ) && $_POST['format'] != '' ) {
703
-
704
- $export_method = sanitize_text_field( $_POST['format'] );
705
-
706
- }
707
-
708
- // set export filename structure ##
709
- $filename = $sitename . 'users.' . date( 'Y-m-d-H-i-s' );
710
-
711
- switch ( $export_method ) {
712
-
713
- case ( 'csv' ):
714
-
715
- // to csv ##
716
- header( 'Content-Description: File Transfer' );
717
- header( 'Content-Disposition: attachment; filename='.$filename.'.csv' );
718
- header( 'Content-Type: text/csv; charset=' . get_option( 'blog_charset' ), true );
719
-
720
- // set a csv check flag
721
- $is_csv = true;
722
-
723
- // nothing here
724
- $doc_begin = '';
725
-
726
- //preformat
727
- $pre = '';
728
-
729
- // how to seperate data ##
730
- $seperator = ','; // comma for csv ##
731
-
732
- // line break ##
733
- $breaker = "\n";
734
-
735
- // nothing here
736
- $doc_end = '';
737
-
738
- break;
739
-
740
- case ( 'excel' ):
741
-
742
- // to xls ##
743
- header( 'Content-Description: File Transfer' );
744
- header("Content-Type: application/vnd.ms-excel");
745
- header("Content-Disposition: attachment; filename=$filename.xls");
746
- header("Pragma: no-cache");
747
- header("Expires: 0");
748
-
749
- // set a csv check flag
750
- $is_csv = false;
751
-
752
- //grab the template file (for tidy formatting)
753
- include( 'xml-template.php' );
754
-
755
- // open xml
756
- $doc_begin = $xml_doc_begin;
757
-
758
- //preformat
759
- $pre = $xml_pre;
760
-
761
- // how to seperate data ##
762
- $seperator = $xml_seperator;
763
-
764
- // line break ##
765
- $breaker = $xml_breaker;
766
-
767
- // close xml
768
- $doc_end = $xml_doc_end;
769
-
770
- break;
771
-
772
- }
773
-
774
-
775
- // check for selected usermeta fields ##
776
- $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '';
777
- #$this->pr( $usermeta );
778
- $usermeta_fields = array();
779
-
780
- if ( $usermeta && is_array( $usermeta ) ) {
781
- foreach( $usermeta as $field ) {
782
- $usermeta_fields[] = sanitize_text_field ( $field );
783
- }
784
- }
785
-
786
- #$this->pr( $usermeta_fields );
787
- #exit;
788
-
789
- // check for selected x profile fields ##
790
- $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '';
791
- $bp_fields_passed = array();
792
- if ( $bp_fields && is_array( $bp_fields ) ) {
793
-
794
- foreach( $bp_fields as $field ) {
795
-
796
- // reverse tidy ##
797
- $field = str_replace( '__', ' ', sanitize_text_field ( $field ) );
798
-
799
- // add to array ##
800
- $bp_fields_passed[] = $field;
801
-
802
- }
803
-
804
- }
805
-
806
- // cwjordan: check for x profile fields we want update time for ##
807
- $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '';
808
- $bp_fields_update_passed = array();
809
- if ( $bp_fields_update && is_array( $bp_fields_update ) ) {
810
-
811
- foreach( $bp_fields_update as $field ) {
812
-
813
- // reverse tidy ##
814
- $field = str_replace( '__', ' ', sanitize_text_field ( $field ) );
815
-
816
- // add to array ##
817
- $bp_fields_update_passed[] = $field . " Update Date";
818
-
819
- }
820
-
821
- }
822
-
823
- // global wpdb object ##
824
- global $wpdb;
825
-
826
- // debug ##
827
- #$this->log( 'merging array' );
828
-
829
- // compile final fields list ##
830
- $fields = array_merge(
831
- $this->get_user_fields() // standard wp_user fields ##
832
- , $this->get_special_fields() // 'special' fields - which are controlled via dedicated checks ##
833
- , $usermeta_fields // wp_user_meta fields ##
834
- , $bp_fields_passed // selected buddypress fields ##
835
- , $bp_fields_update_passed // update date for buddypress fields ##
836
- );
837
-
838
- // test field array ##
839
- #$this->pr( $fields );
840
-
841
- // build the document headers ##
842
- $headers = array();
843
-
844
- foreach ( $fields as $key => $field ) {
845
-
846
- #$this->log( 'Field: '. $field );
847
-
848
- // rename programs field ##
849
- if ( $field == 'member_of_club' ){
850
- $field = 'Program';
851
- }
852
-
853
- // grab fields to exclude from exports ##
854
- if ( in_array( $fields[$key], $this->get_exclude_fields() ) ) {
855
-
856
- #$this->log( 'Dump Field: '. $fields[$key] );
857
-
858
- // ditch 'em ##
859
- unset( $fields[$key] );
860
-
861
- } else {
862
-
863
- if ( $is_csv ) {
864
-
865
- $headers[] = '"' . $field . '"';
866
-
867
- } else {
868
-
869
- $headers[] = $field;
870
- #echo '<script>console.log("Echoing header cell: '.$field.'")</script>';
871
-
872
- }
873
-
874
- }
875
-
876
- }
877
-
878
- // quick check ##
879
- #$this->log( $fields );
880
- #if ( $this->debug ) $this->log( '$bp_fields_passed: '. var_dump( $bp_fields_passed ) );
881
-
882
- // no more buffering while spitting back the export data ##
883
- ob_end_flush();
884
-
885
- // get the value in bytes allocated for Memory via php.ini ##
886
- // @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue
887
- $memory_limit = $this->return_bytes( ini_get('memory_limit') ) * .75;
888
-
889
- // we need to disable caching while exporting because we export so much data that it could blow the memory cache
890
- // if we can't override the cache here, we'll have to clear it later...
891
- if ( function_exists( 'override_function' ) ) {
892
-
893
- override_function('wp_cache_add', '$key, $data, $group="", $expire=0', '');
894
- override_function('wp_cache_set', '$key, $data, $group="", $expire=0', '');
895
- override_function('wp_cache_replace', '$key, $data, $group="", $expire=0', '');
896
- override_function('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', '');
897
-
898
- } elseif ( function_exists( 'runkit_function_redefine' ) ) {
899
-
900
- runkit_function_redefine('wp_cache_add', '$key, $data, $group="", $expire=0', '');
901
- runkit_function_redefine('wp_cache_set', '$key, $data, $group="", $expire=0', '');
902
- runkit_function_redefine('wp_cache_replace', '$key, $data, $group="", $expire=0', '');
903
- runkit_function_redefine('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', '');
904
-
905
- }
906
-
907
- // open doc wrapper.. ##
908
- echo $doc_begin;
909
-
910
- // echo headers ##
911
- echo $pre . implode( $seperator, $headers ) . $breaker;
912
-
913
- #wp_die( $this->pr( $users ) );
914
-
915
- // build row values for each user ##
916
- foreach ( $users as $user ) {
917
-
918
- #wp_die( $this->pr( $user ) );
919
-
920
- // check if we're hitting any Memory limits, if so flush them out ##
921
- // per http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue?replies=2
922
- if ( memory_get_usage( true ) > $memory_limit ) {
923
- wp_cache_flush();
924
- }
925
-
926
- // open up a new empty array ##
927
- $data = array();
928
-
929
- // BP loaded ? ##
930
- if (
931
- ! $this->bp_data_available
932
- && function_exists ( 'bp_is_active' )
933
- && bp_is_active( 'xprofile' )
934
- && class_exists( 'BP_XProfile_ProfileData' )
935
- && method_exists( 'BP_XProfile_ProfileData', 'get_all_for_user' )
936
- && is_callable ( array( 'BP_XProfile_ProfileData', 'get_all_for_user' ) )
937
- ) {
938
-
939
- $this->log( 'XProfile Accessible' );
940
- $this->bp_data_available = true; // we only need to check for BP once ##
941
-
942
- }
943
-
944
- // grab all user data ##
945
- if (
946
- $this->bp_data_available
947
- && ! $bp_data = BP_XProfile_ProfileData::get_all_for_user( $user->ID )
948
- ) {
949
-
950
- // null the data to be sure ##
951
- $bp_data = false;
952
-
953
- $this->log( 'XProfile returned no data ID#: '.$user->ID );
954
-
955
- }
956
-
957
- // single query method - get all user_meta data ##
958
- $get_user_meta = (array)get_user_meta( $user->ID );
959
- #wp_die( $this->pr( $get_user_meta ) );
960
-
961
- // Filter out empty meta data ##
962
- #$get_user_meta = array_filter( array_map( function( $a ) {
963
- # return $a[0];
964
- #}, $get_user_meta ) );
965
-
966
- // loop over each field ##
967
- foreach ( $fields as $field ) {
968
-
969
- // check if this is a BP field ##
970
- if ( isset( $bp_data ) && isset( $bp_data[$field] ) && in_array( $field, $bp_fields_passed ) )
971
- {
972
-
973
- // old way from single BP query ##
974
- $value = $bp_data[$field];
975
-
976
- if ( is_array( $value ) ) {
977
-
978
- $value = maybe_unserialize( $value['field_data'] ); // suggested by @grexican ##
979
- #$value = $value['field_data'];
980
-
981
- /**
982
- * cwjordan
983
- * after unserializing it we then
984
- * need to implode it so
985
- * that we have something readable?
986
- * Going to use :: as a separator
987
- * because that's what Buddypress Members Import
988
- * expects, but we might want to make that
989
- * configurable.
990
- */
991
- if ( is_array( $value ) ) {
992
- $value = implode("::", $value );
993
- }
994
-
995
- }
996
-
997
- // sanitize ##
998
- #$value = $this->sanitize($value);
999
-
1000
- // check if this is a BP field we want the updated date for ##
1001
- }
1002
- elseif ( in_array( $field, $bp_fields_update_passed ) )
1003
- {
1004
-
1005
- global $bp;
1006
-
1007
- $real_field = str_replace(" Update Date", "", $field);
1008
- $field_id = xprofile_get_field_id_from_name( $real_field );
1009
- $value = $wpdb->get_var (
1010
- $wpdb->prepare(
1011
- "
1012
- SELECT last_updated
1013
- FROM {$bp->profile->table_name_data}
1014
- WHERE user_id = %d AND field_id = %d
1015
- "
1016
- , $user->ID
1017
- , $field_id
1018
- )
1019
- );
1020
-
1021
- // include the user's role in the export ##
1022
- }
1023
- elseif ( isset( $_POST['roles'] ) && '1' == $_POST['roles'] && $field == 'roles' )
1024
- {
1025
-
1026
- // add "Role" as $value ##
1027
- $value = isset( $user->roles[0] ) ? implode( $user->roles, '|' ) : '' ; // empty value if no role found - or flat array of user roles ##
1028
-
1029
- // include the user's BP group in the export ##
1030
- }
1031
- elseif ( isset( $_POST['groups'] ) && '1' == $_POST['groups'] && $field == 'groups' )
1032
- {
1033
-
1034
- if ( function_exists( 'groups_get_user_groups' ) ) {
1035
-
1036
- // check if user is a member of any groups ##
1037
- $group_ids = groups_get_user_groups( $user->ID );
1038
-
1039
- #$this->pr( $group_ids );
1040
- #wp_die( pr( 'loaded group data.' ));
1041
-
1042
- if ( ! $group_ids || $group_ids == '' ) {
1043
-
1044
- $value = '';
1045
-
1046
- } else {
1047
-
1048
- // new empty array ##
1049
- $groups = array();
1050
-
1051
- // loop over all groups ##
1052
- foreach( $group_ids["groups"] as $group_id ) {
1053
-
1054
- $groups[] = groups_get_group( array( 'group_id' => $group_id )) -> name . ( end( $group_ids["groups"] ) == $group_id ? '' : '' );
1055
-
1056
- }
1057
-
1058
- // implode it ##
1059
- $value = implode( $groups, '|' );
1060
-
1061
- }
1062
-
1063
- } else {
1064
-
1065
- $value = '';
1066
-
1067
- }
1068
-
1069
- }
1070
- elseif ( $field == 'bp_latest_update' || $field == 'last_activity' )
1071
- {
1072
-
1073
- // https://bpdevel.wordpress.com/2014/02/21/user-last_activity-data-and-buddypress-2-0/ ##
1074
- $value = bp_get_user_last_activity( $user->ID );
1075
-
1076
- // user or usermeta field ##
1077
- }
1078
- else
1079
- {
1080
-
1081
- // the user_meta key isset ##
1082
- if ( isset( $get_user_meta[$field] ) ) {
1083
-
1084
- // take from the bulk get_user_meta call - this returns an array in all cases, so we take the first key ##
1085
- $value = $get_user_meta[$field][0];
1086
-
1087
- // standard WP_User value ##
1088
- } else {
1089
-
1090
- // use the magically assigned value from WP_Users
1091
- $value =isset( $user->{$field} ) ? $user->{$field} : null ;
1092
-
1093
- }
1094
-
1095
-
1096
- // the $value might be serialized ##
1097
- $value = $this->unserialize( $value );
1098
-
1099
- // the value is an array ##
1100
- if ( is_array ( $value ) ) {
1101
-
1102
- // recursive implode it ##
1103
- $value = $this->recursive_implode( $value );
1104
-
1105
- }
1106
-
1107
- // sanitize ##
1108
- #$value = $this->sanitize($value);
1109
-
1110
- }
1111
-
1112
-
1113
- // correct program value to Program Name ##
1114
- if ( $field == 'member_of_club' ) {
1115
-
1116
- $value = get_the_title($value);
1117
-
1118
- }
1119
-
1120
- // sanitize ##
1121
- $value = $this->sanitize($value);
1122
-
1123
- // wrap values in quotes and add to array ##
1124
- if ( $is_csv ) {
1125
-
1126
- $data[] = '"' . str_replace( '"', '""', $this->special_characters( $value ) ) . '"';
1127
-
1128
- // just add to array ##
1129
- } else {
1130
-
1131
- $data[] = $this->special_characters( $value );
1132
- }
1133
-
1134
- }
1135
-
1136
- // echo row data ##
1137
- echo $pre . implode( $seperator, $data ) . $breaker;
1138
-
1139
- }
1140
-
1141
- // close doc wrapper..
1142
- echo $doc_end;
1143
-
1144
- // stop PHP, so file can export correctly ##
1145
- exit;
1146
-
1147
- }
1148
-
1149
-
1150
- /**
1151
- * Content of the settings page
1152
- *
1153
- * @since 0.1
1154
- **/
1155
- public function users_page()
1156
- {
1157
-
1158
- // quick security check ##
1159
- if ( ! current_user_can( 'list_users' ) ) {
1160
-
1161
- wp_die( __( 'You do not have sufficient permissions to access this page.', 'export-user-data' ) );
1162
-
1163
- }
1164
-
1165
- // Save settings button was pressed ##
1166
- if (
1167
- isset( $_POST['save_export'] )
1168
- && check_admin_referer( 'q-eud-export-user-page_export', '_wpnonce-q-eud-export-user-page_export' )
1169
- ) {
1170
-
1171
- // start with an empty variable ##
1172
- $save_export = "";
1173
-
1174
- if ( ! empty( $_POST['save_new_export_name'] ) ) {
1175
-
1176
- // assign value ##
1177
- $save_export = $_POST['save_new_export_name'];
1178
-
1179
- } elseif ( ! empty( $_POST['export_name'] ) ) {
1180
-
1181
- $save_export = $_POST['export_name'];
1182
-
1183
- }
1184
-
1185
- // clean up $save_export ##
1186
- $save_export = sanitize_text_field( $save_export );
1187
-
1188
- // Build array of $options to save and save them ##
1189
- if ( isset( $save_export ) ) {
1190
-
1191
- // prepare all array values ##
1192
- $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '' ;
1193
- $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '' ;
1194
- $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '' ;
1195
- $format = isset( $_POST['format'] ) ? $_POST['format'] : '' ;
1196
- $role = isset( $_POST['role'] ) ? $_POST['role'] : '' ;
1197
- $roles = isset( $_POST['roles'] ) ? $_POST['roles'] : '0' ;
1198
- $user_fields = isset( $_POST['user_fields'] ) ? $_POST['user_fields'] : '0' ;
1199
- $groups = isset( $_POST['groups'] ) ? $_POST['groups'] : '0' ;
1200
- $start_date = isset( $_POST['start_date'] ) ? $_POST['start_date'] : '' ;
1201
- $end_date = isset( $_POST['end_date'] ) ? $_POST['end_date'] : '' ;
1202
- $limit_offset = isset( $_POST['limit_offset'] ) ? $_POST['limit_offset'] : '' ;
1203
- $limit_total = isset( $_POST['limit_total'] ) ? $_POST['limit_total'] : '' ;
1204
- $updated_since_date = isset ( $_POST['updated_since_date'] ) ? $_POST['updated_since_date'] : '' ;
1205
- $field_updated_since = isset ( $_POST['bp_field_updated_since'] ) ? $_POST['bp_field_updated_since'] : '';
1206
-
1207
- // assign all values to an array ##
1208
- $save_array = array (
1209
- 'usermeta_saved_fields' => $usermeta,
1210
- 'bp_fields_saved_fields' => $bp_fields,
1211
- 'bp_fields_update_time_saved_fields' => $bp_fields_update,
1212
- 'role' => $role,
1213
- 'roles' => $roles,
1214
- 'user_fields' => $user_fields,
1215
- 'groups' => $groups,
1216
- 'start_date' => $start_date,
1217
- 'end_date' => $end_date,
1218
- 'limit_offset' => $limit_offset,
1219
- 'limit_total' => $limit_total,
1220
- 'updated_since_date' => $updated_since_date,
1221
- 'field_updated_since' => $field_updated_since,
1222
- 'format' => $format
1223
- );
1224
-
1225
- // store the options, for next load ##
1226
- $this->set_user_options( $save_export, $save_array );
1227
-
1228
- // Display the settings the user just saved instead of blanking the form ##
1229
- $_POST['load_export'] = 'Load Settings';
1230
- $_POST['export_name'] = $save_export;
1231
-
1232
- }
1233
-
1234
- }
1235
-
1236
- // Load settings button was pressed ( or option saved and $_POST variables hijacked )##
1237
- if (
1238
- isset( $_POST['load_export'] )
1239
- && isset( $_POST['export_name'] )
1240
- && check_admin_referer( 'q-eud-export-user-page_export', '_wpnonce-q-eud-export-user-page_export' )
1241
- ) {
1242
-
1243
- $this->get_user_options_by_export( sanitize_text_field( $_POST['export_name'] ) );
1244
-
1245
- }
1246
-
1247
- // Delete settings button was pressed ##
1248
- if (
1249
- isset( $_POST['delete_export'] )
1250
- && isset( $_POST['export_name'] )
1251
- && check_admin_referer( 'q-eud-export-user-page_export', '_wpnonce-q-eud-export-user-page_export' )
1252
- ) {
1253
-
1254
- $this->delete_user_options( sanitize_text_field( $_POST['export_name'] ) );
1255
-
1256
- }
1257
-
1258
- // what's in 'this' ? ##
1259
- #self:pr( $this );
1260
-
1261
- ?>
1262
- <div class="wrap">
1263
- <h2><?php _e( 'Export User Data', 'export-user-data' ); ?></h2>
1264
- <?php
1265
-
1266
- // nothing happening? ##
1267
- if ( isset( $_GET['error'] ) ) {
1268
- echo '<div class="updated"><p><strong>' . __( 'No users found.', 'export-user-data' ) . '</strong></p></div>';
1269
- }
1270
-
1271
- ?>
1272
- <form method="post" action="" enctype="multipart/form-data">
1273
- <?php wp_nonce_field( 'q-eud-export-user-page_export', '_wpnonce-q-eud-export-user-page_export' ); ?>
1274
- <table class="form-table">
1275
- <?php
1276
-
1277
- // allow admin to select user meta fields to export ##
1278
- global $wpdb;
1279
- $meta_keys = $wpdb->get_results( "SELECT distinct(meta_key) FROM $wpdb->usermeta" );
1280
-
1281
- // get meta_key value from object ##
1282
- $meta_keys = wp_list_pluck( $meta_keys, 'meta_key' );
1283
-
1284
- // let's note some of them odd keys ##
1285
- $meta_keys_system = array(
1286
- 'metaboxhidden',
1287
- 'activation',
1288
- 'bp_',
1289
- 'nav_',
1290
- 'wp_',
1291
- 'admin_color',
1292
- 'wpmudev',
1293
- 'screen_',
1294
- 'show_',
1295
- 'rich_',
1296
- 'reward_',
1297
- 'meta-box',
1298
- 'manageedit',
1299
- 'edit_',
1300
- 'closedpostboxes_',
1301
- 'dismissed_',
1302
- 'manage',
1303
- 'comment',
1304
- 'current',
1305
- 'incentive_',
1306
- '_wdp',
1307
- 'ssl',
1308
- 'wdfb',
1309
- 'users_per_page',
1310
- );
1311
-
1312
- // allow array to be filtered ##
1313
- $meta_keys_system = apply_filters( 'export_user_data_meta_keys_system', $meta_keys_system );
1314
-
1315
- // test array ##
1316
- #echo '<pre>'; var_dump($meta_keys); echo '</pre>';
1317
-
1318
- // check if we got anything ? ##
1319
- if ( $meta_keys ) {
1320
-
1321
- ?>
1322
- <tr valign="top">
1323
- <th scope="row">
1324
- <label for="q_eud_usermeta"><?php _e( 'User Meta Fields', 'export-user-data' ); ?></label>
1325
- <p class="filter" style="margin: 10px 0 0;">
1326
- <?php _e('Filter', 'export-user-data'); ?>: <a href="#" class="usermeta-all"><?php _e('All', 'export-user-data'); ?></a> | <a href="#" class="usermeta-common"><?php _e('Common', 'export-user-data'); ?></a>
1327
- </p>
1328
- <p class="filter" style="margin: 10px 0 0;">
1329
- <?php _e('Select', 'export-user-data'); ?>: <a href="#" class="select-all"><?php _e('All', 'export-user-data'); ?></a> | <a href="#" class="select-none"><?php _e('None', 'export-user-data'); ?></a>
1330
- </p>
1331
- </th>
1332
- <td>
1333
- <select multiple="multiple" id="usermeta" name="usermeta[]">
1334
- <?php
1335
-
1336
- foreach ( $meta_keys as $key ) {
1337
-
1338
- #echo "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
1339
-
1340
- // display $key ##
1341
- $display_key = $key;
1342
-
1343
- // rename programs field ##
1344
- if ( $display_key == 'member_of_club' ){
1345
- $display_key = 'program';
1346
- }
1347
-
1348
- // tidy ##
1349
- $display_key = str_replace( "_", " ", ucwords( $display_key ) );
1350
-
1351
- #echo "<label for='".esc_attr( $key )."' title='".esc_attr( $key )."'><input id='".esc_attr( $key )."' type='checkbox' name='usermeta[]' value='".esc_attr( $key )."'/> $display_key</label><br />";
1352
-
1353
- // class ##
1354
- $usermeta_class = 'normal';
1355
-
1356
- foreach ( $meta_keys_system as $drop ) {
1357
-
1358
- if ( strpos( $key, $drop ) !== false ) {
1359
-
1360
- // https://wordpress.org/support/topic/bugfix-numbers-in-export-headers?replies=1
1361
- // removed $key = assignment, as not required ##
1362
- if ( ( array_search( $key, $meta_keys ) ) !== false ) {
1363
-
1364
- $usermeta_class = 'system';
1365
-
1366
- }
1367
-
1368
- }
1369
-
1370
- }
1371
-
1372
- // print key ##
1373
- echo "<option value='".esc_attr( $key )."' title='".esc_attr( $key )."' class='".$usermeta_class."'>$display_key</option>";
1374
-
1375
- }
1376
- ?>
1377
- </select>
1378
- <p class="description"><?php
1379
- printf(
1380
- __( 'Select the user meta keys to export, use the filters to simplify the list.', 'export-user-data' )
1381
- );
1382
- ?></p>
1383
- </td>
1384
- </tr>
1385
- <?php
1386
-
1387
- } // meta_keys found ##
1388
-
1389
- ?>
1390
- <?php
1391
-
1392
- // buddypress x profile data ##
1393
- if ( function_exists ('bp_is_active') ) {
1394
-
1395
- // grab all buddypress x profile fields ##
1396
- $bp_fields = $wpdb->get_results( "SELECT distinct(name) FROM ".$wpdb->base_prefix."bp_xprofile_fields WHERE parent_id = 0" );
1397
-
1398
- // get name value from object ##
1399
- $bp_fields = wp_list_pluck( $bp_fields, 'name' );
1400
-
1401
- // test array ##
1402
- #echo '<pre>'; var_dump($bp_fields); echo '</pre>';
1403
-
1404
- // allow array to be filtered ##
1405
- $bp_fields = apply_filters( 'export_user_data_bp_fields', $bp_fields );
1406
-
1407
- ?>
1408
- <tr valign="top">
1409
- <th scope="row">
1410
- <label for="q_eud_xprofile"><?php _e( 'BP xProfile Fields', 'export-user-data' ); ?></label>
1411
- <p class="filter" style="margin: 10px 0 0;">
1412
- <?php _e('Select', 'export-user-data'); ?>: <a href="#" class="select-all"><?php _e('All', 'export-user-data'); ?></a> | <a href="#" class="select-none"><?php _e('None', 'export-user-data'); ?></a>
1413
- </p>
1414
- </th>
1415
- <td>
1416
- <select multiple="multiple" id="bp_fields" name="bp_fields[]">
1417
- <?php
1418
-
1419
- foreach ( $bp_fields as $key ) {
1420
-
1421
- // tidy up key ##
1422
- #$key_tidy = str_replace( ' ', '__', $key );
1423
-
1424
- #echo "<label for='".esc_attr( $key_tidy )."'><input id='".esc_attr( $key_tidy )."' type='checkbox' name='bp_fields[]' value='".esc_attr( $key_tidy )."'/> $key</label><br />";
1425
-
1426
- // print key ##
1427
- echo "<option value='".esc_attr( $key )."' title='".esc_attr( $key )."'>$key</option>";
1428
-
1429
- }
1430
-
1431
- ?>
1432
- </select>
1433
- <p class="description"><?php
1434
- printf(
1435
- __( 'Select the BuddyPress XProfile keys to export', 'export-user-data' )
1436
- );
1437
- ?></p>
1438
- </td>
1439
- </tr>
1440
- <?php
1441
-
1442
- // allow export of update times ##
1443
-
1444
- ?>
1445
- <tr valign="top" class="toggleable">
1446
- <th scope="row">
1447
- <label for="q_eud_xprofile"><?php _e( 'BP xProfile Fields Update Time', 'export-user-data' ); ?></label>
1448
- <p class="filter" style="margin: 10px 0 0;">
1449
- <?php _e('Select', 'export-user-data'); ?>: <a href="#" class="select-all"><?php _e('All', 'export-user-data'); ?></a> | <a href="#" class="select-none"><?php _e('None', 'export-user-data'); ?></a>
1450
- </p>
1451
- </th>
1452
- <td>
1453
- <select multiple="multiple" id="bp_fields_update_time" name="bp_fields_update_time[]">
1454
- <?php
1455
-
1456
- foreach ( $bp_fields as $key ) {
1457
-
1458
- echo "<option value='".esc_attr( $key )."' title='".esc_attr( $key )."'>$key</option>";
1459
-
1460
- }
1461
-
1462
- ?>
1463
- </select>
1464
- <p class="description"><?php
1465
- printf(
1466
- __( 'Select the BuddyPress XProfile keys updated dates to export', 'export-user-data' )
1467
- );
1468
- ?></p>
1469
- </td>
1470
- </tr>
1471
-
1472
- <tr valign="top" class="toggleable">
1473
- <th scope="row"><label for="groups"><?php _e( 'BP User Groups', 'export-user-data' ); ?></label></th>
1474
- <td>
1475
- <input id='groups' type='checkbox' name='groups' value='1' <?php checked( isset ( $this->groups ) ? intval ( $this->groups ) : '', 1 ); ?> />
1476
- <p class="description"><?php
1477
- printf(
1478
- __( 'Include BuddyPress Group Data. <a href="%s" target="_blank">%s</a>', 'export-user-data' )
1479
- , esc_html('https://codex.buddypress.org/buddypress-components-and-features/groups/')
1480
- , 'Codex'
1481
- );
1482
- ?></p>
1483
- </td>
1484
- </tr>
1485
- <?php
1486
-
1487
- } // BP installed and active ##
1488
-
1489
- ?>
1490
- <tr valign="top" class="toggleable">
1491
- <th scope="row"><label for="user_fields"><?php _e( 'Standard User Fields', 'export-user-data' ); ?></label></th>
1492
- <td>
1493
- <input id='user_fields' type='checkbox' name='user_fields' value='1' <?php checked( isset ( $this->user_fields ) ? intval ( $this->user_fields ) : '', 1 ); ?> />
1494
- <p class="description"><?php
1495
-
1496
- #$this->log( 'user_fields: '.$this->user_fields );
1497
- #echo 'user_fields: '. $this->user_fields;
1498
-
1499
- printf(
1500
- __( 'Include Standard user profile fields, such as user_login. <a href="%s" target="_blank">%s</a>', 'export-user-data' )
1501
- , esc_html('https://codex.wordpress.org/Database_Description#Table:_wp_users')
1502
- , 'Codex'
1503
- );
1504
-
1505
- ?></p>
1506
- </td>
1507
- </tr>
1508
-
1509
- <tr valign="top" class="toggleable">
1510
- <th scope="row"><label for="q_eud_users_role"><?php _e( 'Role', 'export-user-data' ); ?></label></th>
1511
- <td>
1512
- <select name="role" id="q_eud_users_role">
1513
- <?php
1514
-
1515
- echo '<option value="">' . __( 'All Roles', 'export-user-data' ) . '</option>';
1516
- global $wp_roles;
1517
-
1518
- foreach ( $wp_roles->role_names as $role => $name ) {
1519
-
1520
- if ( isset ( $this->role ) && ( $this->role == $role ) ) {
1521
-
1522
- echo "\n\t<option selected value='" . esc_attr( $role ) . "'>$name</option>";
1523
-
1524
- } else {
1525
-
1526
- echo "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
1527
-
1528
- }
1529
- }
1530
-
1531
-
1532
- ?>
1533
- </select>
1534
- <p class="description"><?php
1535
- printf(
1536
- __( 'Filter the exported users by a WordPress Role. <a href="%s" target="_blank">%s</a>', 'export-user-data' )
1537
- , esc_html('http://codex.wordpress.org/Roles_and_Capabilities')
1538
- , 'Codex'
1539
- );
1540
- ?></p>
1541
- </td>
1542
- </tr>
1543
-
1544
- <tr valign="top" class="toggleable">
1545
- <th scope="row"><label for="roles"><?php _e( 'User Roles', 'export-user-data' ); ?></label></th>
1546
- <td>
1547
- <input id='roles' type='checkbox' name='roles' value='1' <?php checked( isset ( $this->roles ) ? intval ( $this->roles ) : '', 1 ); ?> />
1548
- <p class="description"><?php
1549
- printf(
1550
- __( 'Include all of the users <a href="%s" target="_blank">%s</a>', 'export-user-data' )
1551
- , esc_html('http://codex.wordpress.org/Roles_and_Capabilities')
1552
- , 'Roles'
1553
- );
1554
- ?></p>
1555
- </td>
1556
- </tr>
1557
- <?php
1558
-
1559
- // clubs ? ##
1560
- if ( post_type_exists( 'club' ) ) {
1561
-
1562
- ?>
1563
- <tr valign="top" class="toggleable">
1564
- <th scope="row"><label for="q_eud_users_program"><?php _e( 'Programs', 'export-user-data' ); ?></label></th>
1565
- <td>
1566
- <select name="program" id="q_eud_users_program">
1567
- <?php
1568
-
1569
- echo '<option value="">' . __( 'All Programs', 'export-user-data' ) . '</option>';
1570
-
1571
- $clubs_array = get_posts(array( 'post_type'=> 'club', 'posts_per_page' => -1 )); // grab all posts of type "club" ##
1572
-
1573
- foreach ( $clubs_array as $c ) { // loop over all clubs ##
1574
-
1575
- #$clubs[$c->ID] = $c; // grab club ID ##
1576
- echo "\n\t<option value='" . esc_attr( $c->ID ) . "'>$c->post_title</option>";
1577
-
1578
- }
1579
-
1580
- ?>
1581
- </select>
1582
- </td>
1583
- </tr>
1584
- <?php
1585
-
1586
- } // clubs ##
1587
-
1588
- ?>
1589
- <tr valign="top" class="toggleable">
1590
- <th scope="row"><label><?php _e( 'Registered', 'export-user-data' ); ?></label></th>
1591
- <td>
1592
- <input type="text" id="q_eud_users_start_date" name="start_date" value="<?php echo $this->start_date; ?>" class="start-datepicker" />
1593
- <input type="text" id="q_eud_users_end_date" name="end_date" value="<?php echo $this->end_date; ?>" class="end-datepicker" />
1594
- <p class="description"><?php
1595
- printf(
1596
- __( 'Pick a start and end user registration date to limit the results.', 'export-user-data' )
1597
- );
1598
- ?></p>
1599
- </td>
1600
- </tr>
1601
-
1602
- <tr valign="top" class="toggleable">
1603
- <th scope="row"><label><?php _e( 'Limit Range', 'export-user-data' ); ?></label></th>
1604
- <td>
1605
- <input name="limit_offset" type="text" id="q_eud_users_limit_offset" value="<?php echo( $this->limit_offset ); ?>" class="regular-text code numeric" style="width: 136px;" placeholder="<?php _e( 'Offset', 'export-user-data' ); ?>">
1606
- <input name="limit_total" type="text" id="q_eud_users_limit_total" value="<?php echo ( $this->limit_total ); ?>" class="regular-text code numeric" style="width: 136px;" placeholder="<?php _e( 'Total', 'export-user-data' ); ?>">
1607
- <p class="description"><?php
1608
- printf(
1609
- __( 'Enter an offset start number and a total number of users to export. <a href="%s" target="_blank">%s</a>', 'export-user-data' )
1610
- , esc_html('http://codex.wordpress.org/Function_Reference/get_users#Parameters')
1611
- , 'Codex'
1612
- );
1613
- ?></p>
1614
- </td>
1615
- </tr>
1616
-
1617
- <tr valign="top" class="toggleable">
1618
- <th scope="row"><label><?php _e( 'Updated Since', 'export-user-data' ); ?></label></th>
1619
- <td>
1620
- <input type="text" id="q_eud_updated_since_date" name="updated_since_date" value="<?php echo $this->updated_since_date; ?>" class="updated-datepicker" />
1621
- <select id="bp_field_updated_since" name="bp_field_updated_since">
1622
- <?php
1623
-
1624
- foreach ( $bp_fields as $key ) {
1625
- if ( $this->field_updated_since == $key ) {
1626
- echo "<option value='".esc_attr( $key )."' title='".esc_attr( $key )."' selected>$key</option>";
1627
- } else {
1628
- echo "<option value='".esc_attr( $key )."' title='".esc_attr( $key )."'>$key</option>";
1629
- }
1630
- }
1631
-
1632
- ?>
1633
- </select>
1634
-
1635
- <p class="description"><?php
1636
- printf(
1637
- __( 'Limit the results to users who have updated this extended profile field after this date.', 'export-user-data' )
1638
- );
1639
- ?></p>
1640
- </td>
1641
- </tr>
1642
-
1643
- <tr valign="top">
1644
- <th scope="row"><label for="q_eud_users_format"><?php _e( 'Format', 'export-user-data' ); ?></label></th>
1645
- <td>
1646
- <select name="format" id="q_eud_users_format">
1647
- <?php
1648
- if ( isset ( $this->format ) && ( $this->format == 'excel' ) ) {
1649
- echo '<option selected value="excel">' . __( 'Excel', 'export-user-data' ) . '</option>';
1650
- } else {
1651
- echo '<option value="excel">' . __( 'Excel', 'export-user-data' ) . '</option>';
1652
- }
1653
- if ( isset ( $this->format ) && ( $this->format == 'csv' ) ) {
1654
- echo '<option selected value="csv">' . __( 'CSV', 'export-user-data' ) . '</option>';
1655
- } else {
1656
- echo '<option value="csv">' . __( 'CSV', 'export-user-data' ) . '</option>';
1657
- }
1658
- ?>
1659
- </select>
1660
- <p class="description"><?php
1661
- printf(
1662
- __( 'Select the format for the export file.', 'export-user-data' )
1663
- );
1664
- ?></p>
1665
- </td>
1666
- </tr>
1667
-
1668
- <tr valign="top" class="remember">
1669
- <th scope="row"><label for="q_eud_save_options"><?php _e( 'Stored Options', 'export-user-data' ); ?></label></th>
1670
- <td>
1671
-
1672
- <div class="row">
1673
- <input type="text" class="regular-text" name="save_new_export_name" id="q_eud_save_options_new_export" placeholder="<?php _e( 'Export Name', 'export-user-data' ); ?>" value="<?php echo isset( $_POST['export_name'] ) ? $_POST['export_name'] : '' ; ?>">
1674
- <input type="submit" id="save_export" class="button-primary" name="save_export" value="<?php _e( 'Save', 'export-user-data' ); ?>" />
1675
- </div>
1676
- <?php
1677
-
1678
- // check if the user has any saved exports ##
1679
- if ( $this->get_user_options() ) {
1680
-
1681
- ?>
1682
- <div class="row">
1683
- <select name="export_name" id="q_eud_save_options" class="regular-text">
1684
- <?php
1685
-
1686
- // loop over each saved export ##
1687
- foreach( $this->get_user_options() as $export ) {
1688
-
1689
- // select Loaded export name, if selected ##
1690
- if (
1691
- isset( $_POST['load_export'] )
1692
- && isset( $_POST['export_name'] )
1693
- && ( $_POST['export_name'] == $export )
1694
- ) {
1695
-
1696
- echo "<option selected value='$export'>$export</option>";
1697
-
1698
- // just list previous export name ##
1699
- } else {
1700
-
1701
- echo "<option value='$export'>$export</option>";
1702
-
1703
- }
1704
-
1705
- }
1706
-
1707
- ?>
1708
- </select>
1709
-
1710
- <input type="submit" id="load_export" class="button-primary" name="load_export" value="<?php _e( 'Load', 'export-user-data' ); ?>" />
1711
- <input type="submit" id="delete_export" class="button-primary" name="delete_export" value="<?php _e( 'Delete', 'export-user-data' ); ?>" />
1712
- <?php
1713
-
1714
- }
1715
-
1716
- ?>
1717
- </div>
1718
- <p class="description"><?php _e( 'Save, load or delete your stored export options.', 'export-user-data' ); ?></p>
1719
-
1720
- </td>
1721
- </tr>
1722
-
1723
- <tr valign="top">
1724
- <th scope="row">
1725
- <label for="q_eud_xprofile"><?php _e( 'Advanced Options', 'export-user-data' ); ?></label>
1726
- </th>
1727
- <td>
1728
- <div class="toggle">
1729
- <a href="#"><?php _e( 'Show', 'export-user-data' ); ?></a>
1730
- </div>
1731
- </td>
1732
- </tr>
1733
-
1734
- </table>
1735
- <p class="submit">
1736
- <input type="hidden" name="_wp_http_referer" value="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" />
1737
- <input type="submit" class="button-primary" value="<?php _e( 'Run Export', 'export-user-data' ); ?>" />
1738
- </p>
1739
- </form>
1740
- </div>
1741
-
1742
- <?php
1743
- }
1744
-
1745
-
1746
- /**
1747
- * Inline jQuery
1748
- * @since 0.8.2
1749
- */
1750
- public function jquery()
1751
- {
1752
-
1753
- // load the scripts on only the plugin admin page
1754
- if (isset( $_GET['page'] ) && ( $_GET['page'] == 'export-user-data' ) ) {
1755
-
1756
- ?>
1757
- <script>
1758
-
1759
- // lazy load in some jQuery validation ##
1760
- jQuery(document).ready(function($) {
1761
-
1762
- // build super multiselect ##
1763
- jQuery('#usermeta, #bp_fields, #bp_fields_update_time').multiSelect();
1764
-
1765
- //Select any fields from saved settings ##
1766
- jQuery('#usermeta').multiSelect('select',([<?php echo( $this->quote_array( $this->usermeta_saved_fields ) ); ?>]));
1767
- jQuery('#bp_fields').multiSelect('select',([<?php echo( $this->quote_array($this->bp_fields_saved_fields ) ); ?>]));
1768
- jQuery('#bp_fields_update_time').multiSelect('select',([<?php echo( $this->quote_array( $this->bp_fields_update_time_saved_fields ) ); ?>]));
1769
-
1770
- // show only common ##
1771
- jQuery('.usermeta-common').click(function(e){
1772
- e.preventDefault();
1773
- jQuery('#ms-usermeta .ms-selectable li.system').hide();
1774
- });
1775
-
1776
- // show all ##
1777
- jQuery('.usermeta-all').click(function(e){
1778
- e.preventDefault();
1779
- jQuery('#ms-usermeta .ms-selectable li').show();
1780
- });
1781
-
1782
- // select all ##
1783
- jQuery('.select-all').click(function(e){
1784
- e.preventDefault();
1785
- jQuery( jQuery(this).parent().parent().parent().find( 'select' ) ).multiSelect( 'select_all' );
1786
- });
1787
-
1788
- // select none ##
1789
- jQuery('.select-none').click(function(e){
1790
- e.preventDefault();
1791
- jQuery( jQuery(this).parent().parent().parent().find( 'select' ) ).multiSelect( 'deselect_all' );
1792
- });
1793
-
1794
-
1795
- // validate number inputs ##
1796
- $("input.numeric").blur(function() {
1797
-
1798
- //console.log("you entered "+ $(this).val());
1799
-
1800
- if ( $(this).val() && ! $.isNumeric( $(this).val() ) ) {
1801
-
1802
- //console.log("this IS NOT a number");
1803
- $(this).css({ 'background': 'red', 'color': 'white' }); // highlight error ##
1804
- $("p.submit .button-primary").attr('disabled','disabled'); // disable submit ##
1805
-
1806
- } else {
1807
-
1808
- $(this).css({ 'background': 'white', 'color': '#333' }); // remove error highlighting ##
1809
- $("p.submit .button-primary").removeAttr('disabled'); // enable submit ##
1810
-
1811
- }
1812
-
1813
- });
1814
-
1815
- // toggle advanced options ##
1816
- jQuery(".toggle a").click( function(e) {
1817
- e.preventDefault();
1818
- $toggleable = jQuery("tr.toggleable");
1819
- $toggleable.toggle();
1820
- if ( $toggleable.is(":visible") ) {
1821
- jQuery(this).text("<?php _e( 'Hide', 'export-user-data' ); ?>");
1822
- } else {
1823
- jQuery(this).text("<?php _e( 'Show', 'export-user-data' ); ?>");
1824
- }
1825
- });
1826
-
1827
- // validate save button ##
1828
- jQuery("#save_export").click( function(e) {
1829
-
1830
- // grab the value of the input ##
1831
- var q_eud_save_options_new_export = jQuery('#q_eud_save_options_new_export').val();
1832
-
1833
- if ( ! q_eud_save_options_new_export || q_eud_save_options_new_export == '' ) {
1834
-
1835
- e.preventDefault(); // stop things here ##
1836
- jQuery('#q_eud_save_options_new_export').addClass("error");
1837
-
1838
- }
1839
-
1840
- });
1841
-
1842
- // remove validation on focus ##
1843
- jQuery("body").on( 'focus', '#q_eud_save_options_new_export', function(e) {
1844
-
1845
- jQuery(this).removeClass("error");
1846
-
1847
- });
1848
-
1849
- <?php
1850
-
1851
- // method returns an object with "first" & "last" keys ##
1852
- $dates = $this->get_user_registered_dates();
1853
-
1854
- // get date format from WP settings #
1855
- $date_format = 'yy-mm-dd' ; // get_option('date_format') ? get_option('date_format') : 'yy-mm-dd' ;
1856
- $start_of_week = get_option('start_of_week') ? get_option('start_of_week') : 'yy-mm-dd' ;
1857
- #$this->log( 'Date format: '.$date_format );
1858
-
1859
- ?>
1860
-
1861
- // start date picker ##
1862
- jQuery('.start-datepicker').datepicker( {
1863
- dateFormat : '<?php echo $date_format; ?>',
1864
- minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
1865
- maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>',
1866
- firstDay : '<?php echo $start_of_week; ?>'
1867
- } );
1868
-
1869
- // end date picker ##
1870
- jQuery('.end-datepicker').datepicker( {
1871
- dateFormat : '<?php echo $date_format; ?>',
1872
- minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
1873
- maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>',
1874
- firstDay : '<?php echo $start_of_week; ?>'
1875
- } );
1876
-
1877
- // end date picker ##
1878
- // might want to set minDate to something else, but not sure
1879
- // what would be best for everyone
1880
- jQuery('.updated-datepicker').datepicker( {
1881
- dateFormat : '<?php echo $date_format; ?>',
1882
- minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
1883
- maxDate : '0',
1884
- firstDay : '<?php echo $start_of_week; ?>'
1885
- } );
1886
-
1887
- });
1888
-
1889
- </script>
1890
- <?php
1891
- }
1892
-
1893
- }
1894
-
1895
-
1896
- /**
1897
- * Inline CSS
1898
- * @since 0.8.2
1899
- */
1900
- public function css()
1901
- {
1902
-
1903
- // load the scripts on only the plugin admin page
1904
- if (isset( $_GET['page'] ) && ( $_GET['page'] == 'export-user-data' ) ) {
1905
- ?>
1906
- <style>
1907
- .toggleable { display: none; }
1908
- .hidden { display: none; }
1909
- </style>
1910
- <?php
1911
- }
1912
-
1913
- }
1914
-
1915
-
1916
- /**
1917
- * Data to exclude from export
1918
- */
1919
- protected function get_exclude_fields()
1920
- {
1921
-
1922
- $exclude_fields = array (
1923
- 'user_pass'
1924
- , 'q_eud_exports'
1925
- #, 'user_activation_key'
1926
- );
1927
-
1928
- return apply_filters( 'export_user_data_exclude_fields', $exclude_fields );
1929
-
1930
- }
1931
-
1932
-
1933
- /**
1934
- * Get the array of standard WP_User fields to return
1935
- */
1936
- protected function get_user_fields()
1937
- {
1938
-
1939
- // standard wp_users fields ##
1940
- if ( isset( $_POST['user_fields'] ) && '1' == $_POST['user_fields'] ) {
1941
-
1942
- // debug ##
1943
- #$this->log( 'full' );
1944
-
1945
- // exportable user data ##
1946
- $user_fields = array(
1947
- 'ID'
1948
- , 'user_login'
1949
- #, 'user_pass'
1950
- , 'user_nicename'
1951
- , 'user_email'
1952
- , 'user_url'
1953
- , 'user_registered'
1954
- #, 'user_activation_key'
1955
- , 'user_status'
1956
- , 'display_name'
1957
- );
1958
-
1959
- } else {
1960
-
1961
- // debug ##
1962
- #$this->log( 'reduced' );
1963
-
1964
- // just return the user ID
1965
- $user_fields = array(
1966
- 'ID'
1967
- );
1968
-
1969
- }
1970
-
1971
- // kick back values ##
1972
- return apply_filters( 'export_user_data_user_fields', $user_fields );
1973
-
1974
- }
1975
-
1976
-
1977
- /**
1978
- * Get the array of special user fields to return
1979
- */
1980
- protected function get_special_fields()
1981
- {
1982
-
1983
- // exportable user data ##
1984
- $special_fields = array(
1985
- # 'roles' // list of WP Roles
1986
- #, 'groups' // BP Groups
1987
- );
1988
-
1989
- // should we allow groups ##
1990
- if ( isset( $_POST['groups'] ) && '1' == $_POST['groups'] ) {
1991
-
1992
- $special_fields[] = 'groups'; // add groups ##
1993
-
1994
- }
1995
-
1996
- // should we allow groups ##
1997
- if ( isset( $_POST['roles'] ) && '1' == $_POST['roles'] ) {
1998
-
1999
- $special_fields[] = 'roles'; // add groups ##
2000
-
2001
- }
2002
-
2003
- // kick back the array ##
2004
- return apply_filters( 'export_user_data_special_fields', $special_fields );
2005
-
2006
- }
2007
-
2008
-
2009
- /*
2010
- * Pre User Query
2011
- */
2012
- public function pre_user_query( $user_search )
2013
- {
2014
-
2015
- global $wpdb;
2016
-
2017
- $where = '';
2018
-
2019
- if ( ! empty( $_POST['start_date'] ) ) {
2020
-
2021
- $date = new DateTime( sanitize_text_field ( $_POST['start_date'] ). ' 00:00:00' );
2022
- $date_formatted = $date->format( 'Y-m-d H:i:s' );
2023
-
2024
- $where .= $wpdb->prepare( " AND $wpdb->users.user_registered >= %s", $date_formatted );
2025
-
2026
- }
2027
- if ( ! empty( $_POST['end_date'] ) ) {
2028
-
2029
- $date = new DateTime( sanitize_text_field ( $_POST['end_date'] ). ' 00:00:00' );
2030
- $date_formatted = $date->format( 'Y-m-d H:i:s' );
2031
-
2032
- $where .= $wpdb->prepare( " AND $wpdb->users.user_registered < %s", $date_formatted );
2033
-
2034
- }
2035
-
2036
- // search by last update time of BP extended fields ##
2037
- if (
2038
- ( isset ($_POST['updated_since_date'] ) && $_POST['updated_since_date'] != '' )
2039
- && (isset ($_POST['bp_field_updated_since'] ) && $_POST['bp_field_updated_since'] != '' )
2040
- ) {
2041
-
2042
- $last_updated_date = new DateTime( sanitize_text_field ( $_POST['updated_since_date'] ) . ' 00:00:00' );
2043
- $this->updated_since_date = $last_updated_date->format( 'Y-m-d H:i:s' );
2044
- $this->field_updated_since = sanitize_text_field ( $_POST['bp_field_updated_since'] );
2045
- $field_updated_since_id = BP_Xprofile_Field::get_id_from_name( $this->field_updated_since );
2046
- $user_search->query_from .= " JOIN `wp_bp_xprofile_data` XP ON XP.user_id = wp_users.ID ";
2047
- $where .= $wpdb->prepare( " AND XP.field_id = %s AND XP.last_updated >= %s", $field_updated_since_id, $this->updated_since_date );
2048
-
2049
- }
2050
-
2051
- if ( ! empty( $where ) ) {
2052
-
2053
- $user_search->query_where = str_replace( 'WHERE 1=1', "WHERE 1=1 $where", $user_search->query_where );
2054
-
2055
- }
2056
-
2057
- #wp_die( $this->pr( $user_search ) );
2058
- return $user_search;
2059
-
2060
- }
2061
-
2062
-
2063
- /**
2064
- * Export Date Options
2065
- *
2066
- * @since 0.9.6
2067
- * @global type $wpdb
2068
- * @return Array of objects
2069
- */
2070
- protected function get_user_registered_dates()
2071
- {
2072
-
2073
- // invite in global objects ##
2074
- global $wpdb;
2075
-
2076
- // query user table for oldest and newest registration ##
2077
- $range =
2078
- $wpdb->get_results (
2079
- #$wpdb->prepare (
2080
- "
2081
- SELECT
2082
- MIN( user_registered ) AS first,
2083
- MAX( user_registered ) AS last
2084
- FROM
2085
- {$wpdb->users}
2086
- "
2087
- #)
2088
- );
2089
-
2090
- return $range;
2091
-
2092
- }
2093
-
2094
-
2095
- /**
2096
- * Quote array elements and separate with commas
2097
- *
2098
- * @since 0.9.6
2099
- * @return String
2100
- */
2101
- protected function quote_array( $array )
2102
- {
2103
-
2104
- $prefix = ''; // starts empty ##
2105
- $elementlist = '';
2106
- if ( is_array( $array ) ) {
2107
- foreach( $array as $element ) {
2108
- $elementlist .= $prefix . "'" . $element . "'";
2109
- $prefix = ','; // prefix all remaining items with a comma ##
2110
- }
2111
- }
2112
-
2113
- // kick back string to function caller ##
2114
- return( $elementlist );
2115
-
2116
- }
2117
-
2118
-
2119
- /**
2120
- * Recursively implodes an array
2121
- *
2122
- * @since 1.0.1
2123
- * @access public
2124
- * @param array $array multi-dimensional array to recursively implode
2125
- * @param string $glue value that glues elements together
2126
- * @param bool $include_keys include keys before their values
2127
- * @param bool $trim_all trim ALL whitespace from string
2128
- * @return string imploded array
2129
- */
2130
- protected function recursive_implode( $array, $return = null, $glue = '|' )
2131
- {
2132
-
2133
- // unserialize ##
2134
- $array = $this->unserialize( $array );
2135
-
2136
- // kick it back ##
2137
- if ( is_null ( $return ) && ! is_array( $array ) ) {
2138
-
2139
- return $array;
2140
-
2141
- }
2142
-
2143
- // empty return ##
2144
- if ( is_null ( $return ) ) {
2145
-
2146
- $return = '';
2147
-
2148
- } else {
2149
-
2150
- if ( "||" == $glue ) {
2151
-
2152
- $glue = '|||';
2153
-
2154
- } else if ( "|" == $glue ) {
2155
-
2156
- $glue = '||';
2157
-
2158
- }
2159
-
2160
- }
2161
-
2162
- // loop ##
2163
- foreach( $array as $key => $value ) {
2164
-
2165
- // unserialize ##
2166
- $value = $this->unserialize( $value );
2167
-
2168
- if( is_array( $value ) ) {
2169
-
2170
- $return .= $glue . $key . $glue . $this->recursive_implode( $value, $return, $glue );
2171
-
2172
- } else {
2173
-
2174
- $return .= $glue . $key . $glue . $value;
2175
-
2176
- }
2177
-
2178
- }
2179
-
2180
- // Removes first $glue from string ##
2181
- if ( $glue && $return && $return[0] == '|' ) {
2182
-
2183
- $return = ltrim ( $return, '|' );
2184
-
2185
- }
2186
-
2187
- // Trim ALL whitespace ##
2188
- if ( $return ) {
2189
-
2190
- $return = preg_replace( "/(\s)/ixsm", '', $return );
2191
-
2192
- }
2193
-
2194
- // kick it back ##
2195
- return $return;
2196
-
2197
- }
2198
-
2199
-
2200
- /**
2201
- * Save Unserializer
2202
- *
2203
- * @since 1.1.4
2204
- */
2205
- protected function unserialize( $value )
2206
- {
2207
-
2208
- // the $value is serialized ##
2209
- if ( is_serialized( $value ) ) {
2210
-
2211
- // unserliaze to new variable ##
2212
- $unserialized = @unserialize( $value );
2213
-
2214
- // test if unserliazing produced errors ##
2215
- if ( $unserialized !== false || $value == 'b:0;' ) {
2216
-
2217
- #$value = 'UNSERIALIZED_'.$unserialized;
2218
- $value = $unserialized;
2219
-
2220
- } else {
2221
-
2222
- // failed to unserialize - data potentially corrupted in db ##
2223
- #$value = 'NOT_SERIALIZED_'.$value;
2224
- $value = $value;
2225
-
2226
- }
2227
-
2228
- }
2229
-
2230
- // kick it back ##
2231
- return $value;
2232
-
2233
- }
2234
-
2235
-
2236
- /**
2237
- * Encode special characters
2238
- *
2239
- * @param type $string
2240
- * @return string Encoding string
2241
- * @since 1.2.3
2242
- */
2243
- protected function special_characters( $string = null )
2244
- {
2245
-
2246
- // sanity check ##
2247
- if ( is_null( $string ) ) {
2248
-
2249
- return false;
2250
-
2251
- }
2252
-
2253
- // kick it back in a nicer format ##
2254
- return htmlentities( $string, ENT_COMPAT, 'UTF-8' );
2255
-
2256
- }
2257
-
2258
-
2259
- }
2260
-
2261
- // hook plugin to workdpress action - defined in class ##
2262
- add_action( Q_EUD_HOOK, 'q_export_user_data', Q_EUD_PRIORITY );
2263
- /**
2264
- * Instatiate class and load up schortcode
2265
- *
2266
- * @since 1.2.8
2267
- * @return void
2268
- */
2269
- function q_export_user_data()
2270
- {
2271
-
2272
- // admin only ##
2273
- if ( ! is_admin() ) { return false; }
2274
-
2275
- // instatiate class ##
2276
- $export_user_data = new Q_Export_User_Data();
2277
-
2278
- // hook into wp fitlers and actions ##
2279
- $export_user_data->run_hooks();
2280
-
2281
  }
2282
 
2283
-
2284
- }
1
  <?php
2
 
3
  /*
4
+ * Plugin Name: Export User Date
5
+ * Description: Export User data and metadata.
6
+ * Version: 2.0.1
7
+ * Author: Q Studio
8
+ * Author URI: http://qstudio.us/
9
+ * License: GPL2
10
+ * Class: q_report
11
+ * Text Domain: q-report
12
+ * GitHub Plugin URI: qstudio/q-report
13
  */
14
 
15
+ /*
16
+ This plugin will add a "Report" sub menu to the users tab and provide a screen which lists a sent of pre-built report buttons - in some cases with options or filtered by program
17
+ Exports will print to the screen first - and then have a "Download" button to export csv / xls formatted data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ - rebuild export user data with filters, defaults and tweaks to make it most relevant to Club Data ##
20
+ - read reports on WP and address all issues in release ##
21
+ - move all custom filters / hacks to filter system - controlled from q_club ( or functions.php for most theme based controls ) ##
22
+ */
23
 
24
+ defined( 'ABSPATH' ) OR exit;
25
 
26
+ if ( ! class_exists( 'q_report' ) ) {
27
+
28
+ // instatiate plugin via WP plugins_loaded - init is too late for CPT ##
29
+ add_action( 'init', array ( 'q_report', 'get_instance' ), 1000000 );
30
+
31
+ class q_report {
32
+
33
+ // Refers to a single instance of this class. ##
34
+ private static $instance = null;
35
+
36
+ // Plugin Settings
37
+ const version = '2.0.1';
38
+ static $debug = true;
39
+ const text_domain = 'q-report'; // for translation ##
40
+
41
  /* properties */
42
+ public static $q_report_exports = ''; // export settings ##
43
+ public static $usermeta_saved_fields = array();
44
+ public static $bp_fields_saved_fields = array();
45
+ public static $bp_fields_update_time_saved_fields = array();
46
+ public static $role = '';
47
+ public static $roles = '0';
48
+ public static $user_fields = '1';
49
+ public static $groups = '0';
50
+ public static $start_date = '';
51
+ public static $end_date = '';
52
+ public static $limit_offset = '';
53
+ public static $limit_total = '';
54
+ public static $updated_since_date = '';
55
+ public static $field_updated_since = '';
56
+ public static $format = '';
57
+ public static $bp_data_available = false;
58
+ public static $allowed_tags = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
+ // api ##
61
+ public static $api_admin_fields = false;
62
 
63
  /**
64
+ * Creates or returns an instance of this class.
65
  *
66
+ * @return Foo A single instance of this class.
 
 
 
 
 
 
 
 
 
 
 
67
  */
68
+ public static function get_instance()
69
  {
70
 
71
+ if ( null == self::$instance ) {
72
+ self::$instance = new self;
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
 
75
+ return self::$instance;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
+
79
+
80
  /**
81
+ * Instatiate Class
82
+ *
83
+ * @since 0.2
84
+ * @return void
85
  */
86
+ private function __construct()
87
  {
88
+
89
+ // activation ##
90
+ register_activation_hook( __FILE__, array ( $this, 'register_activation_hook' ) );
91
 
92
+ // deactvation ##
93
+ register_deactivation_hook( __FILE__, array ( $this, 'register_deactivation_hook' ) );
 
 
94
 
95
+ // set text domain ##
96
+ add_action( 'init', array( $this, 'load_plugin_textdomain' ), 1 );
97
+
98
+ // load libraries ##
99
+ self::load_libraries();
 
 
 
100
 
101
  }
102
 
103
 
104
+ // the form for sites have to be 1-column-layout
105
+ public function register_activation_hook() {
 
 
 
 
 
 
106
 
107
+ \add_option( 'q_report_configured' );
 
 
 
 
 
 
 
 
108
 
109
+ // flush rewrites ##
110
+ #global $wp_rewrite;
111
+ #$wp_rewrite->flush_rules();
112
 
113
  }
114
 
115
 
116
+ public function register_deactivation_hook() {
117
 
118
+ \delete_option( 'q_report_configured' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  }
121
 
122
 
123
+
124
  /**
125
+ * Load Text Domain for translations
126
+ *
127
+ * @since 1.7.0
128
+ *
 
129
  */
130
+ public function load_plugin_textdomain()
131
  {
132
+
133
+ // set text-domain ##
134
+ $domain = self::text_domain;
135
+
136
+ // The "plugin_locale" filter is also used in load_plugin_textdomain()
137
+ $locale = apply_filters('plugin_locale', get_locale(), $domain);
138
 
139
+ // try from global WP location first ##
140
+ load_textdomain( $domain, WP_LANG_DIR.'/plugins/'.$domain.'-'.$locale.'.mo' );
141
+
142
+ // try from plugin last ##
143
+ load_plugin_textdomain( $domain, FALSE, plugin_dir_path( __FILE__ ).'library/languages/' );
144
+
 
145
  }
146
+
147
+
148
+
149
  /**
150
+ * Get Plugin URL
151
+ *
152
+ * @since 0.1
153
+ * @param string $path Path to plugin directory
154
+ * @return string Absoulte URL to plugin directory
155
  */
156
+ public static function get_plugin_url( $path = '' )
157
  {
158
 
159
+ return plugins_url( $path, __FILE__ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  }
162
+
163
+
164
  /**
165
+ * Get Plugin Path
166
+ *
167
+ * @since 0.1
168
+ * @param string $path Path to plugin directory
169
+ * @return string Absoulte URL to plugin directory
170
  */
171
+ public static function get_plugin_path( $path = '' )
172
  {
173
 
174
+ return plugin_dir_path( __FILE__ ).$path;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  }
177
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
  /**
180
+ * Load Libraries
181
+ *
182
+ * @since 2.0
183
+ */
184
+ private static function load_libraries()
 
 
185
  {
186
 
187
+ // methods ##
188
+ require_once self::get_plugin_path( 'library/core/helper.php' );
189
+ require_once self::get_plugin_path( 'library/core/core.php' );
190
+ require_once self::get_plugin_path( 'library/core/user.php' );
191
+ require_once self::get_plugin_path( 'library/core/buddypress.php' );
192
+ require_once self::get_plugin_path( 'library/core/xml.php' );
193
+ require_once self::get_plugin_path( 'library/core/export.php' );
194
+ require_once self::get_plugin_path( 'library/core/filters.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
 
196
+ // api ##
197
+ require_once self::get_plugin_path( 'library/api/admin.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
+ // backend ##
200
+ require_once self::get_plugin_path( 'library/admin/admin.php' );
201
+
202
  }
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  }
205
 
206
+ }
 
library/admin/admin.php ADDED
@@ -0,0 +1,838 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\admin;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+ use q\report\core\user as user;
8
+ use q\report\core\buddypress as buddypress;
9
+ use q\report\api\admin as api_admin;
10
+
11
+ // load it up ##
12
+ \q\report\admin\admin::run();
13
+
14
+ class admin extends \q_report {
15
+
16
+ public static function run()
17
+ {
18
+
19
+ #global $pagenow;
20
+
21
+ if ( \is_admin() ) {
22
+
23
+ // add export menu inside admin ##
24
+ \add_action( 'admin_menu', array( get_class(), 'add_menu' ) );
25
+
26
+ // UI style and functionality ##
27
+ \add_action( 'admin_enqueue_scripts', array( get_class(), 'admin_enqueue_scripts' ), 1 );
28
+ \add_action( 'admin_footer', array( get_class(), 'jquery' ), 100000 );
29
+ \add_action( 'admin_footer', array( get_class(), 'css' ), 100000 );
30
+
31
+ }
32
+
33
+ }
34
+
35
+
36
+
37
+ /**
38
+ * Add administration menus
39
+ *
40
+ * @since 0.1
41
+ **/
42
+ public static function add_menu()
43
+ {
44
+
45
+ add_users_page (
46
+ __( 'Export User Data', 'q-report' ),
47
+ __( 'Export User Data', 'q-report' ),
48
+ \apply_filters( 'q/report/admin_capability', 'list_users' ),
49
+ 'q-report',
50
+ array(
51
+ get_class(),
52
+ 'admin_page'
53
+ )
54
+ );
55
+
56
+ }
57
+
58
+
59
+ /**
60
+ * Content of the admin page
61
+ *
62
+ * @since 0.1
63
+ */
64
+ public static function admin_page()
65
+ {
66
+
67
+ // quick security check ##
68
+ if ( ! \current_user_can( \apply_filters( 'q/report/admin_capability', 'list_users' ) ) ) {
69
+
70
+ \wp_die( __( 'You do not have sufficient permissions to access this page.', 'q-report' ) );
71
+
72
+ }
73
+
74
+ // Save settings button was pressed ##
75
+ if (
76
+ isset( $_POST['save_export'] )
77
+ && \check_admin_referer( 'q-report-admin-page', '_wpnonce-q-report-admin-page' )
78
+ ) {
79
+
80
+ // start with an empty variable ##
81
+ $save_export = "";
82
+
83
+ if ( ! empty( $_POST['save_new_export_name'] ) ) {
84
+
85
+ // assign value ##
86
+ $save_export = $_POST['save_new_export_name'];
87
+
88
+ } elseif ( ! empty( $_POST['export_name'] ) ) {
89
+
90
+ $save_export = $_POST['export_name'];
91
+
92
+ }
93
+
94
+ // clean up $save_export ##
95
+ $save_export = \sanitize_text_field( $save_export );
96
+
97
+ // Build array of $options to save and save them ##
98
+ if ( isset( $save_export ) ) {
99
+
100
+ // prepare all array values ##
101
+ $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '' ;
102
+ $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '' ;
103
+ $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '' ;
104
+ $format = isset( $_POST['format'] ) ? $_POST['format'] : '' ;
105
+ $role = isset( $_POST['role'] ) ? $_POST['role'] : '' ;
106
+ $roles = isset( $_POST['roles'] ) ? $_POST['roles'] : '0' ;
107
+ $user_fields = isset( $_POST['user_fields'] ) ? $_POST['user_fields'] : '0' ;
108
+ $groups = isset( $_POST['groups'] ) ? $_POST['groups'] : '0' ;
109
+ $start_date = isset( $_POST['start_date'] ) ? $_POST['start_date'] : '' ;
110
+ $end_date = isset( $_POST['end_date'] ) ? $_POST['end_date'] : '' ;
111
+ $limit_offset = isset( $_POST['limit_offset'] ) ? $_POST['limit_offset'] : '' ;
112
+ $limit_total = isset( $_POST['limit_total'] ) ? $_POST['limit_total'] : '' ;
113
+ $updated_since_date = isset ( $_POST['updated_since_date'] ) ? $_POST['updated_since_date'] : '' ;
114
+ $field_updated_since = isset ( $_POST['bp_field_updated_since'] ) ? $_POST['bp_field_updated_since'] : '';
115
+
116
+ // assign all values to an array ##
117
+ $save_array = array (
118
+ 'usermeta_saved_fields' => $usermeta,
119
+ 'bp_fields_saved_fields' => $bp_fields,
120
+ 'bp_fields_update_time_saved_fields' => $bp_fields_update,
121
+ 'role' => $role,
122
+ 'roles' => $roles,
123
+ 'user_fields' => $user_fields,
124
+ 'groups' => $groups,
125
+ 'start_date' => $start_date,
126
+ 'end_date' => $end_date,
127
+ 'limit_offset' => $limit_offset,
128
+ 'limit_total' => $limit_total,
129
+ 'updated_since_date' => $updated_since_date,
130
+ 'field_updated_since' => $field_updated_since,
131
+ 'format' => $format
132
+ );
133
+
134
+ // store the options, for next load ##
135
+ user::set_user_options( $save_export, $save_array );
136
+
137
+ // Display the settings the user just saved instead of blanking the form ##
138
+ $_POST['load_export'] = 'Load Settings';
139
+ $_POST['export_name'] = $save_export;
140
+
141
+ }
142
+
143
+ }
144
+
145
+ // Load settings button was pressed ( or option saved and $_POST variables hijacked )##
146
+ if (
147
+ isset( $_POST['load_export'] )
148
+ && isset( $_POST['export_name'] )
149
+ && \check_admin_referer( 'q-report-admin-page', '_wpnonce-q-report-admin-page' )
150
+ ) {
151
+
152
+ user::get_user_options_by_export( \sanitize_text_field( $_POST['export_name'] ) );
153
+
154
+ }
155
+
156
+ // Delete settings button was pressed ##
157
+ if (
158
+ isset( $_POST['delete_export'] )
159
+ && isset( $_POST['export_name'] )
160
+ && \check_admin_referer( 'q-report-admin-page', '_wpnonce-q-report-admin-page' )
161
+ ) {
162
+
163
+ user::delete_user_options( \sanitize_text_field( $_POST['export_name'] ) );
164
+
165
+ }
166
+
167
+ ?>
168
+ <div class="wrap">
169
+ <h2><?php \_e( 'Export User Data', 'q-report' ); ?></h2>
170
+ <?php
171
+
172
+ // nothing happening? ##
173
+ if ( isset( $_GET['error'] ) ) {
174
+ echo '<div class="updated"><p><strong>' . \__( 'No users found.', 'q-report' ) . '</strong></p></div>';
175
+ }
176
+
177
+ ?>
178
+ <form method="post" action="" enctype="multipart/form-data">
179
+ <?php \wp_nonce_field( 'q-report-admin-page', '_wpnonce-q-report-admin-page' ); ?>
180
+ <table class="form-table">
181
+ <?php
182
+
183
+ // allow admin to select user meta fields to export ##
184
+ global $wpdb;
185
+
186
+ // filterable SQL ##
187
+ $meta_keys = \apply_filters(
188
+ 'q/report/admin/sql',
189
+ $wpdb->get_results( "SELECT distinct(meta_key) FROM $wpdb->usermeta" )
190
+ );
191
+
192
+ // filterable sort ##
193
+ \apply_filters(
194
+ 'q/report/admin/sort',
195
+ asort( $meta_keys )
196
+ );
197
+
198
+ // get meta_key value from object ##
199
+ $meta_keys = \wp_list_pluck( $meta_keys, 'meta_key' );
200
+
201
+ // allow array to be filtered ##
202
+ $meta_keys_common = \apply_filters( 'q/report/admin/meta_keys_common', [] );
203
+
204
+ // test array ##
205
+ #helper::log( $meta_keys );
206
+ #helper::log( $meta_keys_common );
207
+
208
+ // check if we got anything ? ##
209
+ if ( $meta_keys ) {
210
+
211
+ ?>
212
+ <tr valign="top">
213
+ <th scope="row">
214
+ <label for="q_report_usermeta"><?php \_e( 'User Meta Fields', 'q-report' ); ?></label>
215
+ <p class="filter" style="margin: 10px 0 0;">
216
+ <?php \_e('Filter', 'q-report'); ?>: <a href="#" class="usermeta-all"><?php \_e('All', 'q-report'); ?></a> | <a href="#" class="usermeta-common"><?php \_e('Common', 'q-report'); ?></a>
217
+ </p>
218
+ <p class="filter" style="margin: 10px 0 0;">
219
+ <?php \_e('Select', 'q-report'); ?>: <a href="#" class="select-all"><?php \_e('All', 'q-report'); ?></a> | <a href="#" class="select-none"><?php \_e('None', 'q-report'); ?></a>
220
+ </p>
221
+ </th>
222
+ <td>
223
+ <select multiple="multiple" id="usermeta" name="usermeta[]">
224
+ <?php
225
+
226
+ foreach ( $meta_keys as $key ) {
227
+
228
+ // filter key displayed ##
229
+ $display_key = \apply_filters( 'q/report/admin/display_key', $key );
230
+
231
+ // class ##
232
+ $usermeta_class = 'normal';
233
+
234
+ foreach ( $meta_keys_common as $drop ) {
235
+
236
+ #helper::log( 'Checking: '.$drop );
237
+
238
+ if ( strpos( $key, $drop ) !== false ) {
239
+
240
+ #helper::log( 'Checking: '.$key );
241
+
242
+ // https://wordpress.org/support/topic/bugfix-numbers-in-export-headers?replies=1
243
+ // removed $key = assignment, as not required ##
244
+ if ( ( array_search( $key, $meta_keys ) ) !== false ) {
245
+
246
+ #helper::log( 'Found: '.$key );
247
+
248
+ $usermeta_class = 'common';
249
+
250
+ }
251
+
252
+ }
253
+
254
+ }
255
+
256
+ // print key ##
257
+ echo "<option value='".\esc_attr( $key )."' title='".\esc_attr( $key )."' class='".$usermeta_class."'>$display_key</option>";
258
+
259
+ }
260
+ ?>
261
+ </select>
262
+ <p class="description"><?php
263
+ printf(
264
+ \__( 'Select the user meta keys to export, use the filters to simplify the list.', 'q-report' )
265
+ );
266
+ ?></p>
267
+ </td>
268
+ </tr>
269
+ <?php
270
+
271
+ } // meta_keys found ##
272
+
273
+ ?>
274
+ <?php
275
+
276
+ // buddypress x profile data ##
277
+ if ( $bp_fields = buddypress::get_fields() ) {
278
+
279
+ ?>
280
+ <tr valign="top">
281
+ <th scope="row">
282
+ <label for="q_report_xprofile"><?php \_e( 'BP xProfile Fields', 'q-report' ); ?></label>
283
+ <p class="filter" style="margin: 10px 0 0;">
284
+ <?php \_e('Select', 'q-report'); ?>: <a href="#" class="select-all"><?php \_e('All', 'q-report'); ?></a> | <a href="#" class="select-none"><?php \_e('None', 'q-report'); ?></a>
285
+ </p>
286
+ </th>
287
+ <td>
288
+ <select multiple="multiple" id="bp_fields" name="bp_fields[]">
289
+ <?php
290
+
291
+ foreach ( $bp_fields as $key ) {
292
+
293
+ // print key ##
294
+ echo "<option value='".\esc_attr( $key )."' title='".\esc_attr( $key )."'>$key</option>";
295
+
296
+ }
297
+
298
+ ?>
299
+ </select>
300
+ <p class="description"><?php
301
+ printf(
302
+ \__( 'Select the BuddyPress XProfile keys to export', 'q-report' )
303
+ );
304
+ ?></p>
305
+ </td>
306
+ </tr>
307
+ <?php
308
+
309
+ // allow export of update times ##
310
+
311
+ ?>
312
+ <tr valign="top" class="toggleable">
313
+ <th scope="row">
314
+ <label for="q_report_xprofile"><?php \_e( 'BP xProfile Fields Update Time', 'q-report' ); ?></label>
315
+ <p class="filter" style="margin: 10px 0 0;">
316
+ <?php \_e('Select', 'q-report'); ?>: <a href="#" class="select-all"><?php \_e('All', 'q-report'); ?></a> | <a href="#" class="select-none"><?php _e('None', 'q-report'); ?></a>
317
+ </p>
318
+ </th>
319
+ <td>
320
+ <select multiple="multiple" id="bp_fields_update_time" name="bp_fields_update_time[]">
321
+ <?php
322
+
323
+ foreach ( $bp_fields as $key ) {
324
+
325
+ echo "<option value='".\esc_attr( $key )."' title='".\esc_attr( $key )."'>$key</option>";
326
+
327
+ }
328
+
329
+ ?>
330
+ </select>
331
+ <p class="description"><?php
332
+ printf(
333
+ \__( 'Select the BuddyPress XProfile keys updated dates to export', 'q-report' )
334
+ );
335
+ ?></p>
336
+ </td>
337
+ </tr>
338
+
339
+ <tr valign="top" class="toggleable">
340
+ <th scope="row"><label for="groups"><?php \_e( 'BP User Groups', 'q-report' ); ?></label></th>
341
+ <td>
342
+ <input id='groups' type='checkbox' name='groups' value='1' <?php \checked( isset ( self::$groups ) ? intval ( self::$groups ) : '', 1 ); ?> />
343
+ <p class="description"><?php
344
+ printf(
345
+ \__( 'Include BuddyPress Group Data. <a href="%s" target="_blank">%s</a>', 'q-report' )
346
+ , \esc_html('https://codex.buddypress.org/buddypress-components-and-features/groups/')
347
+ , 'Codex'
348
+ );
349
+ ?></p>
350
+ </td>
351
+ </tr>
352
+ <?php
353
+
354
+ } // BP installed and active ##
355
+
356
+ ?>
357
+ <tr valign="top" class="toggleable">
358
+ <th scope="row"><label for="user_fields"><?php \_e( 'Standard User Fields', 'q-report' ); ?></label></th>
359
+ <td>
360
+ <input id='user_fields' type='checkbox' name='user_fields' value='1' <?php \checked( isset ( self::$user_fields ) ? intval ( self::$user_fields ) : '', 1 ); ?> />
361
+ <p class="description"><?php
362
+
363
+ #self::log( 'user_fields: '.self::$user_fields );
364
+ #echo 'user_fields: '. self::$user_fields;
365
+
366
+ printf(
367
+ \__( 'Include Standard user profile fields, such as user_login. <a href="%s" target="_blank">%s</a>', 'q-report' )
368
+ , \esc_html('https://codex.wordpress.org/Database_Description#Table:_wp_users')
369
+ , 'Codex'
370
+ );
371
+
372
+ ?></p>
373
+ </td>
374
+ </tr>
375
+
376
+ <tr valign="top" class="toggleable">
377
+ <th scope="row"><label for="q_report_users_role"><?php \_e( 'Role', 'q-report' ); ?></label></th>
378
+ <td>
379
+ <select name="role" id="q_report_users_role">
380
+ <?php
381
+
382
+ echo '<option value="">' . \__( 'All Roles', 'q-report' ) . '</option>';
383
+
384
+ global $wp_roles;
385
+
386
+ foreach ( $wp_roles->role_names as $role => $name ) {
387
+
388
+ if ( isset ( self::$role ) && ( self::$role == $role ) ) {
389
+
390
+ echo "\n\t<option selected value='" . \esc_attr( $role ) . "'>$name</option>";
391
+
392
+ } else {
393
+
394
+ echo "\n\t<option value='" . \esc_attr( $role ) . "'>$name</option>";
395
+
396
+ }
397
+ }
398
+
399
+
400
+ ?>
401
+ </select>
402
+ <p class="description"><?php
403
+ printf(
404
+ \__( 'Filter the exported users by a WordPress Role. <a href="%s" target="_blank">%s</a>', 'q-report' )
405
+ , \esc_html('http://codex.wordpress.org/Roles_and_Capabilities')
406
+ , 'Codex'
407
+ );
408
+ ?></p>
409
+ </td>
410
+ </tr>
411
+
412
+ <tr valign="top" class="toggleable">
413
+ <th scope="row"><label for="roles"><?php \_e( 'User Roles', 'q-report' ); ?></label></th>
414
+ <td>
415
+ <input id='roles' type='checkbox' name='roles' value='1' <?php \checked( isset ( self::$roles ) ? intval ( self::$roles ) : '', 1 ); ?> />
416
+ <p class="description"><?php
417
+ printf(
418
+ \__( 'Include all of the users <a href="%s" target="_blank">%s</a>', 'q-report' )
419
+ , \esc_html('http://codex.wordpress.org/Roles_and_Capabilities')
420
+ , 'Roles'
421
+ );
422
+ ?></p>
423
+ </td>
424
+ </tr>
425
+
426
+ <tr valign="top" class="toggleable">
427
+ <th scope="row"><label><?php \_e( 'Registered', 'q-report' ); ?></label></th>
428
+ <td>
429
+ <input type="text" id="q_report_users_start_date" name="start_date" value="<?php echo self::$start_date; ?>" class="start-datepicker" />
430
+ <input type="text" id="q_report_users_end_date" name="end_date" value="<?php echo self::$end_date; ?>" class="end-datepicker" />
431
+ <p class="description"><?php
432
+ printf(
433
+ \__( 'Pick a start and end user registration date to limit the results.', 'q-report' )
434
+ );
435
+ ?></p>
436
+ </td>
437
+ </tr>
438
+
439
+ <tr valign="top" class="toggleable">
440
+ <th scope="row"><label><?php \_e( 'Limit Range', 'q-report' ); ?></label></th>
441
+ <td>
442
+ <input name="limit_offset" type="text" id="q_report_users_limit_offset" value="<?php echo( self::$limit_offset ); ?>" class="regular-text code numeric" style="width: 136px;" placeholder="<?php _e( 'Offset', 'q-report' ); ?>">
443
+ <input name="limit_total" type="text" id="q_report_users_limit_total" value="<?php echo ( self::$limit_total ); ?>" class="regular-text code numeric" style="width: 136px;" placeholder="<?php _e( 'Total', 'q-report' ); ?>">
444
+ <p class="description"><?php
445
+ printf(
446
+ \__( 'Enter an offset start number and a total number of users to export. <a href="%s" target="_blank">%s</a>', 'q-report' )
447
+ , \esc_html('http://codex.wordpress.org/Function_Reference/get_users#Parameters')
448
+ , 'Codex'
449
+ );
450
+ ?></p>
451
+ </td>
452
+ </tr>
453
+ <?php
454
+
455
+ // buddypress x profile data ##
456
+ if ( $bp_fields = buddypress::get_fields() ) {
457
+
458
+ ?>
459
+ <tr valign="top" class="toggleable">
460
+ <th scope="row"><label><?php \_e( 'Updated Since', 'q-report' ); ?></label></th>
461
+ <td>
462
+ <input type="text" id="q_report_updated_since_date" name="updated_since_date" value="<?php echo self::$updated_since_date; ?>" class="updated-datepicker" />
463
+ <select id="bp_field_updated_since" name="bp_field_updated_since">
464
+ <?php
465
+
466
+ foreach ( $bp_fields as $key ) {
467
+
468
+ if ( self::$field_updated_since == $key ) {
469
+
470
+ echo "<option value='".\esc_attr( $key )."' title='".\esc_attr( $key )."' selected>$key</option>";
471
+
472
+ } else {
473
+
474
+ echo "<option value='".\esc_attr( $key )."' title='".\esc_attr( $key )."'>$key</option>";
475
+
476
+ }
477
+
478
+ }
479
+
480
+ ?>
481
+ </select>
482
+
483
+ <p class="description"><?php
484
+ printf(
485
+ \__( 'Limit the results to users who have updated this extended profile field after this date.', 'q-report' )
486
+ );
487
+ ?></p>
488
+ </td>
489
+ </tr>
490
+ <?php
491
+
492
+ } // bp date ##
493
+
494
+ // pull in extra export options from api ##
495
+ if ( $api_fields = \apply_filters( 'q/report/api/admin/fields', [] ) ) {
496
+
497
+ foreach( $api_fields as $field ) {
498
+
499
+ api_admin::render( $field );
500
+
501
+ }
502
+
503
+ }
504
+
505
+ ?>
506
+ <tr valign="top">
507
+ <th scope="row"><label for="q_report_users_format"><?php \_e( 'Format', 'q-report' ); ?></label></th>
508
+ <td>
509
+ <select name="format" id="q_report_users_format">
510
+ <?php
511
+ if ( isset ( self::$format ) && ( self::$format == 'excel' ) ) {
512
+
513
+ echo '<option selected value="excel">' . __( 'Excel', 'q-report' ) . '</option>';
514
+
515
+ } else {
516
+
517
+ echo '<option value="excel">' . __( 'Excel', 'q-report' ) . '</option>';
518
+
519
+ }
520
+
521
+ if ( isset ( self::$format ) && ( self::$format == 'csv' ) ) {
522
+
523
+ echo '<option selected value="csv">' . __( 'CSV', 'q-report' ) . '</option>';
524
+
525
+ } else {
526
+
527
+ echo '<option value="csv">' . __( 'CSV', 'q-report' ) . '</option>';
528
+
529
+ }
530
+ ?>
531
+ </select>
532
+ <p class="description"><?php
533
+ printf(
534
+ \__( 'Select the format for the export file.', 'q-report' )
535
+ );
536
+ ?></p>
537
+ </td>
538
+ </tr>
539
+
540
+ <tr valign="top" class="remember">
541
+ <th scope="row"><label for="q_report_save_options"><?php \_e( 'Stored Options', 'q-report' ); ?></label></th>
542
+ <td>
543
+
544
+ <div class="row">
545
+ <input type="text" class="regular-text" name="save_new_export_name" id="q_report_save_options_new_export" placeholder="<?php \_e( 'Export Name', 'q-report' ); ?>" value="<?php echo isset( $_POST['export_name'] ) ? \sanitize_text_field( $_POST['export_name'] ) : '' ; ?>">
546
+ <input type="submit" id="save_export" class="button-primary" name="save_export" value="<?php \_e( 'Save', 'q-report' ); ?>" />
547
+ </div>
548
+ <?php
549
+
550
+ // check if the user has any saved exports ##
551
+ if ( user::get_user_options() ) {
552
+
553
+ ?>
554
+ <div class="row">
555
+ <select name="export_name" id="q_report_save_options" class="regular-text">
556
+ <?php
557
+
558
+ // loop over each saved export ##
559
+ foreach( user::get_user_options() as $export ) {
560
+
561
+ // select Loaded export name, if selected ##
562
+ if (
563
+ isset( $_POST['load_export'] )
564
+ && isset( $_POST['export_name'] )
565
+ && ( $_POST['export_name'] == $export )
566
+ ) {
567
+
568
+ echo "<option selected value='$export'>".$export."</option>";
569
+
570
+ // just list previous export name ##
571
+ } else {
572
+
573
+ echo "<option value='$export'>".$export."</option>";
574
+
575
+ }
576
+
577
+ }
578
+
579
+ ?>
580
+ </select>
581
+
582
+ <input type="submit" id="load_export" class="button-primary" name="load_export" value="<?php _e( 'Load', 'q-report' ); ?>" />
583
+ <input type="submit" id="delete_export" class="button-primary" name="delete_export" value="<?php _e( 'Delete', 'q-report' ); ?>" />
584
+ <?php
585
+
586
+ }
587
+
588
+ ?>
589
+ </div>
590
+ <p class="description"><?php \_e( 'Save, load or delete your stored export options.', 'q-report' ); ?></p>
591
+
592
+ </td>
593
+ </tr>
594
+
595
+ <tr valign="top">
596
+ <th scope="row">
597
+ <label for="q_report_xprofile"><?php \_e( 'Advanced Options', 'q-report' ); ?></label>
598
+ </th>
599
+ <td>
600
+ <div class="toggle">
601
+ <a href="#"><?php \_e( 'Show', 'q-report' ); ?></a>
602
+ </div>
603
+ </td>
604
+ </tr>
605
+
606
+ </table>
607
+ <p class="submit">
608
+ <input type="hidden" name="_wp_http_referer" value="<?php echo \esc_url( $_SERVER['REQUEST_URI'] ); ?>" />
609
+ <input type="submit" class="button-primary" value="<?php \_e( 'Run Export', 'q-report' ); ?>" />
610
+ </p>
611
+ </form>
612
+ </div>
613
+
614
+ <?php
615
+ }
616
+
617
+
618
+
619
+ /**
620
+ * style and interaction
621
+ */
622
+ public static function admin_enqueue_scripts( $hook )
623
+ {
624
+
625
+ // load the scripts on only the plugin admin page ##
626
+ if (
627
+ ! isset( $_GET['page'] )
628
+ || $_GET['page'] != 'q-report'
629
+
630
+ ) {
631
+
632
+ return false;
633
+
634
+ }
635
+
636
+ \wp_register_style( 'q-report-css', \plugins_url( 'css/q-report.css' ,__FILE__ ), '', self::version );
637
+ \wp_enqueue_style( 'q-report-css' );
638
+ \wp_enqueue_script( 'q_report_multi_select_js', \plugins_url( 'javascript/jquery.multi-select.js', __FILE__ ), array('jquery'), '0.9.8', false );
639
+
640
+ // add script ##
641
+ \wp_enqueue_script('jquery-ui-datepicker');
642
+
643
+ // add style ##
644
+ \wp_enqueue_style( 'jquery-ui-datepicker' );
645
+ \wp_enqueue_style('jquery-ui-css', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
646
+
647
+ }
648
+
649
+
650
+
651
+
652
+ /**
653
+ * Inline jQuery
654
+ * @since 0.8.2
655
+ */
656
+ public static function jquery()
657
+ {
658
+
659
+ // load the scripts on only the plugin admin page
660
+ if (
661
+ ! isset( $_GET['page'] )
662
+ || $_GET['page'] != 'q-report'
663
+ ) {
664
+
665
+ return false;
666
+
667
+ }
668
+
669
+ ?>
670
+ <script>
671
+
672
+ // lazy load in some jQuery validation ##
673
+ jQuery(document).ready(function($) {
674
+
675
+ // build super multiselect ##
676
+ jQuery('#usermeta, #bp_fields, #bp_fields_update_time').multiSelect();
677
+
678
+ // Select any fields from saved settings ##
679
+ jQuery('#usermeta').multiSelect('select',([<?php echo( core::quote_array( self::$usermeta_saved_fields ) ); ?>]));
680
+ jQuery('#bp_fields').multiSelect('select',([<?php echo( core::quote_array( self::$bp_fields_saved_fields ) ); ?>]));
681
+ jQuery('#bp_fields_update_time').multiSelect('select',([<?php echo( core::quote_array( self::$bp_fields_update_time_saved_fields ) ); ?>]));
682
+
683
+ // show only common ##
684
+ jQuery('.usermeta-common').click(function(e){
685
+ // console.log( 'Common..' );
686
+ e.preventDefault();
687
+ jQuery('#ms-usermeta .ms-selectable li.normal').hide();
688
+ });
689
+
690
+ // show all ##
691
+ jQuery('.usermeta-all').click(function(e){
692
+ e.preventDefault();
693
+ jQuery('#ms-usermeta .ms-selectable li').show();
694
+ });
695
+
696
+ // select all ##
697
+ jQuery('.select-all').click(function(e){
698
+ e.preventDefault();
699
+ jQuery( jQuery(this).parent().parent().parent().find( 'select' ) ).multiSelect( 'select_all' );
700
+ });
701
+
702
+ // select none ##
703
+ jQuery('.select-none').click(function(e){
704
+ e.preventDefault();
705
+ jQuery( jQuery(this).parent().parent().parent().find( 'select' ) ).multiSelect( 'deselect_all' );
706
+ });
707
+
708
+
709
+ // validate number inputs ##
710
+ $("input.numeric").blur(function() {
711
+
712
+ //console.log("you entered "+ $(this).val());
713
+
714
+ if ( $(this).val() && ! $.isNumeric( $(this).val() ) ) {
715
+
716
+ //console.log("this IS NOT a number");
717
+ $(this).css({ 'background': 'red', 'color': 'white' }); // highlight error ##
718
+ $("p.submit .button-primary").attr('disabled','disabled'); // disable submit ##
719
+
720
+ } else {
721
+
722
+ $(this).css({ 'background': 'white', 'color': '#333' }); // remove error highlighting ##
723
+ $("p.submit .button-primary").removeAttr('disabled'); // enable submit ##
724
+
725
+ }
726
+
727
+ });
728
+
729
+ // toggle advanced options ##
730
+ jQuery(".toggle a").click( function(e) {
731
+ e.preventDefault();
732
+ $toggleable = jQuery("tr.toggleable");
733
+ $toggleable.toggle();
734
+ if ( $toggleable.is(":visible") ) {
735
+ jQuery(this).text("<?php _e( 'Hide', 'q-report' ); ?>");
736
+ } else {
737
+ jQuery(this).text("<?php _e( 'Show', 'q-report' ); ?>");
738
+ }
739
+ });
740
+
741
+ // validate save button ##
742
+ jQuery("#save_export").click( function(e) {
743
+
744
+ // grab the value of the input ##
745
+ var q_report_save_options_new_export = jQuery('#q_report_save_options_new_export').val();
746
+
747
+ if ( ! q_report_save_options_new_export || q_report_save_options_new_export == '' ) {
748
+
749
+ e.preventDefault(); // stop things here ##
750
+ jQuery('#q_report_save_options_new_export').addClass("error");
751
+
752
+ }
753
+
754
+ });
755
+
756
+ // remove validation on focus ##
757
+ jQuery("body").on( 'focus', '#q_report_save_options_new_export', function(e) {
758
+
759
+ jQuery(this).removeClass("error");
760
+
761
+ });
762
+
763
+ <?php
764
+
765
+ // method returns an object with "first" & "last" keys ##
766
+ $dates = core::get_user_registered_dates();
767
+
768
+ // get date format from WP settings #
769
+ $date_format = 'yy-mm-dd' ; // get_option('date_format') ? get_option('date_format') : 'yy-mm-dd' ;
770
+ $start_of_week = \get_option('start_of_week') ? \get_option('start_of_week') : 'yy-mm-dd' ;
771
+ #self::log( 'Date format: '.$date_format );
772
+
773
+ ?>
774
+
775
+ // start date picker ##
776
+ jQuery('.start-datepicker').datepicker( {
777
+ dateFormat : '<?php echo $date_format; ?>',
778
+ minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
779
+ maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>',
780
+ firstDay : '<?php echo $start_of_week; ?>'
781
+ } );
782
+
783
+ // end date picker ##
784
+ jQuery('.end-datepicker').datepicker( {
785
+ dateFormat : '<?php echo $date_format; ?>',
786
+ minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
787
+ maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>',
788
+ firstDay : '<?php echo $start_of_week; ?>'
789
+ } );
790
+
791
+ // end date picker ##
792
+ // might want to set minDate to something else, but not sure
793
+ // what would be best for everyone
794
+ jQuery('.updated-datepicker').datepicker( {
795
+ dateFormat : '<?php echo $date_format; ?>',
796
+ minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
797
+ maxDate : '0',
798
+ firstDay : '<?php echo $start_of_week; ?>'
799
+ } );
800
+
801
+ });
802
+
803
+ </script>
804
+ <?php
805
+
806
+ }
807
+
808
+
809
+
810
+
811
+ /**
812
+ * Inline CSS
813
+ *
814
+ * @since 0.8.2
815
+ */
816
+ public static function css()
817
+ {
818
+
819
+ // load the scripts on only the plugin admin page
820
+ if (
821
+ ! isset( $_GET['page'] )
822
+ || $_GET['page'] != 'q-report'
823
+ ) {
824
+
825
+ return false;
826
+
827
+ }
828
+
829
+ ?>
830
+ <style>
831
+ .toggleable { display: none; }
832
+ .hidden { display: none; }
833
+ </style>
834
+ <?php
835
+
836
+ }
837
+
838
+ }
library/admin/css/image/switch.png ADDED
Binary file
library/admin/css/q-report.css ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ export-user-data.css
3
+
4
+ @since 0.9.6
5
+ */
6
+
7
+
8
+ /* general layout */
9
+
10
+ .form-table tr.remember div.row:first-child {
11
+ margin-bottom: 10px;
12
+ }
13
+
14
+ .form-table tr.remember input.button-primary {
15
+ margin-left: 5px;
16
+ }
17
+
18
+ .form-table tr.remember select {
19
+ width: 25em;
20
+ }
21
+
22
+ input.error {
23
+ background: #D54E21;
24
+ color: #fff;
25
+ border: 1px solid #CCC;
26
+ }
27
+
28
+ th p.filter {
29
+ width: 100%;
30
+ }
31
+
32
+ /* form inputs */
33
+
34
+
35
+ /* multiselects */
36
+
37
+ .ms-container{
38
+ background: transparent url('image/switch.png') no-repeat 50% 50%;
39
+ /* width: 600px; */
40
+ }
41
+
42
+ .ms-container:after{
43
+ content: ".";
44
+ display: block;
45
+ height: 0;
46
+ line-height: 0;
47
+ font-size: 0;
48
+ clear: both;
49
+ min-height: 0;
50
+ visibility: hidden;
51
+ }
52
+
53
+ .ms-container .ms-selectable, .ms-container .ms-selection{
54
+ background: #fff;
55
+ color: #555555;
56
+ float: left;
57
+ width: 45%;
58
+ }
59
+
60
+ .ms-container .ms-list{
61
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
62
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
63
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
64
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
65
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
66
+ -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
67
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
68
+ transition: border linear 0.2s, box-shadow linear 0.2s;
69
+ border: 1px solid #ccc;
70
+ -webkit-border-radius: 3px;
71
+ -moz-border-radius: 3px;
72
+ border-radius: 3px;
73
+ position: relative;
74
+ height: 134px;
75
+ padding: 0;
76
+ overflow-y: auto;
77
+ overflow-x: hidden;
78
+ }
79
+
80
+ .ms-container .ms-selectable{
81
+ margin-right: 10%;
82
+ }
83
+
84
+ .ms-container .ms-list.ms-focus{
85
+ border-color: rgba(82, 168, 236, 0.8);
86
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
87
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
88
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
89
+ outline: 0;
90
+ outline: thin dotted \9;
91
+ }
92
+
93
+ .ms-container ul{
94
+ margin: 0;
95
+ list-style-type: none;
96
+ padding: 0;
97
+ }
98
+
99
+ .ms-container .ms-optgroup-container{
100
+ width: 100%;
101
+ }
102
+
103
+ .ms-container .ms-optgroup-label{
104
+ margin: 0;
105
+ padding: 5px 0px 0px 5px;
106
+ cursor: pointer;
107
+ color: #999;
108
+ }
109
+
110
+ .ms-container .ms-selectable li.ms-elem-selectable,
111
+ .ms-container .ms-selection li.ms-elem-selection{
112
+ border-bottom: 1px #eee solid;
113
+ padding: 4px 10px;
114
+ color: #555;
115
+ font-size: 14px;
116
+ margin-bottom: 0px;
117
+ }
118
+
119
+ .ms-container .ms-selectable li.ms-hover,
120
+ .ms-container .ms-selection li.ms-hover{
121
+ cursor: pointer;
122
+ color: #fff;
123
+ text-decoration: none;
124
+ background-color: #08c;
125
+ margin-bottom: 0px;
126
+ }
127
+
128
+ .ms-container .ms-selectable li.disabled,
129
+ .ms-container .ms-selection li.disabled{
130
+ background-color: #eee;
131
+ color: #aaa;
132
+ cursor: text;
133
+ margin-bottom: 0px;
134
+ }
library/admin/javascript/jquery.multi-select.js ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * MultiSelect v0.9.8
3
+ * Copyright (c) 2012 Louis Cuny
4
+ *
5
+ * This program is free software. It comes without any warranty, to
6
+ * the extent permitted by applicable law. You can redistribute it
7
+ * and/or modify it under the terms of the Do What The Fuck You Want
8
+ * To Public License, Version 2, as published by Sam Hocevar. See
9
+ * http://sam.zoy.org/wtfpl/COPYING for more details.
10
+ */
11
+
12
+ !function ($) {
13
+
14
+ "use strict";
15
+
16
+
17
+ /* MULTISELECT CLASS DEFINITION
18
+ * ====================== */
19
+
20
+ var MultiSelect = function (element, options) {
21
+ this.options = options;
22
+ this.$element = $(element);
23
+
24
+ this.$container = $('<div/>', { 'class': "ms-container" });
25
+ this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });
26
+ this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });
27
+ this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
28
+ this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
29
+ this.scrollTo = 0;
30
+ this.sanitizeRegexp = new RegExp("\\W+", 'gi');
31
+ this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';
32
+ };
33
+
34
+ MultiSelect.prototype = {
35
+ constructor: MultiSelect,
36
+
37
+ init: function(){
38
+ var that = this,
39
+ ms = this.$element;
40
+
41
+ if (ms.next('.ms-container').length === 0){
42
+ ms.css({ position: 'absolute', left: '-9999px' });
43
+ ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
44
+ this.$container.attr('id', 'ms-'+ms.attr('id'));
45
+
46
+ ms.find('option').each(function(){
47
+ that.generateLisFromOption(this);
48
+ });
49
+
50
+ this.$selectionUl.find('.ms-optgroup-label').hide();
51
+
52
+ if (that.options.selectableHeader){
53
+ that.$selectableContainer.append(that.options.selectableHeader);
54
+ }
55
+ that.$selectableContainer.append(that.$selectableUl);
56
+ if (that.options.selectableFooter){
57
+ that.$selectableContainer.append(that.options.selectableFooter);
58
+ }
59
+
60
+ if (that.options.selectionHeader){
61
+ that.$selectionContainer.append(that.options.selectionHeader);
62
+ }
63
+ that.$selectionContainer.append(that.$selectionUl);
64
+ if (that.options.selectionFooter){
65
+ that.$selectionContainer.append(that.options.selectionFooter);
66
+ }
67
+
68
+ that.$container.append(that.$selectableContainer);
69
+ that.$container.append(that.$selectionContainer);
70
+ ms.after(that.$container);
71
+
72
+ that.activeMouse(that.$selectableUl);
73
+ that.activeKeyboard(that.$selectableUl);
74
+
75
+ var action = that.options.dblClick ? 'dblclick' : 'click';
76
+
77
+ that.$selectableUl.on(action, '.ms-elem-selectable', function(){
78
+ that.select($(this).data('ms-value'));
79
+ });
80
+ that.$selectionUl.on(action, '.ms-elem-selection', function(){
81
+ that.deselect($(this).data('ms-value'));
82
+ });
83
+
84
+ that.activeMouse(that.$selectionUl);
85
+ that.activeKeyboard(that.$selectionUl);
86
+
87
+ ms.on('focus', function(){
88
+ that.$selectableUl.focus();
89
+ })
90
+ }
91
+
92
+ var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();
93
+ that.select(selectedValues, 'init');
94
+
95
+ if (typeof that.options.afterInit === 'function') {
96
+ that.options.afterInit.call(this, this.$container);
97
+ }
98
+ },
99
+
100
+ 'generateLisFromOption' : function(option){
101
+ var that = this,
102
+ ms = that.$element,
103
+ attributes = "",
104
+ $option = $(option);
105
+
106
+ for (var cpt = 0; cpt < option.attributes.length; cpt++){
107
+ var attr = option.attributes[cpt];
108
+
109
+ if(attr.name !== 'value'){
110
+ attributes += attr.name+'="'+attr.value+'" ';
111
+ }
112
+ }
113
+ var selectableLi = $('<li '+attributes+'><span>'+$option.text()+'</span></li>'),
114
+ selectedLi = selectableLi.clone(),
115
+ value = $option.val(),
116
+ elementId = that.sanitize(value, that.sanitizeRegexp);
117
+
118
+ selectableLi
119
+ .data('ms-value', value)
120
+ .addClass('ms-elem-selectable')
121
+ .attr('id', elementId+'-selectable');
122
+
123
+ selectedLi
124
+ .data('ms-value', value)
125
+ .addClass('ms-elem-selection')
126
+ .attr('id', elementId+'-selection')
127
+ .hide();
128
+
129
+ if ($option.prop('disabled') || ms.prop('disabled')){
130
+ selectedLi.addClass(that.options.disabledClass);
131
+ selectableLi.addClass(that.options.disabledClass);
132
+ }
133
+
134
+ var $optgroup = $option.parent('optgroup');
135
+
136
+ if ($optgroup.length > 0){
137
+ var optgroupLabel = $optgroup.attr('label'),
138
+ optgroupId = that.sanitize(optgroupLabel, that.sanitizeRegexp),
139
+ $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
140
+ $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
141
+
142
+ if ($selectableOptgroup.length === 0){
143
+ var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',
144
+ optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';
145
+
146
+ $selectableOptgroup = $(optgroupContainerTpl);
147
+ $selectionOptgroup = $(optgroupContainerTpl);
148
+ $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);
149
+ $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);
150
+ $selectableOptgroup.append($(optgroupTpl));
151
+ $selectionOptgroup.append($(optgroupTpl));
152
+ if (that.options.selectableOptgroup){
153
+ $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){
154
+ var values = $optgroup.children(':not(:selected)').map(function(){ return $(this).val() }).get();
155
+ that.select(values);
156
+ });
157
+ $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){
158
+ var values = $optgroup.children(':selected').map(function(){ return $(this).val() }).get();
159
+ that.deselect(values);
160
+ });
161
+ }
162
+ that.$selectableUl.append($selectableOptgroup);
163
+ that.$selectionUl.append($selectionOptgroup);
164
+ }
165
+ $selectableOptgroup.children().append(selectableLi);
166
+ $selectionOptgroup.children().append(selectedLi);
167
+ } else {
168
+ that.$selectableUl.append(selectableLi);
169
+ that.$selectionUl.append(selectedLi);
170
+ }
171
+ },
172
+
173
+ 'activeKeyboard' : function($list){
174
+ var that = this;
175
+
176
+ $list.on('focus', function(){
177
+ $(this).addClass('ms-focus');
178
+ })
179
+ .on('blur', function(){
180
+ $(this).removeClass('ms-focus');
181
+ })
182
+ .on('keydown', function(e){
183
+ switch (e.which) {
184
+ case 40:
185
+ case 38:
186
+ e.preventDefault();
187
+ e.stopPropagation();
188
+ that.moveHighlight($(this), (e.which === 38) ? -1 : 1);
189
+ return;
190
+ case 32:
191
+ e.preventDefault();
192
+ e.stopPropagation();
193
+ that.selectHighlighted($list);
194
+ return;
195
+ case 37:
196
+ case 39:
197
+ e.preventDefault();
198
+ e.stopPropagation();
199
+ that.switchList($list);
200
+ return;
201
+ }
202
+ });
203
+ },
204
+
205
+ 'moveHighlight': function($list, direction){
206
+ var $elems = $list.find(this.elemsSelector),
207
+ $currElem = $elems.filter('.ms-hover'),
208
+ $nextElem = null,
209
+ elemHeight = $elems.first().outerHeight(),
210
+ containerHeight = $list.height(),
211
+ containerSelector = '#'+this.$container.prop('id');
212
+
213
+ // Deactive mouseenter event when move is active
214
+ // It fixes a bug when mouse is over the list
215
+ $elems.off('mouseenter');
216
+
217
+ $elems.removeClass('ms-hover');
218
+ if (direction === 1){ // DOWN
219
+
220
+ $nextElem = $currElem.nextAll(this.elemsSelector).first();
221
+ if ($nextElem.length === 0){
222
+ var $optgroupUl = $currElem.parent();
223
+
224
+ if ($optgroupUl.hasClass('ms-optgroup')){
225
+ var $optgroupLi = $optgroupUl.parent(),
226
+ $nextOptgroupLi = $optgroupLi.next(':visible');
227
+
228
+ if ($nextOptgroupLi.length > 0){
229
+ $nextElem = $nextOptgroupLi.find(this.elemsSelector).first();
230
+ } else {
231
+ $nextElem = $elems.first();
232
+ }
233
+ } else {
234
+ $nextElem = $elems.first();
235
+ }
236
+ }
237
+ } else if (direction === -1){ // UP
238
+
239
+ $nextElem = $currElem.prevAll(this.elemsSelector).first();
240
+ if ($nextElem.length === 0){
241
+ var $optgroupUl = $currElem.parent();
242
+
243
+ if ($optgroupUl.hasClass('ms-optgroup')){
244
+ var $optgroupLi = $optgroupUl.parent(),
245
+ $prevOptgroupLi = $optgroupLi.prev(':visible');
246
+
247
+ if ($prevOptgroupLi.length > 0){
248
+ $nextElem = $prevOptgroupLi.find(this.elemsSelector).last();
249
+ } else {
250
+ $nextElem = $elems.last();
251
+ }
252
+ } else {
253
+ $nextElem = $elems.last();
254
+ }
255
+ }
256
+ }
257
+ if ($nextElem.length > 0){
258
+ $nextElem.addClass('ms-hover');
259
+ var scrollTo = $list.scrollTop() + $nextElem.position().top -
260
+ containerHeight / 2 + elemHeight / 2;
261
+
262
+ $list.scrollTop(scrollTo);
263
+ }
264
+ },
265
+
266
+ 'selectHighlighted' : function($list){
267
+ var $elems = $list.find(this.elemsSelector),
268
+ $highlightedElem = $elems.filter('.ms-hover').first();
269
+
270
+ if ($highlightedElem.length > 0){
271
+ if ($list.parent().hasClass('ms-selectable')){
272
+ this.select($highlightedElem.data('ms-value'));
273
+ } else {
274
+ this.deselect($highlightedElem.data('ms-value'));
275
+ }
276
+ $elems.removeClass('ms-hover');
277
+ }
278
+ },
279
+
280
+ 'switchList' : function($list){
281
+ $list.blur();
282
+ if ($list.parent().hasClass('ms-selectable')){
283
+ this.$selectionUl.focus();
284
+ } else {
285
+ this.$selectableUl.focus();
286
+ }
287
+ },
288
+
289
+ 'activeMouse' : function($list){
290
+ var that = this;
291
+
292
+ $list.on('mousemove', function(){
293
+ var elems = $list.find(that.elemsSelector);
294
+
295
+ elems.on('mouseenter', function(){
296
+ elems.removeClass('ms-hover');
297
+ $(this).addClass('ms-hover');
298
+ });
299
+ });
300
+ },
301
+
302
+ 'refresh' : function() {
303
+ this.destroy();
304
+ this.$element.multiSelect(this.options);
305
+ },
306
+
307
+ 'destroy' : function(){
308
+ $("#ms-"+this.$element.attr("id")).remove();
309
+ this.$element.removeData('multiselect');
310
+ },
311
+
312
+ 'select' : function(value, method){
313
+ if (typeof value === 'string'){ value = [value]; }
314
+
315
+ var that = this,
316
+ ms = this.$element,
317
+ msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),
318
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
319
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
320
+ options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
321
+
322
+ if (selectables.length > 0){
323
+ selectables.addClass('ms-selected').hide();
324
+ selections.addClass('ms-selected').show();
325
+ options.prop('selected', true);
326
+
327
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
328
+ if (selectableOptgroups.length > 0){
329
+ selectableOptgroups.each(function(){
330
+ var selectablesLi = $(this).find('.ms-elem-selectable');
331
+ if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){
332
+ $(this).find('.ms-optgroup-label').hide();
333
+ }
334
+ });
335
+
336
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
337
+ selectionOptgroups.each(function(){
338
+ var selectionsLi = $(this).find('.ms-elem-selection');
339
+ if (selectionsLi.filter('.ms-selected').length > 0){
340
+ $(this).find('.ms-optgroup-label').show();
341
+ }
342
+ });
343
+ } else {
344
+ if (that.options.keepOrder){
345
+ var selectionLiLast = that.$selectionUl.find('.ms-selected');
346
+ if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {
347
+ selections.insertAfter(selectionLiLast.last());
348
+ }
349
+ }
350
+ }
351
+ if (method !== 'init'){
352
+ ms.trigger('change');
353
+ if (typeof that.options.afterSelect === 'function') {
354
+ that.options.afterSelect.call(this, value);
355
+ }
356
+ }
357
+ }
358
+ },
359
+
360
+ 'deselect' : function(value){
361
+ if (typeof value === 'string'){ value = [value]; }
362
+
363
+ var that = this,
364
+ ms = this.$element,
365
+ msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),
366
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
367
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected'),
368
+ options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
369
+
370
+ if (selections.length > 0){
371
+ selectables.removeClass('ms-selected').show();
372
+ selections.removeClass('ms-selected').hide();
373
+ options.prop('selected', false);
374
+
375
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
376
+ if (selectableOptgroups.length > 0){
377
+ selectableOptgroups.each(function(){
378
+ var selectablesLi = $(this).find('.ms-elem-selectable');
379
+ if (selectablesLi.filter(':not(.ms-selected)').length > 0){
380
+ $(this).find('.ms-optgroup-label').show();
381
+ }
382
+ });
383
+
384
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
385
+ selectionOptgroups.each(function(){
386
+ var selectionsLi = $(this).find('.ms-elem-selection');
387
+ if (selectionsLi.filter('.ms-selected').length === 0){
388
+ $(this).find('.ms-optgroup-label').hide();
389
+ }
390
+ });
391
+ }
392
+ ms.trigger('change');
393
+ if (typeof that.options.afterDeselect === 'function') {
394
+ that.options.afterDeselect.call(this, value);
395
+ }
396
+ }
397
+ },
398
+
399
+ 'select_all' : function(){
400
+ var ms = this.$element,
401
+ values = ms.val();
402
+
403
+ ms.find('option:not(":disabled")').prop('selected', true);
404
+ this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();
405
+ this.$selectionUl.find('.ms-optgroup-label').show();
406
+ this.$selectableUl.find('.ms-optgroup-label').hide();
407
+ this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();
408
+ this.$selectionUl.focus();
409
+ ms.trigger('change');
410
+ if (typeof this.options.afterSelect === 'function') {
411
+ var selectedValues = $.grep(ms.val(), function(item){
412
+ return $.inArray(item, values) < 0;
413
+ });
414
+ this.options.afterSelect.call(this, selectedValues);
415
+ }
416
+ },
417
+
418
+ 'deselect_all' : function(){
419
+ var ms = this.$element,
420
+ values = ms.val();
421
+
422
+ ms.find('option').prop('selected', false);
423
+ this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
424
+ this.$selectionUl.find('.ms-optgroup-label').hide();
425
+ this.$selectableUl.find('.ms-optgroup-label').show();
426
+ this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
427
+ this.$selectableUl.focus();
428
+ ms.trigger('change');
429
+ if (typeof this.options.afterDeselect === 'function') {
430
+ this.options.afterDeselect.call(this, values);
431
+ }
432
+ },
433
+
434
+ sanitize: function(value, reg){
435
+ return(value.replace(reg, '_'));
436
+ }
437
+ };
438
+
439
+ /* MULTISELECT PLUGIN DEFINITION
440
+ * ======================= */
441
+
442
+ $.fn.multiSelect = function () {
443
+ var option = arguments[0],
444
+ args = arguments;
445
+
446
+ return this.each(function () {
447
+ var $this = $(this),
448
+ data = $this.data('multiselect'),
449
+ options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);
450
+
451
+ if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }
452
+
453
+ if (typeof option === 'string'){
454
+ data[option](args[1]);
455
+ } else {
456
+ data.init();
457
+ }
458
+ });
459
+ };
460
+
461
+ $.fn.multiSelect.defaults = {
462
+ selectableOptgroup: false,
463
+ disabledClass : 'disabled',
464
+ dblClick : false,
465
+ keepOrder: false
466
+ };
467
+
468
+ $.fn.multiSelect.Constructor = MultiSelect;
469
+
470
+ }(window.jQuery);
library/api/admin.php ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\api;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ #\q\report\api\admin::run();
10
+
11
+ class admin extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // load standard fields ##
19
+ #\add_action( 'admin_init', array( get_class(), 'load' ), 1 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+
27
+ /**
28
+ * Render admin fields
29
+ *
30
+ * @since 2.0.0.
31
+ * @return HTML
32
+ */
33
+ public static function render( $array = null )
34
+ {
35
+
36
+ // check if we have any fields to show ##
37
+ if (
38
+ is_null( $array )
39
+ || ! is_array( $array )
40
+ ) {
41
+
42
+ #helper::log( 'No fields found' );
43
+
44
+ return false;
45
+
46
+ }
47
+
48
+ #helper::log( $array );
49
+
50
+ // check that we have all required arrays ##
51
+ if (
52
+ ! $array['title'] // string ##
53
+ || ! $array['label'] // lowercase string ##
54
+ || ! $array['type']
55
+ #|| ! $array['description']
56
+ ) {
57
+
58
+ #helper::log( 'Missing data' );
59
+
60
+ return false;
61
+
62
+ }
63
+
64
+ // is this toggleable ? ##
65
+ $toggleable = false === $array['title'] ? 'standard' : 'toggleable' ;
66
+
67
+ // keep labels formatted nicely ##
68
+ $array['label'] = \sanitize_key( $array['label'] );
69
+
70
+ #helper::log( $array['options'] );
71
+
72
+ // build out options ##
73
+ if ( ! self::has_options( $array ) ) {
74
+
75
+ #helper::log( 'Missing options for: '.$array['label'] );
76
+
77
+ return false;
78
+
79
+ }
80
+
81
+ ?>
82
+ <tr valign="top" class="<?php echo $toggleable; ?>">
83
+ <th scope="row"><label for="q_report_<?php echo $array['label']; ?>"><?php echo $array['title']; ?></label></th>
84
+ <td>
85
+ <?php
86
+
87
+ // options ##
88
+ self::build_options( $array );
89
+
90
+ // do we have a description ? ##
91
+ if ( isset( $array['description'] ) ) {
92
+
93
+ ?>
94
+ <p class="description"><?php echo $array['description']; ?></p>
95
+ <?php
96
+
97
+ }
98
+
99
+ ?>
100
+ </td>
101
+ </tr>
102
+ <?php
103
+
104
+ }
105
+
106
+
107
+ public static function has_options( $array = null )
108
+ {
109
+
110
+ if (
111
+ is_null( $array )
112
+ || ! is_array( $array )
113
+ || ! isset( $array['options'] )
114
+ || ! isset( $array['label'] )
115
+ || ! is_array( $array['options'] )
116
+ || ! isset( $array['options_ID'] )
117
+ || ! isset( $array['options_title'] )
118
+ || ! isset( $array['label_select'] )
119
+ ) {
120
+
121
+ return false;
122
+
123
+ }
124
+
125
+ // crude ##
126
+ return true;
127
+
128
+ }
129
+
130
+
131
+
132
+ public static function build_options( $array = null )
133
+ {
134
+
135
+ if (
136
+ is_null( $array )
137
+ || ! is_array( $array )
138
+ || ! isset( $array['type'] )
139
+ ) {
140
+
141
+ #helper::log( 'Error building options for: '.$array['label'] );
142
+
143
+ return false;
144
+
145
+ }
146
+
147
+ // start empty ##
148
+ $return = false;
149
+
150
+ switch ( $array['type'] ) {
151
+
152
+ case ( 'select' ) :
153
+
154
+ $return = self::field_select( $array );
155
+
156
+ break ;
157
+
158
+ }
159
+
160
+ // kick it back ##
161
+ return $return;
162
+
163
+ }
164
+
165
+
166
+
167
+ public static function field_select( $array = null )
168
+ {
169
+
170
+ if (
171
+ is_null( $array )
172
+ || ! is_array( $array )
173
+ || ! isset( $array['options'] )
174
+ || ! isset( $array['label'] )
175
+ || ! is_array( $array['options'] )
176
+ || ! isset( $array['options_ID'] )
177
+ || ! isset( $array['options_title'] )
178
+ || ! isset( $array['label_select'] )
179
+ ) {
180
+
181
+ #helper::log( 'Error building select options for: '.$array['label'] );
182
+
183
+ return false;
184
+
185
+ }
186
+
187
+ #helper::log( 'Building select options for: '.$array['label'] );
188
+
189
+ // is this a multiselect ? ##
190
+ $multiselect = isset( $array['multiselect'] ) ? ' multiple="multiple"' : '' ;
191
+
192
+ ?>
193
+ <select <?php echo $multiselect; ?> name="<?php echo $array['label']; ?>" id="q_report_<?php echo $array['label']; ?>">
194
+ <?php
195
+
196
+ // label ##
197
+ echo '<option value="">'.$array['label_select'].'</option>';
198
+
199
+ // loop over all options ##
200
+ foreach ( $array['options'] as $item ) {
201
+
202
+ // id ##
203
+ $id = $item->{$array['options_ID']}; // ID
204
+
205
+ // title
206
+ $title = $item->{$array['options_title']}; // post_title ##
207
+
208
+ // check if option built ##
209
+ if (
210
+ ! $id
211
+ || ! $title
212
+ ) {
213
+
214
+ continue;
215
+
216
+ }
217
+
218
+ ?>
219
+ <option value='<?php echo \esc_attr( $id ); ?>'><?php echo $title; ?></option>
220
+ <?php
221
+
222
+ }
223
+
224
+ ?>
225
+ </select>
226
+ <?php
227
+
228
+ }
229
+
230
+
231
+ }
library/core/buddypress.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ \q\report\core\buddypress::run();
10
+
11
+ class buddypress extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // load BP ##
19
+ \add_action( 'admin_init', array( get_class(), 'load' ), 1000001 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+ /**
27
+ * Get BP fields from DB, if BuddyPress is installed and active
28
+ *
29
+ * @since 2.0.0
30
+ */
31
+ public static function get_fields()
32
+ {
33
+
34
+ // buddypress support deprecated for now ##
35
+ return false;
36
+
37
+ if ( ! function_exists ('bp_is_active') ) {
38
+
39
+ return false;
40
+
41
+ }
42
+
43
+ // introduce global class object ##
44
+ global $wpdb;
45
+
46
+ // grab all buddypress x profile fields ##
47
+ $bp_fields = $wpdb->get_results( "SELECT distinct(name) FROM ".$wpdb->base_prefix."bp_xprofile_fields WHERE parent_id = 0" );
48
+
49
+ // get name value from object ##
50
+ $bp_fields = \wp_list_pluck( $bp_fields, 'name' );
51
+
52
+ // test array ##
53
+ #helper::log( $bp_fields );
54
+
55
+ // allow array to be filtered ##
56
+ $bp_fields = \apply_filters( 'export_user_data_bp_fields', $bp_fields );
57
+
58
+ // kick it back ##
59
+ return $bp_fields;
60
+
61
+ }
62
+
63
+
64
+
65
+ /**
66
+ * Load up saved exports for this user
67
+ * Set to public as hooked into action
68
+ *
69
+ * @since 0.9.6
70
+ * @return Array of saved exports
71
+ */
72
+ public static function load()
73
+ {
74
+
75
+ // do we have a bp object in the globals ##
76
+ if (
77
+ \is_plugin_active( 'buddypress/bp-loader.php' ) // plugin active
78
+ && function_exists ( 'buddypress' ) // loader function exists ##
79
+ && ! isset( $GLOBALS['bp'] ) // but global unavailble ##
80
+ ) {
81
+
82
+ helper::log( 'BP not loaded - calling buddypress()' );
83
+
84
+ // call BP
85
+ buddypress();
86
+
87
+ return true;
88
+
89
+ }
90
+
91
+ #self::log( 'BP loaded' );
92
+
93
+ return true;
94
+
95
+ }
96
+
97
+
98
+
99
+ }
library/core/config.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ // \q\report\core\config::run();
10
+
11
+ class config extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // load standard fields ##
19
+ \add_action( 'admin_init', array( get_class(), 'load' ), 1 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+
27
+ /**
28
+ * Load up saved exports for this user
29
+ * Set to public as hooked into action
30
+ *
31
+ * @since 0.9.6
32
+ * @return Array of saved exports
33
+ */
34
+ public static function load()
35
+ {
36
+
37
+ // load api admin fields ##
38
+ self::get_admin_fields();
39
+
40
+ // kick it back ##
41
+ return true;
42
+
43
+ }
44
+
45
+
46
+
47
+ /**
48
+ * Load up saved exports for this user
49
+ * Set to public as hooked into action
50
+ *
51
+ * @since 0.9.6
52
+ * @return Array of saved exports
53
+ */
54
+ public static function get_admin_fields()
55
+ {
56
+
57
+ // build array ##
58
+ $array = array(
59
+ 'program' => array(
60
+ 'title' => \_e( 'Programs', 'export-user-data' ),
61
+ 'label' => 'program',
62
+ 'description' => \__( 'Select the program that you wish to export.', 'export-user-data' ),
63
+ 'label_select' => \__( 'All Programs', 'export-user-data' ),
64
+ 'options' => \get_posts( array( 'post_type'=> 'program', 'posts_per_page' => -1 ) ),
65
+ 'options_ID' => 'ID',
66
+ 'options_title' => 'post_title'
67
+ )
68
+ );
69
+
70
+ // test it ##
71
+ #self::log( $array );
72
+
73
+ // add to static property ##
74
+ self::$api_admin_fields = $array;
75
+
76
+ // filter and return ##
77
+ apply_filters( 'q/report/api/admin_fields', self::$api_admin_fields );
78
+
79
+ // test it ##
80
+ self::log( self::$api_admin_fields );
81
+
82
+ // kick it back ##
83
+ return true;
84
+
85
+ }
86
+
87
+
88
+ }
library/core/core.php ADDED
@@ -0,0 +1,420 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ #\q\report\core\core::run();
10
+
11
+ class core extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // load user options ##
19
+ #\add_action( 'admin_init', array( get_class(), 'load_user_options' ), 1000002 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+
27
+ /**
28
+ * Get the array of standard WP_User fields to return
29
+ */
30
+ public static function get_user_fields()
31
+ {
32
+
33
+ // standard wp_users fields ##
34
+ if ( isset( $_POST['user_fields'] ) && '1' == $_POST['user_fields'] ) {
35
+
36
+ // debug ##
37
+ #self::log( 'full' );
38
+
39
+ // exportable user data ##
40
+ $user_fields = array(
41
+ 'ID'
42
+ , 'user_login'
43
+ #, 'user_pass'
44
+ , 'user_nicename'
45
+ , 'user_email'
46
+ , 'user_url'
47
+ , 'user_registered'
48
+ #, 'user_activation_key'
49
+ , 'user_status'
50
+ , 'display_name'
51
+ );
52
+
53
+ } else {
54
+
55
+ // debug ##
56
+ #self::log( 'reduced' );
57
+
58
+ // just return the user ID
59
+ $user_fields = array(
60
+ 'ID'
61
+ );
62
+
63
+ }
64
+
65
+ // kick back values via filter ##
66
+ return \apply_filters( 'q/report/export/user_fields', $user_fields );
67
+
68
+ }
69
+
70
+
71
+
72
+
73
+ /**
74
+ * Get the array of special user fields to return
75
+ */
76
+ public static function get_special_fields()
77
+ {
78
+
79
+ // exportable user data ##
80
+ $special_fields = array(
81
+ # 'roles' // list of WP Roles
82
+ #, 'groups' // BP Groups
83
+ );
84
+
85
+ // should we allow groups ##
86
+ if ( isset( $_POST['groups'] ) && '1' == $_POST['groups'] ) {
87
+
88
+ $special_fields[] = 'groups'; // add groups ##
89
+
90
+ }
91
+
92
+ // should we allow roles ##
93
+ if ( isset( $_POST['roles'] ) && '1' == $_POST['roles'] ) {
94
+
95
+ $special_fields[] = 'roles'; // add groups ##
96
+
97
+ }
98
+
99
+ // kick back the array via filter ##
100
+ return \apply_filters( 'q/report/export/special_fields', $special_fields );
101
+
102
+ }
103
+
104
+
105
+
106
+ /**
107
+ * Data to exclude from export
108
+ */
109
+ public static function get_exclude_fields()
110
+ {
111
+
112
+ $exclude_fields = array (
113
+ 'user_pass'
114
+ , 'q_eud_exports'
115
+ #, 'user_activation_key'
116
+ );
117
+
118
+ // kick back array via filter ##
119
+ return \apply_filters( 'q/report/export/exclude_fields', $exclude_fields );
120
+
121
+ }
122
+
123
+
124
+
125
+
126
+ /**
127
+ * Return Byte count of $val
128
+ *
129
+ * @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue?replies=2
130
+ * @since 0.9.6
131
+ */
132
+ public static function return_bytes( $val )
133
+ {
134
+
135
+ $val = trim( $val );
136
+ $last = strtolower($val[strlen($val)-1]);
137
+ switch( $last ) {
138
+
139
+ // The 'G' modifier is available since PHP 5.1.0
140
+ case 'g':
141
+
142
+ $val *= 1024;
143
+
144
+ case 'm':
145
+
146
+ $val *= 1024;
147
+
148
+ case 'k':
149
+
150
+ $val *= 1024;
151
+
152
+ }
153
+
154
+ return $val;
155
+
156
+ }
157
+
158
+
159
+ /**
160
+ * Recursively implodes an array
161
+ *
162
+ * @since 1.0.1
163
+ * @access public
164
+ * @param array $array multi-dimensional array to recursively implode
165
+ * @param string $glue value that glues elements together
166
+ * @param bool $include_keys include keys before their values
167
+ * @param bool $trim_all trim ALL whitespace from string
168
+ * @return string imploded array
169
+ */
170
+ public static function recursive_implode( $array, $return = null, $glue = '|' )
171
+ {
172
+
173
+ // unserialize ##
174
+ $array = self::unserialize( $array );
175
+
176
+ // kick it back ##
177
+ if ( is_null ( $return ) && ! is_array( $array ) ) {
178
+
179
+ return $array;
180
+
181
+ }
182
+
183
+ // empty return ##
184
+ if ( is_null ( $return ) ) {
185
+
186
+ $return = '';
187
+
188
+ } else {
189
+
190
+ if ( "||" == $glue ) {
191
+
192
+ $glue = '|||';
193
+
194
+ } else if ( "|" == $glue ) {
195
+
196
+ $glue = '||';
197
+
198
+ }
199
+
200
+ }
201
+
202
+ // loop ##
203
+ foreach( $array as $key => $value ) {
204
+
205
+ // unserialize ##
206
+ $value = self::unserialize( $value );
207
+
208
+ if( is_array( $value ) ) {
209
+
210
+ $return .= $glue . $key . $glue . self::recursive_implode( $value, $return, $glue );
211
+
212
+ } else {
213
+
214
+ $return .= $glue . $key . $glue . $value;
215
+
216
+ }
217
+
218
+ }
219
+
220
+ // Removes first $glue from string ##
221
+ if ( $glue && $return && $return[0] == '|' ) {
222
+
223
+ $return = ltrim( $return, '|' );
224
+
225
+ }
226
+
227
+ // Trim ALL whitespace ##
228
+ if ( $return ) {
229
+
230
+ $return = preg_replace( "/(\s)/ixsm", '', $return );
231
+
232
+ }
233
+
234
+ // kick it back ##
235
+ return $return;
236
+
237
+ }
238
+
239
+
240
+
241
+
242
+ /**
243
+ * Save Unserializer
244
+ *
245
+ * @since 1.1.4
246
+ */
247
+ public static function unserialize( $value = null )
248
+ {
249
+
250
+ // the $value is serialized ##
251
+ if ( \is_serialized( $value ) ) {
252
+
253
+ // unserliaze to new variable ##
254
+ $unserialized = @unserialize( $value );
255
+
256
+ // test if unserliazing produced errors ##
257
+ if ( $unserialized !== false || $value == 'b:0;' ) {
258
+
259
+ #$value = 'UNSERIALIZED_'.$unserialized;
260
+ $value = $unserialized;
261
+
262
+ } else {
263
+
264
+ // failed to unserialize - data potentially corrupted in db ##
265
+ #$value = 'NOT_SERIALIZED_'.$value;
266
+ $value = $value;
267
+
268
+ }
269
+
270
+ }
271
+
272
+ // kick it back ##
273
+ return $value;
274
+
275
+ }
276
+
277
+
278
+
279
+
280
+ /**
281
+ * Encode special characters
282
+ *
283
+ * @param type $string
284
+ * @return string Encoding string
285
+ * @since 1.2.3
286
+ */
287
+ public static function format_value( $string = null )
288
+ {
289
+
290
+ // sanity check ##
291
+ if ( is_null( $string ) ) {
292
+
293
+ return false;
294
+
295
+ }
296
+
297
+ // kick it back in a nicer format ##
298
+ #return htmlentities( $string, ENT_COMPAT, 'UTF-8' );
299
+
300
+ // kick it back via a filter to allow custom formatting ##
301
+ return \apply_filters( 'q/report/export/format_value', $string );
302
+
303
+ }
304
+
305
+
306
+
307
+ /**
308
+ * Quote array elements and separate with commas
309
+ *
310
+ * @since 0.9.6
311
+ * @return String
312
+ */
313
+ public static function quote_array( $array )
314
+ {
315
+
316
+ $prefix = ''; // starts empty ##
317
+ $elementlist = '';
318
+
319
+ if ( is_array( $array ) ) {
320
+
321
+ foreach( $array as $element ) {
322
+
323
+ $elementlist .= $prefix . "'" . $element . "'";
324
+ $prefix = ','; // prefix all remaining items with a comma ##
325
+
326
+ }
327
+
328
+ }
329
+
330
+ // kick back string to function caller ##
331
+ return( $elementlist );
332
+
333
+ }
334
+
335
+
336
+ /**
337
+ * Export Date Options
338
+ *
339
+ * @since 0.9.6
340
+ * @global type $wpdb
341
+ * @return Array of objects
342
+ */
343
+ public static function get_user_registered_dates()
344
+ {
345
+
346
+ // invite in global objects ##
347
+ global $wpdb;
348
+
349
+ // query user table for oldest and newest registration ##
350
+ $range =
351
+ $wpdb->get_results (
352
+ #$wpdb->prepare (
353
+ "
354
+ SELECT
355
+ MIN( user_registered ) AS first,
356
+ MAX( user_registered ) AS last
357
+ FROM
358
+ {$wpdb->users}
359
+ "
360
+ #)
361
+ );
362
+
363
+ return $range;
364
+
365
+ }
366
+
367
+
368
+
369
+ /**
370
+ * Sanitize data
371
+ *
372
+ * @since 1.2.8
373
+ * @return string
374
+ */
375
+ public static function sanitize( $value )
376
+ {
377
+
378
+ // emove line breaks ##
379
+ $value = str_replace("\r", '', $value);
380
+ $value = str_replace("\n", '', $value);
381
+ $value = str_replace("\t", '', $value);
382
+
383
+ // with wp_kses ##
384
+ $value = \wp_kses( $value, self::get_allowed_tags() );
385
+
386
+ // with esc_html
387
+ $value = \esc_html( $value );
388
+
389
+ // return value ##
390
+ return $value;
391
+
392
+ }
393
+
394
+
395
+ /**
396
+ * Get allowed tags for wp_kses
397
+ *
398
+ * @since 1.2.8
399
+ * @return Array
400
+ */
401
+ public static function get_allowed_tags()
402
+ {
403
+
404
+ $allowed_tags = array(
405
+ 'a' => array(
406
+ 'href' => array(),
407
+ 'title' => array()
408
+ ),
409
+ 'br' => array(),
410
+ 'em' => array(),
411
+ 'strong' => array(),
412
+ );
413
+
414
+ // kick back via filter ##
415
+ return \apply_filters( 'q/report/export/allowed_tags', $allowed_tags );
416
+
417
+ }
418
+
419
+
420
+ }
library/core/export.php ADDED
@@ -0,0 +1,607 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+ use q\report\core\xml as xml;
8
+
9
+ // load it up ##
10
+ \q\report\core\export::run();
11
+
12
+ class export extends \q_report {
13
+
14
+ public static function run()
15
+ {
16
+
17
+ if ( \is_admin() ) {
18
+
19
+ // run export ##
20
+ \add_action( 'admin_init', array( get_class(), 'render' ), 1000003 );
21
+
22
+ }
23
+
24
+ }
25
+
26
+
27
+ /**
28
+ * Attempt to generate the export file based on the passed arguements
29
+ *
30
+ * @since 0.1
31
+ * @return Mixes
32
+ **/
33
+ public static function render()
34
+ {
35
+
36
+ // Check if the user clicked on the Save, Load, or Delete Settings buttons ##
37
+ if (
38
+ ! isset( $_POST['_wpnonce-q-report-admin-page'] )
39
+ || isset( $_POST['load_export'] )
40
+ || isset( $_POST['save_export'] )
41
+ || isset( $_POST['delete_export'] ) )
42
+ {
43
+
44
+ return false;
45
+
46
+ }
47
+
48
+ // Increase maximum execution time to prevent "Maximum execution time exceeded" error ##
49
+ ini_set( 'max_execution_time', -1 );
50
+ ini_set( 'memory_limit', -1 ); // bad idea? ##
51
+
52
+ // check admin referer ##
53
+ \check_admin_referer( 'q-report-admin-page', '_wpnonce-q-report-admin-page' );
54
+
55
+ // build argument array ##
56
+ $args = array(
57
+ 'fields' => ( isset( $_POST['user_fields'] ) && '1' == $_POST['user_fields'] ) ?
58
+ 'all' :
59
+ array( 'ID' ), // exclude standard wp_users fields from get_users query ##
60
+ 'role' => \sanitize_text_field( $_POST['role'] )
61
+ );
62
+
63
+ // is there a range limit in place for the export ? ##
64
+ if ( isset( $_POST['limit_total'] ) && '' != $_POST['limit_total'] ) {
65
+
66
+ // let's just make sure they are integer values ##
67
+ $limit_offset = isset( $_POST['limit_offset'] ) ? (int)$_POST['limit_offset'] : 0 ;
68
+ $limit_total = (int)$_POST['limit_total'];
69
+
70
+ if ( is_int( $limit_offset ) && is_int( $limit_total ) ) { // confirm we have integer values ##
71
+
72
+ $args['offset'] = $limit_offset;
73
+ $args['number'] = $limit_total; // number - Limit the total number of users returned ##
74
+
75
+ // test it ##
76
+ #if ( self::$debug )helper::log( $args );
77
+
78
+ }
79
+
80
+ }
81
+
82
+ // add custom args via filters ##
83
+ $args = \apply_filters( 'q/report/export/args', $args );
84
+
85
+ #helper::log( $args );
86
+
87
+ // pre_user query ##
88
+ \add_action( 'pre_user_query', array( get_class(), 'pre_user_query' ) );
89
+ $users = \get_users( $args );
90
+ \remove_action( 'pre_user_query', array( get_class(), 'pre_user_query' ) );
91
+
92
+ // test args ##
93
+ #if ( self::$debug ) helper::log ( $users );
94
+
95
+ // no users found, so chuck an error into the args array and exit the export ##
96
+ if ( ! $users ) {
97
+
98
+ \wp_redirect( \add_query_arg( 'error', 'empty', \wp_get_referer() ) );
99
+ exit;
100
+
101
+ }
102
+
103
+ // get sitename and clean it up ##
104
+ $sitename = \sanitize_key( \get_bloginfo( 'name' ) );
105
+ if ( ! empty( $sitename ) ) {
106
+ $sitename .= '.';
107
+ }
108
+
109
+ // export method ? ##
110
+ $export_method = 'excel'; // default to Excel export ##
111
+ if ( isset( $_POST['format'] ) && $_POST['format'] != '' ) {
112
+
113
+ $export_method = \sanitize_text_field( $_POST['format'] );
114
+
115
+ }
116
+
117
+ // set export filename structure ##
118
+ $filename = $sitename . 'report.' . date( 'Y-m-d-H-i-s' );
119
+
120
+ switch ( $export_method ) {
121
+
122
+ case ( 'csv' ):
123
+
124
+ // to csv ##
125
+ header( 'Content-Description: File Transfer' );
126
+ header( 'Content-Disposition: attachment; filename='.$filename.'.csv' );
127
+ header( 'Content-Type: text/csv; charset=' . \get_option( 'blog_charset' ), true );
128
+
129
+ // set a csv check flag
130
+ $is_csv = true;
131
+
132
+ // nothing here
133
+ $doc_begin = '';
134
+
135
+ //preformat
136
+ $pre = '';
137
+
138
+ // how to seperate data ##
139
+ $seperator = ','; // comma for csv ##
140
+
141
+ // line break ##
142
+ $breaker = "\n";
143
+
144
+ // nothing here
145
+ $doc_end = '';
146
+
147
+ break;
148
+
149
+ case ( 'excel' ):
150
+
151
+ // to xls ##
152
+ header( 'Content-Description: File Transfer' );
153
+ header("Content-Type: application/vnd.ms-excel");
154
+ header("Content-Disposition: attachment; filename=$filename.xls");
155
+ header("Pragma: no-cache");
156
+ header("Expires: 0");
157
+
158
+ // set a csv check flag
159
+ $is_csv = false;
160
+
161
+ // open xml
162
+ $doc_begin = xml::begin();
163
+
164
+ //preformat
165
+ $pre = xml::pre();
166
+
167
+ // how to seperate data ##
168
+ $seperator = xml::seperator();
169
+
170
+ // line break ##
171
+ $breaker = xml::breaker();
172
+
173
+ // close xml
174
+ $doc_end = xml::end();
175
+
176
+ break;
177
+
178
+ }
179
+
180
+
181
+ // check for selected usermeta fields ##
182
+ $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '';
183
+ #helper::log( $usermeta );
184
+ $usermeta_fields = array();
185
+
186
+ // loop over each field and sanitize ##
187
+ if ( $usermeta && is_array( $usermeta ) ) {
188
+ foreach( $usermeta as $field ) {
189
+ $usermeta_fields[] = \sanitize_text_field ( $field );
190
+ }
191
+ }
192
+
193
+ #helper::log( $usermeta_fields );
194
+ #exit;
195
+
196
+ // check for selected x profile fields ##
197
+ $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '';
198
+ $bp_fields_passed = array();
199
+ if ( $bp_fields && is_array( $bp_fields ) ) {
200
+
201
+ foreach( $bp_fields as $field ) {
202
+
203
+ // reverse tidy ##
204
+ $field = str_replace( '__', ' ', \sanitize_text_field ( $field ) );
205
+
206
+ // add to array ##
207
+ $bp_fields_passed[] = $field;
208
+
209
+ }
210
+
211
+ }
212
+
213
+ // cwjordan: check for x profile fields we want update time for ##
214
+ $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '';
215
+ $bp_fields_update_passed = array();
216
+ if ( $bp_fields_update && is_array( $bp_fields_update ) ) {
217
+
218
+ foreach( $bp_fields_update as $field ) {
219
+
220
+ // reverse tidy ##
221
+ $field = str_replace( '__', ' ', \sanitize_text_field ( $field ) );
222
+
223
+ // add to array ##
224
+ $bp_fields_update_passed[] = $field . " Update Date";
225
+
226
+ }
227
+
228
+ }
229
+
230
+ // global wpdb object ##
231
+ global $wpdb;
232
+
233
+ // debug ##
234
+ #helper::log( 'merging array' );
235
+
236
+ // compile final fields list ##
237
+ $fields = array_merge(
238
+ core::get_user_fields() // standard wp_user fields ##
239
+ , core::get_special_fields() // 'special' fields - which are controlled via dedicated checks ##
240
+ , $usermeta_fields // wp_user_meta fields ##
241
+ , $bp_fields_passed // selected buddypress fields ##
242
+ , $bp_fields_update_passed // update date for buddypress fields ##
243
+ );
244
+
245
+ // test field array ##
246
+ #helper::log( $fields );
247
+
248
+ // build the document headers ##
249
+ $headers = array();
250
+
251
+ foreach ( $fields as $key => $field ) {
252
+
253
+ #helper::log( 'Field: '. $field );
254
+
255
+ // filter field name ##
256
+ $field = \apply_filters( 'q/report/export/field', $field );
257
+
258
+ // grab fields to exclude from exports - filterable ##
259
+ if ( in_array( $fields[$key], core::get_exclude_fields() ) ) {
260
+
261
+ #helper::log( 'Dump Field: '. $fields[$key] );
262
+
263
+ // ditch 'em ##
264
+ unset( $fields[$key] );
265
+
266
+ } else {
267
+
268
+ if ( $is_csv ) {
269
+
270
+ $headers[] = '"' . $field . '"';
271
+
272
+ } else {
273
+
274
+ $headers[] = $field;
275
+
276
+ }
277
+
278
+ }
279
+
280
+ }
281
+
282
+ // quick check ##
283
+ #helper::log( $fields );
284
+ #if ( self::$debug ) #helper::log( $bp_fields_passed );
285
+
286
+ // no more buffering while spitting back the export data ##
287
+ if( ob_get_level() > 0 ) ob_end_flush();
288
+
289
+ // get the value in bytes allocated for Memory via php.ini ##
290
+ // @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue
291
+ $memory_limit = core::return_bytes( ini_get('memory_limit') ) * .75;
292
+
293
+ // we need to disable caching while exporting because we export so much data that it could blow the memory cache
294
+ // if we can't override the cache here, we'll have to clear it later...
295
+ if ( function_exists( 'override_function' ) ) {
296
+
297
+ override_function('wp_cache_add', '$key, $data, $group="", $expire=0', '');
298
+ override_function('wp_cache_set', '$key, $data, $group="", $expire=0', '');
299
+ override_function('wp_cache_replace', '$key, $data, $group="", $expire=0', '');
300
+ override_function('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', '');
301
+
302
+ } elseif ( function_exists( 'runkit_function_redefine' ) ) {
303
+
304
+ runkit_function_redefine('wp_cache_add', '$key, $data, $group="", $expire=0', '');
305
+ runkit_function_redefine('wp_cache_set', '$key, $data, $group="", $expire=0', '');
306
+ runkit_function_redefine('wp_cache_replace', '$key, $data, $group="", $expire=0', '');
307
+ runkit_function_redefine('wp_cache_add_non_persistent_groups', '$key, $data, $group="", $expire=0', '');
308
+
309
+ }
310
+
311
+ // open doc wrapper.. ##
312
+ echo $doc_begin;
313
+
314
+ // echo headers ##
315
+ echo $pre . implode( $seperator, $headers ) . $breaker;
316
+
317
+ #helper::log( $users );
318
+
319
+ // build row values for each user ##
320
+ foreach ( $users as $user ) {
321
+
322
+ #helper::log( $user );
323
+
324
+ // check if we're hitting any Memory limits, if so flush them out ##
325
+ // per http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue?replies=2
326
+ if ( memory_get_usage( true ) > $memory_limit ) {
327
+ \wp_cache_flush();
328
+ }
329
+
330
+ // open up a new empty array ##
331
+ $data = array();
332
+
333
+ // BP loaded ? ##
334
+ if (
335
+ ! self::$bp_data_available
336
+ && function_exists ( 'bp_is_active' )
337
+ && \bp_is_active( 'xprofile' )
338
+ && class_exists( 'BP_XProfile_ProfileData' )
339
+ && method_exists( 'BP_XProfile_ProfileData', 'get_all_for_user' )
340
+ && is_callable ( array( 'BP_XProfile_ProfileData', 'get_all_for_user' ) )
341
+ ) {
342
+
343
+ helper::log( 'XProfile Accessible' );
344
+ self::$bp_data_available = true; // we only need to check for BP once ##
345
+
346
+ }
347
+
348
+ // grab all user data ##
349
+ if (
350
+ self::$bp_data_available
351
+ && ! $bp_data = \BP_XProfile_ProfileData::get_all_for_user( $user->ID )
352
+ ) {
353
+
354
+ // null the data to be sure ##
355
+ $bp_data = false;
356
+
357
+ helper::log( 'XProfile returned no data ID#: '.$user->ID );
358
+
359
+ }
360
+
361
+ // single query method - get all user_meta data ##
362
+ $get_user_meta = (array)\get_user_meta( $user->ID );
363
+ #helper::log( $get_user_meta );
364
+
365
+ // loop over each field ##
366
+ foreach ( $fields as $field ) {
367
+
368
+ // check if this is a BP field ##
369
+ if (
370
+ isset( $bp_data )
371
+ && isset( $bp_data[$field] )
372
+ && in_array( $field, $bp_fields_passed )
373
+ ){
374
+
375
+ // old way from single BP query ##
376
+ $value = $bp_data[$field];
377
+
378
+ if ( is_array( $value ) ) {
379
+
380
+ $value = \maybe_unserialize( $value['field_data'] ); // suggested by @grexican ##
381
+ #$value = $value['field_data'];
382
+
383
+ /**
384
+ * cwjordan
385
+ * after unserializing it we then
386
+ * need to implode it so
387
+ * that we have something readable?
388
+ * Going to use :: as a separator
389
+ * because that's what Buddypress Members Import
390
+ * expects, but we might want to make that
391
+ * configurable.
392
+ */
393
+ if ( is_array( $value ) ) {
394
+ $value = implode( "::", $value );
395
+ }
396
+
397
+ }
398
+
399
+ // sanitize ##
400
+ #$value = $this->sanitize($value);
401
+
402
+ // check if this is a BP field we want the updated date for ##
403
+ }
404
+ elseif ( in_array( $field, $bp_fields_update_passed ) )
405
+ {
406
+
407
+ global $bp;
408
+
409
+ $real_field = str_replace(" Update Date", "", $field);
410
+ $field_id = \xprofile_get_field_id_from_name( $real_field );
411
+ $value = $wpdb->get_var (
412
+ $wpdb->prepare(
413
+ "
414
+ SELECT last_updated
415
+ FROM {$bp->profile->table_name_data}
416
+ WHERE user_id = %d AND field_id = %d
417
+ "
418
+ , $user->ID
419
+ , $field_id
420
+ )
421
+ );
422
+
423
+ // include the user's role in the export ##
424
+ }
425
+ elseif ( isset( $_POST['roles'] ) && '1' == $_POST['roles'] && $field == 'roles' )
426
+ {
427
+
428
+ // add "Role" as $value ##
429
+ $value = isset( $user->roles[0] ) ? implode( $user->roles, '|' ) : '' ; // empty value if no role found - or flat array of user roles ##
430
+
431
+ // include the user's BP group in the export ##
432
+ }
433
+ elseif ( isset( $_POST['groups'] ) && '1' == $_POST['groups'] && $field == 'groups' )
434
+ {
435
+
436
+ if ( function_exists( 'groups_get_user_groups' ) ) {
437
+
438
+ // check if user is a member of any groups ##
439
+ $group_ids = \groups_get_user_groups( $user->ID );
440
+
441
+ #$this->pr( $group_ids );
442
+ #wp_die( pr( 'loaded group data.' ));
443
+
444
+ if ( ! $group_ids || $group_ids == '' ) {
445
+
446
+ $value = '';
447
+
448
+ } else {
449
+
450
+ // new empty array ##
451
+ $groups = array();
452
+
453
+ // loop over all groups ##
454
+ foreach( $group_ids["groups"] as $group_id ) {
455
+
456
+ $groups[] = \groups_get_group( array( 'group_id' => $group_id )) -> name . ( end( $group_ids["groups"] ) == $group_id ? '' : '' );
457
+
458
+ }
459
+
460
+ // implode it ##
461
+ $value = implode( $groups, '|' );
462
+
463
+ }
464
+
465
+ } else {
466
+
467
+ $value = '';
468
+
469
+ }
470
+
471
+ }
472
+ elseif ( $field == 'bp_latest_update' || $field == 'last_activity' )
473
+ {
474
+
475
+ // https://bpdevel.wordpress.com/2014/02/21/user-last_activity-data-and-buddypress-2-0/ ##
476
+ $value = \bp_get_user_last_activity( $user->ID );
477
+
478
+ // user or usermeta field ##
479
+ }
480
+ else
481
+ {
482
+
483
+ // the user_meta key isset ##
484
+ if ( isset( $get_user_meta[$field] ) ) {
485
+
486
+ // take from the bulk get_user_meta call - this returns an array in all cases, so we take the first key ##
487
+ $value = $get_user_meta[$field][0];
488
+
489
+ // standard WP_User value ##
490
+ } else {
491
+
492
+ // use the magically assigned value from WP_Users
493
+ $value = isset( $user->{$field} ) ? $user->{$field} : null ;
494
+
495
+ }
496
+
497
+
498
+ // the $value might be serialized ##
499
+ $value = core::unserialize( $value );
500
+
501
+ // the value is an array ##
502
+ if ( is_array ( $value ) ) {
503
+
504
+ // recursive implode it ##
505
+ $value = core::recursive_implode( $value );
506
+
507
+ }
508
+
509
+ // sanitize ##
510
+ #$value = $this->sanitize($value);
511
+
512
+ }
513
+
514
+ // filter $value ##
515
+ $value = \apply_filters( 'q/report/export/value', $value, $field );
516
+
517
+ // sanitize ##
518
+ $value = core::sanitize( $value );
519
+
520
+ // wrap values in quotes and add to array ##
521
+ if ( $is_csv ) {
522
+
523
+ $data[] = '"' . str_replace( '"', '""', core::format_value( $value ) ) . '"';
524
+
525
+ // just add to array ##
526
+ } else {
527
+
528
+ $data[] = core::format_value( $value );
529
+ }
530
+
531
+ }
532
+
533
+ // echo row data ##
534
+ echo $pre . implode( $seperator, $data ) . $breaker;
535
+
536
+ }
537
+
538
+ // close doc wrapper..
539
+ echo $doc_end;
540
+
541
+ // stop PHP, so file can export correctly ##
542
+ exit;
543
+
544
+ }
545
+
546
+
547
+
548
+
549
+ /**
550
+ * Pre User Query
551
+ *
552
+ * @since 2.0.0
553
+ */
554
+ public static function pre_user_query( $user_search = null )
555
+ {
556
+
557
+ global $wpdb;
558
+
559
+ $where = '';
560
+
561
+ if ( ! empty( $_POST['start_date'] ) ) {
562
+
563
+ $date = new \DateTime( \sanitize_text_field ( $_POST['start_date'] ). ' 00:00:00' );
564
+ $date_formatted = $date->format( 'Y-m-d H:i:s' );
565
+
566
+ $where .= $wpdb->prepare( " AND $wpdb->users.user_registered >= %s", $date_formatted );
567
+
568
+ }
569
+ if ( ! empty( $_POST['end_date'] ) ) {
570
+
571
+ $date = new \DateTime( \sanitize_text_field ( $_POST['end_date'] ). ' 00:00:00' );
572
+ $date_formatted = $date->format( 'Y-m-d H:i:s' );
573
+
574
+ $where .= $wpdb->prepare( " AND $wpdb->users.user_registered < %s", $date_formatted );
575
+
576
+ }
577
+
578
+ // search by last update time of BP extended fields ##
579
+ if (
580
+ class_exists( 'BP_Xprofile_Field' )
581
+ && ( isset ($_POST['updated_since_date'] ) && $_POST['updated_since_date'] != '' )
582
+ && (isset ($_POST['bp_field_updated_since'] ) && $_POST['bp_field_updated_since'] != '' )
583
+ ) {
584
+
585
+ $last_updated_date = new \DateTime( \sanitize_text_field ( $_POST['updated_since_date'] ) . ' 00:00:00' );
586
+ self::$updated_since_date = $last_updated_date->format( 'Y-m-d H:i:s' );
587
+ self::$field_updated_since = \sanitize_text_field ( $_POST['bp_field_updated_since'] );
588
+ $field_updated_since_id = \BP_Xprofile_Field::get_id_from_name( self::$field_updated_since );
589
+ $user_search->query_from .= " JOIN `wp_bp_xprofile_data` XP ON XP.user_id = wp_users.ID ";
590
+ $where .= $wpdb->prepare( " AND XP.field_id = %s AND XP.last_updated >= %s", $field_updated_since_id, self::$updated_since_date );
591
+
592
+ }
593
+
594
+ if ( ! empty( $where ) ) {
595
+
596
+ $user_search->query_where = str_replace( 'WHERE 1=1', "WHERE 1=1 $where", $user_search->query_where );
597
+
598
+ }
599
+
600
+ #wp_die( self::$pr( $user_search ) );
601
+ return $user_search;
602
+
603
+ }
604
+
605
+
606
+
607
+ }
library/core/filters.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ \q\report\core\filters::run();
10
+
11
+ class filters extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // EUD - filter key shown ##
19
+ \add_filter( 'q/report/admin/display_key', [ get_class(), 'display_key' ], 1, 1 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+ /**
27
+ * Filter keys in EUD plugin
28
+ *
29
+ * @since 2.0.0
30
+ */
31
+ public static function display_key( $string = null )
32
+ {
33
+
34
+ #helper::log( 'string from filter: '.$string );
35
+
36
+ if ( is_null( $string ) ) {
37
+
38
+ return false;
39
+
40
+ }
41
+
42
+ // array of translations ##
43
+ $array = [
44
+ 'first_name' => 'First Name',
45
+ ];
46
+
47
+ // check if $string exists as key in $array and if so, replace and return ##
48
+ if ( array_key_exists( $string, $array ) ) {
49
+
50
+ return $array[$string];
51
+
52
+ }
53
+
54
+ // kick it back ##
55
+ return $string;
56
+
57
+ }
58
+
59
+ }
library/core/helper.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // namespace ##
4
+ namespace q\report\core;
5
+
6
+ // piggyback Q helper ##
7
+ use q\core\helper as q_helper;
8
+
9
+ /**
10
+ * helper Class
11
+ * @package q_report\core
12
+ */
13
+ class helper extends \q_report {
14
+
15
+
16
+ /**
17
+ * Write to WP Error Log
18
+ *
19
+ * @since 1.5.0
20
+ * @return void
21
+ */
22
+ public static function log( $log )
23
+ {
24
+
25
+ if ( true === WP_DEBUG ) {
26
+
27
+ $trace = debug_backtrace();
28
+ $caller = $trace[1];
29
+
30
+ $suffix = sprintf(
31
+ __( ' - %s%s() %s:%d', 'Q' )
32
+ , isset($caller['class']) ? $caller['class'].'::' : ''
33
+ , $caller['function']
34
+ , isset( $caller['file'] ) ? $caller['file'] : 'n'
35
+ , isset( $caller['line'] ) ? $caller['line'] : 'x'
36
+ );
37
+
38
+ if ( is_array( $log ) || is_object( $log ) ) {
39
+ error_log( print_r( $log, true ).$suffix );
40
+ } else {
41
+ error_log( $log.$suffix );
42
+ }
43
+
44
+ }
45
+
46
+ }
47
+
48
+
49
+ }
library/core/user.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ // load it up ##
9
+ \q\report\core\user::run();
10
+
11
+ class user extends \q_report {
12
+
13
+ public static function run()
14
+ {
15
+
16
+ if ( \is_admin() ) {
17
+
18
+ // load user options ##
19
+ \add_action( 'admin_init', array( get_class(), 'load' ), 1000002 );
20
+
21
+ }
22
+
23
+ }
24
+
25
+
26
+ /**
27
+ * Load up saved exports for this user
28
+ * Set to public as hooked into action
29
+ *
30
+ * @since 0.9.6
31
+ * @return Array of saved exports
32
+ */
33
+ public static function load()
34
+ {
35
+
36
+ return self::$q_report_exports =
37
+ \get_user_meta( \get_current_user_id(), 'q_report_exports' ) ?
38
+ \get_user_meta( \get_current_user_id(), 'q_report_exports', true ) :
39
+ array() ;
40
+
41
+ #self::log( $this->q_report_exports );
42
+
43
+ }
44
+
45
+
46
+
47
+ /**
48
+ * Get list of saved exports for this user
49
+ *
50
+ * @since 0.9.4
51
+ * @return Array of saved exports
52
+ */
53
+ public static function get_user_options()
54
+ {
55
+
56
+ // get the stored options - filter empty array items ##
57
+ $q_report_exports = array_filter( self::$q_report_exports );
58
+
59
+ // quick check if the array is empty ##
60
+ if ( empty ( $q_report_exports ) ) {
61
+
62
+ return false;
63
+
64
+ }
65
+
66
+ // test the array of saved exports ##
67
+ #$this->pr( $q_report_exports );
68
+
69
+ // start with an empty array ##
70
+ $exports = array();
71
+
72
+ // loop over each saved export and grab each key ##
73
+ foreach ( $q_report_exports as $key => $value ) {
74
+
75
+ $exports[] = $key;
76
+
77
+ }
78
+
79
+ // kick back array ##
80
+ return $exports;
81
+
82
+ }
83
+
84
+
85
+ /**
86
+ * Check for and load stored user options
87
+ *
88
+ * @since 0.9.3
89
+ * @return void
90
+ */
91
+ public static function get_user_options_by_export( $export = null )
92
+ {
93
+
94
+ // sanity check ##
95
+ if ( is_null ( $export ) ) { return false; }
96
+
97
+ if ( isset( self::$q_report_exports[$export] ) ) {
98
+
99
+ self::$usermeta_saved_fields = self::$q_report_exports[$export]['usermeta_saved_fields'];
100
+ self::$bp_fields_saved_fields = self::$q_report_exports[$export]['bp_fields_saved_fields'];
101
+ self::$bp_fields_update_time_saved_fields = self::$q_report_exports[$export]['bp_fields_update_time_saved_fields'];
102
+ self::$updated_since_date = isset( self::$q_report_exports[$export]['updated_since_date'] ) ? self::$q_report_exports[$export]['updated_since_date'] : null ;
103
+ self::$field_updated_since = isset( self::$q_report_exports[$export]['field_updated_since'] ) ? self::$q_report_exports[$export]['field_updated_since'] : null ;
104
+ self::$role = self::$q_report_exports[$export]['role'];
105
+ self::$roles = self::$q_report_exports[$export]['roles'];
106
+ self::$groups = self::$q_report_exports[$export]['groups'];
107
+ self::$user_fields = isset( self::$q_report_exports[$export]['user_fields'] ) ? self::$q_report_exports[$export]['user_fields'] : null ;
108
+ self::$start_date = self::$q_report_exports[$export]['start_date'];
109
+ self::$end_date = self::$q_report_exports[$export]['end_date'];
110
+ self::$limit_offset = self::$q_report_exports[$export]['limit_offset'];
111
+ self::$limit_total = self::$q_report_exports[$export]['limit_total'];
112
+ self::$format = self::$q_report_exports[$export]['format'];
113
+
114
+ } else {
115
+
116
+ self::$usermeta_saved_fields = array();
117
+ self::$bp_fields_saved_fields = array();
118
+ self::$bp_fields_update_time_saved_fields = array();
119
+ self::$updated_since_date = '';
120
+ self::$field_updated_since = '';
121
+ self::$role = '';
122
+ self::$user_fields = '1';
123
+ self::$roles = '1';
124
+ self::$groups = '1';
125
+ self::$start_date = '';
126
+ self::$end_date = '';
127
+ self::$limit_offset = '';
128
+ self::$limit_total = '';
129
+ self::$format = '';
130
+
131
+ }
132
+
133
+ }
134
+
135
+
136
+ /**
137
+ * Method to store user options
138
+ *
139
+ * @param string $save_export Export Key name
140
+ * @param array $save_options Array of export options to save
141
+ * @since 0.9.3
142
+ * @return void
143
+ */
144
+ public static function set_user_options( $key = null, $options = null )
145
+ {
146
+
147
+ // sanity check ##
148
+ if ( is_null ( $key ) || is_null ( $options ) ) {
149
+
150
+ #$this->pr( 'missing save values' );
151
+ return false;
152
+
153
+ }
154
+
155
+ #$this->pr( $key );
156
+ #$this->pr( $options );
157
+
158
+ // for now, I'm simply allowing keys to be resaved - but this is not so logical ##
159
+ if ( array_key_exists( $key, self::$q_report_exports ) ) {
160
+
161
+ #$this->pr( 'key exists, skipping save' );
162
+ #return false;
163
+
164
+ }
165
+
166
+ if ( isset( $options ) && is_array( $options ) ) {
167
+
168
+ // update_option sanitizes the option name but not the option value ##
169
+ foreach ( $options as $field_name => $field_value ) {
170
+
171
+ // so do that here. ##
172
+ if ( is_array( $field_value ) ) {
173
+
174
+ foreach ( $field_value as $field_array_key => $field_array_value ) {
175
+
176
+ $options[$field_name][$field_array_key] = \sanitize_text_field( $field_array_value );
177
+
178
+ }
179
+
180
+ } else {
181
+
182
+ $options[$field_name] = \sanitize_text_field( $field_value );
183
+
184
+ }
185
+
186
+ }
187
+
188
+ // assign the sanitized array of values to the class property $q_report_exports as a new array with key $key ##
189
+ self::$q_report_exports[$key] = $options;
190
+
191
+ // update stored user_meta values, if previous key found ##
192
+ if ( \get_user_meta( \get_current_user_id(), 'q_report_exports' ) !== false ) {
193
+
194
+ #update_option( 'q_report_exports', $this->q_report_exports );
195
+ \update_user_meta( \get_current_user_id(), 'q_report_exports', self::$q_report_exports );
196
+
197
+ // create new user meta key ##
198
+ } else {
199
+
200
+ #add_option( 'q_report_exports', $this->q_report_exports, $deprecated, $autoload );
201
+ \add_user_meta( \get_current_user_id(), 'q_report_exports', self::$q_report_exports );
202
+
203
+ }
204
+
205
+ }
206
+
207
+ }
208
+
209
+
210
+ /**
211
+ * method to delete user options
212
+ *
213
+ * @param $key String Key name to drop from property
214
+ * @since 0.9.3
215
+ * @return void
216
+ */
217
+ public static function delete_user_options( $key = null )
218
+ {
219
+
220
+ // sanity check ##
221
+ if ( is_null ( $key ) || ! array_key_exists( $key, self::$q_report_exports ) ) { return false; }
222
+
223
+ // clean it up ##
224
+ $key = \sanitize_text_field( $key );
225
+
226
+ // check it out ##
227
+ #$this->pr( $key );
228
+
229
+ // drop the array by it's key name from the class property ##
230
+ unset( self::$q_report_exports[$key] );
231
+
232
+ // update the saved data ##
233
+ \update_user_meta( \get_current_user_id(), 'q_report_exports', self::$q_report_exports );
234
+
235
+ }
236
+
237
+
238
+
239
+ }
library/core/xml.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace q\report\core;
4
+
5
+ use q\report\core\core as core;
6
+ use q\report\core\helper as helper;
7
+
8
+ /**
9
+ * XML template for excel file format
10
+ *
11
+ * @since 0.7.7
12
+ **/
13
+
14
+ // load it up ##
15
+ #\q\report\core\core::run();
16
+
17
+ class xml extends \q_report {
18
+
19
+ public static function begin()
20
+ {
21
+
22
+ /*
23
+ $xml_string = <<<XML
24
+ <xml version="1.0">
25
+ <mso-application progid="Excel.Sheet">
26
+ <Workbook
27
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet"
28
+ xmlns:o="urn:schemas-microsoft-com:office:office"
29
+ xmlns:x="urn:schemas-microsoft-com:office:excel"
30
+ xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
31
+ xmlns:html="http://www.w3.org/TR/REC-html40">
32
+ <Worksheet ss:Name="Exported Users">
33
+ <Table>
34
+ XML;
35
+ $xml_object = new \SimpleXMLElement($xml_string);
36
+ return $xml_object->asXML();
37
+ #Changed by Benny to PHP XML syntax to clear 500
38
+ */
39
+ $xml_doc_begin =
40
+ '<?xml version="1.0"?>
41
+ <?mso-application progid="Excel.Sheet"?>
42
+ <Workbook
43
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet"
44
+ xmlns:o="urn:schemas-microsoft-com:office:office"
45
+ xmlns:x="urn:schemas-microsoft-com:office:excel"
46
+ xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
47
+ xmlns:html="http://www.w3.org/TR/REC-html40">
48
+ <Worksheet ss:Name="Exported Users">
49
+ <Table>';
50
+
51
+ return $xml_doc_begin;
52
+
53
+ }
54
+
55
+
56
+
57
+
58
+ public static function pre()
59
+ {
60
+
61
+ $xml_pre =
62
+ '<Row>
63
+ <Cell>
64
+ <Data ss:Type="String">';
65
+
66
+ return $xml_pre;
67
+
68
+ }
69
+
70
+
71
+
72
+ public static function seperator()
73
+ {
74
+
75
+ $xml_seperator =
76
+ '</Data>
77
+ </Cell>
78
+ <Cell>
79
+ <Data ss:Type="String">';
80
+
81
+ return $xml_seperator;
82
+
83
+ }
84
+
85
+
86
+
87
+ public static function breaker()
88
+ {
89
+
90
+ $xml_breaker =
91
+ '</Data>
92
+ </Cell>
93
+ </Row>';
94
+
95
+ return $xml_breaker;
96
+
97
+ }
98
+
99
+
100
+ public static function end()
101
+ {
102
+
103
+ $xml_doc_end = '
104
+ </Table>
105
+ </Worksheet>
106
+ </Workbook>';
107
+
108
+ return $xml_doc_end;
109
+
110
+ }
111
+
112
+ }
library/languages/default.mo ADDED
Binary file
library/languages/default.po ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Export User Data\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/export-users-to-csv\n"
5
+ "POT-Creation-Date: 2014-03-15 09:46-0000\n"
6
+ "PO-Revision-Date: 2014-03-15 09:46-0000\n"
7
+ "Last-Translator: Ray <ray@qstudio.us>\n"
8
+ "Language-Team: Q Studio <team@qstudio.us>\n"
9
+ "Language: en\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 1.6.3\n"
14
+ "X-Poedit-KeywordsList: _;_e;_n;__\n"
15
+ "X-Poedit-Basepath: .\n"
16
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+ "X-Poedit-SearchPath-1: ..\n"
20
+
21
+ #: ../export-user-data.php:85 ../export-user-data.php:450
22
+ msgid "Export User Data"
23
+ msgstr ""
24
+
25
+ #: ../export-user-data.php:445
26
+ msgid "You do not have sufficient permissions to access this page."
27
+ msgstr ""
28
+
29
+ #: ../export-user-data.php:455
30
+ msgid "No users found."
31
+ msgstr ""
32
+
33
+ #: ../export-user-data.php:511
34
+ msgid "User Meta Fields"
35
+ msgstr ""
36
+
37
+ #: ../export-user-data.php:513
38
+ msgid "Filter"
39
+ msgstr ""
40
+
41
+ #: ../export-user-data.php:513
42
+ msgid "All"
43
+ msgstr ""
44
+
45
+ #: ../export-user-data.php:513
46
+ msgid "Common"
47
+ msgstr ""
48
+
49
+ #: ../export-user-data.php:564
50
+ msgid ""
51
+ "Select the user meta keys to export, use the filters to simplify the list."
52
+ msgstr ""
53
+
54
+ #: ../export-user-data.php:593
55
+ msgid "BP xProfile Fields"
56
+ msgstr ""
57
+
58
+ #: ../export-user-data.php:614
59
+ msgid "Select the BuddyPress XProfile keys to export"
60
+ msgstr ""
61
+
62
+ #: ../export-user-data.php:626
63
+ msgid "BP xProfile Fields Update Time"
64
+ msgstr ""
65
+
66
+ #: ../export-user-data.php:642
67
+ msgid "Select the BuddyPress XProfile keys updated dates to export"
68
+ msgstr ""
69
+
70
+ #: ../export-user-data.php:653
71
+ msgid "Role"
72
+ msgstr ""
73
+
74
+ #: ../export-user-data.php:658
75
+ msgid "All Roles"
76
+ msgstr ""
77
+
78
+ #: ../export-user-data.php:668
79
+ #, php-format
80
+ msgid ""
81
+ "Filter the exported users by a WordPress Role. <a href=\"%s\" target=\"_blank"
82
+ "\">%s</a>"
83
+ msgstr ""
84
+
85
+ #: ../export-user-data.php:682
86
+ msgid "Programs"
87
+ msgstr ""
88
+
89
+ #: ../export-user-data.php:687
90
+ msgid "All Programs"
91
+ msgstr ""
92
+
93
+ #: ../export-user-data.php:708
94
+ msgid "Registered"
95
+ msgstr ""
96
+
97
+ #: ../export-user-data.php:711
98
+ msgid "Start Date"
99
+ msgstr ""
100
+
101
+ #: ../export-user-data.php:715
102
+ msgid "End Date"
103
+ msgstr ""
104
+
105
+ #: ../export-user-data.php:720
106
+ msgid "Pick a start and end user registration date to limit the results."
107
+ msgstr ""
108
+
109
+ #: ../export-user-data.php:727
110
+ msgid "Limit Range"
111
+ msgstr ""
112
+
113
+ #: ../export-user-data.php:729
114
+ msgid "Offset"
115
+ msgstr ""
116
+
117
+ #: ../export-user-data.php:730
118
+ msgid "Total"
119
+ msgstr ""
120
+
121
+ #: ../export-user-data.php:733
122
+ #, php-format
123
+ msgid ""
124
+ "Enter an offset start number and a total number of users to export. <a href="
125
+ "\"%s\" target=\"_blank\">%s</a>"
126
+ msgstr ""
127
+
128
+ #: ../export-user-data.php:742
129
+ msgid "Format"
130
+ msgstr ""
131
+
132
+ #: ../export-user-data.php:747
133
+ msgid "Excel"
134
+ msgstr ""
135
+
136
+ #: ../export-user-data.php:748
137
+ msgid "CSV"
138
+ msgstr ""
139
+
140
+ #: ../export-user-data.php:754
141
+ msgid "Select the format for the export file."
142
+ msgstr ""
143
+
144
+ #: ../export-user-data.php:762
145
+ msgid "Advanced Options"
146
+ msgstr ""
147
+
148
+ #: ../export-user-data.php:766 ../export-user-data.php:840
149
+ msgid "Show"
150
+ msgstr ""
151
+
152
+ #: ../export-user-data.php:774
153
+ msgid "Export"
154
+ msgstr ""
155
+
156
+ #: ../export-user-data.php:838
157
+ msgid "Hide"
158
+ msgstr ""
library/languages/export-user-data-el.mo ADDED
Binary file
library/languages/export-user-data-el.po ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Export User Data\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/export-users-to-csv\n"
5
+ "POT-Creation-Date: 2014-03-15 09:46-0000\n"
6
+ "PO-Revision-Date: 2015-05-26 16:27+0200\n"
7
+ "Last-Translator: Ray <ray@qstudio.us>\n"
8
+ "Language-Team: Q Studio <team@qstudio.us>\n"
9
+ "Language: en\n"
10
+ "MIME-Version: 1.0\n"
11
+ "Content-Type: text/plain; charset=UTF-8\n"
12
+ "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 1.7.5\n"
14
+ "X-Poedit-KeywordsList: _;_e;_n;__\n"
15
+ "X-Poedit-Basepath: .\n"
16
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
+ "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+ "X-Poedit-SearchPath-1: ..\n"
20
+
21
+ #: ../export-user-data.php:85 ../export-user-data.php:450
22
+ msgid "Export User Data"
23
+ msgstr "Εξαγωγή Δεδομένων Χρήστη"
24
+
25
+ #: ../export-user-data.php:445
26
+ msgid "You do not have sufficient permissions to access this page."
27
+ msgstr "Δεν έχετε επαρκή δικαιώματα για πρόσβαση στη σελίδα."
28
+
29
+ #: ../export-user-data.php:455
30
+ msgid "No users found."
31
+ msgstr "Δεν βρέθηκαν χρήστες"
32
+
33
+ #: ../export-user-data.php:511
34
+ msgid "User Meta Fields"
35
+ msgstr "Meta Πεδία Χρήστη"
36
+
37
+ #: ../export-user-data.php:513
38
+ msgid "Filter"
39
+ msgstr "Φίλτράρισμα"
40
+
41
+ #: ../export-user-data.php:513
42
+ msgid "All"
43
+ msgstr "Όλα"
44
+
45
+ #: ../export-user-data.php:513
46
+ msgid "Common"
47
+ msgstr "Κοινά"
48
+
49
+ #: ../export-user-data.php:564
50
+ msgid ""
51
+ "Select the user meta keys to export, use the filters to simplify the list."
52
+ msgstr ""
53
+ "Επιλέξτε τα meta κλειδιά του χρήστη προς εξαγωγή, χρησιμοποιήστε το "
54
+ "φιλτράρισμα για να απλοποιήσετε τη λίστα."
55
+
56
+ #: ../export-user-data.php:593
57
+ msgid "BP xProfile Fields"
58
+ msgstr "BP xProfile Πεδία"
59
+
60
+ #: ../export-user-data.php:614
61
+ msgid "Select the BuddyPress XProfile keys to export"
62
+ msgstr "Επιλέξτε τα BuddyPress XProfile κλειδιά προς εξαγωγή."
63
+
64
+ #: ../export-user-data.php:626
65
+ msgid "BP xProfile Fields Update Time"
66
+ msgstr "Ενημέρωση ώρας BP xProfile Πεδίων"
67
+
68
+ #: ../export-user-data.php:642
69
+ msgid "Select the BuddyPress XProfile keys updated dates to export"
70
+ msgstr ""
71
+ "Επιλέξτε τις ημερομηνίες ενημέρωσης των BuddyPress XProfile κλειδιών προς "
72
+ "εξαγωγή."
73
+
74
+ #: ../export-user-data.php:653
75
+ msgid "Role"
76
+ msgstr "Ρόλοι"
77
+
78
+ #: ../export-user-data.php:658
79
+ msgid "All Roles"
80
+ msgstr "Όλοι οι Ρόλοι"
81
+
82
+ #: ../export-user-data.php:668
83
+ #, php-format
84
+ msgid ""
85
+ "Filter the exported users by a WordPress Role. <a href=\"%s\" target=\"_blank"
86
+ "\">%s</a>"
87
+ msgstr ""
88
+ "Φιλτράρετε τους χρήστες προς εξαγωγή ως προς το Wordpress ρόλο τους. <a href="
89
+ "\"%s\" target=\"_blank\">%s</a>"
90
+
91
+ #: ../export-user-data.php:682
92
+ msgid "Programs"
93
+ msgstr "Προγράμματα"
94
+
95
+ #: ../export-user-data.php:687
96
+ msgid "All Programs"
97
+ msgstr "Όλα τα προγράμματα"
98
+
99
+ #: ../export-user-data.php:708
100
+ msgid "Registered"
101
+ msgstr "Εγγεγραμμένοι"
102
+
103
+ #: ../export-user-data.php:711
104
+ msgid "Start Date"
105
+ msgstr "Ημερομηνία Έναρξης"
106
+
107
+ #: ../export-user-data.php:715
108
+ msgid "End Date"
109
+ msgstr "Ημερομηνία Λήξης"
110
+
111
+ #: ../export-user-data.php:720
112
+ msgid "Pick a start and end user registration date to limit the results."
113
+ msgstr ""
114
+ "Επιλέξτε ημερομηνία έναρξης και λήξης για να περιορίσετε τα αποτελέσματα."
115
+
116
+ #: ../export-user-data.php:727
117
+ msgid "Limit Range"
118
+ msgstr "Εύρος"
119
+
120
+ #: ../export-user-data.php:729
121
+ msgid "Offset"
122
+ msgstr "Offset"
123
+
124
+ #: ../export-user-data.php:730
125
+ msgid "Total"
126
+ msgstr "Σύνολο"
127
+
128
+ #: ../export-user-data.php:733
129
+ #, php-format
130
+ msgid ""
131
+ "Enter an offset start number and a total number of users to export. <a href="
132
+ "\"%s\" target=\"_blank\">%s</a>"
133
+ msgstr ""
134
+ "Πληκτρολογήστε έναν offset αριθμό έναρξης και το συνολικό αριθμό των χρηστών "
135
+ "προς εξαγωγή. <a href=\"%s\" target=\"_blank\">%s</a>"
136
+
137
+ #: ../export-user-data.php:742
138
+ msgid "Format"
139
+ msgstr "Φορμάτ"
140
+
141
+ #: ../export-user-data.php:747
142
+ msgid "Excel"
143
+ msgstr "Excel"
144
+
145
+ #: ../export-user-data.php:748
146
+ msgid "CSV"
147
+ msgstr "CSV"
148
+
149
+ #: ../export-user-data.php:754
150
+ msgid "Select the format for the export file."
151
+ msgstr "Επιλέξτε το format για το αρχείο προς εξαγωγή."
152
+
153
+ #: ../export-user-data.php:762
154
+ msgid "Advanced Options"
155
+ msgstr "Σύνθετες επιλογές"
156
+
157
+ #: ../export-user-data.php:766 ../export-user-data.php:840
158
+ msgid "Show"
159
+ msgstr "Προβολή"
160
+
161
+ #: ../export-user-data.php:774
162
+ msgid "Export"
163
+ msgstr "Εξαγωγή"
164
+
165
+ #: ../export-user-data.php:838
166
+ msgid "Hide"
167
+ msgstr "Απόκρυψη"
library/languages/export-user-data-es_ES.mo ADDED
Binary file
library/languages/export-user-data-es_ES.po ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Export User Data\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/export-users-to-csv\n"
5
+ "POT-Creation-Date: 2014-03-15 09:46-0000\n"
6
+ "PO-Revision-Date: Tue Dec 15 2015 15:03:14 GMT+0100 (Hora estándar romance)\n"
7
+ "Last-Translator: elias <elias@estudions.es>\n"
8
+ "Language-Team: Q Studio <team@qstudio.us>\n"
9
+ "Language: Spanish (Spain)\n"
10
+ "Plural-Forms: nplurals=2; plural=n != 1\n"
11
+ "MIME-Version: 1.0\n"
12
+ "Content-Type: text/plain; charset=UTF-8\n"
13
+ "Content-Transfer-Encoding: 8bit\n"
14
+ "X-Poedit-SourceCharset: UTF-8\n"
15
+ "X-Generator: Loco - https://localise.biz/\n"
16
+ "X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
17
+ "__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
18
+ "_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
19
+ "esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
20
+ "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
21
+ "X-Poedit-Basepath: .\n"
22
+ "X-Poedit-SearchPath-0: .\n"
23
+ "X-Poedit-SearchPath-1: ..\n"
24
+ "X-Loco-Target-Locale: es_ES"
25
+
26
+ #: ../export-user-data.php:626
27
+ msgid "BP xProfile Fields Update Time"
28
+ msgstr ""
29
+
30
+ #: ../export-user-data.php:642
31
+ msgid "Select the BuddyPress XProfile keys updated dates to export"
32
+ msgstr ""
33
+
34
+ #: ../export-user-data.php:682
35
+ msgid "Programs"
36
+ msgstr ""
37
+
38
+ #: ../export-user-data.php:687
39
+ msgid "All Programs"
40
+ msgstr ""
41
+
42
+ #: ../export-user-data.php:729
43
+ msgid "Offset"
44
+ msgstr ""
45
+
46
+ #: ../export-user-data.php:733
47
+ #, php-format
48
+ msgid ""
49
+ "Enter an offset start number and a total number of users to export. <a "
50
+ "href=\"%s\" target=\"_blank\">%s</a>"
51
+ msgstr ""
52
+
53
+ #: ../export-user-data.php:762
54
+ msgid "Advanced Options"
55
+ msgstr "Opciones avanzadas"
56
+
57
+ #: ../export-user-data.php:766 ../export-user-data.php:840
58
+ msgid "Show"
59
+ msgstr "Mostrar"
60
+
61
+ #: ../export-user-data.php:774
62
+ msgid "Export"
63
+ msgstr "Exportar"
64
+
65
+ #: ../export-user-data.php:838
66
+ msgid "Hide"
67
+ msgstr "Ocultar"
68
+
69
+ #: ../export-user-data.php:85 ../export-user-data.php:450
70
+ msgid "Export User Data"
71
+ msgstr "Exportar datos de Usuarios"
72
+
73
+ #: ../export-user-data.php:445
74
+ msgid "You do not have sufficient permissions to access this page."
75
+ msgstr "No tienes suficientes permisos para acceder a esta página."
76
+
77
+ #: ../export-user-data.php:455
78
+ msgid "No users found."
79
+ msgstr "No se han encontrado usuarios"
80
+
81
+ #: ../export-user-data.php:511
82
+ msgid "User Meta Fields"
83
+ msgstr "Campos 'meta' de los usuarios"
84
+
85
+ #: ../export-user-data.php:513
86
+ msgid "Filter"
87
+ msgstr "Filtrar"
88
+
89
+ #: ../export-user-data.php:513
90
+ msgid "All"
91
+ msgstr "Todo"
92
+
93
+ #: ../export-user-data.php:513
94
+ msgid "Common"
95
+ msgstr "Común"
96
+
97
+ #: ../export-user-data.php:564
98
+ msgid "Select the user meta keys to export, use the filters to simplify the list."
99
+ msgstr "Elige las claves 'meta' a export, usa el filtro para reducir la lista."
100
+
101
+ #: ../export-user-data.php:593
102
+ msgid "BP xProfile Fields"
103
+ msgstr "Campos 'xProfile' de BuddyPress"
104
+
105
+ #: ../export-user-data.php:614
106
+ msgid "Select the BuddyPress XProfile keys to export"
107
+ msgstr "Elige los campos 'xProfile' de BuddyPress a exportar"
108
+
109
+ #: ../export-user-data.php:653
110
+ msgid "Role"
111
+ msgstr "Rol"
112
+
113
+ #: ../export-user-data.php:658
114
+ msgid "All Roles"
115
+ msgstr "Todos los Roles"
116
+
117
+ #: ../export-user-data.php:668
118
+ #, php-format
119
+ msgid ""
120
+ "Filter the exported users by a WordPress Role. <a href=\"%s\" "
121
+ "target=\"_blank\">%s</a>"
122
+ msgstr ""
123
+ "Filtrar los usuarios exportados por un Rol de WordPress. <a href=\"%s\" "
124
+ "target=\"_blank\">%s</a>"
125
+
126
+ #: ../export-user-data.php:708
127
+ msgid "Registered"
128
+ msgstr "Registrado"
129
+
130
+ #: ../export-user-data.php:711
131
+ msgid "Start Date"
132
+ msgstr "Fecha de inicio"
133
+
134
+ #: ../export-user-data.php:715
135
+ msgid "End Date"
136
+ msgstr "Fecha final"
137
+
138
+ #: ../export-user-data.php:720
139
+ msgid "Pick a start and end user registration date to limit the results."
140
+ msgstr ""
141
+ "Elige un intervalo de fechas de registro del usuario para reducir los "
142
+ "resultados."
143
+
144
+ #: ../export-user-data.php:727
145
+ msgid "Limit Range"
146
+ msgstr "Limitar intervalo"
147
+
148
+ #: ../export-user-data.php:730
149
+ msgid "Total"
150
+ msgstr "Total"
151
+
152
+ #: ../export-user-data.php:742
153
+ msgid "Format"
154
+ msgstr "Formato"
155
+
156
+ #: ../export-user-data.php:747
157
+ msgid "Excel"
158
+ msgstr "Excel"
159
+
160
+ #: ../export-user-data.php:748
161
+ msgid "CSV"
162
+ msgstr "CSV"
163
+
164
+ #: ../export-user-data.php:754
165
+ msgid "Select the format for the export file."
166
+ msgstr "Elige el formato para el fichero que se exportará."
library/languages/export-user-data-fr_FR.mo ADDED
Binary file
library/languages/export-user-data-fr_FR.po ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Export User Data\n"
4
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/export-users-to-csv\n"
5
+ "POT-Creation-Date: 2014-01-26 00:56+0100\n"
6
+ "PO-Revision-Date: 2014-03-13 14:08+0100\n"
7
+ "Last-Translator: aurélie <administratif@urbancube.fr>\n"
8
+ "Language-Team: urbancube <contact@urbancube.fr>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.6.4\n"
13
+ "X-Poedit-KeywordsList: _;_e;_n;__\n"
14
+ "X-Poedit-Basepath: .\n"
15
+ "Plural-Forms: nplurals=2; plural=(n > 1);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "Language: fr\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+ "X-Poedit-SearchPath-1: ..\n"
20
+
21
+ #: ../export-user-data.php:85 ../export-user-data.php:450
22
+ msgid "Export User Data"
23
+ msgstr "Exportez les données utilisateurs."
24
+
25
+ #: ../export-user-data.php:445
26
+ msgid "You do not have sufficient permissions to access this page."
27
+ msgstr "Vous n'avez pas la permission d'accéder à cette page."
28
+
29
+ #: ../export-user-data.php:455
30
+ msgid "No users found."
31
+ msgstr "Aucun utilisateur trouvé."
32
+
33
+ #: ../export-user-data.php:511
34
+ msgid "User Meta Fields"
35
+ msgstr "Champs de balise utilisateurs"
36
+
37
+ #: ../export-user-data.php:513
38
+ msgid "Filter"
39
+ msgstr "Filtre"
40
+
41
+ #: ../export-user-data.php:513
42
+ msgid "All"
43
+ msgstr "Tous"
44
+
45
+ #: ../export-user-data.php:513
46
+ msgid "Common"
47
+ msgstr "Commun"
48
+
49
+ #: ../export-user-data.php:564
50
+ msgid ""
51
+ "Select the user meta keys to export, use the filters to simplify the list."
52
+ msgstr ""
53
+ "Choisissez les balises clés d'utilisateur pour exporter, utiliser les "
54
+ "filtres pour simplifier la liste."
55
+
56
+ #: ../export-user-data.php:593
57
+ msgid "BP xProfile Fields"
58
+ msgstr "Champs BP xProfile"
59
+
60
+ #: ../export-user-data.php:614
61
+ msgid "Select the BuddyPress XProfile keys to export"
62
+ msgstr "Choisissez le bouton BuddyPress XProfile pour exporter"
63
+
64
+ #: ../export-user-data.php:626
65
+ msgid "BP xProfile Fields Update Time"
66
+ msgstr "Champs de temps passé BP xProfile"
67
+
68
+ #: ../export-user-data.php:642
69
+ msgid "Select the BuddyPress XProfile keys updated dates to export"
70
+ msgstr ""
71
+ "Choisissez les touches BuddyPress XProfile des dates mises à jour pour "
72
+ "exporter"
73
+
74
+ #: ../export-user-data.php:653
75
+ msgid "Role"
76
+ msgstr "Rôle"
77
+
78
+ #: ../export-user-data.php:658
79
+ msgid "All Roles"
80
+ msgstr "Tous les rôles"
81
+
82
+ #: ../export-user-data.php:668
83
+ #, php-format
84
+ msgid ""
85
+ "Filter the exported users by a WordPress Role. <a href=\"%s\" target=\"_blank"
86
+ "\">%s</a>"
87
+ msgstr ""
88
+ "Filtrez les utilisateurs exportés par un Rôle WordPress. <a href=\"%s\" "
89
+ "target=\"_blank\">%s</a>"
90
+
91
+ #: ../export-user-data.php:682
92
+ msgid "Programs"
93
+ msgstr "Programmes"
94
+
95
+ #: ../export-user-data.php:687
96
+ msgid "All Programs"
97
+ msgstr "Tous les programmes"
98
+
99
+ #: ../export-user-data.php:708
100
+ msgid "Registered"
101
+ msgstr "Enregistré"
102
+
103
+ #: ../export-user-data.php:711
104
+ msgid "Start Date"
105
+ msgstr "Date de début"
106
+
107
+ #: ../export-user-data.php:715
108
+ msgid "End Date"
109
+ msgstr "Date de fin"
110
+
111
+ #: ../export-user-data.php:720
112
+ msgid "Pick a start and end user registration date to limit the results."
113
+ msgstr ""
114
+ "Choisissez une date de début et de fin d'enregistrement utilisateur pour "
115
+ "limiter les résultats."
116
+
117
+ #: ../export-user-data.php:727
118
+ msgid "Limit Range"
119
+ msgstr "Limite supérieure"
120
+
121
+ #: ../export-user-data.php:729
122
+ msgid "From"
123
+ msgstr "De"
124
+
125
+ #: ../export-user-data.php:730
126
+ msgid "To"
127
+ msgstr "A"
128
+
129
+ #: ../export-user-data.php:733
130
+ #, php-format
131
+ msgid ""
132
+ "Enter an offset start number and a total number to export. <a href=\"%s\" "
133
+ "target=\"_blank\">%s</a>"
134
+ msgstr "Entrez un nombre de début décalé et un nombre total pour exporter"
135
+
136
+ #: ../export-user-data.php:742
137
+ msgid "Format"
138
+ msgstr "Format"
139
+
140
+ #: ../export-user-data.php:747
141
+ msgid "Excel"
142
+ msgstr "Excel"
143
+
144
+ #: ../export-user-data.php:748
145
+ msgid "CSV"
146
+ msgstr "CSV"
147
+
148
+ #: ../export-user-data.php:754
149
+ msgid "Select the format for the export file."
150
+ msgstr "Choisissez le format d'exportation du fichier."
151
+
152
+ #: ../export-user-data.php:762
153
+ msgid "Advanced Options"
154
+ msgstr "Options avancées"
155
+
156
+ #: ../export-user-data.php:766 ../export-user-data.php:840
157
+ msgid "Show"
158
+ msgstr "Montrer"
159
+
160
+ #: ../export-user-data.php:774
161
+ msgid "Export"
162
+ msgstr "Export"
163
+
164
+ #: ../export-user-data.php:838
165
+ msgid "Hide"
166
+ msgstr "En cache"
readme.md CHANGED
@@ -1,198 +1,23 @@
1
- # Export User Data #
2
- **Contributors:** qlstudio
3
- **Tags:** user, users, xprofile, usermeta csv, excel, batch, export, save, download
4
- **Requires at least:** 3.2
5
- **Tested up to:** 4.4.2
6
- **Stable tag:** 1.3.1
7
- **License:** GPLv2
8
-
9
- Export users data, metadata and buddypress xprofile data to a csv or Excel file
10
-
11
- ## Description ##
12
-
13
- A plugin that exports all user data, meta data and BuddyPress xProfile data.
14
-
15
- Includes an option to export the users by role, registration date range, usermeta option and two export formats.
16
-
17
- ### Features ###
18
-
19
- * Exports all users fields
20
- * Exports users meta
21
- * Exports users by role
22
- * Exports users by date range
23
- * Export user BuddyPress xProfile data
24
-
25
- For feature request and bug reports, [please use the Q Support Website](https://qstudio.us/support/categories/export-user-data).
26
-
27
- Please do not use the Wordpress.org forum to report bugs, as we no longer monitor or respond to questions there.
28
-
29
- ## Installation ##
30
-
31
- For an automatic installation through WordPress:
32
-
33
- 1. Go to the 'Add New' plugins screen in your WordPress admin area
34
- 2. Search for 'Export User Data'
35
- 3. Click 'Install Now' and activate the plugin
36
- 4. Go the 'Export User Data' menu, under 'Users'
37
-
38
- For a manual installation via FTP:
39
-
40
- 1. Upload the `export-user-data` directory to the `/wp-content/plugins/` directory
41
- 2. Activate the plugin through the 'Plugins' screen in your WordPress admin area
42
- 3. Go the 'Export User Data' menu, under 'Users'
43
-
44
- To upload the plugin through WordPress, instead of FTP:
45
-
46
- 1. Upload the downloaded zip file on the 'Add New' plugins screen (see the 'Upload' tab) in your WordPress admin area and activate.
47
- 2. Go the 'Export User Data' menu, under 'Users'
48
-
49
- ## Frequently Asked Questions ##
50
-
51
- ### How to use? ###
52
-
53
- Click on the 'Export User Data' link in the 'Users' menu, choose the role and the date range or don't select anything if you want to export all users, then click 'Export'. That's all!
54
-
55
- ## Screenshots ##
56
-
57
- ### 1. User export screen ###
58
- ![ScreenShot](http://s.w.org/plugins/export-user-data/screenshot-1.png?r=859689)
59
-
60
- ## Changelog ##
61
-
62
- *** 1.3.1 ***
63
- * Moved all internal action hooks to admin_init to allow for internal function loading
64
-
65
- *** 1.3.0 ***
66
- * Added extra data sanitization before outputting to file - thanks to Hely Shah <helyhshah@gmail.com> for te heads-up
67
-
68
- *** 1.2.8 ***
69
- * New: Added load_buddypress() methods to test for buddypress and load up if missing
70
- * New: move action hooks and priority to load later
71
- * New: Plugin no longer uses singleton model to instatiate - instead called from action hook to public function
72
- * New: added log() to debug.log file to help debugging issues
73
- * Update: jQuery datepickers pull start_of_week value from WordPress
74
- * Tested on 4.4.2
75
-
76
- *** 1.2.7 ***
77
- * Added: Spanish translation - thanks Elías Gómez Sainz ( elias@estudions.es )
78
-
79
- *** 1.2.6 ***
80
- * Update: WP 4.4.1
81
-
82
- ### 1.2.3 ###
83
- * Fix: to remove minor security loop hole
84
- * New: Added option to remove standard wp_users data from export
85
- * Fix: removed roles and groups columns from export when options hidden
86
-
87
- ### 1.2.2 ###
88
- * Minor FIxes
89
-
90
- ### 1.2.1 ###
91
- * Checked on WP 4.3.1
92
- * Moved text-domain to string in preperation for addition to translate.wordpress.org
93
- * Added Log() method to allow for debugging to WP Error Log
94
- * Added Greek translation - Thanks @Leonidas Mi
95
- * Added option to limit export by last_updated date of specific xprofile field - Thanks to @cwjordan
96
-
97
- ### 1.2.0 ###
98
- * Data stored in recursive and serialized arrays is now exported in a flat string format with safe delimiters ( ||, ||| - etc. )
99
-
100
- ### 1.1.1 ###
101
- * Removed accidently included .git files
102
-
103
- ### 1.1.0 ###
104
- * Version change to sync SVN on wordpress.org
105
-
106
- ### 1.0.4 ###
107
- * Added unserialize function with @ fallback
108
- * Removed anonymous function to allow support for PHP < 5.2
109
-
110
- ### 1.0.3 ###
111
- * Tested as working on WordPress 4.1.0.
112
-
113
- ### 1.0.2 ###
114
- * Removed get_user_meta method, as not effective.
115
- * Added registration date from and to pickers - to replace monthly <select> lists.
116
-
117
- ### 1.0.1 ###
118
- * Added recursive_implode() method to flatten data stored in arrays ( exported with keys and values divided by "|" )
119
-
120
- ### 1.0.0 ###
121
- * Reduced all get_user_meta queries to a single call to improve performance
122
- * Serialized data is now returned in it's pure stored format - not imploded or unserialized to avoid data structure loss
123
-
124
- ### 0.9.9 ###
125
- * get_uermeta renamed get_user_meta to be more consistent with WP
126
- * get_user_meta tidied up and tested on larger exports
127
- * added option to export user BP Groups
128
- * added option to export all user WP Roles
129
-
130
- ### 0.9.8 ###
131
- * added get_usermeta() to check if meta keys are unique and return an array if not
132
- * removed known_arrays() filter to allow for array data to be returned correctly - too hacky
133
-
134
- ### 0.9.7 ###
135
- * Added known_arrays() filter to allow for array data to be returned correctly
136
-
137
- ### 0.9.6 ###
138
- * Save, load and delete stored export settings - thanks to @cwjordan
139
- * Overcome memory outages on large exports - thanks to @grexican
140
- * Tested on WP 4.0.0 & BP 2.1.0
141
-
142
- ### 0.9.5 ###
143
- * BP Serialized data fixes - thanks to @nicmare & @grexican
144
- * Tested on WP 3.9.2 & BP 2.0.2
145
-
146
- ### 0.9.4 ###
147
- * BP X Profile Export Fix ( > version 2.0 )
148
-
149
- ### 0.9.3 ###
150
- * fix for hidden admin bar
151
-
152
- ### 0.9.2 ###
153
- * removed $key assignment casting to integer
154
-
155
- ### 0.9.1 ###
156
- * Tested with WP 3.9
157
- * Fix for BuddyPress 2.0 bug
158
-
159
- ### 0.9.0 ###
160
- * Moved plugin class to singleton model
161
- * Improved language handling
162
- * French translation - thanks @bastho - http://wordpress.org/support/profile/bastho
163
-
164
- ### 0.8.3 ###
165
- * clarified export limit options
166
-
167
- ### 0.8.2 ###
168
- * corrected buddypress export option - broken in 0.8.1
169
- * changed get_users arguments, in attempt to reduce memory usage
170
-
171
- ### 0.8.1 ###
172
- * Added experimental range limiter for exports
173
- * Extra input data sanitizing
174
-
175
- ### 0.8 ###
176
- * moved plugin instatiation to the WP hook: init
177
- * moved bp calls outside export loop
178
- * added extra isset calls on values in export loop to clean up error log not sets
179
-
180
- ### 0.7.8 ###
181
- * added xml template for Excel exports - thanks to phil@fixitlab.com :)
182
-
183
- ### 0.7.2 ###
184
- * fixes to allow exports without selecting extra user date from usermeta or x-profile
185
-
186
- ### 0.6.3 ###
187
- * added multiselect to pick usermeta and xprofile fields
188
-
189
- ### 0.5 ###
190
- * First public release.
191
-
192
- ## Upgrade Notice ##
193
-
194
- ### 0.6.3 ###
195
- Latest.
196
-
197
- ### 0.5 ###
198
- First release.
1
+ # Export User Data #
2
+
3
+ **Contributors:** qlstudio
4
+ **Tags:** user, users, xprofile, usermeta csv, excel, batch, export, save, download
5
+ **Requires at least:** 5.0.0
6
+ **Tested up to:** 5.0.0
7
+ **Stable tag:** 2.0.1
8
+ **License:** GPLv2
9
+
10
+ Export users data and metadata to a csv or Excel file
11
+
12
+ ## Description ##
13
+
14
+ A plugin that exports WordPress user data and metadata.
15
+
16
+ Includes an option to export the users by role, registration date range, usermeta option and two export formats.
17
+
18
+ ### Features ###
19
+
20
+ * Exports all users fields
21
+ * Exports users meta
22
+ * Exports users by role
23
+ * Exports users by date range
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,205 +1,9 @@
1
  === Export User Data ===
2
  Contributors: qlstudio
3
  Tags: user, users, xprofile, usermeta csv, excel, batch, export, save, download
4
- Requires at least: 3.2
5
- Tested up to: 4.4.2
6
- Stable tag: 1.3.1
7
  License: GPLv2
8
 
9
- Export users data, metadata and buddypress xprofile data to a csv or Excel file
10
-
11
- == Description ==
12
-
13
- A plugin that exports all user data, meta data and BuddyPress xProfile data.
14
-
15
- Includes an option to export the users by role, registration date range, usermeta option and two export formats.
16
-
17
- = Features =
18
-
19
- * Exports all users fields
20
- * Exports users meta
21
- * Exports users by role
22
- * Exports users by date range
23
- * Export user BuddyPress xProfile data
24
-
25
- For feature request and bug reports, [please use the Q Support Website](https://qstudio.us/support/categories/export-user-data).
26
-
27
- Please do not use the Wordpress.org forum to report bugs, as we no longer monitor or respond to questions there.
28
-
29
- == Installation ==
30
-
31
- For an automatic installation through WordPress:
32
-
33
- 1. Go to the 'Add New' plugins screen in your WordPress admin area
34
- 2. Search for 'Export User Data'
35
- 3. Click 'Install Now' and activate the plugin
36
- 4. Go the 'Export User Data' menu, under 'Users'
37
-
38
- For a manual installation via FTP:
39
-
40
- 1. Upload the `export-user-data` directory to the `/wp-content/plugins/` directory
41
- 2. Activate the plugin through the 'Plugins' screen in your WordPress admin area
42
- 3. Go the 'Export User Data' menu, under 'Users'
43
-
44
- To upload the plugin through WordPress, instead of FTP:
45
-
46
- 1. Upload the downloaded zip file on the 'Add New' plugins screen (see the 'Upload' tab) in your WordPress admin area and activate.
47
- 2. Go the 'Export User Data' menu, under 'Users'
48
-
49
- == Frequently Asked Questions ==
50
-
51
- = How to use? =
52
-
53
- Click on the 'Export User Data' link in the 'Users' menu, choose the role and the date range or don't select anything if you want to export all users, then click 'Export'. That's all!
54
-
55
- == Screenshots ==
56
-
57
- 1. User export screen
58
-
59
- == Changelog ==
60
-
61
- = 1.3.1 =
62
- * Moved all internal action hooks to admin_init to allow for internal function loading
63
-
64
- = 1.3.0 =
65
- * Added extra data sanitization before outputting to file - thanks to Hely Shah <helyhshah@gmail.com> for the heads-up
66
-
67
- = 1.2.8 =
68
- * New: Added load_buddypress() methods to test for buddypress and load up if missing
69
- * New: move action hooks and priority to load later
70
- * New: Plugin no longer uses singleton model to instatiate - instead called from action hook to public function
71
- * New: added log() to debug.log file to help debugging issues
72
- * Update: jQuery datepickers pull start_of_week value from WordPress
73
- * Tested on 4.4.2
74
-
75
- = 1.2.7 =
76
- * Added: Spanish translation - thanks Elías Gómez Sainz ( elias@estudions.es )
77
-
78
- = 1.2.6 =
79
- * Update: WP 4.4.1
80
-
81
- = 1.2.4 =
82
- * Fix: Removed comments to screen
83
-
84
- = 1.2.3 =
85
- * Fix: to remove minor security loop hole
86
- * New: Added option to remove standard wp_users data from export
87
- * Fix: removed roles and groups columns from export when options hidden
88
-
89
- = 1.2.2 =
90
- * Minor Fixes
91
-
92
- = 1.2.1 =
93
- * Checked on WP 4.3.1
94
- * Moved text-domain to string in preperation for addition to translate.wordpress.org
95
- * Added Log() method to allow for debugging to WP Error Log
96
- * Added Greek translation - Thanks @Leonidas Mi
97
- * Added option to limit export by last_updated date of specific xprofile field - Thanks to @cwjordan
98
-
99
- = 1.2.0 =
100
- * Data stored in recursive and serialized arrays is now exported in a flat string format with safer delimiters ( ||, ||| - etc. )
101
- * Removed anonymous function calls giving errors on older versions of PHP
102
-
103
- = 1.1.1 =
104
- * Removed accidently included .git files
105
-
106
- = 1.1.0 =
107
- * Version change to sync SVN on wordpress.org
108
-
109
- = 1.1.1 =
110
- * Removed accidently included .git files
111
-
112
- = 1.1.0 =
113
- = 1.0.4 =
114
- * Added unserialize function with @ fallback
115
- * Removed anonymous function to allow support for PHP < 5.2
116
-
117
- = 1.0.3 =
118
- * Tested as working on WordPress 4.1.0.
119
-
120
- = 1.0.2 =
121
- * Removed get_user_meta method, as not effective.
122
- * Added registration date from and to pickers - to replace monthly <select> lists.
123
-
124
- = 1.0.1 =
125
- * Added recursive_implode() method to flatten data stored in arrays ( exported with keys and values divided by "|" )
126
-
127
- = 1.0.0 =
128
- * Reduced all get_user_meta queries to a single call to improve performance
129
- * Serialized data is now returned in it's pure stored format - not imploded or unserialized to avoid data structure loss
130
-
131
- = 0.9.9 =
132
- * get_uermeta renamed get_user_meta to be more consistent with WP
133
- * get_user_meta tidied up and tested on larger exports
134
- * added option to export user BP Groups
135
- * added option to export all user WP Roles
136
-
137
- = 0.9.8 =
138
- * added get_usermeta() to check if meta keys are unique and return an array if not
139
- * removed known_arrays() filter to allow for array data to be returned correctly - too hacky
140
-
141
- = 0.9.7 =
142
- * Added known_arrays() filter to allow for array data to be returned correctly
143
-
144
- = 0.9.6 =
145
- * Save, load and delete stored export settings - thanks to @cwjordan
146
- * Overcome memory outages on large exports - thanks to @grexican
147
- * Tested on WP 4.0.0 & BP 2.1.0
148
-
149
- = 0.9.5 =
150
- * BP Serialized data fixes - thanks to @nicmare & @grexican
151
- * Tested on WP 3.9.2 & BP 2.0.2
152
-
153
- = 0.9.4 =
154
- * BP X Profile Export Fix ( > version 2.0 )
155
-
156
- = 0.9.3 =
157
- * fix for hidden admin bar
158
-
159
- = 0.9.2 =
160
- * removed $key assignment casting to integer
161
-
162
- = 0.9.1 =
163
- * Tested with WP 3.9
164
- * Fix for BuddyPress 2.0 bug
165
-
166
- = 0.9.0 =
167
- * Moved plugin class to singleton model
168
- * Improved language handling
169
- * French translation - thanks @bastho - http://wordpress.org/support/profile/bastho
170
-
171
- = 0.8.3 =
172
- * clarified export limit options
173
-
174
- = 0.8.2 =
175
- * corrected buddypress export option - broken in 0.8.1
176
- * changed get_users arguments, in attempt to reduce memory usage
177
-
178
- = 0.8.1 =
179
- * Added experimental range limiter for exports
180
- * Extra input data sanitizing
181
-
182
- = 0.8 =
183
- * moved plugin instatiation to the WP hook: init
184
- * moved bp calls outside export loop
185
- * added extra isset calls on values in export loop to clean up error log not sets
186
-
187
- = 0.7.8 =
188
- * added xml template for Excel exports - thanks to phil@fixitlab.com :)
189
-
190
- = 0.7.2 =
191
- * fixes to allow exports without selecting extra user date from usermeta or x-profile
192
-
193
- = 0.6.3 =
194
- * added multiselect to pick usermeta and xprofile fields
195
-
196
- = 0.5 =
197
- * First public release.
198
-
199
- == Upgrade Notice ==
200
-
201
- = 0.6.3 =
202
- Latest.
203
-
204
- = 0.5 =
205
- First release.
1
  === Export User Data ===
2
  Contributors: qlstudio
3
  Tags: user, users, xprofile, usermeta csv, excel, batch, export, save, download
4
+ Requires at least: 4.8.0
5
+ Tested up to: 5.0.0
6
+ Stable tag: 2.0.1
7
  License: GPLv2
8
 
9
+ Export users data and metadata to a csv or Excel fil