During development I has a case, where via a Mailing List api in order to retrieve the deleted subscribers from it.
// Making an Adapter (using GoF adapter pattern)
class MailingListApiAdapter
{
const USUBBED_SUBSCRIBERS='....';
const DELETED_SUBSCRIBERS='....';
// Some Implementation here
public function retrieveUnsubbedUsers(int $page=1,int &$total_pages): array
{
return $this->retrieveSubscribers(USUBBED_SUBSCRIBERS,$page,$total_pages);
}
public function retrieveDeletedUsers(int $page=1,int &$total_pages): array
{
return $this->retrieveSubscribers(DELETED_SUBSCRIBERS,$page,$total_pages);
}
private function retrieveSubscribers(string $url,int $page=1,int &$total_pages):array
{
// call api and return array
}
}
And due to a misconfig I had the stored consent of a user not on par with the mailing list. Therefore, I wanted to scan the existing lists and update the consent into the DB.
The consents is into the following RDBS table (I know it is not a specific db I try to keep db agnostic) :
user_consent
----
int user_id
string email
string consent_type
bool given_consent
And I did the following script to update the consent:
function scan_list_and_update_consent(\PDO $dbh, Callable $retreiveSubscribersFunction){
$dbh
$page=1;
$total_pages = 1;
$sql = "UPDATE user_consent SET given_consent=false where consent_type='MAILING_LIST' and given_consent=true and email = :email";
$stmt = $dbh->prepare($sql);
do {
$dbh->beginTransaction();
try{
$subs = $retreiveSubscribersFunction($page,$limit);
foreach($subs as $email){
$stmt->execute(['email'=>$email]);
}
$dbh->commit();
} catch(\Exception $e){
$dbh->rollback();
}
$page++;
// We slow down the request frequency in order to avoid throttling
sleep(3);
}while($page<=$total_pages);
}
As you can see we iterate all pages (The second param is passed by reference at both retrieveUnsubbedUsers
and retrieveDeletedUsers
so we can retrieve the total pages with a singlwe request)
Also we assume that both both retrieveUnsubbedUsers
and retrieveDeletedUsers
return an array with emails:
[
'user@example.com',
....
]
So having a known logic we can call the function scan_list_and_update_consent
like this:
function scan_list_and_update_consent(\PDO $dbh, Callable $retreiveSubscribersFunction){
$dbh
$page=1;
$total_pages = 1;
$sql = "UPDATE user_consent SET given_consent=false where consent_type='MAILING_LIST' and given_consent=true and email = :email";
$stmt = $dbh->prepare($sql);
do {
$dbh->beginTransaction();
try{
$subs = $retreiveSubscribersFunction($page,$limit);
foreach($subs as $email){
$stmt->execute(['email'=>$email]);
}
$dbh->commit();
} catch(\Exception $e){
$dbh->rollback();
}
$page++;
// We slow down the request frequency in order to avoid throttling
sleep(3);
}while($page<=$total_pages);
}
$pdo = new PDO();
// Config pdo futher here
$mailingList = new MailingListApiAdapter();
// call $mailinglist->retrieveDeletedUsers
scan_list_and_update_consent($pdo,[$mailingList,'retrieveDeletedUsers']);
// call $mailinglist->retrieveUnsubbedUsers
scan_list_and_update_consent($pdo,[$mailingList,'retrieveUnsubbedUsers']);
So as a result we can use functions with same signature (aka same parameter number and types) with a single piece of code avoiding duplicate code.
In our case we can add another function (eg. getNonReceivingEmailSubscribers
) with same parameters ($page and $total_pages) and still be able to use it with scan_list_and_update_consent
:
// call $mailinglist->retrieveUnsubbedUsers
scan_list_and_update_consent($pdo,[$mailingList,'getNonReceivingEmailSubscribers']);
And we do not need to re-write the loop and the logic for fetching all pages for api calls.
Top comments (0)