first commit

This commit is contained in:
2024-07-15 11:28:08 +02:00
commit f52d538ea5
21891 changed files with 6161164 additions and 0 deletions

View File

@@ -0,0 +1,333 @@
<?php
defined('ABSPATH') || exit;
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
$id = (int) $_GET['id'];
$user = $module->get_user($id);
if ($controls->is_action('save')) {
$email = $module->normalize_email($controls->data['email']);
if (empty($email)) {
$controls->errors = __('Wrong email address', 'newsletter');
} else {
$controls->data['email'] = $email;
}
if (empty($controls->errors)) {
$u = $module->get_user($controls->data['email']);
if ($u && $u->id != $id) {
$controls->errors = __('The email address is already in use', 'newsletter');
}
}
if (empty($controls->errors)) {
// For unselected preferences, force the zero value
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
if (!isset($controls->data['list_' . $i])) {
$controls->data['list_' . $i] = 0;
}
}
if (empty($controls->data['token'])) {
$controls->data['token'] = $module->get_token();
}
$controls->data['id'] = $id;
$user = $module->save_user($controls->data);
$module->add_user_log($user, 'edit');
if ($user === false) {
$controls->errors = __('Error. Check the log files.', 'newsletter');
} else {
$controls->add_message_saved();
$controls->data = (array) $user;
}
}
}
if ($controls->is_action('delete')) {
$module->delete_user($id);
$controls->js_redirect($module->get_admin_page_url('index'));
return;
}
if (!$controls->is_action()) {
$controls->data = (array) $user;
}
$options_profile = NewsletterSubscription::instance()->get_options('profile');
function percent($value, $total) {
if ($total == 0) {
return '-';
}
return sprintf("%.2f", $value / $total * 100) . '%';
}
function percentValue($value, $total) {
if ($total == 0) {
return 0;
}
return round($value / $total * 100);
}
?>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages': ['corechart', 'geomap']});
</script>
<div class="wrap tnp-users tnp-users-edit" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Editing', 'newsletter') ?> <?php echo esc_html($controls->data['email']) ?></h2>
</div>
<div id="tnp-body">
<form method="post" action="">
<p>
<?php $controls->button_back('?page=newsletter_users_index'); ?>
<?php $controls->button_save(); ?>
</p>
<?php $controls->init(); ?>
<div id="tabs">
<ul>
<li><a href="#tabs-general"><?php _e('General', 'newsletter') ?></a></li>
<li><a href="#tabs-preferences"><?php _e('Lists', 'newsletter') ?></a></li>
<li><a href="#tabs-profile"><?php _e('Extra fields', 'newsletter') ?></a></li>
<li><a href="#tabs-other"><?php _e('Other', 'newsletter') ?></a></li>
<li><a href="#tabs-newsletters"><?php _e('Newsletters', 'newsletter') ?></a></li>
<li><a href="#tabs-history"><?php _e('Logs', 'newsletter') ?></a></li>
</ul>
<div id="tabs-general" class="tnp-tab">
<?php do_action('newsletter_users_edit_general', $id, $controls) ?>
<table class="form-table">
<tr>
<th><?php _e('Email', 'newsletter'); ?></th>
<td>
<?php $controls->text_email('email', 60); ?>
</td>
</tr>
<tr>
<th><?php _e('First name', 'newsletter'); ?></th>
<td>
<?php $controls->text('name', 50); ?>
</td>
</tr>
<tr>
<th><?php _e('Last name', 'newsletter'); ?></th>
<td>
<?php $controls->text('surname', 50); ?>
</td>
</tr>
<tr>
<th><?php _e('Gender', 'newsletter'); ?></th>
<td>
<?php $controls->select('sex', array('n' => 'Not specified', 'f' => 'female', 'm' => 'male')); ?>
</td>
</tr>
<tr>
<th><?php _e('Status', 'newsletter'); ?></th>
<td>
<?php $controls->select('status', array('C' => 'Confirmed', 'S' => 'Not confirmed', 'U' => 'Unsubscribed', 'B' => 'Bounced')); ?>
</td>
</tr>
<tr>
<th><?php _e('Language', 'newsletter'); ?></th>
<td>
<?php $controls->language(); ?>
</td>
</tr>
<tr>
<th><?php _e('Test subscriber', 'newsletter'); ?>
<br><?php $controls->help('https://www.thenewsletterplugin.com/documentation/subscribers#test-subscribers') ?></th>
<td>
<?php $controls->yesno('test'); ?>
</td>
</tr>
<?php do_action('newsletter_user_edit_extra', $controls); ?>
<tr>
<th>Feed by mail</th>
<td>
<?php $controls->yesno('feed'); ?>
</td>
</tr>
</table>
</div>
<div id="tabs-preferences" class="tnp-tab">
<table class="form-table">
<tr>
<th><?php _e('Lists', 'newsletter') ?><br><?php echo $controls->help('https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-preferences') ?></th>
<td>
<?php $controls->preferences('list'); ?>
</td>
</tr>
</table>
</div>
<div id="tabs-profile" class="tnp-tab">
<table class="widefat">
<thead>
<tr>
<th>#</th>
<th><?php _e('Name', 'newsletter'); ?></th>
<th><?php _e('Value', 'newsletter'); ?></th>
</tr>
</thead>
<tbody>
<?php
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
echo '<tr><td>';
echo $i;
echo '</td><td>';
echo esc_html($options_profile['profile_' . $i]);
echo '</td><td>';
$controls->text('profile_' . $i, 70);
echo '</td></tr>';
}
?>
</tbody>
</table>
</div>
<div id="tabs-other" class="tnp-tab">
<table class="form-table">
<tr>
<th>ID</th>
<td>
<?php $controls->value('id'); ?>
</td>
</tr>
<tr>
<th><?php _e('Created', 'newsletter') ?></th>
<td>
<?php echo $controls->print_date(strtotime($controls->data['created'])); ?>
</td>
</tr>
<tr>
<th><?php _e('Last activity', 'newsletter') ?></th>
<td>
<?php echo $controls->print_date($controls->data['last_activity']); ?>
</td>
</tr>
<tr>
<th><?php _e('WP user ID', 'newsletter') ?></th>
<td>
<?php $controls->text('wp_user_id'); ?>
</td>
</tr>
<tr>
<th><?php _e('IP address', 'newsletter'); ?></th>
<td>
<?php $controls->value('ip'); ?>
</td>
</tr>
<tr>
<th><?php _e('Secret token', 'newsletter'); ?></th>
<td>
<?php $controls->text('token', 50); ?>
</td>
</tr>
<tr>
<th><?php _e('Profile URL', 'newsletter'); ?></th>
<td>
<?php $profile_url = NewsletterProfile::instance()->get_profile_url($user) ?>
<a href='<?php echo $profile_url ?>' target="_blank"><?php echo $profile_url ?></a>
</td>
</tr>
</table>
</div>
<div id="tabs-newsletters" class="tnp-tab">
<?php if (!has_action('newsletter_user_newsletters_tab') && !has_action('newsletter_users_edit_newsletters')) { ?>
<div class="tnp-tab-notice">
This panel requires the <a href="https://www.thenewsletterplugin.com/plugins/newsletter/reports-module" target="_blank">Reports Extension 4+</a>.
</div>
<?php
} else {
do_action('newsletter_user_newsletters_tab', $id);
do_action('newsletter_users_edit_newsletters', $id);
}
?>
</div>
<div id="tabs-history" class="tnp-tab">
<?php
$logs = $wpdb->get_results($wpdb->prepare("select * from {$wpdb->prefix}newsletter_user_logs where user_id=%d order by id desc", $id));
?>
<?php if (empty($logs)) { ?>
<p>No logs available</p>
<?php } else { ?>
<p>Only public lists are recorded.</p>
<table class="widefat" style="width: auto">
<thead>
<tr>
<th>Date</th>
<th>Source</th>
<th>IP</th>
<th>Lists</th>
</tr>
<tbody>
<?php foreach ($logs as $log) { ?>
<?php
$data = json_decode($log->data, ARRAY_A);
if (isset($data['new']))
$data = $data['new'];
?>
<tr>
<td><?php echo $controls->print_date($log->created) ?></td>
<td><?php echo esc_html($log->source) ?></td>
<td><?php echo esc_html($log->ip) ?></td>
<td>
<?php
if (is_array($data)) {
foreach ($data as $key => $value) {
echo esc_html(str_replace('_', ' ', $key)), ': ', esc_html($value) . '<br>';
}
}
?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php } ?>
</div>
</div>
<p>
<?php $controls->button_save(); ?>
<?php $controls->button_delete(); ?>
</p>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,53 @@
<?php
@include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$options_profile = get_option('newsletter_profile');
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
?>
<div class="wrap" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Export', 'newsletter') ?></h2>
<p>
<strong>The import and export functions ARE NOT for backup</strong>.
If you want to backup you should consider to backup the <code><?php echo $wpdb->prefix ?>newsletter*</code> tables.
</p>
</div>
<div id="tnp-body" class="tnp-users tnp-users-export">
<form method="post" action="<?php echo admin_url('admin-ajax.php') ?>?action=newsletter_users_export">
<?php $controls->init(); ?>
<table class="form-table">
<tr>
<th><?php _e('Field separator', 'newsletter') ?></th>
<td>
<?php $controls->select('separator', array(';' => 'Semicolon', ',' => 'Comma', 'tab' => 'Tabulation')); ?>
<p class="description">Try to change the separator if Excel does not recognize the columns.</p>
</td>
</tr>
<tr>
<th><?php _e('List', 'newsletter') ?></th>
<td>
<?php $controls->lists_select('list', __('All', 'newsletter')); ?>
</td>
</tr>
</table>
<p>
<?php $controls->button('export', __('Export', 'newsletter')); ?>
</p>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,276 @@
<?php
if (!defined('ABSPATH'))
exit;
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
$options_profile = get_option('newsletter_profile');
if ($controls->is_action('import')) {
$mode = $controls->data['mode'];
// TODO: to be removed, it's not safe
@set_time_limit(0);
$results = '';
if (is_uploaded_file($_FILES['csv_file']['tmp_name'])) {
$lines = file($_FILES['csv_file']['tmp_name']);
} else {
$csv = stripslashes($controls->data['csv']);
$lines = explode("\n", $csv);
}
// Set the selected preferences inside the
if (!isset($controls->data['preferences']) || !is_array($controls->data['preferences']))
$controls->data['preferences'] = array();
// if ($options['followup'] == 'activate') {
// $subscriber['followup'] = 1;
// }
$error_count = 0;
$added_count = 0;
$updated_count = 0;
$skipped_count = 0;
foreach ($lines as &$line) {
// Parse the CSV line
$line = trim($line);
if ($line == '') {
continue;
}
if ($line[0] == '#' || $line[0] == ';') {
continue;
}
$separator = $controls->data['separator'];
if ($separator == 'tab') {
$separator = "\t";
}
$data = explode($separator, $line);
// Builds a subscriber data structure
$email = $newsletter->normalize_email($data[0]);
if (empty($email)) {
continue;
}
if (!$newsletter->is_email($email)) {
$results .= '[INVALID EMAIL] ' . $line . "\n";
$error_count++;
continue;
}
$subscriber = $module->get_user($email, ARRAY_A);
if ($subscriber == null) {
$subscriber = array();
$subscriber['email'] = $email;
if (isset($data[1])) {
$subscriber['name'] = $module->normalize_name($data[1]);
}
if (isset($data[2])) {
$subscriber['surname'] = $module->normalize_name($data[2]);
}
if (isset($data[3])) {
$subscriber['sex'] = $module->normalize_sex($data[3]);
}
$subscriber['status'] = $controls->data['import_as'];
foreach ($controls->data['preferences'] as $i) {
$subscriber['list_' . $i] = 1;
}
$module->save_user($subscriber);
$results .= '[ADDED] ' . $line . "\n";
$added_count++;
} else {
if ($mode == 'skip') {
$results .= '[SKIPPED] ' . $line . "\n";
$skipped_count++;
continue;
}
if ($mode == 'overwrite') {
if (isset($data[1])) {
$subscriber['name'] = $module->normalize_name($data[1]);
}
if (isset($data[2])) {
$subscriber['surname'] = $module->normalize_name($data[2]);
}
if (isset($data[3])) {
$subscriber['sex'] = $module->normalize_sex($data[3]);
}
if (isset($controls->data['override_status'])) {
$subscriber['status'] = $controls->data['import_as'];
}
// Prepare the preference to zero
for ($i = 1; $i < NEWSLETTER_LIST_MAX; $i++) {
$subscriber['list_' . $i] = 0;
}
foreach ($controls->data['preferences'] as $i) {
$subscriber['list_' . $i] = 1;
}
}
if ($mode == 'update') {
$subscriber['name'] = $module->normalize_name($data[1]);
$subscriber['surname'] = $module->normalize_name($data[2]);
if (isset($data[3])) {
$subscriber['sex'] = $module->normalize_sex($data[3]);
}
if (isset($controls->data['override_status'])) {
$subscriber['status'] = $controls->data['import_as'];
}
foreach ($controls->data['preferences'] as $i) {
$subscriber['list_' . $i] = 1;
}
}
NewsletterUsers::instance()->save_user($subscriber);
$results .= '[UPDATED] ' . $line . "\n";
$updated_count++;
}
}
if ($error_count) {
$controls->errors = "Import completed but with errors.";
}
$controls->messages = "Import completed: $error_count errors, $added_count added, $updated_count updated, $skipped_count skipped.";
}
?>
<div class="wrap" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Import', 'newsletter') ?></h2>
<p>
The import and export functions <strong>ARE NOT for backup</strong>. If you want to backup you should consider to backup the
wp_newsletter* tables. Please, read on bottom of this page the data format to use and other important notes.</p>
</div>
<div id="tnp-body" class="tnp-users tnp-users-import">
<?php if (!empty($results)) { ?>
<h3>Results</h3>
<textarea wrap="off" style="width: 100%; height: 150px; font-size: 11px; font-family: monospace"><?php echo esc_html($results) ?></textarea>
<?php } ?>
<form method="post" enctype="multipart/form-data">
<?php $controls->init(); ?>
<table class="form-table">
<tr>
<th><?php _e('Import Subscribers As', 'newsletter') ?></th>
<td>
<?php $controls->select('import_as', array('C' => __('Confirmed', 'newsletter'), 'S' => __('Not confirmed', 'newsletter'))); ?>
<br>
<?php $controls->checkbox('override_status', __('Override status of existing users', 'newsletter')) ?>
</td>
</tr>
<tr>
<th><?php _e('Import mode', 'newsletter') ?></th>
<td>
<?php $controls->select('mode', array('update' => 'Update', 'overwrite' => 'Overwrite', 'skip' => 'Skip')); ?>
if email is already present
<p class="description">
<strong>Update</strong>: <?php _e('user data will be updated, existing preferences will be left untouched and new ones will be added.', 'newsletter') ?><br />
<strong>Overwrite</strong>: <?php _e('user data will be overwritten with new informations (like name and preferences).', 'newsletter') ?><br />
<strong>Skip</strong>: <?php _e('user data will be left untouched if already present.', 'newsletter') ?>
</p>
</td>
</tr>
<tr>
<th><?php _e('Lists', 'newsletter') ?></th>
<td>
<?php $controls->preferences_group('preferences', true); ?>
<div class="hints">
Every new imported or updated subscriber will be associate with selected preferences above.
</div>
</td>
</tr>
<tr>
<th><?php _e('Field separator', 'newsletter') ?></th>
<td>
<?php $controls->select('separator', array(';' => 'Semicolon', ',' => 'Comma', 'tab' => 'Tabulation')); ?>
</td>
</tr>
<tr>
<th>
<?php _e('CSV file', 'newsletter') ?>
<div class="tnp-tip">
<span class="tip-button">Tip</span>
<span class="tip-content">
Upload a CSV file, see format description <a href="#import_format">below</a>.
</span>
</div>
</th>
<td>
<input type="file" name="csv_file" />
</td>
</tr>
<tr>
<th>CSV text
<div class="tnp-tip">
<span class="tip-button">Tip</span>
<span class="tip-content">
Simply paste CSV text here.
</span>
</div>
</th>
<td>
<textarea name="options[csv]" wrap="off" style="width: 100%; height: 200px; font-size: 11px; font-family: monospace"><?php echo $controls->data['csv']; ?></textarea>
</td>
</tr>
<tr>
<th>&nbsp;</th><td><?php $controls->button('import', 'Import'); ?></td>
</tr>
<tr>
<th>
<a name="import_format"></a>
Data format<br>and other notes
<div class="tnp-tip">
<span class="tip-button">Tip</span>
<span class="tip-content">Consider to split up your input list if you get errors, blank pages or partially imported lists: it can be a time/resource limit
of your provider. It's safe to import the same list a second time, no duplications will occur.</span>
</th>
<td>
<p>
Import list format is:
<p><strong>email</strong><i>[separator]</i><strong>first name</strong><i>[separator]</i><strong>last name</strong><i>[separator]</i><strong>gender</strong><i>[new line]</i></p>
Example:
<p style="border: 1px solid #bfbfbf">
email1@example.com;first name 1;last name 1;m<br />
email2@example.com;first name 2;last name 2;f
</p>
<p>
where [separator] must be selected from the available ones. Empty lines and lines starting with "#" will be skipped. There is
no separator escaping mechanism, so be sure that field values do not contain the selected separator. The only required field is the email
all other fields are options. Gender must be "m" or "f".
</p>
</td>
</tr>
</table>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,248 @@
<?php
defined('ABSPATH') || exit;
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
$options = $controls->data;
$options_profile = get_option('newsletter_profile');
$options_main = get_option('newsletter_main');
// Move to base zero
if ($controls->is_action()) {
if ($controls->is_action('reset')) {
$controls->data = array();
} else {
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
}
$module->save_options($controls->data, 'search');
} else {
$controls->data = $module->get_options('search');
if (empty($controls->data['search_page']))
$controls->data['search_page'] = 0;
}
if ($controls->is_action('resend')) {
$user = $module->get_user($controls->button_data);
NewsletterSubscription::instance()->send_message('confirmation', $user, true);
$controls->messages = __('Activation email sent.', 'newsletter');
}
if ($controls->is_action('resend_welcome')) {
$user = $module->get_user($controls->button_data);
NewsletterSubscription::instance()->send_message('confirmed', $user, true);
$controls->messages = __('Welcome email sent.', 'newsletter');
}
if ($controls->is_action('remove')) {
$module->delete_user($controls->button_data);
unset($controls->data['subscriber_id']);
}
if ($controls->is_action('delete_selected')) {
$r = Newsletter::instance()->delete_user($_POST['ids']);
$controls->messages .= $r . ' user(s) deleted';
}
// We build the query condition
$where = 'where 1=1';
$query_args = array();
$text = trim($controls->get_value('search_text'));
if ($text) {
$query_args[] = '%' . $text . '%';
$query_args[] = '%' . $text . '%';
$query_args[] = '%' . $text . '%';
$where .= " and (email like %s or name like %s or surname like %s)";
}
if (!empty($controls->data['search_status'])) {
if ($controls->data['search_status'] == 'T') {
$where .= " and test=1";
} else {
$query_args[] = $controls->data['search_status'];
$where .= " and status=%s";
}
}
if (!empty($controls->data['search_list'])) {
$where .= " and list_" . ((int) $controls->data['search_list']) . "=1";
}
$filtered = $where != 'where 1=1';
// Total items, total pages
$items_per_page = 20;
if (!empty($query_args)) {
$where = $wpdb->prepare($where, $query_args);
}
$count = Newsletter::instance()->store->get_count(NEWSLETTER_USERS_TABLE, $where);
$last_page = floor($count / $items_per_page) - ($count % $items_per_page == 0 ? 1 : 0);
if ($last_page < 0)
$last_page = 0;
if ($controls->is_action('last')) {
$controls->data['search_page'] = $last_page;
}
if ($controls->is_action('first')) {
$controls->data['search_page'] = 0;
}
if ($controls->is_action('next')) {
$controls->data['search_page'] = (int) $controls->data['search_page'] + 1;
}
if ($controls->is_action('prev')) {
$controls->data['search_page'] = (int) $controls->data['search_page'] - 1;
}
if ($controls->is_action('search')) {
$controls->data['search_page'] = 0;
}
// Eventually fix the page
if (!isset($controls->data['search_page']) || $controls->data['search_page'] < 0)
$controls->data['search_page'] = 0;
if ($controls->data['search_page'] > $last_page)
$controls->data['search_page'] = $last_page;
$query = "select * from " . NEWSLETTER_USERS_TABLE . ' ' . $where . " order by id desc";
$query .= " limit " . ($controls->data['search_page'] * $items_per_page) . "," . $items_per_page;
$list = $wpdb->get_results($query);
// Move to base 1
$controls->data['search_page'] ++;
?>
<div class="wrap tnp-users tnp-users-index" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Subscribers', 'newsletter') ?>
<a class="tnp-btn-h1" href="?page=newsletter_users_new"><?php _e('Add a subscriber', 'newsletter') ?></a>
</h2>
</div>
<div id="tnp-body">
<form id="channel" method="post" action="">
<?php $controls->init(); ?>
<div class="tnp-subscribers-search">
<?php $controls->text('search_text', 45, __('Search text', 'newsletter')); ?>
<?php _e('filter by', 'newsletter') ?>:
<?php $controls->select('search_status', array('' => 'Any status', 'T' => 'Test subscribers', 'C' => 'Confirmed', 'S' => 'Not confirmed', 'U' => 'Unsubscribed', 'B' => 'Bounced')); ?>
<?php $controls->lists_select('search_list', '-'); ?>
<?php $controls->button('search', __('Search', 'newsletter')); ?>
<?php if ($where != "where 1=1") { ?>
<?php $controls->button('reset', __('Reset Filters', 'newsletter')); ?>
<?php } ?>
<br>
<?php $controls->checkbox('show_preferences', __('Show lists', 'newsletter')); ?>
</div>
<?php if ($filtered) { ?>
<p><?php _e('The list below is filtered.', 'newsletter') ?></p>
<?php } ?>
<div class="tnp-paginator">
<?php $controls->button('first', '«'); ?>
<?php $controls->button('prev', ''); ?>
<?php $controls->text('search_page', 3); ?> of <?php echo $last_page + 1 ?> <?php $controls->button('go', __('Go', 'newsletter')); ?>
<?php $controls->button('next', ''); ?>
<?php $controls->button('last', '»'); ?>
<?php echo $count ?> <?php _e('subscriber(s) found', 'newsletter') ?>
<?php $controls->button_confirm('delete_selected', __('Delete selected', 'newsletter')); ?>
</div>
<table class="widefat">
<thead>
<tr>
<th><input type="checkbox" onchange="jQuery('input.tnp-selector').prop('checked', this.checked)"</th>
<th>Id</th>
<th>Email</th>
<th><?php _e('Name', 'newsletter') ?></th>
<th><?php _e('Status', 'newsletter') ?></th>
<?php if (isset($options['show_preferences']) && $options['show_preferences'] == 1) { ?>
<th><?php _e('Lists', 'newsletter') ?></th>
<?php } ?>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
</thead>
<?php $i = 0; ?>
<?php foreach ($list as $s) { ?>
<tr class="<?php echo ($i++ % 2 == 0) ? 'alternate' : ''; ?>">
<td><input class="tnp-selector" type="checkbox" name="ids[]" value="<?php echo $s->id; ?>"/></td>
<td>
<?php echo $s->id; ?>
</td>
<td>
<?php echo esc_html($s->email); ?>
</td>
<td>
<?php echo esc_html($s->name); ?> <?php echo esc_html($s->surname); ?>
</td>
<td>
<small>
<?php echo $module->get_user_status_label($s) ?>
</small>
</td>
<?php if (isset($options['show_preferences']) && $options['show_preferences'] == 1) { ?>
<td>
<small>
<?php
$lists = $module->get_lists();
foreach ($lists as $item) {
$l = 'list_' . $item->id;
if ($s->$l == 1)
echo esc_html($item->name) . '<br>';
}
?>
</small>
</td>
<?php } ?>
<td>
<a class="button-secondary" href="<?php echo $module->get_admin_page_url('edit'); ?>&amp;id=<?php echo $s->id; ?>"><?php _e('Edit', 'newsletter') ?></a>
</td>
<td>
<?php $controls->button_confirm('remove', __('Remove', 'newsletter'), '', $s->id); ?>
</td>
<td style="text-align: center">
<?php if ($s->status == "C") { ?>
<?php $controls->button_confirm('resend_welcome', __('Resend welcome', 'newsletter'), '', $s->id); ?>
<?php } else { ?>
<?php $controls->button_confirm('resend', __('Resend activation', 'newsletter'), '', $s->id); ?>
<?php } ?>
</td>
</tr>
<?php } ?>
</table>
<div class="tnp-paginator">
<?php $controls->button('first', '«'); ?>
<?php $controls->button('prev', ''); ?>
<?php $controls->text('search_page', 3); ?> of <?php echo $last_page + 1 ?> <?php $controls->button('go', __('Go', 'newsletter')); ?>
<?php $controls->button('next', ''); ?>
<?php $controls->button('last', '»'); ?>
</div>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,351 @@
<?php
/* @var $wpdb wpdb */
defined('ABSPATH') || exit;
@include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
if ($controls->is_action('remove_unconfirmed')) {
$r = $wpdb->query("delete from " . NEWSLETTER_USERS_TABLE . " where status='S'");
$controls->messages = __('Subscribers not confirmed deleted: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('remove_unsubscribed')) {
$r = $wpdb->query("delete from " . NEWSLETTER_USERS_TABLE . " where status='U'");
$controls->messages = __('Subscribers unsubscribed deleted: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('remove_bounced')) {
$r = $wpdb->query("delete from " . NEWSLETTER_USERS_TABLE . " where status='B'");
$controls->messages = __('Subscribers bounced deleted: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('unconfirm_all')) {
$r = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . " set status='S' where status='C'");
$controls->messages = __('Subscribers changed to not confirmed: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('confirm_all')) {
$r = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . " set status='C' where status='S'");
$controls->messages = __('Subscribers changed to confirmed: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('remove_all')) {
$r = $wpdb->query("delete from " . NEWSLETTER_USERS_TABLE);
$controls->messages = __('Subscribers deleted: ', 'newsletter') . $r . '.';
}
if ($controls->is_action('list_add')) {
$r = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . " set list_" . ((int) $controls->data['list']) . "=1");
$controls->messages = $r . ' ' . __('added to list', 'newsletter') . ' ' . $controls->data['list'];
}
if ($controls->is_action('list_remove')) {
$r = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . " set list_" . ((int) $controls->data['list']) . "=0");
$controls->messages = $r . ' ' . __('removed from list', 'newsletter') . ' ' . $controls->data['list'];
}
if ($controls->is_action('list_delete')) {
$count = $wpdb->query("delete from " . NEWSLETTER_USERS_TABLE . " where list_" . ((int) $controls->data['list']) . "<>0");
$module->clean_sent_table();
$module->clean_stats_table();
$controls->messages = $count . ' ' . __('deleted', 'newsletter');
}
if ($controls->is_action('language')) {
$count = $wpdb->query($wpdb->prepare("update " . NEWSLETTER_USERS_TABLE . " set language=%s where language=''", $controls->data['language']));
$controls->add_message_done();
}
if ($controls->is_action('list_manage')) {
if ($controls->data['list_action'] == 'move') {
$wpdb->query("update " . NEWSLETTER_USERS_TABLE . ' set list_' . ((int) $controls->data['list_1']) . '=0, list_' . ((int) $controls->data['list_2']) . '=1' .
' where list_' . $controls->data['list_1'] . '=1');
}
if ($controls->data['list_action'] == 'add') {
$wpdb->query("update " . NEWSLETTER_USERS_TABLE . ' set list_' . ((int) $controls->data['list_2']) . '=1' .
' where list_' . $controls->data['list_1'] . '=1');
}
}
if ($controls->is_action('list_none')) {
$where = '1=1';
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
$where .= ' and list_' . $i . '=0';
}
$count = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . ' set list_' . ((int) $controls->data['list_3']) . '=1' .
' where ' . $where);
$controls->messages = $count . ' subscribers updated';
}
if ($controls->is_action('update_inactive')) {
$wpdb->query("update `{$wpdb->prefix}newsletter` n join (select user_id, max(s.time) as max_time from `{$wpdb->prefix}newsletter_sent` s where s.open>0 group by user_id) as ss
on n.id=ss.user_id set last_activity=ss.max_time");
$inactive_time = (int) $controls->data['inactive_time'];
$where = 'last_activity > 0 and last_activity<' . (time() - $inactive_time * 30 * 24 * 3600);
$count = $wpdb->query("update " . NEWSLETTER_USERS_TABLE . ' set list_' . ((int) $controls->data['list_inactive']) . '=1 where ' . $where);
$controls->messages = $count . ' subscribers updated';
}
if ($controls->is_action('bounces')) {
$lines = explode("\n", $controls->data['bounced_emails']);
$total = 0;
$marked = 0;
$error = 0;
$not_found = 0;
$already_bounced = 0;
$results = '';
foreach ($lines as &$email) {
$email = trim($email);
if (empty($email))
continue;
$total++;
$email = NewsletterModule::normalize_email($email);
if (empty($email)) {
$results .= '[INVALID] ' . $email . "\n";
$error++;
continue;
}
$user = NewsletterUsers::instance()->get_user($email);
if ($user == null) {
$results .= '[NOT FOUND] ' . $email . "\n";
$not_found++;
continue;
}
if ($user->status == 'B') {
$results .= '[ALREADY BOUNCED] ' . $email . "\n";
$already_bounced++;
continue;
}
$r = $wpdb->query($wpdb->prepare('update ' . NEWSLETTER_USERS_TABLE . " set status='B' where email=%s limit 1", $email));
if ($r === 1) {
$results .= '[BOUNCED] ' . $email . "\n";
$marked++;
continue;
}
}
$controls->messages .= 'Total: ' . $total . '<br>';
$controls->messages .= 'Bounce: ' . $marked . '<br>';
$controls->messages .= 'Errors: ' . $error . '<br>';
$controls->messages .= 'Not found: ' . $not_found . '<br>';
$controls->messages .= 'Already bounced: ' . $already_bounced . '<br>';
}
?>
<div class="wrap tnp-users tnp-users-massive" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Subscribers Maintenance', 'newsletter') ?></h2>
<p><?php _e('Please, backup before run a massive action.', 'newsletter') ?></p>
</div>
<div id="tnp-body">
<?php if (!empty($results)) { ?>
<h3>Results</h3>
<textarea wrap="off" style="width: 100%; height: 150px; font-size: 11px; font-family: monospace"><?php echo htmlspecialchars($results) ?></textarea>
<?php } ?>
<form method="post" action="">
<?php $controls->init(); ?>
<div id="tabs">
<ul>
<li><a href="#tabs-1"><?php _e('General', 'newsletter') ?></a></li>
<li><a href="#tabs-2"><?php _e('Lists', 'newsletter') ?></a></li>
<li><a href="#tabs-4"><?php _e('Bounces', 'newsletter') ?></a></li>
</ul>
<div id="tabs-1">
<table class="widefat" style="width: auto">
<thead>
<tr>
<th><?php _e('Status', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?></th>
<th><?php _e('Actions', 'newsletter') ?></th>
</tr>
</thead>
<tr>
<td><?php _e('Total collected emails', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE); ?>
</td>
<td nowrap>
<?php $controls->button_confirm('remove_all', __('Delete all', 'newsletter'), __('Are you sure you want to remove ALL subscribers?', 'newsletter')); ?>
</td>
</tr>
<tr>
<td><?php _e('Confirmed', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='C'"); ?>
</td>
<td nowrap>
<?php $controls->button_confirm('unconfirm_all', __('Unconfirm all', 'newsletter')); ?>
</td>
</tr>
<tr>
<td>Not confirmed</td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='S'"); ?>
</td>
<td nowrap>
<?php $controls->button_confirm('remove_unconfirmed', __('Delete all not confirmed', 'newsletter'), __('Are you sure you want to delete ALL not confirmed subscribers?', 'newsletter')); ?>
<?php $controls->button_confirm('confirm_all', __('Confirm all', 'newsletter'), __('Are you sure you want to mark ALL subscribers as confirmed?', 'newsletter')); ?>
<p class="description">
<a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#resend-activation" target="_blank"><?php _e('We have some tips about global actions, read more.', 'newsletter') ?></a>
</p>
</td>
</tr>
<tr>
<td><?php _e('Unsubscribed', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='U'"); ?>
</td>
<td>
<?php $controls->button_confirm('remove_unsubscribed', __('Delete all unsubscribed', 'newsletter')); ?>
</td>
</tr>
<tr>
<td><?php _e('Bounced', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='B'"); ?>
</td>
<td>
<?php $controls->button_confirm('remove_bounced', __('Delete all bounced', 'newsletter')); ?>
</td>
</tr>
<tr>
<td><?php _e('Inactive since', 'newsletter') ?></td>
<td>
<?php
$controls->select('inactive_time', array(
'6' => '6 ' . __('months', 'newsletter'),
'12' => '1 ' . __('year', 'newsletter'),
'24' => '2 ' . __('years', 'newsletter'),
'36' => '3 ' . __('years', 'newsletter'),
'48' => '4 ' . __('years', 'newsletter'),
'60' => '5 ' . __('years', 'newsletter'),
'72' => '6 ' . __('years', 'newsletter'),
'84' => '7 ' . __('years', 'newsletter'),
'96' => '8 ' . __('years', 'newsletter'),
'108' => '9 ' . __('years', 'newsletter'),
'120' => '10 ' . __('years', 'newsletter')
))
?>
to
<?php $controls->lists_select('list_inactive'); ?>
</td>
<td>
<?php $controls->button_confirm('update_inactive', __('Update', 'newsletter')); ?>
</td>
</tr>
<?php if ($module->is_multilanguage()) { ?>
<tr>
<td>Language</td>
<td>
<?php _e('Set to', 'newsletter') ?>
<?php $controls->language('language', false) ?> <?php _e('subscribers without a language', 'newsletter') ?>
</td>
<td>
<?php $controls->button_confirm('language', '&raquo;'); ?>
</td>
</tr>
<?php } ?>
</table>
</div>
<div id="tabs-2">
<table class="form-table">
<tr>
<th>&nbsp;</th>
<td>
<?php $controls->lists_select('list') ?>:
<?php $controls->button_confirm('list_add', 'Activate for everyone'); ?>
<?php $controls->button_confirm('list_remove', 'Deactivate for everyone'); ?>
<?php $controls->button_confirm('list_delete', 'Delete everyone in that list'); ?>
<br><br>
<?php $controls->select('list_action', array('move' => 'Change', 'add' => 'Add')); ?>
<?php _e('all subscribers in', 'newsletter') ?> <?php $controls->lists_select('list_1'); ?>
<?php _e('to', 'newsletter') ?> <?php $controls->lists_select('list_2'); ?>
<?php $controls->button_confirm('list_manage', '&raquo;'); ?>
<p class="description">
If you choose to <strong>delete</strong> users in a list, they will be
<strong>physically deleted</strong> from the database (no way back).
</p>
</td>
</tr>
<tr>
<th>&nbsp;</th>
<td>
<?php _e('Add to list', 'newsletter') ?>
<?php $controls->lists_select('list_3') ?> <?php _e('subscribers without a list', 'newsletter') ?> <?php $controls->button_confirm('list_none', '&raquo;'); ?>
</td>
</tr>
</table>
</div>
<div id="tabs-4">
<p>
Import a set of bounced email addresses: they will be marked as "bounced" and no more contacted. Sending
messages to bounced address (many times) can put your server in some black list.
</p>
<table class="form-table">
<tr>
<th><?php _e('Bounced addresses', 'newsletter') ?></th>
<td>
<?php $controls->textarea('bounced_emails'); ?>
<p class="description">
<?php _e('One email address per line.', 'newsletter') ?>
</p>
</td>
</tr>
</table>
<?php $controls->button_confirm('bounces', 'Mark those emails as bounced'); ?>
</div>
</div>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,62 @@
<?php
defined('ABSPATH') || exit;
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
$module = NewsletterUsers::instance();
if ($controls->is_action('save')) {
if (!is_email($controls->data['email'])) {
$controls->errors = __('Wrong email address.', 'newsletter');
}
if (empty($controls->errors)) {
$controls->data['status'] = 'C';
$controls->data['sex'] = 'n';
$user = $module->save_user($controls->data);
if ($user === false) {
$controls->errors = __('This subscriber already exists.', 'newsletter');
} else {
echo '<script>';
echo 'location.href="' . $module->get_admin_page_url('edit') . '&id=' . $user->id . '"';
echo '</script>';
return;
}
}
}
?>
<div class="wrap" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('New Subscriber', 'newsletter') ?></h2>
</div>
<div id="tnp-body" class="tnp-users tnp-users-new">
<form method="post" action="">
<?php $controls->init(); ?>
<table class="form-table">
<tr>
<th><?php _e('Email', 'newsletter')?></th>
<td>
<?php $controls->text_email('email', 60); ?>
<?php $controls->button('save', '&raquo;'); ?>
</td>
</tr>
</table>
</form>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,2 @@
<p>The country detection and report can be enabled with the Reports Extension.</p>

View File

@@ -0,0 +1,53 @@
<?php
defined('ABSPATH') || exit;
?>
<div class="row">
<div class="col-md-6">
<h3><?php _e('Subscriptions by month (max 12 months)', 'newsletter') ?></h3>
<?php
$months = $wpdb->get_results("select count(*) as c, concat(year(created), '-', date_format(created, '%m')) as d from " . NEWSLETTER_USERS_TABLE . " where status='C' group by concat(year(created), '-', date_format(created, '%m')) order by d desc limit 12");
?>
<table class="widefat">
<thead>
<tr>
<th><?php _e('Year and month', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?></th>
</tr>
</thead>
<?php foreach ($months as &$day) { ?>
<tr>
<td><?php echo $day->d; ?></td>
<td><?php echo $day->c; ?></td>
</tr>
<?php } ?>
</table>
</div>
<div class="col-md-6">
<h3><?php _e('Subscriptions by day (max 90 days)', 'newsletter') ?></h3>
<?php
$list = $wpdb->get_results("select count(*) as c, date(created) as d from " . NEWSLETTER_USERS_TABLE . " where status='C' group by date(created) order by d desc limit 90");
?>
<table class="widefat">
<thead>
<tr>
<th><?php _e('Date', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?></th>
</tr>
</thead>
<?php foreach ($list as $day) { ?>
<tr>
<td><?php echo $day->d; ?></td>
<td><?php echo $day->c; ?></td>
</tr>
<?php } ?>
</table>
</div>
</div>

View File

@@ -0,0 +1,305 @@
<?php
if (!defined('ABSPATH'))
exit;
@include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
wp_enqueue_script('tnp-chart');
$all_count = $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE);
$options_profile = get_option('newsletter_profile');
$module = NewsletterUsers::instance();
$controls = new NewsletterControls();
?>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {packages: ['corechart', 'geochart', 'geomap']});
</script>
<div class="wrap" id="tnp-wrap">
<?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
<div id="tnp-heading">
<h2><?php _e('Subscriber statistics', 'newsletter') ?></h2>
</div>
<div id="tnp-body" class="tnp-users-statistics">
<?php $controls->init(); ?>
<div id="tabs">
<ul>
<li><a href="#tab-overview">Overview</a></li>
<li><a href="#tabs-lists">Lists</a></li>
<li><a href="#tabs-countries">World Map</a></li>
<li><a href="#tabs-referrers">Referrer</a></li>
<li><a href="#tabs-sources">Sources</a></li>
<li><a href="#tabs-gender">Gender</a></li>
<li><a href="#tabs-time">By time</a></li>
</ul>
<div id="tab-overview">
<table class="widefat" style="width: auto">
<thead>
<tr>
<th><?php _e('Status', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?php _e('Any', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE); ?>
</td>
</tr>
<tr>
<td><?php _e('Confirmed', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='C'"); ?>
</td>
</tr>
<tr>
<td><?php _e('Not confirmed', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='S'"); ?>
</td>
</tr>
<tr>
<td><?php _e('Unsubscribed', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='U'"); ?>
</td>
</tr>
<tr>
<td><?php _e('Bounced', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where status='B'"); ?>
</td>
</tr>
</tbody>
</table>
<?php if ($module->is_multilanguage()) { ?>
<h3>By language</h3>
<?php $languages = $module->get_languages(); ?>
<table class="widefat" style="width: auto">
<thead>
<tr>
<th><?php _e('Status', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?></th>
</tr>
<tbody>
<?php foreach ($languages as $code=>$label) { ?>
<tr>
<td><?php echo esc_html($label) ?></td>
<td>
<?php echo $wpdb->get_var($wpdb->prepare("select count(*) from " . NEWSLETTER_USERS_TABLE . " where language=%s", $code)); ?>
</td>
</tr>
<?php } ?>
<tr>
<td><?php _e('Without language', 'newsletter') ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where language=''"); ?>
</td>
</tr>
</thead>
</tbody>
</table>
<?php } ?>
</div>
<div id="tabs-lists">
<table class="widefat" style="width: auto">
<thead>
<tr>
<th>&nbsp;</th>
<th><?php _e('List', 'newsletter') ?></th>
<th><?php _e('Total', 'newsletter') ?> (*)</th>
</tr>
</thead>
<tbody>
<?php $lists = $module->get_lists(); ?>
<?php foreach ($lists as $list) { ?>
<tr>
<td><?php echo $list->id ?></td>
<td><?php echo esc_html($list->name) ?></td>
<td>
<?php echo $wpdb->get_var("select count(*) from " . NEWSLETTER_USERS_TABLE . " where list_" . $list->id . "=1 and status='C'"); ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
(*) <?php _e('Confirmed', 'newsletter') ?>
</div>
<div id="tabs-countries">
<?php
if (!has_action('newsletter_users_statistics_countries')) {
include __DIR__ . '/statistics-countries.php';
} else {
do_action('newsletter_users_statistics_countries', $controls);
}
?>
</div>
<div id="tabs-referrers">
<p>
<?php $controls->panel_help('https://www.thenewsletterplugin.com/documentation/subscribers-statistics#referrer') ?>
</p>
<?php
$list = $wpdb->get_results("select referrer, SUM(if(status='C', 1, 0)) as confirmed, SUM(if(status='S', 1, 0)) as unconfirmed, SUM(if(status='B', 1, 0)) as bounced, SUM(if(status='U', 1, 0)) as unsubscribed from " . NEWSLETTER_USERS_TABLE . " group by referrer order by confirmed desc");
?>
<table class="widefat" style="width: auto">
<thead>
<tr>
<th><?php _e('Referrer', 'newsletter') ?></th>
<th><?php _e('Confirmed', 'newsletter') ?></th>
<th><?php _e('Not confirmed', 'newsletter') ?></th>
<th><?php _e('Unsubscribed', 'newsletter') ?></th>
<th><?php _e('Bounced', 'newsletter') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($list as $row) { ?>
<tr>
<td><?php echo empty($row->referrer) ? '[not set]' : esc_html($row->referrer) ?></td>
<td><?php echo $row->confirmed; ?></td>
<td><?php echo $row->unconfirmed; ?></td>
<td><?php echo $row->unsubscribed; ?></td>
<td><?php echo $row->bounced; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<div id="tabs-sources">
<p>
<?php $controls->panel_help('https://www.thenewsletterplugin.com/documentation/subscribers-statistics#source') ?>
</p>
<?php
$list = $wpdb->get_results("select http_referer, SUM(if(status='C', 1, 0)) as confirmed, SUM(if(status='S', 1, 0)) as unconfirmed, SUM(if(status='B', 1, 0)) as bounced, SUM(if(status='U', 1, 0)) as unsubscribed from " . NEWSLETTER_USERS_TABLE . " group by http_referer order by count(*) desc limit 100");
?>
<table class="widefat" style="width: auto">
<thead>
<tr>
<th>URL</th>
<th><?php _e('Confirmed', 'newsletter') ?></th>
<th><?php _e('Not confirmed', 'newsletter') ?></th>
<th><?php _e('Unsubscribed', 'newsletter') ?></th>
<th><?php _e('Bounced', 'newsletter') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($list as $row) { ?>
<tr>
<td><?php echo empty($row->http_referer) ? '[not set]' : $controls->print_truncated($row->http_referer, 120) ?></td>
<td><?php echo $row->confirmed; ?></td>
<td><?php echo $row->unconfirmed; ?></td>
<td><?php echo $row->unsubscribed; ?></td>
<td><?php echo $row->bounced; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<div id="tabs-gender">
<?php
$male_count = $wpdb->get_row("select SUM(if(status='C', 1, 0)) as confirmed, SUM(if(status='S', 1, 0)) as unconfirmed, SUM(if(status='B', 1, 0)) as bounced, SUM(if(status='U', 1, 0)) as unsubscribed from " . NEWSLETTER_USERS_TABLE . " where sex='m'");
$female_count = $wpdb->get_row("select SUM(if(status='C', 1, 0)) as confirmed, SUM(if(status='S', 1, 0)) as unconfirmed, SUM(if(status='B', 1, 0)) as bounced, SUM(if(status='U', 1, 0)) as unsubscribed from " . NEWSLETTER_USERS_TABLE . " where sex='f'");
$none_count = $wpdb->get_row("select SUM(if(status='C', 1, 0)) as confirmed, SUM(if(status='S', 1, 0)) as unconfirmed, SUM(if(status='B', 1, 0)) as bounced, SUM(if(status='U', 1, 0)) as unsubscribed from " . NEWSLETTER_USERS_TABLE . " where sex='n'");
?>
<table class="widefat">
<thead>
<tr>
<th><?php _e('Gender', 'newsletter')?></th>
<th><?php _e('Confirmed', 'newsletter') ?></th>
<th><?php _e('Not confirmed', 'newsletter') ?></th>
<th><?php _e('Unsubscribed', 'newsletter') ?></th>
<th><?php _e('Bounced', 'newsletter') ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?php _e('Female', 'newsletter')?></td>
<td><?php echo $female_count->confirmed; ?></td>
<td><?php echo $female_count->unconfirmed; ?></td>
<td><?php echo $female_count->unsubscribed; ?></td>
<td><?php echo $female_count->bounced; ?></td>
</tr>
<tr>
<td><?php _e('Male', 'newsletter')?></td>
<td><?php echo $male_count->confirmed; ?></td>
<td><?php echo $male_count->unconfirmed; ?></td>
<td><?php echo $male_count->unsubscribed; ?></td>
<td><?php echo $male_count->bounced; ?></td>
</tr>
<tr>
<td><?php _e('Not specified', 'newsletter')?></td>
<td><?php echo $none_count->confirmed; ?></td>
<td><?php echo $none_count->unconfirmed; ?></td>
<td><?php echo $none_count->unsubscribed; ?></td>
<td><?php echo $none_count->bounced; ?></td>
</tr>
</tbody>
</table>
</div>
<div id="tabs-time">
<?php
if (!has_action('newsletter_users_statistics_time')) {
include __DIR__ . '/statistics-time.php';
} else {
do_action('newsletter_users_statistics_time', $controls);
}
?>
</div>
<?php
if (isset($panels['user_statistics'])) {
foreach ($panels['user_statistics'] as $panel) {
call_user_func($panel['callback'], $id, $controls);
}
}
?>
</div>
</div>
<?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
</div>

View File

@@ -0,0 +1,201 @@
<?php
defined('ABSPATH') || exit;
require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
class NewsletterUsers extends NewsletterModule {
static $instance;
/**
* @return NewsletterUsers
*/
static function instance() {
if (self::$instance == null) {
self::$instance = new NewsletterUsers();
}
return self::$instance;
}
function __construct() {
parent::__construct('users', '1.3.0');
add_action('init', array($this, 'hook_init'));
}
function hook_init() {
if (is_admin()) {
add_action('wp_ajax_newsletter_users_export', array($this, 'hook_wp_ajax_newsletter_users_export'));
}
}
function hook_wp_ajax_newsletter_users_export() {
$newsletter = Newsletter::instance();
if ($newsletter->is_allowed()) {
require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
$controls = new NewsletterControls();
if ($controls->is_action('export')) {
$this->export($controls->data);
}
} else {
die('Not allowed.');
}
}
function upgrade() {
global $wpdb, $charset_collate;
parent::upgrade();
$sql = "CREATE TABLE `" . $wpdb->prefix . "newsletter` (
`name` varchar(100) NOT NULL DEFAULT '',
`email` varchar(100) NOT NULL DEFAULT '',
`token` varchar(50) NOT NULL DEFAULT '',
`language` varchar(10) NOT NULL DEFAULT '',
`status` varchar(1) NOT NULL DEFAULT 'S',
`id` int(11) NOT NULL AUTO_INCREMENT,
`profile` mediumtext,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated` int(11) NOT NULL DEFAULT '0',
`last_activity` int(11) NOT NULL DEFAULT '0',
`followup_step` tinyint(4) NOT NULL DEFAULT '0',
`followup_time` bigint(20) NOT NULL DEFAULT '0',
`followup` tinyint(4) NOT NULL DEFAULT '0',
`surname` varchar(100) NOT NULL DEFAULT '',
`sex` char(1) NOT NULL DEFAULT 'n',
`feed_time` bigint(20) NOT NULL DEFAULT '0',
`feed` tinyint(4) NOT NULL DEFAULT '0',
`referrer` varchar(50) NOT NULL DEFAULT '',
`ip` varchar(50) NOT NULL DEFAULT '',
`wp_user_id` int(11) NOT NULL DEFAULT '0',
`http_referer` varchar(255) NOT NULL DEFAULT '',
`geo` tinyint(4) NOT NULL DEFAULT '0',
`country` varchar(4) NOT NULL DEFAULT '',
`region` varchar(100) NOT NULL DEFAULT '',
`city` varchar(100) NOT NULL DEFAULT '',
`bounce_type` varchar(50) NOT NULL DEFAULT '',
`bounce_time` int(11) NOT NULL DEFAULT '0',
`unsub_email_id` int(11) NOT NULL DEFAULT '0',
`unsub_time` int(11) NOT NULL DEFAULT '0',\n";
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
$sql .= "`list_$i` tinyint(4) NOT NULL DEFAULT '0',\n";
}
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
$sql .= "`profile_$i` varchar(255) NOT NULL DEFAULT '',\n";
}
// Leave as last
$sql .= "`test` tinyint(4) NOT NULL DEFAULT '0',\n";
$sql .= "PRIMARY KEY (`id`),\nUNIQUE KEY `email` (`email`),\nKEY `wp_user_id` (`wp_user_id`)\n) $charset_collate;";
dbDelta($sql);
if ($this->old_version < '1.2.7') {
$this->query("update " . NEWSLETTER_USERS_TABLE . " set geo=1 where country<>''");
}
if ($this->old_version > '1.2.5' && $this->old_version < '1.2.9') {
$this->upgrade_query("ALTER TABLE " . NEWSLETTER_USERS_TABLE . " DROP COLUMN last_ip;");
}
}
function admin_menu() {
$this->add_menu_page('index', 'Subscribers');
$this->add_admin_page('new', 'New subscriber');
$this->add_admin_page('edit', 'Subscribers Edit');
$this->add_admin_page('massive', 'Massive Management');
$this->add_admin_page('export', 'Export');
$this->add_admin_page('import', 'Import');
$this->add_admin_page('statistics', 'Statistics');
}
function export($options = null) {
global $wpdb;
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');
// BOM
echo "\xEF\xBB\xBF";
$sep = ';';
if ($options) {
$sep = $options['separator'];
}
if ($sep == 'tab') {
$sep = "\t";
}
// CSV header
echo '"Email"' . $sep . '"Name"' . $sep . '"Surname"' . $sep . '"Gender"' . $sep . '"Status"' . $sep . '"Date"' . $sep . '"Token"' . $sep;
// In table profiles
for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
echo '"Profile ' . $i . '"' . $sep; // To adjust with field name
}
// Lists
for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
echo '"List ' . $i . '"' . $sep;
}
echo '"Feed by mail"' . $sep . '"Follow up"' . $sep;
echo '"IP"' . $sep . '"Referrer"' . $sep . '"Country"';
echo "\n";
$page = 0;
while (true) {
$query = "select * from " . NEWSLETTER_USERS_TABLE . "";
$list = (int) $_POST['options']['list'];
if (!empty($list)) {
$query .= " where list_" . $list . "=1";
}
$recipients = $wpdb->get_results($query . " order by email limit " . $page * 500 . ",500");
for ($i = 0; $i < count($recipients); $i++) {
echo '"' . $recipients[$i]->email . '"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->name) .
'"' . $sep . '"' . $this->sanitize_csv($recipients[$i]->surname) .
'"' . $sep . '"' . $recipients[$i]->sex .
'"' . $sep . '"' . $recipients[$i]->status . '"' . $sep . '"' . $recipients[$i]->created . '"' . $sep . '"' . $recipients[$i]->token . '"' . $sep;
for ($j = 1; $j <= NEWSLETTER_PROFILE_MAX; $j++) {
$column = 'profile_' . $j;
echo '"' . $this->sanitize_csv($recipients[$i]->$column) . '"' . $sep;
}
for ($j = 1; $j <= NEWSLETTER_LIST_MAX; $j++) {
$list = 'list_' . $j;
echo '"' . $recipients[$i]->$list . '"' . $sep;
}
echo '"' . $recipients[$i]->feed . '"' . $sep;
echo '"' . $recipients[$i]->followup . '"' . $sep;
echo '"' . $recipients[$i]->ip . '"' . $sep;
echo '"' . $recipients[$i]->referrer . '"' . $sep;
echo '"' . $recipients[$i]->country . '"' . $sep;
echo "\n";
flush();
}
if (count($recipients) < 500)
break;
$page++;
}
die();
}
function sanitize_csv($text) {
$text = str_replace('"', "'", $text);
$text = str_replace("\n", ' ', $text);
$text = str_replace("\r", ' ', $text);
$text = str_replace(";", ' ', $text);
return $text;
}
}
NewsletterUsers::instance();