279 lines
7.7 KiB
PHP
279 lines
7.7 KiB
PHP
<?php namespace RainLab\User\Models;
|
|
|
|
use Form;
|
|
use Model;
|
|
use System\Models\MailTemplate;
|
|
use Exception;
|
|
|
|
/**
|
|
* Mail Blocker
|
|
*
|
|
* A utility model that allows a user to block specific
|
|
* mail views/templates from being sent to their address.
|
|
*/
|
|
class MailBlocker extends Model
|
|
{
|
|
/**
|
|
* @var string The database table used by the model.
|
|
*/
|
|
public $table = 'rainlab_user_mail_blockers';
|
|
|
|
/**
|
|
* @var array Guarded fields
|
|
*/
|
|
protected $guarded = [];
|
|
|
|
/**
|
|
* @var array Relations
|
|
*/
|
|
public $belongsTo = [
|
|
'user' => User::class
|
|
];
|
|
|
|
/**
|
|
* @var array Templates names that cannot be blocked.
|
|
*/
|
|
protected static $safeTemplates = [
|
|
'rainlab.user::mail.restore'
|
|
];
|
|
|
|
/**
|
|
* Sets mail blocking preferences for a user. Eg:
|
|
*
|
|
* MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0])
|
|
*
|
|
* MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0], [fillable => [acme.blog::post.new_reply]])
|
|
*
|
|
* MailBlocker::setPreferences($user, [template_alias => 0], [aliases => [template_alias => acme.blog::post.new_reply]])
|
|
*
|
|
* Supported options:
|
|
* - aliases: Alias definitions, with alias as key and template as value.
|
|
* - fillable: An array of expected templates, undefined templates are ignored.
|
|
* - verify: Only allow mail templates that are registered in the system.
|
|
*
|
|
* @param array $templates Template name as key and boolean as value. If false, template is blocked.
|
|
* @param RainLab\User\Models\User $user
|
|
* @param array $options
|
|
* @return void
|
|
*/
|
|
public static function setPreferences($user, $templates, $options = [])
|
|
{
|
|
$templates = (array) $templates;
|
|
|
|
if (!$user) {
|
|
throw new Exception('A user must be provided for MailBlocker::setPreferences');
|
|
}
|
|
|
|
extract(array_merge([
|
|
'aliases' => [],
|
|
'fillable' => [],
|
|
'verify' => false,
|
|
], $options));
|
|
|
|
if ($aliases) {
|
|
$fillable = array_merge($fillable, array_values($aliases));
|
|
$templates = array_build($templates, function($key, $value) use ($aliases) {
|
|
return [array_get($aliases, $key, $key), $value];
|
|
});
|
|
}
|
|
|
|
if ($fillable) {
|
|
$templates = array_intersect_key($templates, array_flip($fillable));
|
|
}
|
|
|
|
if ($verify) {
|
|
$existing = MailTemplate::listAllTemplates();
|
|
$templates = array_intersect_key($templates, $existing);
|
|
}
|
|
|
|
$currentBlocks = array_flip(static::checkAllForUser($user));
|
|
foreach ($templates as $template => $value) {
|
|
// User wants to receive mail and is blocking
|
|
if ($value && isset($currentBlocks[$template])) {
|
|
static::removeBlock($template, $user);
|
|
}
|
|
// User does not want to receive mail and not blocking
|
|
elseif (!$value && !isset($currentBlocks[$template])) {
|
|
static::addBlock($template, $user);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a block for a user and a mail view/template code.
|
|
* @param string $template
|
|
* @param RainLab\User\Models\User $user
|
|
* @return bool
|
|
*/
|
|
public static function addBlock($template, $user)
|
|
{
|
|
$blocker = static::where([
|
|
'template' => $template,
|
|
'user_id' => $user->id
|
|
])->first();
|
|
|
|
if ($blocker && $blocker->email == $user->email) {
|
|
return false;
|
|
}
|
|
|
|
if (!$blocker) {
|
|
$blocker = new static;
|
|
$blocker->template = $template;
|
|
$blocker->user_id = $user->id;
|
|
}
|
|
|
|
$blocker->email = $user->email;
|
|
$blocker->save();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Removes a block for a user and a mail view/template code.
|
|
* @param string $template
|
|
* @param RainLab\User\Models\User $user
|
|
* @return bool
|
|
*/
|
|
public static function removeBlock($template, $user)
|
|
{
|
|
$blocker = static::where([
|
|
'template' => $template,
|
|
'user_id' => $user->id
|
|
])->orWhere(function ($query) use ($template, $user) {
|
|
$query->where([
|
|
'template' => $template,
|
|
'email' => $user->email
|
|
]);
|
|
})->get();
|
|
|
|
if (!$blocker->count()) {
|
|
return false;
|
|
}
|
|
|
|
$blocker->each(function($block) {
|
|
$block->delete();
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Blocks all mail messages for a user.
|
|
* @param RainLab\User\Models\User $user
|
|
* @return bool
|
|
*/
|
|
public static function blockAll($user)
|
|
{
|
|
return static::addBlock('*', $user);
|
|
}
|
|
|
|
/**
|
|
* Removes block on all mail messages for a user.
|
|
* @param RainLab\User\Models\User $user
|
|
* @return bool
|
|
*/
|
|
public static function unblockAll($user)
|
|
{
|
|
return static::removeBlock('*', $user);
|
|
}
|
|
|
|
/**
|
|
* Checks if a user is blocking all templates.
|
|
* @param RainLab\User\Models\User $user
|
|
* @return bool
|
|
*/
|
|
public static function isBlockAll($user)
|
|
{
|
|
return count(static::checkForEmail('*', $user->email)) > 0;
|
|
}
|
|
|
|
/**
|
|
* Updates mail blockers for a user if they change their email address
|
|
* @param Model $user
|
|
* @return mixed
|
|
*/
|
|
public static function syncUser($user)
|
|
{
|
|
return static::where('user_id', $user->id)->update(['email' => $user->email]);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of mail templates blocked by the user.
|
|
* @param Model $user
|
|
* @return array
|
|
*/
|
|
public static function checkAllForUser($user)
|
|
{
|
|
return static::where('user_id', $user->id)->lists('template');
|
|
}
|
|
|
|
/**
|
|
* checkForEmail checks if an email address has blocked a given template,
|
|
* returns an array of blocked emails.
|
|
* @param string $template
|
|
* @param string $email
|
|
* @return array
|
|
*/
|
|
public static function checkForEmail($template, $email)
|
|
{
|
|
if (in_array($template, static::$safeTemplates)) {
|
|
return [];
|
|
}
|
|
|
|
if (empty($email)) {
|
|
return [];
|
|
}
|
|
|
|
if (!is_array($email)) {
|
|
$email = [$email => null];
|
|
}
|
|
|
|
$emails = array_keys($email);
|
|
|
|
return static::where(function($q) use ($template) {
|
|
$q->where('template', $template)->orWhere('template', '*');
|
|
})
|
|
->whereIn('email', $emails)
|
|
->lists('email');
|
|
}
|
|
|
|
/**
|
|
* filterMessage filters a Illuminate\Mail\Message and removes blocked recipients.
|
|
* If no recipients remain, false is returned. Returns null if mailing
|
|
* should proceed.
|
|
* @param string $template
|
|
* @param Illuminate\Mail\Message $message
|
|
* @return bool|null
|
|
*/
|
|
public static function filterMessage($template, $message)
|
|
{
|
|
$recipients = $message->getTo();
|
|
$blockedAddresses = static::checkForEmail($template, $recipients);
|
|
|
|
if (!count($blockedAddresses)) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($recipients as $index => $address) {
|
|
// October v2
|
|
if ($address instanceof \Symfony\Component\Mime\Address) {
|
|
if (in_array($address->getAddress(), $blockedAddresses)) {
|
|
unset($recipients[$index]);
|
|
}
|
|
}
|
|
// October v1
|
|
else {
|
|
// Swift message, index is address
|
|
if (in_array($index, $blockedAddresses)) {
|
|
unset($recipients[$index]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Override recipients
|
|
$message->to($recipients, null, true);
|
|
|
|
return count($recipients) ? null : false;
|
|
}
|
|
}
|