Export User Data - Version 1.0.3

Version Description

  • Tested as working on WordPress 4.1.0.
Download this release

Release Info

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

Code changes from version 0.9.6 to 1.0.3

Files changed (5) hide show
  1. css/export-user-data.css +1 -1
  2. css/multi-select.css +0 -97
  3. export-user-data.php +426 -170
  4. readme.md +29 -2
  5. readme.txt +29 -2
css/export-user-data.css CHANGED
@@ -71,7 +71,7 @@ th p.filter {
71
  -moz-border-radius: 3px;
72
  border-radius: 3px;
73
  position: relative;
74
- height: 200px;
75
  padding: 0;
76
  overflow-y: auto;
77
  }
71
  -moz-border-radius: 3px;
72
  border-radius: 3px;
73
  position: relative;
74
+ height: 134px;
75
  padding: 0;
76
  overflow-y: auto;
77
  }
css/multi-select.css DELETED
@@ -1,97 +0,0 @@
1
- .ms-container{
2
- background: transparent url('../img/switch.png') no-repeat 50% 50%;
3
- width: 600px;
4
- }
5
-
6
- .ms-container:after{
7
- content: ".";
8
- display: block;
9
- height: 0;
10
- line-height: 0;
11
- font-size: 0;
12
- clear: both;
13
- min-height: 0;
14
- visibility: hidden;
15
- }
16
-
17
- .ms-container .ms-selectable, .ms-container .ms-selection{
18
- background: #fff;
19
- color: #555555;
20
- float: left;
21
- width: 45%;
22
- }
23
-
24
- .ms-container .ms-list{
25
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
26
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
27
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
28
- -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
29
- -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
30
- -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
31
- -o-transition: border linear 0.2s, box-shadow linear 0.2s;
32
- transition: border linear 0.2s, box-shadow linear 0.2s;
33
- border: 1px solid #ccc;
34
- -webkit-border-radius: 3px;
35
- -moz-border-radius: 3px;
36
- border-radius: 3px;
37
- position: relative;
38
- height: 200px;
39
- padding: 0;
40
- overflow-y: auto;
41
- }
42
-
43
- .ms-container .ms-selectable{
44
- margin-right: 10%;
45
- }
46
-
47
- .ms-container .ms-list.ms-focus{
48
- border-color: rgba(82, 168, 236, 0.8);
49
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
50
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
51
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
52
- outline: 0;
53
- outline: thin dotted \9;
54
- }
55
-
56
- .ms-container ul{
57
- margin: 0;
58
- list-style-type: none;
59
- padding: 0;
60
- }
61
-
62
- .ms-container .ms-optgroup-container{
63
- width: 100%;
64
- }
65
-
66
- .ms-container .ms-optgroup-label{
67
- margin: 0;
68
- padding: 5px 0px 0px 5px;
69
- cursor: pointer;
70
- color: #999;
71
- }
72
-
73
- .ms-container .ms-selectable li.ms-elem-selectable,
74
- .ms-container .ms-selection li.ms-elem-selection{
75
- border-bottom: 1px #eee solid;
76
- padding: 4px 10px;
77
- color: #555;
78
- font-size: 14px;
79
- margin-bottom: 0px;
80
- }
81
-
82
- .ms-container .ms-selectable li.ms-hover,
83
- .ms-container .ms-selection li.ms-hover{
84
- cursor: pointer;
85
- color: #fff;
86
- text-decoration: none;
87
- background-color: #08c;
88
- margin-bottom: 0px;
89
- }
90
-
91
- .ms-container .ms-selectable li.disabled,
92
- .ms-container .ms-selection li.disabled{
93
- background-color: #eee;
94
- color: #aaa;
95
- cursor: text;
96
- margin-bottom: 0px;
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
export-user-data.php CHANGED
@@ -4,7 +4,7 @@
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: 0.9.6
8
  Author: Q Studio
9
  Author URI: http://qstudio.us
10
  License: GPL2
@@ -23,7 +23,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
23
  {
24
 
25
  // plugin version
26
- define( 'Q_EXPORT_USER_DATA_VERSION', '0.9.6' ); // version ##
27
 
28
  // instatiate class via hook, only if inside admin
29
  if ( is_admin() ) {
@@ -52,6 +52,8 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
52
  private $bp_fields_saved_fields = array();
53
  private $bp_fields_update_time_saved_fields = array();
54
  private $role = '';
 
 
55
  private $start_date = '';
56
  private $end_date = '';
57
  private $limit_offset = '';
@@ -94,9 +96,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
94
  add_action( 'admin_footer', array( $this, 'jquery' ), 100000 );
95
  add_action( 'admin_footer', array( $this, 'css' ), 100000 );
96
 
97
- // check for saved settings, default to empty array ##
98
-
99
-
100
  }
101
 
102
  }
@@ -140,7 +139,14 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
140
  wp_register_style( 'q_export_user_data', plugins_url( 'css/export-user-data.css' ,__FILE__ ));
141
  wp_enqueue_style( 'q_export_user_data' );
142
  wp_enqueue_script( 'q_eud_multi_select_js', plugins_url( 'js/jquery.multi-select.js', __FILE__ ), array('jquery'), '0.9.8', false );
 
 
 
143
 
 
 
 
 
144
  }
145
 
146
  }
@@ -246,7 +252,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
246
  }
247
 
248
 
249
-
250
  /**
251
  * Check for and load stored user options
252
  *
@@ -265,6 +270,8 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
265
  $this->bp_fields_saved_fields = $this->q_eud_exports[$export]['bp_fields_saved_fields'];
266
  $this->bp_fields_update_time_saved_fields = $this->q_eud_exports[$export]['bp_fields_update_time_saved_fields'];
267
  $this->role = $this->q_eud_exports[$export]['role'];
 
 
268
  $this->start_date = $this->q_eud_exports[$export]['start_date'];
269
  $this->end_date = $this->q_eud_exports[$export]['end_date'];
270
  $this->limit_offset = $this->q_eud_exports[$export]['limit_offset'];
@@ -277,6 +284,8 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
277
  $this->bp_fields_saved_fields = array();
278
  $this->bp_fields_update_time_saved_fields = array();
279
  $this->role = '';
 
 
280
  $this->start_date = '';
281
  $this->end_date = '';
282
  $this->limit_offset = '';
@@ -287,12 +296,10 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
287
 
288
  }
289
 
290
-
291
 
292
  /**
293
  * method to store user options
294
  *
295
- * @todo sanitizing function is not correct - yet... ##
296
  * @param string $save_export Export Key name
297
  * @param array $save_options Array of export options to save
298
  * @since 0.9.3
@@ -322,29 +329,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
322
 
323
  if ( isset( $options ) && is_array( $options ) ) {
324
 
325
- // @todo - sanitizing function is not correct - yet... ##
326
- /*
327
- // update_option sanitizes the option name but not the option value ##
328
- foreach ( $options as $field_name => $field_value ) {
329
-
330
- // so do that here. ##
331
- if ( is_array( $field_value ) ) {
332
-
333
- foreach ( $field_value as $field_array_key => $field_array_value ) {
334
-
335
- $options[$key][$field_name][$field_array_key] = sanitize_text_field( $field_array_value );
336
-
337
- }
338
-
339
- } else {
340
-
341
- $options[$key][$field_name] = sanitize_text_field( $field_value );
342
-
343
- }
344
-
345
- }
346
- */
347
-
348
  // update_option sanitizes the option name but not the option value ##
