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