File: /var/www/html/wp-content/plugins/memberpress/app/controllers/MeprExportCtrl.php
<?php
if (!defined('ABSPATH')) {
die('You are not allowed to call this page directly.');
}
class MeprExportCtrl extends MeprBaseCtrl
{
/**
* Load hooks for the export functionality.
*
* @return void
*/
public function load_hooks()
{
add_action('init', 'MeprExportCtrl::export_users_csv');
add_action('init', 'MeprExportCtrl::export_inactive_users_csv');
add_filter('wp_privacy_personal_data_exporters', [$this, 'register_pii_exporter'], 10);
}
/**
* Registers callback for PII exporter.
*
* @param array $exporters The existing exporters.
* @return array The modified exporters.
*/
public static function register_pii_exporter($exporters)
{
$exporters[MEPR_PLUGIN_SLUG] = [
'exporter_friendly_name' => MEPR_PLUGIN_NAME,
'callback' => ['MeprExportCtrl', 'export_pii'],
];
return $exporters;
}
/**
* Gathers PII data stored by MemberPress for export.
*
* @param string $email The email address of the requested user to export.
* @param integer $page The page number for pagination.
* @return array An array containing the data and a done flag.
*/
public static function export_pii($email, $page = 1)
{
$user = get_user_by('email', $email);
$mepr_user = new MeprUser($user->ID);
$mepr_data = [];
// Export address fields.
if ($mepr_user->address_is_set()) {
$address = $mepr_user->formatted_address();
$mepr_data[] = [
'group_id' => MEPR_PLUGIN_NAME,
'group_label' => __('Membership Data', 'memberpress'),
'item_id' => 'mepr-user-data',
'data' => [
[
'name' => __('Address', 'memberpress'),
'value' => $address,
],
],
];
}
// Export VAT data.
$vat_number = get_user_meta($user->ID, 'mepr_vat_number', true);
if (!empty($vat_number)) {
$mepr_data[] = [
'group_id' => MEPR_PLUGIN_NAME,
'group_label' => __('Membership Data', 'memberpress'),
'item_id' => 'mepr-user-data',
'data' => [
[
'name' => __('VAT Number', 'memberpress'),
'value' => $vat_number,
],
],
];
}
// Export Geo located country.
$geo_country = get_user_meta($user->ID, 'mepr-geo-country', true);
if (!empty($geo_country)) {
$mepr_data[] = [
'group_id' => MEPR_PLUGIN_NAME,
'group_label' => __('Membership Data', 'memberpress'),
'item_id' => 'mepr-user-data',
'data' => [
[
'name' => __('Geo Location Country', 'memberpress'),
'value' => $geo_country,
],
],
];
}
return [
'data' => $mepr_data,
'done' => true,
];
}
/**
* Exports users to a CSV file.
*
* This will need a major overhaul eventually, but we needed a quick fix for some clients
* So this is the quick fix. It can only be accessed via
* /wp-admin/admin.php?page=memberpress-options&mepr-export-users-csv currently.
* If we change this, we definitely need to let the folks at theballstonjournal.com know
*
* @return void
*/
public static function export_users_csv()
{
global $wpdb;
if (!MeprUtils::is_mepr_admin()) { // Make sure we're an admin.
return;
}
if (isset($_GET['page']) && $_GET['page'] === 'memberpress-options' && isset($_GET['mepr-export-users-csv'])) {
$q = "SELECT u.ID AS user_ID, u.user_login AS username, u.user_email AS email, f.meta_value AS first_name, l.meta_value AS last_name, a1.meta_value AS address1, a2.meta_value AS address2, c.meta_value AS city, s.meta_value AS state, z.meta_value AS zip, u.user_registered AS start_date, t.expires_at AS end_date, p.post_title AS membership, t.gateway, cp.post_title AS coupon
FROM {$wpdb->users} AS u
LEFT JOIN {$wpdb->usermeta} AS f
ON u.ID = f.user_id AND f.meta_key = 'first_name'
LEFT JOIN {$wpdb->usermeta} AS l
ON u.ID = l.user_id AND l.meta_key = 'last_name'
LEFT JOIN {$wpdb->usermeta} AS a1
ON u.ID = a1.user_id AND a1.meta_key = 'mepr-address-one'
LEFT JOIN {$wpdb->usermeta} AS a2
ON u.ID = a2.user_id AND a2.meta_key = 'mepr-address-two'
LEFT JOIN {$wpdb->usermeta} AS c
ON u.ID = c.user_id AND c.meta_key = 'mepr-address-city'
LEFT JOIN {$wpdb->usermeta} AS s
ON u.ID = s.user_id AND s.meta_key = 'mepr-address-state'
LEFT JOIN {$wpdb->usermeta} AS z
ON u.ID = z.user_id AND z.meta_key = 'mepr-address-zip'
INNER JOIN {$wpdb->mepr_transactions} AS t
ON u.ID = t.user_id AND (t.status = 'complete' OR t.status = 'confirmed') AND (t.expires_at IS NULL OR t.expires_at = 0 OR t.expires_at >= %s)
LEFT JOIN {$wpdb->posts} AS p
ON t.product_id = p.ID
LEFT JOIN {$wpdb->posts} AS cp
ON t.coupon_id = cp.ID";
// Output headers so that the file is downloaded rather than displayed.
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=active_customers.csv');
// Create a file pointer connected to the output stream.
$output = fopen('php://output', 'w');
// Output the column headings.
fputcsv($output, [
'User_ID',
'Username',
'Email',
'First Name',
'Last Name',
'Address 1',
'Address 2',
'City',
'State',
'Zip',
'Start Date',
'End Date',
'Subscription',
'Gateway',
'Coupon',
]);
// Fetch the data.
$wpdb->query('SET SQL_BIG_SELECTS=1'); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
$rows = $wpdb->get_results($wpdb->prepare($q, MeprUtils::db_now()), ARRAY_A); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter
// Loop over the rows, outputting them.
foreach ($rows as $row) {
fputcsv($output, $row);
}
// Close the file and exit.
fclose($output); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
exit;
}
}
/**
* Exports inactive users to a CSV file.
*
* This will need a major overhaul eventually, but we needed a quick fix for some clients
* So this is the quick fix. It can only be accessed via
* /wp-admin/admin.php?page=memberpress-options&mepr-export-inactive-users-csv currently.
* If we change this, we definitely need to let the folks at theballstonjournal.com know
*
* @return void
*/
public static function export_inactive_users_csv()
{
global $wpdb;
if (!MeprUtils::is_mepr_admin()) { // Make sure we're an admin.
return;
}
if (isset($_GET['page']) && $_GET['page'] === 'memberpress-options' && isset($_GET['mepr-export-inactive-users-csv'])) {
$q = "SELECT u.ID AS user_ID, u.user_login AS username, u.user_email AS email, f.meta_value AS first_name, l.meta_value AS last_name, a1.meta_value AS address1, a2.meta_value AS address2, c.meta_value AS city, s.meta_value AS state, z.meta_value AS zip, u.user_registered AS start_date, t.expires_at AS end_date, p.post_title AS membership, t.gateway, cp.post_title AS coupon
FROM {$wpdb->users} AS u
LEFT JOIN {$wpdb->usermeta} AS f
ON u.ID = f.user_id AND f.meta_key = 'first_name'
LEFT JOIN {$wpdb->usermeta} AS l
ON u.ID = l.user_id AND l.meta_key = 'last_name'
LEFT JOIN {$wpdb->usermeta} AS a1
ON u.ID = a1.user_id AND a1.meta_key = 'mepr-address-one'
LEFT JOIN {$wpdb->usermeta} AS a2
ON u.ID = a2.user_id AND a2.meta_key = 'mepr-address-two'
LEFT JOIN {$wpdb->usermeta} AS c
ON u.ID = c.user_id AND c.meta_key = 'mepr-address-city'
LEFT JOIN {$wpdb->usermeta} AS s
ON u.ID = s.user_id AND s.meta_key = 'mepr-address-state'
LEFT JOIN {$wpdb->usermeta} AS z
ON u.ID = z.user_id AND z.meta_key = 'mepr-address-zip'
INNER JOIN (SELECT *
FROM {$wpdb->mepr_transactions}
WHERE user_id NOT IN (SELECT user_id
FROM {$wpdb->mepr_transactions}
WHERE (expires_at >= %s
OR expires_at IS NULL
OR expires_at = %s)
AND status IN ('complete', 'confirmed')
GROUP BY user_id)
GROUP BY user_id) AS t ON u.ID = t.user_id
LEFT JOIN {$wpdb->posts} AS p
ON p.ID = t.product_id
LEFT JOIN {$wpdb->posts} AS cp
ON t.coupon_id = cp.ID
GROUP BY u.ID";
// Output headers so that the file is downloaded rather than displayed.
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=inactive_customers.csv');
// Create a file pointer connected to the output stream.
$output = fopen('php://output', 'w');
// Output the column headings.
fputcsv($output, [
'User_ID',
'Username',
'Email',
'First Name',
'Last Name',
'Address 1',
'Address 2',
'City',
'State',
'Zip',
'Start Date',
'End Date',
'Subscription',
'Gateway',
'Coupon',
]);
// Fetch the data.
$wpdb->query('SET SQL_BIG_SELECTS=1'); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
$rows = $wpdb->get_results($wpdb->prepare($q, MeprUtils::db_now(), MeprUtils::db_lifetime()), ARRAY_A); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter
// Loop over the rows, outputting them.
foreach ($rows as $row) {
fputcsv($output, $row);
}
// Close the file and exit.
fclose($output); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
exit;
}
}
}