349
  foreach ( $options as $field_name => $field_value ) {
350
 
@@ -387,7 +371,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
387
  }
388
 
389
 
390
-
391
  /**
392
  * method to delete user options
393
  *
@@ -471,7 +454,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
471
  }
472
 
473
 
474
-
475
  /**
476
  * Process content of CSV file
477
  *
@@ -480,9 +462,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
480
  public function generate_data()
481
  {
482
 
483
- // This function runs before we display the admin page, so we need to skip
484
- // the rest of this function if the user didn't click on the
485
- // Save, Load, or Delete Settings buttons
486
  if (
487
  ! isset( $_POST['_wpnonce-q-eud-export-user-page_export'] )
488
  || isset( $_POST['load_export'] )
@@ -499,8 +479,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
499
 
500
  // build argument array ##
501
  $args = array(
502
- #'fields' => 'all_with_meta',
503
- 'fields' => 'all', // reduce initial data load and call up required fields inside the loop ##
504
  'role' => sanitize_text_field( $_POST['role'] )
505
  );
506
 
@@ -514,44 +493,41 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
514
  }
515
 
516
  // is there a range limit in place for the export ? ##
517
- if ( isset( $_POST['limit_offset'] ) && $_POST['limit_offset'] != '' && isset( $_POST['limit_total'] ) && $_POST['limit_total'] != '' ) {
518
 
519
  // let's just make sure they are integer values ##
520
- $limit_offset = (int)$_POST['limit_offset'];
521
  $limit_total = (int)$_POST['limit_total'];
522
 
523
  if ( is_int( $limit_offset ) && is_int( $limit_total ) ) {
524
 
525
  $args['offset'] = $limit_offset;
526
- /* cwjordan codex says:
527
- * number - Limit the total number of users returned
528
- * so don't subtract the offset, like as not
529
- * that will give us a negative number for $args['number']
530
- * e.g. offset of 1000 total of 100 */
531
- $args['number'] = $limit_total;
532
- // $args['number'] = $limit_total - $limit_offset;
533
-
534
- #wp_die(pr($args));
535
 
536
  }
537
 
538
  }
539
 
540
- /* pre_user query */
541
  add_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
542
  $users = get_users( $args );
543
  remove_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
544
-
545
- /* no users found, so chuck an error into the args array and exit the export */
 
 
 
546
  if ( ! $users ) {
547
 
548
- $referer = add_query_arg( 'error', 'empty', wp_get_referer() );
549
- wp_redirect( $referer );
550
  exit;
551
 
552
  }
553
 
554
- /* get sitename and clean it up */
555
  $sitename = sanitize_key( get_bloginfo( 'name' ) );
556
  if ( ! empty( $sitename ) ) {
557
  $sitename .= '.';
@@ -570,7 +546,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
570
 
571
  switch ( $export_method ) {
572
 
573
- case "csv":
574
 
575
  // to csv ##
576
  header( 'Content-Description: File Transfer' );
@@ -597,7 +573,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
597
 
598
  break;
599
 
600
- case ('excel'):
601
 
602
  // to xls ##
603
  header( 'Content-Description: File Transfer' );
@@ -632,11 +608,9 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
632
  }
633
 
634
 
635
- // function to exclude data ##
636
- $exclude_data = apply_filters( 'q_eud_exclude_data', array() );
637
-
638
  // check for selected usermeta fields ##
639
  $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '';
 
640
  $usermeta_fields = array();
641
 
642
  if ( $usermeta && is_array( $usermeta ) ) {
@@ -645,13 +619,13 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
645
  }
646
  }
647
 
648
- #pr($usermeta_fields);
649
  #exit;
650
 
651
  // check for selected x profile fields ##
652
  $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '';
653
  $bp_fields_passed = array();
