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