/plugins/rainlab/user/models/MailBlocker.php

https://gitlab.com/gideonmarked/wellmarketing · PHP · 269 lines · 141 code · 35 blank · 93 comment · 16 complexity · 18b3319a7e6915ead6e43edb57e8cb8d MD5 · raw file

  1. <?php namespace RainLab\User\Models;
  2. use Form;
  3. use Model;
  4. use System\Models\MailTemplate;
  5. use Exception;
  6. /**
  7. * Mail Blocker
  8. *
  9. * A utility model that allows a user to block specific
  10. * mail views/templates from being sent to their address.
  11. */
  12. class MailBlocker extends Model
  13. {
  14. /**
  15. * @var string The database table used by the model.
  16. */
  17. public $table = 'rainlab_user_mail_blockers';
  18. /**
  19. * @var array Guarded fields
  20. */
  21. protected $guarded = [];
  22. /**
  23. * @var array Relations
  24. */
  25. public $belongsTo = [
  26. 'user' => ['RainLab\User\Models\User']
  27. ];
  28. /**
  29. * Sets mail blocking preferences for a user. Eg:
  30. *
  31. * MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0])
  32. *
  33. * MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0], [fillable => [acme.blog::post.new_reply]])
  34. *
  35. * MailBlocker::setPreferences($user, [template_alias => 0], [aliases => [template_alias => acme.blog::post.new_reply]])
  36. *
  37. * Supported options:
  38. * - aliases: Alias definitions, with alias as key and template as value.
  39. * - fillable: An array of expected templates, undefined templates are ignored.
  40. * - verify: Only allow mail templates that are registered in the system.
  41. *
  42. * @param array $templates Template name as key and boolean as value. If false, template is blocked.
  43. * @param RainLab\User\Models\User $user
  44. * @param array $options
  45. * @return void
  46. */
  47. public static function setPreferences($user, $templates, $options = [])
  48. {
  49. $templates = (array) $templates;
  50. if (!$user) {
  51. throw new Exception('A user must be provided for MailBlocker::setPreferences');
  52. }
  53. extract(array_merge([
  54. 'aliases' => [],
  55. 'fillable' => [],
  56. 'verify' => false,
  57. ], $options));
  58. if ($aliases) {
  59. $fillable = array_merge($fillable, array_values($aliases));
  60. $templates = array_build($templates, function($key, $value) use ($aliases) {
  61. return [array_get($aliases, $key, $key), $value];
  62. });
  63. }
  64. if ($fillable) {
  65. $templates = array_intersect_key($templates, array_flip($fillable));
  66. }
  67. if ($verify) {
  68. $existing = MailTemplate::listAllTemplates();
  69. $templates = array_intersect_key($templates, $existing);
  70. }
  71. $currentBlocks = array_flip(static::checkAllForUser($user));
  72. foreach ($templates as $template => $value) {
  73. // User wants to receive mail and is blocking
  74. if ($value && isset($currentBlocks[$template])) {
  75. static::removeBlock($template, $user);
  76. }
  77. // User does not want to receive mail and not blocking
  78. elseif (!$value && !isset($currentBlocks[$template])) {
  79. static::addBlock($template, $user);
  80. }
  81. }
  82. }
  83. /**
  84. * Adds a block for a user and a mail view/template code.
  85. * @param string $template
  86. * @param RainLab\User\Models\User $user
  87. * @return bool
  88. */
  89. public static function addBlock($template, $user)
  90. {
  91. $blocker = static::firstOrNew([
  92. 'template' => $template,
  93. 'user_id' => $user->id
  94. ]);
  95. $blocker->email = $user->email;
  96. $blocker->save();
  97. return $blocker;
  98. }
  99. /**
  100. * Removes a block for a user and a mail view/template code.
  101. * @param string $template
  102. * @param RainLab\User\Models\User $user
  103. * @return bool
  104. */
  105. public static function removeBlock($template, $user)
  106. {
  107. $blocker = static::where([
  108. 'template' => $template,
  109. 'user_id' => $user->id
  110. ])->first();
  111. if (!$blocker) {
  112. return false;
  113. }
  114. $blocker->delete();
  115. return true;
  116. }
  117. /**
  118. * Blocks all mail messages for a user.
  119. * @param RainLab\User\Models\User $user
  120. * @return bool
  121. */
  122. public static function blockAll($user)
  123. {
  124. return static::addBlock('*', $user);
  125. }
  126. /**
  127. * Removes block on all mail messages for a user.
  128. * @param RainLab\User\Models\User $user
  129. * @return bool
  130. */
  131. public static function unblockAll($user)
  132. {
  133. return static::removeBlock('*', $user);
  134. }
  135. /**
  136. * Checks if a user is blocking all templates.
  137. * @param RainLab\User\Models\User $user
  138. * @return bool
  139. */
  140. public static function isBlockAll($user)
  141. {
  142. return static::checkForEmail('*', $user->email);
  143. }
  144. /**
  145. * Updates mail blockers for a user if they change their email address
  146. * @param Model $user
  147. * @return mixed
  148. */
  149. public static function syncUser($user)
  150. {
  151. return static::where('user_id', $user->id)->update(['email' => $user->email]);
  152. }
  153. /**
  154. * Returns a list of mail templates blocked by the user.
  155. * @param Model $user
  156. * @return array
  157. */
  158. public static function checkAllForUser($user)
  159. {
  160. return static::where('user_id', $user->id)->lists('template');
  161. }
  162. /**
  163. * Checks if an email address has blocked a given template,
  164. * returns an array of blocked emails.
  165. * @param string $template
  166. * @param string $email
  167. * @return array
  168. */
  169. public static function checkForEmail($template, $email)
  170. {
  171. if (empty($email)) {
  172. return [];
  173. }
  174. if (!is_array($email)) {
  175. $email = [$email => null];
  176. }
  177. $emails = array_keys($email);
  178. return static::where(function($q) use ($template) {
  179. $q->where('template', $template)->orWhere('template', '*');
  180. })
  181. ->whereIn('email', $emails)
  182. ->lists('email');
  183. }
  184. /**
  185. * Filters a Illuminate\Mail\Message and removes blocked recipients.
  186. * If no recipients remain, false is returned. Returns true if mailing
  187. * should proceed.
  188. * @param string $template
  189. * @param Illuminate\Mail\Message $message
  190. * @return bool
  191. */
  192. public static function filterMessage($template, $message)
  193. {
  194. $recipients = $message->getTo();
  195. $blockedAddresses = static::checkForEmail($template, $recipients);
  196. if (!count($blockedAddresses)) {
  197. return true;
  198. }
  199. foreach ($recipients as $address => $name) {
  200. if (in_array($address, $blockedAddresses)) {
  201. unset($recipients[$address]);
  202. }
  203. }
  204. $message->setTo($recipients);
  205. return count($recipients) ? true : false;
  206. }
  207. /**
  208. * @deprecated Use MailBlocker::setPreferences instead
  209. * @TODO Remove this function in the next major version or if year >= 2017
  210. */
  211. public static function toggleBlocks($templates, $user, array $inTemplates = null)
  212. {
  213. traceLog('MailBlocker::toggleBlocks is deprecated, please use MailBlocker::setPreferences instead');
  214. foreach ((array) $templates as $template => $value) {
  215. if (
  216. $inTemplates &&
  217. !array_key_exists($template, $inTemplates) &&
  218. !in_array($template, $inTemplates)
  219. ) {
  220. continue;
  221. }
  222. // Template uses an alias
  223. if (isset($inTemplates[$template])) {
  224. $template = $inTemplates[$template];
  225. }
  226. if ($value) {
  227. static::removeBlock($template, $user);
  228. }
  229. else {
  230. static::addBlock($template, $user);
  231. }
  232. }
  233. }
  234. }