654
- if ( $bp_fields && is_array($bp_fields) ) {
655
 
656
  foreach( $bp_fields as $field ) {
657
 
@@ -685,34 +659,24 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
685
  // global wpdb object ##
686
  global $wpdb;
687
 
688
- // exportable user data ##
689
- $data_keys = array(
690
- 'ID'
691
- , 'user_login'
692
- #, 'user_pass'
693
- , 'user_nicename'
694
- , 'user_email'
695
- , 'user_url'
696
- , 'user_registered'
697
- #, 'user_activation_key'
698
- #, 'user_status',
699
- , 'display_name'
700
- );
701
-
702
  // compile final fields list ##
703
- $fields = array_merge( $data_keys, $usermeta_fields, $bp_fields_passed, $bp_fields_update_passed );
704
-
 
 
 
705
  // build the document headers ##
706
  $headers = array();
707
-
708
  foreach ( $fields as $key => $field ) {
709
 
710
  // rename programs field ##
711
  if ( $field == 'member_of_club' ){
712
  $field = 'Program';
713
  }
714
-
715
- if ( in_array( $field, $exclude_data ) ) {
 
716
 
717
  unset( $fields[$key] );
718
 
@@ -737,7 +701,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
737
  ob_end_flush();
738
 
739
  // get the value in bytes allocated for Memory via php.ini ##
740
- // @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue?replies=2
741
  $memory_limit = $this->return_bytes( ini_get('memory_limit') ) * .75;
742
 
743
  // we need to disable caching while exporting because we export so much data that it could blow the memory cache
@@ -777,22 +741,34 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
777
  $data = array();
778
 
779
  // BP loaded ? ##
780
- if ( function_exists ('bp_is_active') ) {
 
781
  #$bp_data = BP_XProfile_ProfileData::get_all_for_user( $user->ID );
782
- $bp_data = self::get_all_for_user( $user->ID ); // take from old BP method ##
 
783
  }
784
-
 
 
 
 
 
 
 
 
 
785
  // loop over each field ##
786
  foreach ( $fields as $field ) {
787
-
788
  // check if this is a BP field ##
789
- if ( isset( $bp_data ) && isset( $bp_data[$field] ) && in_array( $field, $bp_fields_passed ) ) {
 
790
 
791
  $value = $bp_data[$field];
792
 
793
  if ( is_array( $value ) ) {
794
 
795
- $value = maybe_unserialize($value['field_data']); // suggested by @grexican ##
796
  #$value = $value['field_data'];
797
 
798
  /**
@@ -814,7 +790,9 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
814
  $value = $this->sanitize($value);
815
 
816
  // check if this is a BP field we want the updated date for ##
817
- } elseif ( in_array( $field, $bp_fields_update_passed ) ) {
 
 
818
 
819
  global $bp;
820
 
@@ -833,28 +811,124 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
833
  );
834
 
835
  // include the user's role in the export ##
836
- } elseif ( isset( $_POST['q_eud_role'] ) && $_POST['q_eud_role'] != '' && $field == 'role' ){
 
 
837
 
838
  // add "Role" as $value ##
839
- $value = $user->roles[0] ? $user->roles[0] : '' ; // empty value if no role found - note: we only take the first role assigned to the user ##
 
 
 
 
 
 
 
840
 
841
- // user data or usermeta ##
842
- } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
843
 
844
- $value = isset( $user->{$field} ) ? $user->{$field} : '';
845
- #$value = is_array( $value ) ? serialize( $value ) : $value; // maybe serialize the value ##
846
- $value = is_array( $value ) ? implode(", ", $value ) : $value; // maybe serialize the value - suggested by @nicmare ##
 
 
 
 
 
 
 
 
 
 
 
 
 
847
 
848
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
849
 
 
 
 
 
 
 
 
 
850
  // correct program value to Program Name ##
851
  if ( $field == 'member_of_club' ) {
 
852
  $value = get_the_title($value);
 
853
  }
854
-
 
855
  if ( $is_csv ) {
 
856
  $data[] = '"' . str_replace( '"', '""', $value ) . '"';
 
 
857
  } else {
 
858
  $data[] = $value;
859
  }
860
 
@@ -871,7 +945,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
871
  // stop PHP, so file can export correctly ##
872
  exit;
873
 
874
-
875
  }
876
 
877
 
@@ -914,7 +987,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
914
  $save_export = sanitize_text_field( $save_export );
915
 
916
  // Build array of $options to save and save them ##
917
- if ( $save_export != "" ) {
918
 
919
  // prepare all array values ##
920
  $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '' ;
@@ -922,25 +995,27 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
922
  $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '' ;
923
  $format = isset( $_POST['format'] ) ? $_POST['format'] : '' ;
924
  $role = isset( $_POST['role'] ) ? $_POST['role'] : '' ;
 
 
925
  $start_date = isset( $_POST['start_date'] ) ? $_POST['start_date'] : '' ;
926
  $end_date = isset( $_POST['end_date'] ) ? $_POST['end_date'] : '' ;
927
  $limit_offset = isset( $_POST['limit_offset'] ) ? $_POST['limit_offset'] : '' ;
928
  $limit_total = isset( $_POST['limit_total'] ) ? $_POST['limit_total'] : '' ;
929
 
930
- // assign all values to a multidimensional array with $save_export as the key of the upper array ##
931
- #$options = array (
932
- $save_array = array (
933
- 'usermeta_saved_fields' => $usermeta,
934
- 'bp_fields_saved_fields' => $bp_fields,
935
- 'bp_fields_update_time_saved_fields' => $bp_fields_update,
936
- 'role' => $role,
937
- 'start_date' => $start_date,
938
- 'end_date' => $end_date,
939
- 'limit_offset' => $limit_offset,
940
- 'limit_total' => $limit_total,
941
- 'format' => $format
942
- );
943
- #);
944
 
945
  // store the options, for next load ##
946
  $this->set_user_options( $save_export, $save_array );
@@ -1106,8 +1181,8 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1106
  ?>
1107
  <?php
1108
 
1109
- // buddypress x profile data ##
1110
- if ( function_exists ('bp_is_active') ) {
1111
 
1112
  // grab all buddypress x profile fields ##
1113
  $bp_fields = $wpdb->get_results( "SELECT distinct(name) FROM ".$wpdb->base_prefix."bp_xprofile_fields WHERE parent_id = 0" );
@@ -1185,9 +1260,23 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1185
  ?></p>
1186
  </td>
1187
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1188
  <?php
1189
 
1190
- } // BP installed and active ##
1191
 
1192
  ?>
1193
  <tr valign="top" class="toggleable">
@@ -1198,12 +1287,18 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1198
 
1199
  echo '<option value="">' . __( 'All Roles', $this->text_domain ) . '</option>';
1200
  global $wp_roles;
 
1201
  foreach ( $wp_roles->role_names as $role => $name ) {
1202
- if ( isset ( $this->role ) && ( $this->role == $role ) ) {
1203
- echo "\n\t<option selected value='" . esc_attr( $role ) . "'>$name</option>";
1204
- } else {
1205
- echo "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
1206
- }
 
 
 
 
 
1207
  }
1208
 
1209
 
@@ -1218,6 +1313,20 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1218
  ?></p>
1219
  </td>
1220
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1221
  <?php
1222
 
1223
  // clubs ? ##
@@ -1253,14 +1362,8 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1253
  <tr valign="top" class="toggleable">
1254
  <th scope="row"><label><?php _e( 'Registered', $this->text_domain ); ?></label></th>
1255
  <td>
1256
- <select name="start_date" id="q_eud_users_start_date">
1257
- <option value="0"><?php _e( 'Start Date', $this->text_domain ); ?></option>
1258
- <?php $this->export_date_options($this->start_date); ?>
1259
- </select>
1260
- <select name="end_date" id="q_eud_users_end_date">
1261
- <option value="0"><?php _e( 'End Date', $this->text_domain ); ?></option>
1262
- <?php $this->export_date_options($this->end_date); ?>
1263
- </select>
1264
  <p class="description"><?php
1265
  printf(
1266
  __( 'Pick a start and end user registration date to limit the results.', $this->text_domain )
@@ -1284,19 +1387,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1284
  </td>
1285
  </tr>
1286
 
1287
- <tr valign="top" class="hidden">
1288
- <th scope="row"><label for="q_eud_role"><?php _e( 'Include Role', $this->text_domain ); ?></label></th>
1289
- <td>
1290
- <input id='q_eud_role' type='checkbox' name='q_eud_role' value=''/></label>
1291
- <p class="description"><?php
1292
- printf(
1293
- __( 'Checking this option will add a column that includes the user\'s role.', $this->text_domain )
1294
- );
1295
- ?></p>
1296
- </td>
1297
- </tr>
1298
- </tr>
1299
-
1300
  <tr valign="top">
1301
  <th scope="row"><label for="q_eud_users_format"><?php _e( 'Format', $this->text_domain ); ?></label></th>
1302
  <td>
@@ -1327,7 +1417,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1327
  <td>
1328
 
1329
  <div class="row">
1330
- <input type="text" class="regular-text" name="save_new_export_name" id="q_eud_save_options_new_export" placeholder="<?php _e( 'Export Name', $this->text_domain ); ?>">
1331
  <input type="submit" id="save_export" class="button-primary" name="save_export" value="<?php _e( 'Save', $this->text_domain ); ?>" />
1332
  </div>
1333
  <?php
@@ -1400,7 +1490,7 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1400
  }
1401
 
1402
 
1403
- /**
1404
  * Inline jQuery
1405
  * @since 0.8.2
1406
  */
@@ -1480,7 +1570,6 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1480
  }
1481
  });
1482
 
1483
- // @todo - probably we're going to require more validation on these buttons ##
1484
  // validate save button ##
1485
  jQuery("#save_export").click( function(e) {
1486
 
@@ -1503,6 +1592,27 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1503
 
1504
  });
1505
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1506
  });
1507
 
1508
  </script>
@@ -1535,15 +1645,61 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1535
  /**
1536
  * Data to exclude from export
1537
  */
1538
- public function exclude_data()
1539
  {
 
 
 
 
 
 
 
1540
 
1541
- $exclude = array( 'user_pass', 'user_activation_key' );
1542
- return $exclude;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1543
 
1544
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1545
 
 
1546
 
 
 
 
1547
  /*
1548
  * Pre User Query
1549
  */
@@ -1554,15 +1710,30 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1554
 
1555
  $where = '';
1556
 
1557
- if ( ! empty( $_POST['start_date'] ) )
1558
- $where .= $wpdb->prepare( " AND $wpdb->users.user_registered >= %s", date( 'Y-m-d', strtotime( sanitize_text_field ( $_POST['start_date'] ) ) ) );
1559
-
1560
- if ( ! empty( $_POST['end_date'] ) )
1561
- $where .= $wpdb->prepare( " AND $wpdb->users.user_registered < %s", date( 'Y-m-d', strtotime( '+1 month', strtotime( sanitize_text_field ( $_POST['end_date'] ) ) ) ) );
1562
-
1563
- if ( ! empty( $where ) )
 
 
 
 
 
 
 
 
 
 
 
 
1564
  $user_search->query_where = str_replace( 'WHERE 1=1', "WHERE 1=1 $where", $user_search->query_where );
 
 
1565
 
 
1566
  return $user_search;
1567
 
1568
  }
@@ -1573,48 +1744,96 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1573
  *
1574
  * @since 0.9.6
1575
  * @global type $wpdb
1576
- * @global type $wp_locale
1577
- * @return void
1578
  */
1579
- private function export_date_options( $selected_date)
1580
  {
1581
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1582
  global $wpdb, $wp_locale;
1583
 
 
1584
  $months = $wpdb->get_results( "
1585
- SELECT DISTINCT YEAR( user_registered ) AS year, MONTH( user_registered ) AS month
1586
  FROM $wpdb->users
1587
  ORDER BY user_registered DESC
1588
  " );
1589
 
 
1590
  $month_count = count( $months );
1591
- if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
 
 
 
1592
  return;
 
 
1593
 
 
 
 
1594
  foreach ( $months as $date ) {
1595
- if ( 0 == $date->year )
 
 
1596
  continue;
1597
-
 
 
1598
  $month = zeroise( $date->month, 2 );
 
 
1599
  $date_string = $date->year . '-' . $month;
 
 
1600
  if ( $selected_date == $date_string ) {
1601
- echo( '<option selected value="' . $date_string . '">' . $wp_locale->get_month( $month ) . ' ' . $date->year . '</option>' );
 
 
 
 
1602
  } else {
1603
- echo( '<option value="' . $date_string . '">' . $wp_locale->get_month( $month ) . ' ' . $date->year . '</option>' );
 
 
 
 
1604
  }
1605
 
1606
  }
 
1607
 
1608
  }
1609
 
 
1610
  /**
1611
  * Quote array elements and separate with commas
1612
  *
1613
  * @since 0.9.6
1614
  * @return String
1615
  */
1616
- private function quote_array( $array )
1617
- {
1618
 
1619
  $prefix = ''; // starts empty ##
1620
  $elementlist = '';
@@ -1630,16 +1849,53 @@ if ( ! class_exists( 'Q_Export_User_Data' ) )
1630
 
1631
  }
1632
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1633
 
1634
  /**
1635
  * Nicer var_dump
1636
  *
1637
  * @since 0.9.6
1638
  */
1639
- function pr ($thing)
1640
  {
1641
  echo '<pre>';
1642
- print_r ($thing);
1643
  echo '</pre>';
1644
  }
1645
 
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.0.2
8
  Author: Q Studio
9
  Author URI: http://qstudio.us
10
  License: GPL2
23
  {
24
 
25
  // plugin version
26
+ define( 'Q_EXPORT_USER_DATA_VERSION', '1.0.0' ); // version ##
27
 
28
  // instatiate class via hook, only if inside admin
29
  if ( is_admin() ) {
52
  private $bp_fields_saved_fields = array();
53
  private $bp_fields_update_time_saved_fields = array();
54
  private $role = '';
55
+ private $roles = '1';
56
+ private $groups = '1';
57
  private $start_date = '';
58
  private $end_date = '';
59
  private $limit_offset = '';
96
  add_action( 'admin_footer', array( $this, 'jquery' ), 100000 );
97
  add_action( 'admin_footer', array( $this, 'css' ), 100000 );
98
 
 
 
 
99
  }
100
 
101
  }
139
  wp_register_style( 'q_export_user_data', plugins_url( 'css/export-user-data.css' ,__FILE__ ));
140
  wp_enqueue_style( 'q_export_user_data' );
141
  wp_enqueue_script( 'q_eud_multi_select_js', plugins_url( 'js/jquery.multi-select.js', __FILE__ ), array('jquery'), '0.9.8', false );
142
+
143
+ // add script ##
144
+ wp_enqueue_script('jquery-ui-datepicker');
145
 
146
+ // add style ##
147
+ wp_enqueue_style( 'jquery-ui-datepicker' );
148
+ wp_enqueue_style('jquery-ui-css', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
149
+
150
  }
151
 
152
  }
252
  }
253
 
254
 
 
255
  /**
256
  * Check for and load stored user options
257
  *
270
  $this->bp_fields_saved_fields = $this->q_eud_exports[$export]['bp_fields_saved_fields'];
271
  $this->bp_fields_update_time_saved_fields = $this->q_eud_exports[$export]['bp_fields_update_time_saved_fields'];
272
  $this->role = $this->q_eud_exports[$export]['role'];
273
+ $this->roles = $this->q_eud_exports[$export]['roles'];
274
+ $this->groups = $this->q_eud_exports[$export]['groups'];
275
  $this->start_date = $this->q_eud_exports[$export]['start_date'];
276
  $this->end_date = $this->q_eud_exports[$export]['end_date'];
277
  $this->limit_offset = $this->q_eud_exports[$export]['limit_offset'];
284
  $this->bp_fields_saved_fields = array();
285
  $this->bp_fields_update_time_saved_fields = array();
286
  $this->role = '';
287
+ $this->roles = '1';
288
+ $this->groups = '1';
289
  $this->start_date = '';
290
  $this->end_date = '';
291
  $this->limit_offset = '';
296
 
297
  }
298
 
 
299
 
300
  /**
301
  * method to store user options
302
  *
 
303
  * @param string $save_export Export Key name
304
  * @param array $save_options Array of export options to save
305
  * @since 0.9.3
329
 
330
  if ( isset( $options ) && is_array( $options ) ) {
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  // update_option sanitizes the option name but not the option value ##
333
  foreach ( $options as $field_name => $field_value ) {
334
 
371
  }
372
 
373
 
 
374
  /**
375
  * method to delete user options
376
  *
454
  }
455
 
456
 
 
457
  /**
458
  * Process content of CSV file
459
  *
462
  public function generate_data()
463
  {
464
 
465
+ // Check if the user clicked on the Save, Load, or Delete Settings buttons ##
 
 
466
  if (
467
  ! isset( $_POST['_wpnonce-q-eud-export-user-page_export'] )
468
  || isset( $_POST['load_export'] )
479
 
480
  // build argument array ##
481
  $args = array(
482
+ 'fields' => 'all',
 
483
  'role' => sanitize_text_field( $_POST['role'] )
484
  );
485
 
493
  }
494
 
495
  // is there a range limit in place for the export ? ##
496
+ if ( isset( $_POST['limit_total'] ) && $_POST['limit_total'] != '' ) {
497
 
498
  // let's just make sure they are integer values ##
499
+ $limit_offset = isset( $_POST['limit_offset'] ) ? (int)$_POST['limit_offset'] : 0 ;
500
  $limit_total = (int)$_POST['limit_total'];
501
 
502
  if ( is_int( $limit_offset ) && is_int( $limit_total ) ) {
503
 
504
  $args['offset'] = $limit_offset;
505
+ $args['number'] = $limit_total; // number - Limit the total number of users returned ##
506
+
507
+ // test it ##
508
+ #wp_die( $this->pr( $args ) );
 
 
 
 
 
509
 
510
  }
511
 
512
  }
513
 
514
+ // pre_user query ##
515
  add_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
516
  $users = get_users( $args );
517
  remove_action( 'pre_user_query', array( $this, 'pre_user_query' ) );
518
+
519
+ // test args ##
520
+ #wp_die( $this->pr ( $users ) );
521
+
522
+ // no users found, so chuck an error into the args array and exit the export ##
523
  if ( ! $users ) {
524
 
525
+ wp_redirect( add_query_arg( 'error', 'empty', wp_get_referer() ) );
 
526
  exit;
527
 
528
  }
529
 
530
+ // get sitename and clean it up ##
531
  $sitename = sanitize_key( get_bloginfo( 'name' ) );
532
  if ( ! empty( $sitename ) ) {
533
  $sitename .= '.';
546
 
547
  switch ( $export_method ) {
548
 
549
+ case ( 'csv' ):
550
 
551
  // to csv ##
552
  header( 'Content-Description: File Transfer' );
573
 
574
  break;
575
 
576
+ case ( 'excel' ):
577
 
578
  // to xls ##
579
  header( 'Content-Description: File Transfer' );
608
  }
609
 
610
 
 
 
 
611
  // check for selected usermeta fields ##
612
  $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '';
613
+ #$this->pr( $usermeta );
614
  $usermeta_fields = array();
615
 
616
  if ( $usermeta && is_array( $usermeta ) ) {
619
  }
620
  }
621
 
622
+ #$this->pr( $usermeta_fields );
623
  #exit;
624
 
625
  // check for selected x profile fields ##
626
  $bp_fields = isset( $_POST['bp_fields'] ) ? $_POST['bp_fields'] : '';
627
  $bp_fields_passed = array();
628
+ if ( $bp_fields && is_array( $bp_fields ) ) {
629
 
630
  foreach( $bp_fields as $field ) {
631
 
659
  // global wpdb object ##
660
  global $wpdb;
661
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  // compile final fields list ##
663
+ $fields = array_merge( $this->get_user_fields(), $this->get_special_fields(), $usermeta_fields, $bp_fields_passed, $bp_fields_update_passed );
664
+
665
+ // test field array ##
666
+ #$this->pr( $fields );
667
+
668
  // build the document headers ##
669
  $headers = array();
670
+
671
  foreach ( $fields as $key => $field ) {
672
 
673
  // rename programs field ##
674
  if ( $field == 'member_of_club' ){
675
  $field = 'Program';
676
  }
677
+
678
+ // grab fields to exclude from exports ##
679
+ if ( in_array( $field, $this->get_exclude_fields() ) ) {
680
 
681
  unset( $fields[$key] );
682
 
701
  ob_end_flush();
702
 
703
  // get the value in bytes allocated for Memory via php.ini ##
704
+ // @link http://wordpress.org/support/topic/how-to-exporting-a-lot-of-data-out-of-memory-issue
705
  $memory_limit = $this->return_bytes( ini_get('memory_limit') ) * .75;
706
 
707
  // we need to disable caching while exporting because we export so much data that it could blow the memory cache
741
  $data = array();
742
 
743
  // BP loaded ? ##
744
+ if ( function_exists ( 'bp_is_active' ) ) {
745
+
746
  #$bp_data = BP_XProfile_ProfileData::get_all_for_user( $user->ID );
747
+ $bp_data = self::get_all_for_user( $user->ID ); // taken from old BP method ##
748
+
749
  }
750
+
751
+ // single query method - get all user_meta data ##
752
+ $get_user_meta = (array)get_user_meta( $user->ID );
753
+ #wp_die( $this->pr( $get_user_meta ) );
754
+
755
+ // Filter out empty meta data ##
756
+ $get_user_meta = array_filter( array_map( function( $a ) {
757
+ return $a[0];
758
+ }, $get_user_meta ) );
759
+
760
  // loop over each field ##
761
  foreach ( $fields as $field ) {
762
+
763
  // check if this is a BP field ##
764
+ if ( isset( $bp_data ) && isset( $bp_data[$field] ) && in_array( $field, $bp_fields_passed ) )
765
+ {
766
 
767
  $value = $bp_data[$field];
768
 
769
  if ( is_array( $value ) ) {
770
 
771
+ $value = maybe_unserialize( $value['field_data'] ); // suggested by @grexican ##
772
  #$value = $value['field_data'];
773
 
774
  /**
790
  $value = $this->sanitize($value);
791
 
792
  // check if this is a BP field we want the updated date for ##
793
+ }
794
+ elseif ( in_array( $field, $bp_fields_update_passed ) )
795
+ {
796
 
797
  global $bp;
798
 
811
  );
812
 
813
  // include the user's role in the export ##
814
+ }
815
+ elseif ( isset( $_POST['roles'] ) && $_POST['roles'] == '1' && $field == 'roles' )
816
+ {
817
 
818
  // add "Role" as $value ##
819
+ $value = isset( $user->roles[0] ) ? implode( $user->roles, '|' ) : '' ; // empty value if no role found - or flat array of user roles ##
820
+
821
+ // include the user's BP group in the export ##
822
+ }
823
+ elseif ( isset( $_POST['groups'] ) && $_POST['groups'] == '1' && $field == 'groups' )
824
+ {
825
+
826
+ if ( function_exists( 'groups_get_user_groups' ) ) {
827
 
828
+ // check if user is a member of any groups ##
829
+ $group_ids = groups_get_user_groups( $user->ID );
830
+
831
+ if ( ! $group_ids || $group_ids == '' ) {
832
+
833
+ $value = '';
834
+
835
+ } else {
836
+
837
+ // new empty array ##
838
+ $groups = array();
839
+
840
+ // loop over all groups ##
841
+ foreach( $group_ids["groups"] as $group_id ) {
842
+
843
+ $groups[] = groups_get_group( array( 'group_id' => $group_id )) -> name . ( end( $group_ids["groups"] ) == $group_id ? '' : '' );
844
 
845
+ }
846
+
847
+ // implode it ##
848
+ $value = implode( $groups, '|' );
849
+
850
+ }
851
+
852
+ } else {
853
+
854
+ $value = '';
855
+
856
+ }
857
+
858
+ }
859
+ elseif ( $field == 'bp_latest_update' )
860
+ {
861
 
862
+ // https://bpdevel.wordpress.com/2014/02/21/user-last_activity-data-and-buddypress-2-0/ ##
863
+ $value = bp_get_user_last_activity( $user->ID );
864
+
865
+ // user or usermeta field ##
866
+ }
867
+ else
868
+ {
869
+
870
+ // the user_meta key isset ##
871
+ if ( isset( $get_user_meta[$field] ) ) {
872
+
873
+ // take from the bulk get_user_meta call ##
874
+ $value = $get_user_meta[$field];
875
+
876
+ // standard WP_User value ##
877
+ } else {
878
+
879
+ // use the magically assigned value from WP_Users
880
+ $value = $user->{$field};
881
+
882
+ }
883
+
884
+
885
+ // the $value is serialized ##
886
+ if ( is_serialized( $value ) ) {
887
+
888
+ // unserliaze to new variable ##
889
+ $unserialized = @unserialize( $value );
890
+
891
+ // test if unserliazing produced errors ##
892
+ if ( $unserialized !== false || $value == 'b:0;' ) {
893
+
894
+ #$value = 'UNSERIALIZED_'.$value;
895
+ $value = $unserialized;
896
+
897
+ } else {
898
+
899
+ // failed to unserialize - data potentially corrupted in db ##
900
+ $value = $value;
901
+
902
+ }
903
+
904
+ }
905
+
906
+ // the value is an array ##
907
+ if ( is_array ( $value ) ) {
908
 
909
+ // recursive implode it ##
910
+ $value = self::recursive_implode( $value );
911
+
912
+ }
913
+
914
+ }
915
+
916
+
917
  // correct program value to Program Name ##
918
  if ( $field == 'member_of_club' ) {
919
+
920
  $value = get_the_title($value);
921
+
922
  }
923
+
924
+ // wrap values in quotes and add to array ##
925
  if ( $is_csv ) {
926
+
927
  $data[] = '"' . str_replace( '"', '""', $value ) . '"';
928
+
929
+ // just add to array ##
930
  } else {
931
+
932
  $data[] = $value;
933
  }
934
 
945
  // stop PHP, so file can export correctly ##
946
  exit;
947
 
 
948
  }
949
 
950
 
987
  $save_export = sanitize_text_field( $save_export );
988
 
989
  // Build array of $options to save and save them ##
990
+ if ( isset( $save_export ) ) {
991
 
992
  // prepare all array values ##
993
  $usermeta = isset( $_POST['usermeta'] ) ? $_POST['usermeta']: '' ;
995
  $bp_fields_update = isset( $_POST['bp_fields_update_time'] ) ? $_POST['bp_fields_update_time'] : '' ;
996
  $format = isset( $_POST['format'] ) ? $_POST['format'] : '' ;
997
  $role = isset( $_POST['role'] ) ? $_POST['role'] : '' ;
998
+ $roles = isset( $_POST['roles'] ) ? $_POST['roles'] : '0' ;
999
+ $groups = isset( $_POST['groups'] ) ? $_POST['groups'] : '0' ;
1000
  $start_date = isset( $_POST['start_date'] ) ? $_POST['start_date'] : '' ;
1001
  $end_date = isset( $_POST['end_date'] ) ? $_POST['end_date'] : '' ;
1002
  $limit_offset = isset( $_POST['limit_offset'] ) ? $_POST['limit_offset'] : '' ;
1003
  $limit_total = isset( $_POST['limit_total'] ) ? $_POST['limit_total'] : '' ;
1004
 
1005
+ // assign all values to an array ##
1006
+ $save_array = array (
1007
+ 'usermeta_saved_fields' => $usermeta,
1008
+ 'bp_fields_saved_fields' => $bp_fields,
1009
+ 'bp_fields_update_time_saved_fields' => $bp_fields_update,
1010
+ 'role' => $role,
1011
+ 'roles' => $roles,
1012
+ 'groups' => $groups,
1013
+ 'start_date' => $start_date,
1014
+ 'end_date' => $end_date,
1015
+ 'limit_offset' => $limit_offset,
1016
+ 'limit_total' => $limit_total,
1017
+ 'format' => $format
1018
+ );
1019
 
1020
  // store the options, for next load ##
1021
  $this->set_user_options( $save_export, $save_array );
1181
  ?>
1182
  <?php
1183
 
1184
+ // buddypress x profile data ##
1185
+ if ( function_exists ('bp_is_active') ) {
1186
 
1187
  // grab all buddypress x profile fields ##
1188
  $bp_fields = $wpdb->get_results( "SELECT distinct(name) FROM ".$wpdb->base_prefix."bp_xprofile_fields WHERE parent_id = 0" );
1260
  ?></p>
1261
  </td>
1262
  </tr>
1263
+
1264
+ <tr valign="top" class="toggleable">
1265
+ <th scope="row"><label for="groups"><?php _e( 'BP User Groups', $this->text_domain ); ?></label></th>
1266
+ <td>
1267
+ <input id='groups' type='checkbox' name='groups' value='1' <?php checked( isset ( $this->groups ) ? intval ( $this->groups ) : '', 1 ); ?> />
1268
+ <p class="description"><?php
1269
+ printf(
1270
+ __( 'Include BuddyPress Group Data. <a href="%s" target="_blank">%s</a>', $this->text_domain )
1271
+ , esc_html('https://codex.buddypress.org/buddypress-components-and-features/groups/')
1272
+ , 'Codex'
1273
+ );
1274
+ ?></p>
1275
+ </td>
1276
+ </tr>
1277
  <?php
1278
 
1279
+ } // BP installed and active ##
1280
 
1281
  ?>
1282
  <tr valign="top" class="toggleable">
1287
 
1288
  echo '<option value="">' . __( 'All Roles', $this->text_domain ) . '</option>';
1289
  global $wp_roles;
1290
+
1291
  foreach ( $wp_roles->role_names as $role => $name ) {
1292
+
1293
+ if ( isset ( $this->role ) && ( $this->role == $role ) ) {
1294
+
1295
+ echo "\n\t<option selected value='" . esc_attr( $role ) . "'>$name</option>";
1296
+
1297
+ } else {
1298
+
1299
+ echo "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
1300
+
1301
+ }
1302
  }
1303
 
1304
 
1313
  ?></p>
1314
  </td>
1315
  </tr>
1316
+
1317
+ <tr valign="top" class="toggleable">
1318
+ <th scope="row"><label for="roles"><?php _e( 'User Roles', $this->text_domain ); ?></label></th>
1319
+ <td>
1320
+ <input id='roles' type='checkbox' name='roles' value='1' <?php checked( isset ( $this->roles ) ? intval ( $this->roles ) : '', 1 ); ?> />
1321
+ <p class="description"><?php
1322
+ printf(
1323
+ __( 'Include all of the users <a href="%s" target="_blank">%s</a>', $this->text_domain )
1324
+ , esc_html('http://codex.wordpress.org/Roles_and_Capabilities')
1325
+ , 'Roles'
1326
+ );
1327
+ ?></p>
1328
+ </td>
1329
+ </tr>
1330
  <?php
1331
 
1332
  // clubs ? ##
1362
  <tr valign="top" class="toggleable">
1363
  <th scope="row"><label><?php _e( 'Registered', $this->text_domain ); ?></label></th>
1364
  <td>
1365
+ <input type="text" id="q_eud_users_start_date" name="start_date" value="<?php echo $this->start_date; ?>" class="start-datepicker" />
1366
+ <input type="text" id="q_eud_users_end_date" name="end_date" value="<?php echo $this->end_date; ?>" class="end-datepicker" />
 
 
 
 
 
 
1367
  <p class="description"><?php
1368
  printf(
1369
  __( 'Pick a start and end user registration date to limit the results.', $this->text_domain )
1387
  </td>
1388
  </tr>
1389
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1390
  <tr valign="top">
1391
  <th scope="row"><label for="q_eud_users_format"><?php _e( 'Format', $this->text_domain ); ?></label></th>
1392
  <td>
1417
  <td>
1418
 
1419
  <div class="row">
1420
+ <input type="text" class="regular-text" name="save_new_export_name" id="q_eud_save_options_new_export" placeholder="<?php _e( 'Export Name', $this->text_domain ); ?>" value="<?php echo isset( $_POST['export_name'] ) ? $_POST['export_name'] : '' ; ?>">
1421
  <input type="submit" id="save_export" class="button-primary" name="save_export" value="<?php _e( 'Save', $this->text_domain ); ?>" />
1422
  </div>
1423
  <?php
1490
  }
1491
 
1492
 
1493
+ /**
1494
  * Inline jQuery
1495
  * @since 0.8.2
1496
  */
1570
  }
