<?php
 class vB_Library_Unsubscribe extends vB_Library { protected array $mailhashCache = []; protected array $mailoptionCache = []; const EMAILOPTION_DEFAULT = 0; const EMAILOPTION_UNSUBSCRIBED = 1; const EMAILOPTION_OPTED_IN = 2; public function prefetchUserHashes(array $userids) : void { if (!$userids) { return; } $assertor = vB::getDbAssertor(); $conditions = [ 'userid' => $userids, ]; $existing = $assertor->getRows('mailhash', $conditions, false, 'userid'); $this->mailhashCache = $existing; $inserts = []; foreach ($userids AS $__userid) { if (!isset($existing[$__userid])) { $inserts[$__userid] = $this->createMailhashArrayForUser($__userid); $this->mailhashCache[$__userid] = $inserts[$__userid]; } } if ($inserts) { $first = reset($inserts); $fields = array_keys($first); $assertor->insertMultiple('mailhash', $fields, $inserts); } $this->bulkUpdateTokenLastused($existing); } public function bulkUpdateTokenLastused(array $useridHashArray, bool $shutdown = false) { $timenow = vB::getRequest()->getTimeNow(); $assertor = vB::getDbAssertor(); foreach ($useridHashArray AS ['userid' => $__userid, 'hash' => $__hash]) { $assertor->update('mailhash', ['tokenlastused' => $timenow], ['userid' => $__userid, 'hash' => $__hash], $shutdown); } } public function ensureUserHash(int $userid) : array { if ($userid <= 0) { return [ 'userid' => '', 'hash' => '', ]; } if (isset($this->mailhashCache[$userid])) { return $this->mailhashCache[$userid]; } $assertor = vB::getDbAssertor(); $check = $assertor->getRow('mailhash', ['userid' => $userid]); if (empty($check)) { $data = $this->createMailhashArrayForUser($userid); $assertor->insert('mailhash', $data); $this->mailhashCache[$userid] = $data; } else { $this->mailhashCache[$userid] = $check; } return $this->mailhashCache[$userid]; } private function createMailhashArrayForUser($userid) : array { $timenow = vB::getRequest()->getTimeNow(); $random = new vB_Utility_Random(); $seed = $random->alphanumeric(32); $hash = hash('sha256', $userid . '-' . $seed); $data = [ 'userid' => $userid, 'hash' => $hash, 'tokencreated' => $timenow, 'tokenlastused' => $timenow, ]; return $data; } public function resetAllHashes() { $assertor = vB::getDbAssertor(); $assertor->assertQuery('truncateTable', ['table' => 'mailhash']); } public function resetSingleHash(int $userid) { $assertor = vB::getDbAssertor(); $assertor->delete('mailhash', ['userid' => $userid]); } public function afterUserDelete(int $userid) { $assertor = vB::getDbAssertor(); $assertor->delete('mailhash', ['userid' => $userid]); $assertor->delete('mailoption', ['userid' => $userid]); } public function fetchUrlParameters(int $userid) : array { $info = $this->ensureUserHash($userid); if (empty($info['hash'])) { return [ 'userid' => 0, 'hash' => '', ]; } return [ 'userid' => $userid, 'hash' => $info['hash'], ]; } public function verifyHash(int $userid, string $hash) : bool { $assertor = vB::getDbAssertor(); $check = $assertor->getRow('mailhash', ['userid' => $userid, 'hash' => $hash,]); return !empty($check['userid']); } public function prefetchUserMailOptions(array $userids) : void { $assertor = vB::getDbAssertor(); $conditions = [ 'userid' => $userids, ]; $this->mailoptionCache = $assertor->getRows('mailoption', $conditions, false, 'userid'); foreach ($userids AS $__userid) { if (!isset($this->mailoptionCache[$__userid])) { $this->mailoptionCache[$__userid] = [ 'userid' => $__userid, 'emailoption' => self::EMAILOPTION_DEFAULT, 'emailoptionupdated' => 0, ]; } } } public function trackEmailOptInOut(int $userid, int $option = self::EMAILOPTION_DEFAULT) : void { $assertor = vB::getDbAssertor(); $timenow = vB::getRequest()->getTimeNow(); $values = [ 'userid' => $userid, 'emailoption' => $option, 'emailoptionupdated' => $timenow ]; $assertor->replace('mailoption', $values); $this->mailoptionCache[$userid] = $values; } public function isUserOptedOutOfEmail(int $userid) : bool { if (empty($this->mailoptionCache[$userid])) { $assertor = vB::getDbAssertor(); $check = $assertor->getRow('mailoption', ['userid' => $userid]); if (!$check) { $check = [ 'userid' => $userid, 'emailoption' => self::EMAILOPTION_DEFAULT, 'emailoptionupdated' => 0, ]; } $this->mailoptionCache[$userid] = $check; } switch ($this->mailoptionCache[$userid]['emailoption']) { case self::EMAILOPTION_UNSUBSCRIBED: return true; break; case self::EMAILOPTION_OPTED_IN: return false; break; case self::EMAILOPTION_DEFAULT: default: return false; break; } } } 