Architecture Overview
Core Components
bp-xprofile-export-import/
├── bp-xprofile-export-import.php # Main plugin file
├── includes/
│ ├── class-bp-xprofile-export-import.php # Core plugin class
│ ├── class-bp-xprofile-export-import-loader.php # Hook/filter loader
│ ├── class-bp-xprofile-export-import-i18n.php # Internationalization
│ └── cli/ # WP-CLI commands
├── admin/
│ ├── class-bp-xprofile-export-import-admin.php # Admin interface
│ ├── class-bp-xprofile-admin-export-ajax.php # Export AJAX handler
│ ├── class-bp-xprofile-admin-import-ajax.php # Import AJAX handler
│ └── class-bp-groups-export-ajax.php # Groups export handler
└── edd-license/ # License management
Class Hierarchy
Bp_Xprofile_Export_Import (Main Controller)
├── Bp_Xprofile_Export_Import_Loader (Hook Management)
├── Bp_Xprofile_Export_Import_Admin (Admin Interface)
├── Bp_Xprofile_Export_Import_Admin_Export_Ajax (Export Handler)
├── Bp_Xprofile_Export_Import_Admin_Import_Ajax (Import Handler)
├── Bp_Groups_Export_Ajax (Groups Handler)
└── BP_Member_CLI (CLI Commands)
Data Flow
Export Process
- User selects members/fields in admin UI
- AJAX request to
bpxp_export_xprofile_data - Data fetched from database in batches
- CSV generated with proper encoding
- File sent to browser for download
Import Process
- User uploads CSV file
- File parsed and headers extracted
- User maps CSV columns to xProfile fields
- AJAX batch processing of user creation/updates
- Progress reported back to UI
Key Files and Their Purposes
Main Plugin File
// bp-xprofile-export-import.php
define('BPXP_PLUGIN_VERSION', '1.6.0');
define('BPXP_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('BPXP_PLUGIN_URL', plugin_dir_url(__FILE__));
Core Plugin Class
// includes/class-bp-xprofile-export-import.php
class Bp_Xprofile_Export_Import {
protected $loader;
protected $plugin_name;
protected $version;
public function __construct() {
$this->plugin_name = 'bp-xprofile-export-import';
$this->version = BPXP_PLUGIN_VERSION;
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
$this->define_cli_commands();
}
}
Action Hooks
Export Page Hooks
// Before/After user selection dropdown
do_action('bpxp_before_export_select_user');
do_action('bpxp_after_export_select_user');
// Before/After field group selection
do_action('bpxp_before_export_fields_group');
do_action('bpxp_after_export_fields_group');
// Before/After individual field selection
do_action('bpxp_before_export_prof_fields');
do_action('bpxp_after_export_prof_fields');
// After export button
do_action('bpxp_after_export_buttons');
Import Page Hooks
// Server limits section
do_action('bpxp_before_import_limit');
do_action('bpxp_after_import_limit');
// File upload section
do_action('bpxp_before_import_file');
do_action('bpxp_after_import_file');
// Update existing users option
do_action('bpxp_before_import_update_user');
do_action('bpxp_after_import_update_user');
// After import button
do_action('bpxp_after_import_button');
Processing Hooks
// Before/After export processing
do_action('bpxp_before_export_process', $user_ids, $fields);
do_action('bpxp_after_export_process', $csv_content, $user_count);
// Before/After import processing
do_action('bpxp_before_import_process', $csv_data, $field_mapping);
do_action('bpxp_after_import_process', $import_results);
// Before/After user creation/update
do_action('bpxp_before_user_import', $user_data, $is_update);
do_action('bpxp_after_user_import', $user_id, $user_data, $is_update);
// Before/After xProfile update
do_action('bpxp_before_xprofile_update', $user_id, $field_id, $value);
do_action('bpxp_after_xprofile_update', $user_id, $field_id, $value);
Filter Hooks
Configuration Filters
// Maximum users to display in dropdown
add_filter('bpxp_max_users_display', function($limit) {
return 500; // Default: 200
});
// Export batch size
add_filter('bpxp_export_batch_size', function($size, $total_users) {
if ($total_users > 50000) {
return 500;
}
return 1000; // Default
}, 10, 2);
// Import batch size
add_filter('bpxp_import_batch_size', function($size) {
return 25; // Default: 10
});
// Memory limit for operations
add_filter('bpxp_memory_limit', function($limit) {
return '512M'; // Default: 256M
});
Data Processing Filters
// Filter export data before CSV generation
add_filter('bpxp_export_user_data', function($user_data, $user_id) {
// Modify user data before export
return $user_data;
}, 10, 2);
// Filter import data before processing
add_filter('bpxp_import_user_data', function($user_data, $csv_row) {
// Modify user data before import
return $user_data;
}, 10, 2);
// Filter xProfile field value during export
add_filter('bpxp_export_field_value', function($value, $field_id, $user_id) {
// Modify field value for export
return $value;
}, 10, 3);
// Filter xProfile field value during import
add_filter('bpxp_import_field_value', function($value, $field_id, $user_id) {
// Modify field value before saving
return $value;
}, 10, 3);
// Filter CSV headers
add_filter('bpxp_csv_headers', function($headers) {
// Add custom headers
$headers[] = 'custom_field';
return $headers;
});
// Filter user meta fields to export
add_filter('bpxp_export_user_meta_fields', function($fields) {
// Add/remove meta fields
$fields[] = 'custom_meta_key';
return $fields;
});
Validation Filters
// Validate user data before import
add_filter('bpxp_validate_user_data', function($is_valid, $user_data) {
// Custom validation logic
if (empty($user_data['user_email'])) {
return false;
}
return $is_valid;
}, 10, 2);
// Validate field value
add_filter('bpxp_validate_field_value', function($is_valid, $value, $field) {
// Custom field validation
return $is_valid;
}, 10, 3);
AJAX Endpoints
Export Endpoints
Get xProfile Fields
// Action: bpxp_get_export_xprofile_fields
jQuery.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'bpxp_get_export_xprofile_fields',
group_ids: [1, 2, 3],
nonce: bpxp_export_object.nonce
},
success: function(response) {
// Handle fields data
}
});
Export Members
// Action: bpxp_export_xprofile_data
jQuery.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'bpxp_export_xprofile_data',
user_ids: [1, 2, 3],
field_ids: [1, 2, 3],
include_standard: true,
include_meta: true,
nonce: bpxp_export_object.nonce
},
success: function(response) {
// Handle CSV download
}
});
Import Endpoints
Parse CSV Headers
// Action: bpxp_import_header_fields
var formData = new FormData();
formData.append('action', 'bpxp_import_header_fields');
formData.append('csv_file', fileInput.files[0]);
formData.append('nonce', bpxp_import_object.nonce);
jQuery.ajax({
url: ajaxurl,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
// Handle header mapping UI
}
});
Import CSV Data
// Action: bpxp_import_csv_data
jQuery.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'bpxp_import_csv_data',
csv_data: csvData,
field_mapping: fieldMapping,
update_existing: true,
batch_size: 10,
offset: 0,
nonce: bpxp_import_object.nonce
},
success: function(response) {
// Handle import progress
}
});
Extending the Plugin
Adding Custom Export Fields
// Add custom field to export
add_filter('bpxp_export_user_data', function($user_data, $user_id) {
// Add custom calculation
$user_data['total_posts'] = count_user_posts($user_id);
// Add from custom table
global $wpdb;
$custom_value = $wpdb->get_var($wpdb->prepare(
"SELECT value FROM {$wpdb->prefix}custom_table WHERE user_id = %d",
$user_id
));
$user_data['custom_value'] = $custom_value;
return $user_data;
}, 10, 2);
// Add corresponding header
add_filter('bpxp_csv_headers', function($headers) {
$headers[] = 'total_posts';
$headers[] = 'custom_value';
return $headers;
});
Custom Import Processing
// Process custom fields during import
add_action('bpxp_after_user_import', function($user_id, $user_data, $is_update) {
if (isset($user_data['custom_field'])) {
update_user_meta($user_id, 'custom_field', $user_data['custom_field']);
}
// Trigger custom action
if (!$is_update) {
do_action('my_custom_new_user_imported', $user_id, $user_data);
}
}, 10, 3);
Adding Custom Validation
// Validate email domain
add_filter('bpxp_validate_user_data', function($is_valid, $user_data) {
if (isset($user_data['user_email'])) {
$domain = substr(strrchr($user_data['user_email'], "@"), 1);
$allowed_domains = ['company.com', 'organization.org'];
if (!in_array($domain, $allowed_domains)) {
return new WP_Error(
'invalid_domain',
'Email domain not allowed: ' . $domain
);
}
}
return $is_valid;
}, 10, 2);
Custom Field Type Handler
// Register custom field type handler
add_filter('bpxp_field_type_handlers', function($handlers) {
$handlers['custom_type'] = 'MyCustomFieldHandler';
return $handlers;
});
class MyCustomFieldHandler {
public static function export($field_id, $user_id) {
$value = xprofile_get_field_data($field_id, $user_id);
// Custom export processing
return json_encode($value);
}
public static function import($field_id, $user_id, $value) {
// Custom import processing
$processed_value = json_decode($value, true);
return xprofile_set_field_data($field_id, $user_id, $processed_value);
}
}
Custom Field Types
Handling Complex Field Types
Multi-Select Fields
// Export multi-select values
add_filter('bpxp_export_field_value', function($value, $field_id, $user_id) {
$field = xprofile_get_field($field_id);
if ($field->type == 'multiselectbox') {
if (is_array($value)) {
return implode('|', $value);
}
}
return $value;
}, 10, 3);
// Import multi-select values
add_filter('bpxp_import_field_value', function($value, $field_id, $user_id) {
$field = xprofile_get_field($field_id);
if ($field->type == 'multiselectbox') {
return explode('|', $value);
}
return $value;
}, 10, 3);
Date Fields
// Handle date field formats
add_filter('bpxp_export_field_value', function($value, $field_id, $user_id) {
$field = xprofile_get_field($field_id);
if ($field->type == 'datebox') {
// Convert to standard format
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
if ($date) {
return $date->format('Y-m-d');
}
}
return $value;
}, 10, 3);
File Upload Fields
// Export file URLs
add_filter('bpxp_export_field_value', function($value, $field_id, $user_id) {
$field = xprofile_get_field($field_id);
if ($field->type == 'file') {
// Convert attachment ID to URL
if (is_numeric($value)) {
return wp_get_attachment_url($value);
}
}
return $value;
}, 10, 3);
// Import files from URLs
add_filter('bpxp_import_field_value', function($value, $field_id, $user_id) {
$field = xprofile_get_field($field_id);
if ($field->type == 'file' && filter_var($value, FILTER_VALIDATE_URL)) {
// Download and create attachment
$attachment_id = bpxp_import_file_from_url($value, $user_id);
return $attachment_id;
}
return $value;
}, 10, 3);
Performance Optimization
Memory Management
// Optimize memory for large exports
add_action('bpxp_before_export_process', function($user_ids, $fields) {
// Increase memory limit
ini_set('memory_limit', '512M');
// Disable query logging
global $wpdb;
$wpdb->queries = array();
// Clear object cache
wp_cache_flush();
});
// Batch processing optimization
add_filter('bpxp_export_batch_size', function($size, $total_users) {
$memory_limit = ini_get('memory_limit');
$memory_bytes = wp_convert_hr_to_bytes($memory_limit);
// Adjust batch size based on available memory
if ($memory_bytes < 134217728) { // Less than 128MB
return 100;
} elseif ($memory_bytes < 268435456) { // Less than 256MB
return 500;
} else {
return 1000;
}
}, 10, 2);
Database Optimization
// Optimize queries for large datasets
add_filter('bpxp_user_query_args', function($args) {
// Add specific fields to reduce memory
$args['fields'] = ['ID', 'user_login', 'user_email'];
// Disable meta queries if not needed
$args['meta_query'] = array();
return $args;
});
// Use direct database queries for performance
add_action('bpxp_export_direct_query', function($user_ids) {
global $wpdb;
$user_ids_str = implode(',', array_map('intval', $user_ids));
$results = $wpdb->get_results("
SELECT u.ID, u.user_login, u.user_email,
GROUP_CONCAT(DISTINCT g.name) as groups
FROM {$wpdb->users} u
LEFT JOIN {$wpdb->prefix}bp_groups_members gm ON u.ID = gm.user_id
LEFT JOIN {$wpdb->prefix}bp_groups g ON gm.group_id = g.id
WHERE u.ID IN ($user_ids_str)
GROUP BY u.ID
");
return $results;
});
Caching Strategy
// Cache xProfile field structure
add_filter('bpxp_get_xprofile_fields', function($fields) {
$cache_key = 'bpxp_xprofile_fields';
$cached = wp_cache_get($cache_key);
if ($cached !== false) {
return $cached;
}
// Get fields from database
$fields = BP_XProfile_Group::get(array(
'fetch_fields' => true
));
// Cache for 1 hour
wp_cache_set($cache_key, $fields, '', HOUR_IN_SECONDS);
return $fields;
});
Security Considerations
Capability Checks
// Add custom capability check
add_filter('bpxp_export_capability', function($capability) {
// Require higher permission for export
return 'export_users'; // Default: 'manage_options'
});
add_filter('bpxp_import_capability', function($capability) {
// Require specific capability for import
return 'import_users'; // Default: 'manage_options'
});
Data Sanitization
// Sanitize import data
add_filter('bpxp_import_user_data', function($user_data, $csv_row) {
// Sanitize email
if (isset($user_data['user_email'])) {
$user_data['user_email'] = sanitize_email($user_data['user_email']);
}
// Sanitize username
if (isset($user_data['user_login'])) {
$user_data['user_login'] = sanitize_user($user_data['user_login']);
}
// Sanitize HTML content
if (isset($user_data['description'])) {
$user_data['description'] = wp_kses_post($user_data['description']);
}
return $user_data;
}, 10, 2);
File Upload Validation
// Validate CSV file upload
add_filter('bpxp_validate_csv_file', function($is_valid, $file) {
// Check file extension
$allowed_types = ['csv', 'txt'];
$file_ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($file_ext, $allowed_types)) {
return new WP_Error('invalid_file_type', 'Only CSV files allowed');
}
// Check MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mime_type, ['text/csv', 'text/plain'])) {
return new WP_Error('invalid_mime_type', 'Invalid file type');
}
// Check file size (10MB limit)
if ($file['size'] > 10485760) {
return new WP_Error('file_too_large', 'File size exceeds 10MB');
}
return $is_valid;
}, 10, 2);
Code Examples
Complete Export Integration
/**
* Custom export integration with additional data
*/
class My_Custom_Export_Integration {
public function __construct() {
add_filter('bpxp_export_user_data', [$this, 'add_custom_data'], 10, 2);
add_filter('bpxp_csv_headers', [$this, 'add_custom_headers']);
add_action('bpxp_after_export_process', [$this, 'log_export'], 10, 2);
}
public function add_custom_data($user_data, $user_id) {
// Add WooCommerce order count
if (class_exists('WooCommerce')) {
$user_data['order_count'] = wc_get_customer_order_count($user_id);
$user_data['total_spent'] = wc_get_customer_total_spent($user_id);
}
// Add forum post count
if (function_exists('bbp_get_user_post_count')) {
$user_data['forum_posts'] = bbp_get_user_post_count($user_id);
}
// Add custom meta
$user_data['last_login'] = get_user_meta($user_id, 'last_login', true);
return $user_data;
}
public function add_custom_headers($headers) {
if (class_exists('WooCommerce')) {
$headers[] = 'order_count';
$headers[] = 'total_spent';
}
if (function_exists('bbp_get_user_post_count')) {
$headers[] = 'forum_posts';
}
$headers[] = 'last_login';
return $headers;
}
public function log_export($csv_content, $user_count) {
// Log export activity
$log_entry = sprintf(
'[%s] Exported %d users by %s',
current_time('mysql'),
$user_count,
wp_get_current_user()->user_login
);
error_log($log_entry, 3, WP_CONTENT_DIR . '/bpxp-export.log');
}
}
new My_Custom_Export_Integration();
Complete Import Integration
/**
* Custom import integration with validation and processing
*/
class My_Custom_Import_Integration {
public function __construct() {
add_filter('bpxp_validate_user_data', [$this, 'validate_data'], 10, 2);
add_filter('bpxp_import_user_data', [$this, 'process_data'], 10, 2);
add_action('bpxp_after_user_import', [$this, 'after_import'], 10, 3);
}
public function validate_data($is_valid, $user_data) {
// Validate email domain
if (isset($user_data['user_email'])) {
$domain = substr(strrchr($user_data['user_email'], "@"), 1);
if ($domain === 'blocked.com') {
return new WP_Error('blocked_domain', 'This email domain is not allowed');
}
}
// Validate age if present
if (isset($user_data['age']) && $user_data['age'] < 18) {
return new WP_Error('underage', 'Users must be 18 or older');
}
return $is_valid;
}
public function process_data($user_data, $csv_row) {
// Process phone number format
if (isset($user_data['phone'])) {
$user_data['phone'] = preg_replace('/[^0-9]/', '', $user_data['phone']);
}
// Set default values
if (!isset($user_data['role'])) {
$user_data['role'] = 'subscriber';
}
// Generate username from email if not provided
if (!isset($user_data['user_login']) && isset($user_data['user_email'])) {
$user_data['user_login'] = strstr($user_data['user_email'], '@', true);
}
return $user_data;
}
public function after_import($user_id, $user_data, $is_update) {
// Add to custom group
if (!$is_update && function_exists('groups_join_group')) {
groups_join_group(array(
'group_id' => 1, // New members group
'user_id' => $user_id
));
}
// Send custom notification
if (!$is_update) {
$this->send_welcome_notification($user_id, $user_data);
}
// Log import
$this->log_import($user_id, $user_data, $is_update);
}
private function send_welcome_notification($user_id, $user_data) {
$subject = 'Welcome to our community!';
$message = sprintf(
'Hello %s, welcome to our platform!',
$user_data['display_name'] ?? $user_data['user_login']
);
wp_mail($user_data['user_email'], $subject, $message);
}
private function log_import($user_id, $user_data, $is_update) {
$action = $is_update ? 'updated' : 'created';
$log_entry = sprintf(
'[%s] User %s (%d) %s',
current_time('mysql'),
$user_data['user_login'],
$user_id,
$action
);
error_log($log_entry, 3, WP_CONTENT_DIR . '/bpxp-import.log');
}
}
new My_Custom_Import_Integration();
API Reference
Global Functions
/**
* Get xProfile fields for export
* @param array $group_ids Optional group IDs to filter
* @return array Field data
*/
function bpxp_get_export_fields($group_ids = array()) {
return apply_filters('bpxp_export_fields', $fields, $group_ids);
}
/**
* Export users to CSV
* @param array $user_ids User IDs to export
* @param array $field_ids Field IDs to include
* @param array $options Export options
* @return string CSV content
*/
function bpxp_export_users($user_ids, $field_ids, $options = array()) {
$defaults = array(
'include_standard' => true,
'include_meta' => false,
'include_avatar' => false,
'include_groups' => false
);
$options = wp_parse_args($options, $defaults);
// Process export
return apply_filters('bpxp_export_csv', $csv, $user_ids, $field_ids, $options);
}
/**
* Import users from CSV data
* @param array $csv_data Parsed CSV data
* @param array $field_mapping Column to field mapping
* @param array $options Import options
* @return array Import results
*/
function bpxp_import_users($csv_data, $field_mapping, $options = array()) {
$defaults = array(
'update_existing' => false,
'send_notification' => false,
'default_role' => 'subscriber',
'batch_size' => 10
);
$options = wp_parse_args($options, $defaults);
// Process import
return apply_filters('bpxp_import_results', $results, $csv_data, $field_mapping, $options);
}
/**
* Parse CSV file
* @param string $file_path Path to CSV file
* @return array Parsed CSV data
*/
function bpxp_parse_csv($file_path) {
$csv_data = array();
if (($handle = fopen($file_path, 'r')) !== false) {
$headers = fgetcsv($handle);
while (($row = fgetcsv($handle)) !== false) {
$csv_data[] = array_combine($headers, $row);
}
fclose($handle);
}
return apply_filters('bpxp_parsed_csv', $csv_data, $file_path);
}
Class Methods
// Export handler methods
Bp_Xprofile_Export_Import_Admin_Export_Ajax::export_users()
Bp_Xprofile_Export_Import_Admin_Export_Ajax::get_xprofile_fields()
Bp_Xprofile_Export_Import_Admin_Export_Ajax::generate_csv()
// Import handler methods
Bp_Xprofile_Export_Import_Admin_Import_Ajax::import_users()
Bp_Xprofile_Export_Import_Admin_Import_Ajax::parse_csv_headers()
Bp_Xprofile_Export_Import_Admin_Import_Ajax::process_batch()
// Utility methods
Bp_Xprofile_Export_Import::get_user_meta_fields()
Bp_Xprofile_Export_Import::sanitize_field_value()
Bp_Xprofile_Export_Import::validate_csv_data()
Support
For developer support:
- GitHub Issues: github.com/wbcomdesigns
- Support Forum: wbcomdesigns.com/support