1571
  });
1572
 
 
1573
  // validate save button ##
1574
  jQuery("#save_export").click( function(e) {
1575
 
1592
 
1593
  });
1594
 
1595
+ <?php
1596
+
1597
+ // method returns an object with "first" & "last" keys ##
1598
+ $dates = self::get_user_registered_dates();
1599
+
1600
+ ?>
1601
+
1602
+ // start date picker ##
1603
+ jQuery('.start-datepicker').datepicker( {
1604
+ dateFormat : 'yy-mm-dd',
1605
+ minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
1606
+ maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>'
1607
+ } );
1608
+
1609
+ // end date picker ##
1610
+ jQuery('.end-datepicker').datepicker( {
1611
+ dateFormat : 'yy-mm-dd',
1612
+ minDate : '<?php echo substr( $dates["0"]->first, 0, 10 ); ?>',
1613
+ maxDate : '<?php echo substr( $dates["0"]->last, 0, 10 ); ?>'
1614
+ } );
1615
+
1616
  });
1617
 
1618
  </script>
1645
  /**
1646
  * Data to exclude from export
1647
  */
1648
+ public function get_exclude_fields()
1649
  {
1650
+
1651
+ $exclude_fields = array (
1652
+ 'user_pass'
1653
+ #, 'user_activation_key'
1654
+ );
1655
+
1656
+ return apply_filters( 'export_user_data_exclude_fields', $exclude_fields );
1657
 
1658
+ }
1659
+
1660
+
1661
+ /**
1662
+ * Get the array of standard WP_User fields to return
1663
+ */
1664
+ public function get_user_fields()
1665
+ {
1666
+
1667
+ // exportable user data ##
1668
+ $user_fields = array(
1669
+ 'ID'
1670
+ , 'user_login'
1671
+ #, 'user_pass'
1672
+ , 'user_nicename'
1673
+ , 'user_email'
1674
+ , 'user_url'
1675
+ , 'user_registered'
1676
+ #, 'user_activation_key'
1677
+ , 'user_status'
1678
+ , 'display_name'
1679
+ );
1680
+
1681
+ return apply_filters( 'export_user_data_user_fields', $user_fields );
1682
 
1683
  }
