Last active
October 22, 2018 23:08
-
-
Save Roy-Orbison/93806ac74c4dbd66d5ee1cb3b6e3b78e to your computer and use it in GitHub Desktop.
Sendy duplicate subscription removal (tested with v3.0.3 and PHP v5.3.29)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
include('includes/header.php'); | |
include('includes/login/auth.php'); | |
include('includes/subscribers/main.php'); | |
include('includes/helpers/short.php'); | |
#ini_set('error_reporting', E_ALL & ~E_NOTICE); | |
#ini_set('display_errors', 1); | |
$subscribers = $lists = array(); | |
try { | |
if (!empty($_POST['del'])) { | |
$emails_del_count_last = 0; | |
foreach ($_POST['del'] as $list_id => $emails_del_all) { | |
while ($emails_del_all) { | |
$emails_del = array_splice($emails_del_all, 0, 20);# delete in batches of 20 at most | |
$emails_del_count = count($emails_del); | |
if ($emails_del_count != $emails_del_count_last) { | |
$mysqli_stmt = $mysqli->prepare( | |
'DELETE FROM subscribers | |
WHERE list = ? AND email IN (' . implode(', ', array_fill(0, $emails_del_count, '?')) . ')' | |
); | |
$bind_param_types = 'i' . str_repeat('s', $emails_del_count); | |
$emails_del_count_last = $emails_del_count; | |
} | |
$bind_param_args = array( | |
$bind_param_types, | |
&$list_id, | |
); | |
foreach ($emails_del as $i => $email_del) { | |
$bind_param_args[] = &$emails_del[$i]; | |
} | |
call_user_func_array(array(&$mysqli_stmt, 'bind_param'), $bind_param_args); | |
if (!$mysqli_stmt->execute()) { | |
throw new Exception($mysqli_stmt->error); | |
} | |
} | |
} | |
} | |
$mysqli_result = $mysqli->query( | |
'SELECT email, GROUP_CONCAT(list) AS lists, COUNT(list) AS list_count, SUM(unsubscribed) AS has_unsubscribed | |
FROM subscribers GROUP BY email | |
HAVING list_count > 1 AND has_unsubscribed = 0' | |
); | |
if ($mysqli_result) { | |
while ($dupe = $mysqli_result->fetch_assoc()) { | |
$dupe_lists = array_fill_keys(explode(',', $dupe['lists']), true); | |
$subscribers[$dupe['email']] = $dupe_lists; | |
$lists += $dupe_lists; | |
} | |
} | |
if ($lists) { | |
$list_ids = array_keys($lists); | |
$lists = array(); | |
$list_count = count($list_ids); | |
$mysqli_stmt = $mysqli->prepare( | |
'SELECT id, name FROM lists | |
WHERE id IN (' . implode(', ', array_fill(0, $list_count, '?')) . ') | |
ORDER BY name' | |
); | |
$bind_param_args = array(str_repeat('i', $list_count)); | |
foreach ($list_ids as $i => $list_id) { | |
$bind_param_args[] = &$list_ids[$i]; | |
} | |
call_user_func_array(array(&$mysqli_stmt, 'bind_param'), $bind_param_args); | |
if (!$mysqli_stmt->execute()) { | |
throw new Exception($mysqli_stmt->error); | |
} | |
$mysqli_stmt->bind_result($list_id, $list_name); | |
while ($mysqli_stmt->fetch()) { | |
$lists[$list_id] = $list_name; | |
} | |
} | |
} | |
catch (Exception $e) { | |
?> | |
<div class="alert alert-error"> | |
<button type="button" class="close" data-dismiss="alert">×</button> | |
<strong><?php echo htmlspecialchars($e->getMessage());?></strong> | |
</div> | |
<?php | |
} | |
?> | |
<style type="text/css"> | |
@media (min-width: 768px) { | |
.sticky-head { | |
max-height: calc(100vh - 200px); | |
overflow: auto; | |
} | |
.sticky-head thead { | |
position: sticky; | |
top: 0; | |
background: white; | |
} | |
tr:hover { | |
background: lightgray; | |
} | |
} | |
</style> | |
<h2><?php echo _('Duplicate removal');?></h2> | |
<?php if ($subscribers) {?> | |
<form action="" method="post" class="sticky-head"> | |
<table> | |
<thead> | |
<tr> | |
<th><?php echo _('Subscriber');?></th> | |
<?php foreach ($lists as $list_id => $list_name) {?> | |
<th><?php echo htmlspecialchars($list_name);?></th> | |
<?php }?> | |
</tr> | |
</thead> | |
<tbody> | |
<?php foreach ($subscribers as $subscriber_email => $subscriber_lists) {?> | |
<tr> | |
<td><?php echo htmlspecialchars($subscriber_email);?></td> | |
<?php foreach ($lists as $list_id => $list_name) {?> | |
<td><?php if (isset($subscriber_lists[$list_id])) { | |
?><input type="checkbox" name="del[<?php echo $list_id;?>][]" | |
value="<?php echo htmlspecialchars($subscriber_email);?>"><?php | |
}?></td> | |
<?php }?> | |
</tr> | |
<?php }?> | |
</tbody> | |
</table> | |
<button type="submit" class="btn"><?php echo _('Remove selected');?></button> | |
</form> | |
<?php } else {?> | |
<p><?php echo _('None found');?></p> | |
<?php } | |
include('includes/footer.php'); |
Have changed this to fix styles and to hide those who've unsubscribed from any list, because we use the Sendy setting where an unsubscribe counts as from all lists.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Was inspired to do a simpler, thorough version of this http://www.tech-and-dev.com/2017/07/removing-duplicates-from-different-lists-sendy.html
Sendy does not distinguish, schema-wise between subscribers and subscriptions so this is the best you'll get. Warning: it will unceremoniously, and permanently wipe the selected subscribers from your database.