1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Services; 21 22use Fisharebest\Webtrees\Auth; 23use Fisharebest\Webtrees\Carbon; 24use Fisharebest\Webtrees\Contracts\UserInterface; 25use Fisharebest\Webtrees\I18N; 26use Fisharebest\Webtrees\SiteUser; 27use Fisharebest\Webtrees\Tree; 28use Illuminate\Database\Capsule\Manager as DB; 29use Illuminate\Support\Collection; 30 31use function array_filter; 32use function in_array; 33use function view; 34 35/** 36 * Send messages between users and from visitors to the site. 37 */ 38class MessageService 39{ 40 /** @var UserService */ 41 private $user_service; 42 43 /** @var EmailService */ 44 private $email_service; 45 46 /** 47 * MessageService constructor. 48 * 49 * @param EmailService $email_service 50 * @param UserService $user_service 51 */ 52 public function __construct(EmailService $email_service, UserService $user_service) 53 { 54 $this->email_service = $email_service; 55 $this->user_service = $user_service; 56 } 57 58 /** 59 * Contact messages can only be sent to the designated contacts 60 * 61 * @param Tree $tree 62 * 63 * @return UserInterface[] 64 */ 65 public function validContacts(Tree $tree): array 66 { 67 $contacts = [ 68 $this->user_service->find((int) $tree->getPreference('CONTACT_USER_ID')), 69 $this->user_service->find((int) $tree->getPreference('WEBMASTER_USER_ID')), 70 ]; 71 72 return array_filter($contacts); 73 } 74 75 /** 76 * Add a message to a user's inbox, send it to them via email, or both. 77 * 78 * @param UserInterface $sender 79 * @param UserInterface $recipient 80 * @param string $subject 81 * @param string $body 82 * @param string $url 83 * @param string $ip 84 * 85 * @return bool 86 */ 87 public function deliverMessage(UserInterface $sender, UserInterface $recipient, string $subject, string $body, string $url, string $ip): bool 88 { 89 $success = true; 90 91 // Temporarily switch to the recipient's language 92 $old_language = I18N::languageTag(); 93 I18N::init($recipient->getPreference('language')); 94 95 $body_text = view('emails/message-user-text', [ 96 'sender' => $sender, 97 'recipient' => $recipient, 98 'message' => $body, 99 'url' => $url, 100 ]); 101 102 $body_html = view('emails/message-user-html', [ 103 'sender' => $sender, 104 'recipient' => $recipient, 105 'message' => $body, 106 'url' => $url, 107 ]); 108 109 // Send via the internal messaging system. 110 if ($this->sendInternalMessage($recipient)) { 111 DB::table('message')->insert([ 112 'sender' => Auth::check() ? Auth::user()->email() : $sender->email(), 113 'ip_address' => $ip, 114 'user_id' => $recipient->id(), 115 'subject' => $subject, 116 'body' => $body_text, 117 ]); 118 } 119 120 // Send via email 121 if ($this->sendEmail($recipient)) { 122 $success = $this->email_service->send( 123 new SiteUser(), 124 $recipient, 125 $sender, 126 I18N::translate('webtrees message') . ' - ' . $subject, 127 $body_text, 128 $body_html 129 ); 130 } 131 132 I18N::init($old_language); 133 134 return $success; 135 } 136 137 /** 138 * Should we send messages to this user via internal messaging? 139 * 140 * @param UserInterface $user 141 * 142 * @return bool 143 */ 144 public function sendInternalMessage(UserInterface $user): bool 145 { 146 return in_array($user->getPreference('contactmethod'), [ 147 'messaging', 148 'messaging2', 149 'mailto', 150 'none', 151 ], true); 152 } 153 154 /** 155 * Should we send messages to this user via email? 156 * 157 * @param UserInterface $user 158 * 159 * @return bool 160 */ 161 public function sendEmail(UserInterface $user): bool 162 { 163 return in_array($user->getPreference('contactmethod'), [ 164 'messaging2', 165 'messaging3', 166 'mailto', 167 'none', 168 ], true); 169 } 170 171 /** 172 * Convert a username (or mailing list name) into an array of recipients. 173 * 174 * @param string $to 175 * 176 * @return Collection 177 */ 178 public function recipientUsers(string $to): Collection 179 { 180 switch ($to) { 181 default: 182 case 'all': 183 return $this->user_service->all(); 184 case 'never_logged': 185 return $this->user_service->all()->filter(static function (UserInterface $user): bool { 186 return $user->getPreference('verified_by_admin') && $user->getPreference('reg_timestamp') > $user->getPreference('sessiontime'); 187 }); 188 case 'last_6mo': 189 $six_months_ago = Carbon::now()->subMonths(6)->unix(); 190 191 return $this->user_service->all()->filter(static function (UserInterface $user) use ($six_months_ago): bool { 192 $session_time = (int) $user->getPreference('sessiontime'); 193 194 return $session_time > 0 && $session_time < $six_months_ago; 195 }); 196 } 197 } 198 199 /** 200 * @param string $to 201 * 202 * @return string 203 */ 204 public function recipientDescription(string $to): string 205 { 206 switch ($to) { 207 default: 208 case 'all': 209 return I18N::translate('Send a message to all users'); 210 case 'never_logged': 211 return I18N::translate('Send a message to users who have never signed in'); 212 case 'last_6mo': 213 return I18N::translate('Send a message to users who have not signed in for 6 months'); 214 } 215 } 216} 217