1684
+
1685
+
1686
+ /**
1687
+ * Get the array of special user fields to return
1688
+ */
1689
+ public function get_special_fields()
1690
+ {
1691
+
1692
+ // exportable user data ##
1693
+ $special_fields = array(
1694
+ 'roles' // list of WP Roles
1695
+ , 'groups' // BP Groups
1696
+ );
1697
 
1698
+ return apply_filters( 'export_user_data_special_fields', $special_fields );
1699
 
1700
+ }
1701
+
1702
+
1703
  /*
1704
  * Pre User Query
1705
  */
1710
 
1711
  $where = '';
1712
 
1713
+ if ( ! empty( $_POST['start_date'] ) ) {
1714
+
1715
+ $date = new DateTime( sanitize_text_field ( $_POST['start_date'] ). ' 00:00:00' );
1716
+ $date_formatted = $date->format( 'Y-m-d H:i:s' );
1717
+
1718
+ $where .= $wpdb->prepare( " AND $wpdb->users.user_registered >= %s", $date_formatted );
1719
+
1720
+ }
1721
+ if ( ! empty( $_POST['end_date'] ) ) {
1722
+
1723
+ $date = new DateTime( sanitize_text_field ( $_POST['end_date'] ). ' 00:00:00' );
1724
+ $date_formatted = $date->format( 'Y-m-d H:i:s' );
1725
+
1726
+ $where .= $wpdb->prepare( " AND $wpdb->users.user_registered < %s", $date_formatted );
1727
+
1728
+ }
1729
+
1730
+ if ( ! empty( $where ) ) {
1731
+
1732
  $user_search->query_where = str_replace( 'WHERE 1=1', "WHERE 1=1 $where", $user_search->query_where );
1733
+
1734
+ }
1735
 
