xref: /webtrees/app/Services/MessageService.php (revision 89f7189b61a494347591c99bdb92afb7d8b66e1b)
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
15*89f7189bSGreg 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{
41e381f98dSGreg Roach    /** @var UserService */
42e381f98dSGreg Roach    private $user_service;
43e381f98dSGreg Roach
44e381f98dSGreg Roach    /** @var EmailService */
45e381f98dSGreg Roach    private $email_service;
46e381f98dSGreg Roach
47e381f98dSGreg Roach    /**
48e381f98dSGreg Roach     * MessageService constructor.
49e381f98dSGreg Roach     *
50e381f98dSGreg Roach     * @param EmailService $email_service
51e381f98dSGreg Roach     * @param UserService  $user_service
52e381f98dSGreg Roach     */
53e381f98dSGreg Roach    public function __construct(EmailService $email_service, UserService $user_service)
54e381f98dSGreg Roach    {
55e381f98dSGreg Roach        $this->email_service = $email_service;
56e381f98dSGreg Roach        $this->user_service  = $user_service;
57e381f98dSGreg Roach    }
58e381f98dSGreg Roach
59e381f98dSGreg Roach    /**
60e381f98dSGreg Roach     * Contact messages can only be sent to the designated contacts
61e381f98dSGreg Roach     *
62e381f98dSGreg Roach     * @param Tree $tree
63e381f98dSGreg Roach     *
64e381f98dSGreg Roach     * @return UserInterface[]
65e381f98dSGreg Roach     */
66e381f98dSGreg Roach    public function validContacts(Tree $tree): array
67e381f98dSGreg Roach    {
68e381f98dSGreg Roach        $contacts = [
69e381f98dSGreg Roach            $this->user_service->find((int) $tree->getPreference('CONTACT_USER_ID')),
70e381f98dSGreg Roach            $this->user_service->find((int) $tree->getPreference('WEBMASTER_USER_ID')),
71e381f98dSGreg Roach        ];
72e381f98dSGreg Roach
73e381f98dSGreg Roach        return array_filter($contacts);
74e381f98dSGreg Roach    }
75e381f98dSGreg Roach
76e381f98dSGreg Roach    /**
77e381f98dSGreg Roach     * Add a message to a user's inbox, send it to them via email, or both.
78e381f98dSGreg Roach     *
79e381f98dSGreg Roach     * @param UserInterface $sender
80e381f98dSGreg Roach     * @param UserInterface $recipient
81e381f98dSGreg Roach     * @param string        $subject
82e381f98dSGreg Roach     * @param string        $body
83e381f98dSGreg Roach     * @param string        $url
84e381f98dSGreg Roach     * @param string        $ip
85e381f98dSGreg Roach     *
86e381f98dSGreg Roach     * @return bool
87e381f98dSGreg Roach     */
88e381f98dSGreg Roach    public function deliverMessage(UserInterface $sender, UserInterface $recipient, string $subject, string $body, string $url, string $ip): bool
89e381f98dSGreg Roach    {
90e381f98dSGreg Roach        $success = true;
91e381f98dSGreg Roach
92e381f98dSGreg Roach        // Temporarily switch to the recipient's language
93e381f98dSGreg Roach        $old_language = I18N::languageTag();
941fe542e9SGreg Roach        I18N::init($recipient->getPreference(UserInterface::PREF_LANGUAGE));
95e381f98dSGreg Roach
96e381f98dSGreg Roach        $body_text = view('emails/message-user-text', [
97e381f98dSGreg Roach            'sender'    => $sender,
98e381f98dSGreg Roach            'recipient' => $recipient,
99e381f98dSGreg Roach            'message'   => $body,
100e381f98dSGreg Roach            'url'       => $url,
101e381f98dSGreg Roach        ]);
102e381f98dSGreg Roach
103e381f98dSGreg Roach        $body_html = view('emails/message-user-html', [
104e381f98dSGreg Roach            'sender'    => $sender,
105e381f98dSGreg Roach            'recipient' => $recipient,
106e381f98dSGreg Roach            'message'   => $body,
107e381f98dSGreg Roach            'url'       => $url,
108e381f98dSGreg Roach        ]);
109e381f98dSGreg Roach
110e381f98dSGreg Roach        // Send via the internal messaging system.
111e381f98dSGreg Roach        if ($this->sendInternalMessage($recipient)) {
112e381f98dSGreg Roach            DB::table('message')->insert([
113e381f98dSGreg Roach                'sender'     => Auth::check() ? Auth::user()->email() : $sender->email(),
114e381f98dSGreg Roach                'ip_address' => $ip,
115e381f98dSGreg Roach                'user_id'    => $recipient->id(),
116e381f98dSGreg Roach                'subject'    => $subject,
117e381f98dSGreg Roach                'body'       => $body_text,
118e381f98dSGreg Roach            ]);
119e381f98dSGreg Roach        }
120e381f98dSGreg Roach
121e381f98dSGreg Roach        // Send via email
122e381f98dSGreg Roach        if ($this->sendEmail($recipient)) {
123e381f98dSGreg Roach            $success = $this->email_service->send(
124e381f98dSGreg Roach                new SiteUser(),
125e381f98dSGreg Roach                $recipient,
126e381f98dSGreg Roach                $sender,
127e381f98dSGreg Roach                I18N::translate('webtrees message') . ' - ' . $subject,
128e381f98dSGreg Roach                $body_text,
129e381f98dSGreg Roach                $body_html
130e381f98dSGreg Roach            );
131e381f98dSGreg Roach        }
132e381f98dSGreg Roach
133e381f98dSGreg Roach        I18N::init($old_language);
134e381f98dSGreg Roach
135e381f98dSGreg Roach        return $success;
136e381f98dSGreg Roach    }
137e381f98dSGreg Roach
138e381f98dSGreg Roach    /**
139e381f98dSGreg Roach     * Should we send messages to this user via internal messaging?
140e381f98dSGreg Roach     *
141e381f98dSGreg Roach     * @param UserInterface $user
142e381f98dSGreg Roach     *
143e381f98dSGreg Roach     * @return bool
144e381f98dSGreg Roach     */
145e381f98dSGreg Roach    public function sendInternalMessage(UserInterface $user): bool
146e381f98dSGreg Roach    {
1471fe542e9SGreg Roach        return in_array($user->getPreference(UserInterface::PREF_CONTACT_METHOD), [
148e381f98dSGreg Roach            'messaging',
149e381f98dSGreg Roach            'messaging2',
150e381f98dSGreg Roach            'mailto',
151e381f98dSGreg Roach            'none',
152e381f98dSGreg Roach        ], true);
153e381f98dSGreg Roach    }
154e381f98dSGreg Roach
155e381f98dSGreg Roach    /**
156e381f98dSGreg Roach     * Should we send messages to this user via email?
157e381f98dSGreg Roach     *
158e381f98dSGreg Roach     * @param UserInterface $user
159e381f98dSGreg Roach     *
160e381f98dSGreg Roach     * @return bool
161e381f98dSGreg Roach     */
162e381f98dSGreg Roach    public function sendEmail(UserInterface $user): bool
163e381f98dSGreg Roach    {
1641fe542e9SGreg Roach        return in_array($user->getPreference(UserInterface::PREF_CONTACT_METHOD), [
165e381f98dSGreg Roach            'messaging2',
166e381f98dSGreg Roach            'messaging3',
167e381f98dSGreg Roach            'mailto',
168e381f98dSGreg Roach            'none',
169e381f98dSGreg Roach        ], true);
170e381f98dSGreg Roach    }
171e381f98dSGreg Roach
172e381f98dSGreg Roach    /**
173e381f98dSGreg Roach     * Convert a username (or mailing list name) into an array of recipients.
174e381f98dSGreg Roach     *
175e381f98dSGreg Roach     * @param string $to
176e381f98dSGreg Roach     *
177b5c8fd7eSGreg Roach     * @return Collection<User>
178e381f98dSGreg Roach     */
179e381f98dSGreg Roach    public function recipientUsers(string $to): Collection
180e381f98dSGreg Roach    {
181e381f98dSGreg Roach        switch ($to) {
182e381f98dSGreg Roach            default:
183e381f98dSGreg Roach            case 'all':
184e381f98dSGreg Roach                return $this->user_service->all();
185e381f98dSGreg Roach            case 'never_logged':
186e381f98dSGreg Roach                return $this->user_service->all()->filter(static function (UserInterface $user): bool {
1871fe542e9SGreg Roach                    return $user->getPreference(UserInterface::PREF_IS_ACCOUNT_APPROVED) === '1' && $user->getPreference(UserInterface::PREF_TIMESTAMP_REGISTERED) > $user->getPreference(UserInterface::PREF_TIMESTAMP_ACTIVE);
188e381f98dSGreg Roach                });
189e381f98dSGreg Roach            case 'last_6mo':
190e381f98dSGreg Roach                $six_months_ago = Carbon::now()->subMonths(6)->unix();
191e381f98dSGreg Roach
192e381f98dSGreg Roach                return $this->user_service->all()->filter(static function (UserInterface $user) use ($six_months_ago): bool {
1931fe542e9SGreg Roach                    $session_time = (int) $user->getPreference(UserInterface::PREF_TIMESTAMP_ACTIVE);
194e381f98dSGreg Roach
195e381f98dSGreg Roach                    return $session_time > 0 && $session_time < $six_months_ago;
196e381f98dSGreg Roach                });
197e381f98dSGreg Roach        }
198e381f98dSGreg Roach    }
199e381f98dSGreg Roach
200e381f98dSGreg Roach    /**
201e381f98dSGreg Roach     * @param string $to
202e381f98dSGreg Roach     *
203e381f98dSGreg Roach     * @return string
204e381f98dSGreg Roach     */
205e381f98dSGreg Roach    public function recipientDescription(string $to): string
206e381f98dSGreg Roach    {
207e381f98dSGreg Roach        switch ($to) {
208e381f98dSGreg Roach            default:
209e381f98dSGreg Roach            case 'all':
210e381f98dSGreg Roach                return I18N::translate('Send a message to all users');
211e381f98dSGreg Roach            case 'never_logged':
212e381f98dSGreg Roach                return I18N::translate('Send a message to users who have never signed in');
213e381f98dSGreg Roach            case 'last_6mo':
214e381f98dSGreg Roach                return I18N::translate('Send a message to users who have not signed in for 6 months');
215e381f98dSGreg Roach        }
216e381f98dSGreg Roach    }
217f91b18ebSGreg Roach
218f91b18ebSGreg Roach    /**
219f91b18ebSGreg Roach     * A list of contact methods (e.g. for an edit control).
220f91b18ebSGreg Roach     *
221f91b18ebSGreg Roach     * @return string[]
222f91b18ebSGreg Roach     */
223f91b18ebSGreg Roach    public function contactMethods(): array
224f91b18ebSGreg Roach    {
225f91b18ebSGreg Roach        return [
226f91b18ebSGreg Roach            'messaging'  => I18N::translate('Internal messaging'),
227f91b18ebSGreg Roach            'messaging2' => I18N::translate('Internal messaging with emails'),
228f91b18ebSGreg Roach            'messaging3' => I18N::translate('webtrees sends emails with no storage'),
229f91b18ebSGreg Roach            'mailto'     => I18N::translate('Mailto link'),
230f91b18ebSGreg Roach            'none'       => I18N::translate('No contact'),
231f91b18ebSGreg Roach        ];
232f91b18ebSGreg Roach    }
233e381f98dSGreg Roach}
234