xref: /webtrees/app/Services/MessageService.php (revision da7f6dd728aff7a0c0b922f5fd8849698cf0456d)
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