1736
+ #wp_die( self::pr( $user_search ) );
1737
  return $user_search;
1738
 
1739
  }
1744
  *
1745
  * @since 0.9.6
1746
  * @global type $wpdb
1747
+ * @return Array of objects
 
1748
  */
1749
+ private static function get_user_registered_dates()
1750
  {
1751
+
1752
+ // invite in global objects ##
1753
+ global $wpdb;
1754
+
1755
+ // query user table for oldest and newest registration ##
1756
+ $range =
1757
+ $wpdb->get_results (
1758
+ #$wpdb->prepare (
1759
+ "
1760
+ SELECT
1761
+ MIN( user_registered ) AS first,
1762
+ MAX( user_registered ) AS last
1763
+ FROM
1764
+ {$wpdb->users}
1765
+ "
1766
+ #)
1767
+ );
1768
+
1769
+ return $range;
1770
+
1771
+ /*
1772
+ // invite in global objects ##
1773
  global $wpdb, $wp_locale;
1774
 
1775
+ // grab list of years and months available
1776
  $months = $wpdb->get_results( "
1777
+ SELECT DISTINCT YEAR( user_registered ) AS year, MONTH( user_registered ) AS month, DAY( user_registered ) AS day
1778
  FROM $wpdb->users
1779
  ORDER BY user_registered DESC
1780
  " );
1781
 
1782
+ // check if we got a result ##
1783
  $month_count = count( $months );
1784
+
1785
+ // nothing cokking ##
1786
+ if ( ! $month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) {
1787
+
1788
  return;
1789
+
1790
+ }
1791
 
1792
+ #wp_die( self::pr( $months ) );
1793
+
1794
+ // loop over each month ##
1795
  foreach ( $months as $date ) {
1796
+
1797
+ // skip if year == '0' ##
1798
+ if ( 0 == $date->year ) {
1799
  continue;
1800
+ }
1801
+
1802
+ // make sure the month is in a MM two digit format ##
1803
  $month = zeroise( $date->month, 2 );
1804
+
1805
+ // build up a tae string - YYYY-MM ##
1806
  $date_string = $date->year . '-' . $month;
1807
+
1808
+ // check if passed date matches this string ##
1809
  if ( $selected_date == $date_string ) {
1810
+
1811
+ ?>
1812
+ <option selected value="<?php echo $date_string; ?>"><?php echo $wp_locale->get_month( $month ); ?> <?php echo $date->year; ?></option>
1813
+ <?php
1814
+
1815
  } else {
1816
+
1817
+ ?>
1818
+ <option value="<?php echo $date_string; ?>"><?php echo $wp_locale->get_month( $month ); ?> <?php echo $date->year; ?></option>
1819
+ <?php
1820
+
1821
  }
1822
 
1823
  }
1824
+ */
1825
 
1826
  }
