]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Events/ContribListener.php
Contribution email was not sent to member
[galette.git] / galette / lib / Galette / Events / ContribListener.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Event listener for contributions
7 *
8 * PHP version 5
9 *
10 * Copyright © 2020 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Events
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2020 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 2020-08-25
35 */
36
37 namespace Galette\Events;
38
39 use Galette\Core\Db;
40 use Galette\Core\GaletteMail;
41 use Galette\Core\History;
42 use Galette\Core\Login;
43 use Galette\Core\Password;
44 use Galette\Core\Preferences;
45 use Galette\Entity\Adherent;
46 use Galette\Entity\Contribution;
47 use Galette\Entity\Texts;
48 use Analog\Analog;
49 use League\Event\Event;
50 use League\Event\ListenerAcceptorInterface;
51 use League\Event\ListenerProviderInterface;
52 use Slim\Flash\Messages;
53 use Slim\Router;
54
55 /**
56 * Event listener for contributions
57 *
58 * @category Events
59 * @name MemberListener
60 * @package Galette
61 * @author Johan Cwiklinski <johan@x-tnd.be>
62 * @copyright 2020 The Galette Team
63 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
64 * @link https://galette.eu
65 * @since Available since 2020-08-25
66 */
67 class ContribListener implements ListenerProviderInterface
68 {
69 /** @var Preferences */
70 private $preferences;
71 /** @var Router */
72 private $router;
73 /** @var History */
74 private $history;
75 /** @var Messages */
76 private $flash;
77 /** @var Login */
78 private $login;
79 /** @var Db */
80 private $zdb;
81
82 /**
83 * Constructor
84 *
85 * @param Preferences $preferences Preferences instance
86 * @param Router $router Router instance
87 * @param History $history History instance
88 * @param Messages $flash Messages instance
89 * @param Login $login Login instance
90 * @param Db $zdb Db instance
91 */
92 public function __construct(
93 Preferences $preferences,
94 Router $router,
95 History $history,
96 Messages $flash,
97 Login $login,
98 Db $zdb
99 ) {
100 $this->preferences = $preferences;
101 $this->router = $router;
102 $this->history = $history;
103 $this->flash = $flash;
104 $this->login = $login;
105 $this->zdb = $zdb;
106 }
107
108 /**
109 * Set up contribution listeners
110 *
111 * @param ListenerAcceptorInterface $acceptor Listener
112 *
113 * @return void
114 */
115 public function provideListeners(ListenerAcceptorInterface $acceptor)
116 {
117 $acceptor->addListener(
118 'contribution.add',
119 function ($event, $contrib) {
120 $this->contributionAdded($event, $contrib);
121 }
122 );
123 }
124
125 /**
126 * Contribution added listener
127 *
128 * @param Event $event Raised event
129 * @param Contribution $contrib Added contribution
130 *
131 * @return void
132 */
133 public function contributionAdded(Event $event, Contribution $contrib)
134 {
135 Analog::log(
136 '[' . get_class($this) . '] Event contribution.add emitted for #' . $contrib->id,
137 Analog::DEBUG
138 );
139
140 $this->callPostContributionScript($contrib);
141
142 if ($contrib->sendEMail()) {
143 $this->sendContribEmail($contrib, true);
144 }
145 $this->sendAdminEmail($contrib, true);
146 }
147
148 /**
149 * Get texts replacements array for member
150 *
151 * @param Contribution $contrib Contribution instance
152 * @param Adherent $member Member instance
153 *
154 * @return array
155 */
156 private function getReplacements(Contribution $contrib, Adherent $member): array
157 {
158 $mreplaces = [];
159 $mreplaces = [
160 'name_adh' => custom_html_entity_decode(
161 $member->sname
162 ),
163 'firstname_adh' => custom_html_entity_decode(
164 $member->surname
165 ),
166 'lastname_adh' => custom_html_entity_decode(
167 $member->name
168 ),
169 'mail_adh' => custom_html_entity_decode(
170 $member->getEmail()
171 ),
172 'login_adh' => custom_html_entity_decode(
173 $member->login
174 ),
175 'deadline' => custom_html_entity_decode(
176 $contrib->end_date
177 ),
178 'contrib_info' => custom_html_entity_decode(
179 $contrib->info
180 ),
181 'contrib_amount' => custom_html_entity_decode(
182 $contrib->amount
183 ),
184 'contrib_type' => custom_html_entity_decode(
185 $contrib->type->libelle
186 )
187
188 ];
189 return $mreplaces;
190 }
191
192 /**
193 * Send account email to member
194 *
195 * @param Contribution $contrib Contribution
196 * @param boolean $new New contribution or editing existing one
197 *
198 * @return void
199 */
200 private function sendContribEmail(Contribution $contrib, $new)
201 {
202 if ($this->preferences->pref_mail_method == GaletteMail::METHOD_DISABLED) {
203 //if email has been disabled in the preferences, we should not be here ;
204 //we do not throw an error, just a simple warning that will be show later
205 $msg = _T("You asked Galette to send a confirmation email to the member, but email has been disabled in the preferences.");
206 $this->flash->addMessage(
207 'warning_detected',
208 $msg
209 );
210 return;
211 }
212
213 // Get member information
214 $member = new Adherent($this->zdb);
215 $member->load($contrib->member);
216
217 if ($member->getEmail() == '' && !$member->self_adh) {
218 $this->flash->addMessage(
219 'error_detected',
220 _T("- You can't send a confirmation by email if the member hasn't got an address!")
221 );
222 return;
223 }
224
225 $texts = new Texts(
226 $this->preferences,
227 $this->router,
228 $this->getReplacements($contrib, $member)
229 );
230
231 $text = 'contrib';
232 if (!$contrib->isCotis()) {
233 $text = 'donation';
234 }
235 $mtxt = $texts->getTexts($text, $member->language);
236
237 $mail = new GaletteMail($this->preferences);
238 $mail->setSubject($texts->getSubject());
239 $mail->setRecipients(
240 array(
241 $member->getEmail() => $member->sname
242 )
243 );
244
245 $link_card = '';
246 if (strpos($mtxt->tbody, '{LINK_MEMBERCARD}') !== false) {
247 //member card link is present in mail model, let's add it
248 $links = new Links($this->zdb);
249 if ($hash = $links->generateNewLink(Links::TARGET_MEMBERCARD, $contrib->member)) {
250 $link_card = $this->preferences->getURL() .
251 $this->router->pathFor('directlink', ['hash' => $hash]);
252 }
253 }
254
255 $link_pdf = '';
256 if (strpos($mtxt->tbody, '{LINK_CONTRIBPDF}') !== false) {
257 //contribution receipt link is present in mail model, let's add it
258 $links = new Links($this->zdb);
259 $ltype = $contrib->type->isExtension() ? Links::TARGET_INVOICE : Links::TARGET_RECEIPT;
260 if ($hash = $links->generateNewLink($ltype, $contrib->id)) {
261 $link_pdf = $this->preferences->getURL() .
262 $this->router->pathFor('directlink', ['hash' => $hash]);
263 }
264 }
265
266 //set replacements, even if empty, to be sure.
267 $texts->setReplaces([
268 'link_membercard' => $link_card,
269 'link_contribpdf' => $link_pdf
270 ]);
271
272 $mail->setMessage($texts->getBody());
273 $sent = $mail->send();
274
275 if ($sent) {
276 $this->history->add(
277 preg_replace(
278 array('/%name/', '/%email/'),
279 array($member->sname, $member->getEmail()),
280 _T("Email sent to user %name (%email)")
281 )
282 );
283 } else {
284 $txt = preg_replace(
285 array('/%name/', '/%email/'),
286 array($member->sname, $member->getEmail()),
287 _T("A problem happened while sending contribution receipt to user %name (%email)")
288 );
289 $this->history->add($txt);
290 $this->flash->addMessage(
291 'warning_detected',
292 $txt
293 );
294 }
295 }
296
297 /**
298 * Send new contribution email to admin
299 *
300 * @param Contribution $contrib Contribution
301 * @param boolean $new New contribution or editing existing one
302 *
303 * @return void
304 */
305 private function sendAdminEmail(Contribution $contrib, $new)
306 {
307 if (
308 $this->preferences->pref_mail_method == GaletteMail::METHOD_DISABLED
309 || !$this->preferences->pref_bool_mailadh
310 || (!$new && $contrib->member != $this->login->id)
311 ) {
312 return;
313 }
314
315 // Get member information
316 $member = new Adherent($this->zdb);
317 $member->load($contrib->member);
318
319 $texts = new Texts(
320 $this->preferences,
321 $this->router,
322 $this->getReplacements($contrib, $member)
323 );
324
325 // Sent email to admin if pref checked
326 // Get email text in database
327 $text = 'newcont';
328 if (!$contrib->isCotis()) {
329 $text = 'newdonation';
330 }
331 $texts->getTexts($text, $this->preferences->pref_lang);
332
333 $mail = new GaletteMail($this->preferences);
334 $mail->setSubject($texts->getSubject());
335
336 $recipients = [];
337 foreach ($this->preferences->vpref_email_newadh as $pref_email) {
338 $recipients[$pref_email] = $pref_email;
339 }
340 $mail->setRecipients($recipients);
341
342 $mail->setMessage($texts->getBody());
343 $sent = $mail->send();
344
345 if ($sent) {
346 $this->history->add(
347 preg_replace(
348 array('/%name/', '/%email/'),
349 array($member->sname, $member->getEmail()),
350 _T("Email sent to admin for user %name (%email)")
351 )
352 );
353 } else {
354 $txt = preg_replace(
355 array('/%name/', '/%email/'),
356 array($member->sname, $member->getEmail()),
357 _T("A problem happened while sending to admin notification for user %name (%email) contribution")
358 );
359 $this->history->add($txt);
360 $this->flash->addMessage(
361 'warning_detected',
362 $txt
363 );
364 }
365 }
366
367 /**
368 * Call post contribution script from Preferences
369 *
370 * @param Contribution $contrib Added contribution
371 *
372 * @return void
373 */
374 private function callPostContributionScript($contrib)
375 {
376 //if an external script has been configured, we call it
377 if ($this->preferences->pref_new_contrib_script) {
378 $es = new \Galette\IO\ExternalScript($this->preferences);
379 $res = $contrib->executePostScript($es);
380
381 if ($res !== true) {
382 //send admin an email with all details
383 if ($this->preferences->pref_mail_method > GaletteMail::METHOD_DISABLED) {
384 $mail = new GaletteMail($this->preferences);
385 $mail->setSubject(
386 _T("Post contribution script failed")
387 );
388
389 $recipients = [];
390 foreach ($this->preferences->vpref_email_newadh as $pref_email) {
391 $recipients[$pref_email] = $pref_email;
392 }
393 $mail->setRecipients($recipients);
394
395 $message = _T("The configured post contribution script has failed.");
396 $message .= "\n" . _T("You can find contribution information and script output below.");
397 $message .= "\n\n";
398 $message .= $res;
399
400 $mail->setMessage($message);
401 $sent = $mail->send();
402
403 if (!$sent) {
404 $txt = _T('Post contribution script has failed.');
405 $this->history->add($txt, $message);
406 $warning_detected[] = $txt;
407 //Mails are disabled... We log (not safe, but)...
408 Analog::log(
409 'Email to admin has not been sent. Here was the data: ' .
410 "\n" . print_r($res, true),
411 Analog::ERROR
412 );
413 }
414 } else {
415 //Mails are disabled... We log (not safe, but)...
416 Analog::log(
417 'Post contribution script has failed. Here was the data: ' .
418 "\n" . print_r($res, true),
419 Analog::ERROR
420 );
421 }
422 }
423 }
424 }
425 }