1827
 
1828
+
1829
  /**
1830
  * Quote array elements and separate with commas
1831
  *
1832
  * @since 0.9.6
1833
  * @return String
1834
  */
1835
+ private function quote_array( $array )
1836
+ {
1837
 
1838
  $prefix = ''; // starts empty ##
1839
  $elementlist = '';
1849
 
1850
  }
1851
 
1852
+
1853
+ /**
1854
+ * Recursively implodes an array
1855
+ *
1856
+ * @since 1.0.1
1857
+ * @access public
1858
+ * @param array $array multi-dimensional array to recursively implode
1859
+ * @param string $glue value that glues elements together
1860
+ * @param bool $include_keys include keys before their values
1861
+ * @param bool $trim_all trim ALL whitespace from string
1862
+ * @return string imploded array
1863
+ * @link https://gist.github.com/jimmygle/2564610
1864
+ */
1865
+ public static function recursive_implode( array $array, $glue = '|', $include_keys = true, $trim_all = true )
1866
+ {
1867
+
1868
+ $glued_string = '';
1869
+ $glue_count = 0;
1870
+
1871
+ // Recursively iterates array and adds key/value to glued string ##
1872
+ array_walk_recursive( $array, function( $value, $key ) use ( $glue, $include_keys, &$glued_string, $glue_count )
1873
+ {
1874
+ $include_keys and $glued_string .= $key.$glue;
1875
+ $glued_string .= $value.$glue; //.'GC_'.$glue_count.$glue;
1876
+ $glue_count ++;
1877
+ });
1878
+
1879
+ // Removes last $glue from string ##
1880
+ strlen( $glue) > 0 and $glued_string = substr( $glued_string, 0, -strlen( $glue ) );
1881
+
1882
+ // Trim ALL whitespace ##
1883
+ $trim_all and $glued_string = preg_replace( "/(\s)/ixsm", '', $glued_string );
1884
+
1885
+ return (string) $glued_string;
1886
+
1887
+ }
1888
+
1889
 
1890
  /**
1891
  * Nicer var_dump
1892
  *
1893
  * @since 0.9.6
1894
  */
1895
+ public function pr ( $variable )
1896
  {
1897
  echo '<pre>';
1898
+ print_r ( $variable );
1899
  echo '</pre>';
1900
  }
1901
 
readme.md CHANGED
@@ -2,8 +2,8 @@
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.0.0
6
- **Stable tag:** 0.9.6
7
  **License:** GPLv2
8
 
9
  Export users data, metadata and buddypress xprofile data to a csv or Excel file
@@ -59,6 +59,33 @@ Click on the 'Export User Data' link in the 'Users' menu, choose the role and th
59
 
60
  ## Changelog ##
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  ### 0.9.6 ###
63
  * Save, load and delete stored export settings - thanks to @cwjordan
64
  * Overcome memory outages on large exports - thanks to @grexican
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.1.0
6
+ **Stable tag:** 1.0.3
7
  **License:** GPLv2
8
 
9
  Export users data, metadata and buddypress xprofile data to a csv or Excel file
59
 
60
  ## Changelog ##
61
 
62
+ ### 1.0.3 ###
63
+ * Tested as working on WordPress 4.1.0.
64
+
65
+ ### 1.0.2 ###
66
+ * Removed get_user_meta method, as not effective.
67
+ * Added registration date from and to pickers - to replace monthly <select> lists.
68
+
69
+ ### 1.0.1 ###
70
+ * Added recursive_implode() method to flatten data stored in arrays ( exported with keys and values divided by "|" )
71
+
72
+ ### 1.0.0 ###
73
+ * Reduced all get_user_meta queries to a single call to improve performance
74
+ * Serialized data is now returned in it's pure stored format - not imploded or unserialized to avoid data structure loss
75
+
76
+ ### 0.9.9 ###
77
+ * get_uermeta renamed get_user_meta to be more consistent with WP
78
+ * get_user_meta tidied up and tested on larger exports
79
+ * added option to export user BP Groups
80
+ * added option to export all user WP Roles
81
+
82
+ ### 0.9.8 ###
83
+ * added get_usermeta() to check if meta keys are unique and return an array if not
84
+ * removed known_arrays() filter to allow for array data to be returned correctly - too hacky
85
+
86
+ ### 0.9.7 ###
87
+ * Added known_arrays() filter to allow for array data to be returned correctly
88
+
89
  ### 0.9.6 ###
90
  * Save, load and delete stored export settings - thanks to @cwjordan
91
  * Overcome memory outages on large exports - thanks to @grexican
readme.txt CHANGED
@@ -2,8 +2,8 @@
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.0.0
6
- Stable tag: 0.9.6
7
  License: GPLv2
8
 
9
  Export users data, metadata and buddypress xprofile data to a csv or Excel file
@@ -58,6 +58,33 @@ Click on the 'Export User Data' link in the 'Users' menu, choose the role and th
58
 
59
  == Changelog ==
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  = 0.9.6 =
62
  * Save, load and delete stored export settings - thanks to @cwjordan
63
  * Overcome memory outages on large exports - thanks to @grexican
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.1.0
6
+ Stable tag: 1.0.3
7
  License: GPLv2
8
 
9
  Export users data, metadata and buddypress xprofile data to a csv or Excel file
58
 
59
  == Changelog ==
60
 
61
+ = 1.0.3 =
62
+ * Tested as working on WordPress 4.1.0.
63
+
64
+ = 1.0.2 =
65
+ * Removed get_user_meta method, as not effective.
66
+ * Added registration date from and to pickers - to replace monthly <select> lists.
67
+
68
+ = 1.0.1 =
69
+ * Added recursive_implode() method to flatten data stored in arrays ( exported with keys and values divided by "|" )
70
+
71
+ = 1.0.0 =
72
+ * Reduced all get_user_meta queries to a single call to improve performance
73
+ * Serialized data is now returned in it's pure stored format - not imploded or unserialized to avoid data structure loss
74
+
75
+ = 0.9.9 =
76
+ * get_uermeta renamed get_user_meta to be more consistent with WP
77
+ * get_user_meta tidied up and tested on larger exports
78
+ * added option to export user BP Groups
79
+ * added option to export all user WP Roles
80
+
81
+ = 0.9.8 =
82
+ * added get_usermeta() to check if meta keys are unique and return an array if not
83
+ * removed known_arrays() filter to allow for array data to be returned correctly - too hacky
84
+
85
+ = 0.9.7 =
86
+ * Added known_arrays() filter to allow for array data to be returned correctly
87
+
88
  = 0.9.6 =
89
  * Save, load and delete stored export settings - thanks to @cwjordan
90
  * Overcome memory outages on large exports - thanks to @grexican