1<?php
2/* Copyright (C) 2015-2017 Laurent Destailleur  <eldy@users.sourceforge.net>
3 * Copyright (C) 2018-2021 Nicolas ZABOURI	<info@inovea-conseil.com>
4 * Copyright (C) 2018 	   Juanjo Menent  <jmenent@2byte.es>
5 * Copyright (C) 2019 	   Ferran Marcet  <fmarcet@2byte.es>
6 * Copyright (C) 2019-2021 Frédéric France <frederic.france@netlogic.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * or see https://www.gnu.org/
21 */
22
23/**
24 *    \file            htdocs/core/actions_massactions.inc.php
25 *  \brief            Code for actions done with massaction button (send by email, merge pdf, delete, ...)
26 */
27
28
29// $massaction must be defined
30// $objectclass and $objectlabel must be defined
31// $parameters, $object, $action must be defined for the hook.
32
33// $permissiontoread, $permissiontoadd, $permissiontodelete, $permissiontoclose may be defined
34// $uploaddir may be defined (example to $conf->projet->dir_output."/";)
35// $toselect may be defined
36// $diroutputmassaction may be defined
37
38
39// Protection
40if (empty($objectclass) || empty($uploaddir)) {
41	dol_print_error(null, 'include of actions_massactions.inc.php is done but var $objectclass or $uploaddir was not defined');
42	exit;
43}
44
45// For backward compatibility
46if (!empty($permtoread) && empty($permissiontoread)) {
47	$permissiontoread = $permtoread;
48}
49if (!empty($permtocreate) && empty($permissiontoadd)) {
50	$permissiontoadd = $permtocreate;
51}
52if (!empty($permtodelete) && empty($permissiontodelete)) {
53	$permissiontodelete = $permtodelete;
54}
55
56
57// Mass actions. Controls on number of lines checked.
58$maxformassaction = (empty($conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS) ? 1000 : $conf->global->MAIN_LIMIT_FOR_MASS_ACTIONS);
59if (!empty($massaction) && is_array($toselect) && count($toselect) < 1) {
60	$error++;
61	setEventMessages($langs->trans("NoRecordSelected"), null, "warnings");
62}
63if (!$error && is_array($toselect) && count($toselect) > $maxformassaction) {
64	setEventMessages($langs->trans('TooManyRecordForMassAction', $maxformassaction), null, 'errors');
65	$error++;
66}
67
68if (!$error && $massaction == 'confirm_presend_attendees' && !GETPOST('sendmail')) {  // If we do not choose button send (for example when we change template or limit), we must not send email, but keep on send email form
69	$massaction = 'presend_attendees';
70}
71if (!$error && $massaction == 'confirm_presend_attendees') {
72	$resaction = '';
73	$nbsent = 0;
74	$nbignored = 0;
75	$langs->load("mails");
76	include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
77
78	$listofobjectid = array();
79
80	$listofobjectref = array();
81	$oneemailperrecipient = (GETPOST('oneemailperrecipient') == 'on' ? 1 : 0);
82
83	if (!$error) {
84		require_once DOL_DOCUMENT_ROOT . '/eventorganization/class/conferenceorboothattendee.class.php';
85		$attendee = new ConferenceOrBoothAttendee($db);
86		$listofselectedid = array();
87		$listofselectedref = array();
88		$objecttmp = new $objectclass($db);
89
90		foreach ($toselect as $toselectid) {
91			$result = $objecttmp->fetch($toselectid);
92			if ($result > 0) {
93				$attendees = $attendee->fetchAll('', '', 0, 0, array('t.fk_actioncomm' => $objecttmp->id));
94				if (is_array($attendees) && count($attendees) > 0) {
95					foreach ($attendees as $attmail) {
96						if (!empty($attmail->email)) {
97							$attmail->fetch_thirdparty();
98							$listofselectedid[$attmail->email] = $attmail;
99							$listofselectedref[$attmail->email] = $objecttmp;
100						}
101					}
102				}
103			}
104		}
105	}
106
107	// Check mandatory parameters
108	if (GETPOST('fromtype', 'alpha') === 'user' && empty($user->email)) {
109		$error++;
110		setEventMessages($langs->trans("NoSenderEmailDefined"), null, 'warnings');
111		$massaction = 'presend_attendees';
112	}
113
114	$receiver = $_POST['receiver'];
115	if (!is_array($receiver)) {
116		if (empty($receiver) || $receiver == '-1') {
117			$receiver = array();
118		} else {
119			$receiver = array($receiver);
120		}
121	}
122	if (!trim($_POST['sendto']) && count($receiver) == 0 && count($listofselectedid) == 1) {    // if only one recipient, receiver is mandatory
123		$error++;
124		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Recipient")), null, 'warnings');
125		$massaction = 'presend_attendees';
126	}
127
128	if (!GETPOST('subject', 'restricthtml')) {
129		$error++;
130		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("MailTopic")), null, 'warnings');
131		$massaction = 'presend_attendees';
132	}
133
134	if (!$error) {
135		$objecttmp->fetch_thirdparty();
136		foreach ($listofselectedid as $email => $attendees) {
137			$sendto = '';
138			$sendtocc = '';
139			$sendtobcc = '';
140			$sendtoid = array();
141
142			// Define $sendto
143			$sendto = $attendees->thirdparty->name . '<' . trim($attendees->email) . '>';
144
145			// Define $sendtocc
146			$receivercc = $_POST['receivercc'];
147			if (!is_array($receivercc)) {
148				if ($receivercc == '-1') {
149					$receivercc = array();
150				} else {
151					$receivercc = array($receivercc);
152				}
153			}
154			$tmparray = array();
155			if (trim($_POST['sendtocc'])) {
156				$tmparray[] = trim($_POST['sendtocc']);
157			}
158			$sendtocc = implode(',', $tmparray);
159
160
161			$langs->load("commercial");
162
163			$reg = array();
164			$fromtype = GETPOST('fromtype');
165			if ($fromtype === 'user') {
166				$from = $user->getFullName($langs) . ' <' . $user->email . '>';
167			} elseif ($fromtype === 'company') {
168				$from = $conf->global->MAIN_INFO_SOCIETE_NOM . ' <' . $conf->global->MAIN_INFO_SOCIETE_MAIL . '>';
169			} elseif (preg_match('/user_aliases_(\d+)/', $fromtype, $reg)) {
170				$tmp = explode(',', $user->email_aliases);
171				$from = trim($tmp[($reg[1] - 1)]);
172			} elseif (preg_match('/global_aliases_(\d+)/', $fromtype, $reg)) {
173				$tmp = explode(',', $conf->global->MAIN_INFO_SOCIETE_MAIL_ALIASES);
174				$from = trim($tmp[($reg[1] - 1)]);
175			} elseif (preg_match('/senderprofile_(\d+)_(\d+)/', $fromtype, $reg)) {
176				$sql = 'SELECT rowid, label, email FROM ' . MAIN_DB_PREFIX . 'c_email_senderprofile WHERE rowid = ' . (int) $reg[1];
177				$resql = $db->query($sql);
178				$obj = $db->fetch_object($resql);
179				if ($obj) {
180					$from = $obj->label . ' <' . $obj->email . '>';
181				}
182			} else {
183				$from = $_POST['fromname'] . ' <' . $_POST['frommail'] . '>';
184			}
185
186			$replyto = $from;
187			$subject = GETPOST('subject', 'restricthtml');
188			$message = GETPOST('message', 'restricthtml');
189
190			$sendtobcc = GETPOST('sendtoccc');
191
192			// $objecttmp is a real object or an empty object if we choose to send one email per thirdparty instead of one per object
193			// Make substitution in email content
194			$substitutionarray = getCommonSubstitutionArray($langs, 0, null, $attendees);
195
196			if (!empty($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY)) {
197				$urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
198				$urlwithroot = $urlwithouturlroot . DOL_URL_ROOT;
199				$url_link = $urlwithroot . '/public/agenda/agendaexport.php?format=ical' . ($conf->entity > 1 ? "&entity=" . $conf->entity : "");
200				$url_link .= '&exportkey=' . ($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY ? urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY) : '...');
201				$url_link .= "&project=" . $listofselectedref[$email]->fk_project . '&module=' . urlencode('@eventorganization') . '&status=' . ConferenceOrBooth::STATUS_CONFIRMED;
202				$html_link = '<a href="' . $url_link . '">' . $langs->trans('DownloadICSLink') . '</a>';
203			}
204			$substitutionarray['__EVENTORGANIZATION_ICS_LINK__'] = $html_link;
205			$substitutionarray['__EVENTORGANIZATION_URL_LINK__'] = $url_link;
206			$substitutionarray['__CHECK_READ__'] = '<img src="' . DOL_MAIN_URL_ROOT . '/public/emailing/mailing-read.php?tag=' . urlencode($attendees->thirdparty->tag) . '&securitykey=' . urlencode($conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY) . '" width="1" height="1" style="width:1px;height:1px" border="0"/>';
207
208			$parameters = array('mode' => 'formemail');
209
210			if (!empty($listofobjectref)) {
211				$parameters['listofobjectref'] = $listofobjectref;
212			}
213
214			complete_substitutions_array($substitutionarray, $langs, $attendees, $parameters);
215
216			$subjectreplaced = make_substitutions($subject, $substitutionarray);
217			$messagereplaced = make_substitutions($message, $substitutionarray);
218
219
220			if (empty($sendcontext)) {
221				$sendcontext = 'standard';
222			}
223
224			// Send mail (substitutionarray must be done just before this)
225			require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
226			$mailfile = new CMailFile($subjectreplaced, $sendto, $from, $messagereplaced, array(), array(), array(), $sendtocc, $sendtobcc, $deliveryreceipt, -1, '', '', "attendees_".$attendees->id, '', $sendcontext);
227			if ($mailfile->error) {
228				$resaction .= '<div class="error">' . $mailfile->error . '</div>';
229			} else {
230				$result = $mailfile->sendfile();
231				if ($result) {
232					$resaction .= $langs->trans('MailSuccessfulySent', $mailfile->getValidAddress($from, 2), $mailfile->getValidAddress($sendto, 2)) . '<br>'; // Must not contain "
233					$error = 0;
234
235					dol_syslog("Try to insert email event into agenda for objid=" . $attendees->id . " => objectobj=" . get_class($attendees));
236
237					$actionmsg = $langs->transnoentities('MailSentBy') . ' ' . $from . ' ' . $langs->transnoentities('To') . ' ' . $sendto;
238					if ($message) {
239						if ($sendtocc) {
240							$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc') . ": " . $sendtocc);
241						}
242						$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic') . ": " . $subjectreplaced);
243						$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody') . ":");
244						$actionmsg = dol_concatdesc($actionmsg, $messagereplaced);
245					}
246					$actionmsg2 = '';
247
248					$objectobj2 = $listofselectedref[$email];
249					// Initialisation donnees
250					$objectobj2->actionmsg = $actionmsg; // Long text
251					$objectobj2->actionmsg2 = $actionmsg2; // Short text
252					$objectobj2->fk_element = $objectobj2->id;
253					$objectobj2->elementtype = $objectobj2->element;
254
255					$triggername = 'CONFERENCEORBOOTHATTENDEE_SENTBYMAIL';
256					if (!empty($triggername)) {
257						// Call trigger
258						$result = $objectobj2->call_trigger($triggername, $user);
259						if ($result < 0) {
260							$error++;
261						}
262						// End call triggers
263
264						if ($error) {
265							setEventMessages($db->lasterror(), $objectobj2->errors, 'errors');
266							dol_syslog("Error in trigger " . $triggername . ' ' . $db->lasterror(), LOG_ERR);
267						}
268					}
269
270					$nbsent++; // Nb of object sent
271				} else {
272					$langs->load("other");
273					if ($mailfile->error) {
274						$resaction .= $langs->trans('ErrorFailedToSendMail', $from, $sendto);
275						$resaction .= '<br><div class="error">' . $mailfile->error . '</div>';
276					} elseif (!empty($conf->global->MAIN_DISABLE_ALL_MAILS)) {
277						$resaction .= '<div class="warning">No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS</div>';
278					} else {
279						$resaction .= $langs->trans('ErrorFailedToSendMail', $from, $sendto) . '<br><div class="error">(unhandled error)</div>';
280					}
281				}
282			}
283		}
284	}
285	$resaction .= ($resaction ? '<br>' : $resaction);
286	$resaction .= '<strong>' . $langs->trans("ResultOfMailSending") . ':</strong><br>' . "\n";
287	$resaction .= $langs->trans("NbSelected") . ': ' . count($toselect) . "\n<br>";
288	$resaction .= $langs->trans("NbIgnored") . ': ' . ($nbignored ? $nbignored : 0) . "\n<br>";
289	$resaction .= $langs->trans("NbSent") . ': ' . ($nbsent ? $nbsent : 0) . "\n<br>";
290
291	if ($nbsent) {
292		$action = ''; // Do not show form post if there was at least one successfull sent
293		//setEventMessages($langs->trans("EMailSentToNRecipients", $nbsent.'/'.count($toselect)), null, 'mesgs');
294		setEventMessages($langs->trans("EMailSentForNElements", $nbsent . '/' . count($toselect)), null, 'mesgs');
295		setEventMessages($resaction, null, 'mesgs');
296	} else {
297		//setEventMessages($langs->trans("EMailSentToNRecipients", 0), null, 'warnings');  // May be object has no generated PDF file
298		setEventMessages($resaction, null, 'warnings');
299	}
300
301	$action = 'list';
302	$massaction = '';
303}
304
305
306
307$parameters['toselect'] = $toselect;
308$parameters['uploaddir'] = $uploaddir;
309$parameters['massaction'] = $massaction;
310$parameters['diroutputmassaction'] = isset($diroutputmassaction) ? $diroutputmassaction : null;
311
312$reshook = $hookmanager->executeHooks('doMassActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
313if ($reshook < 0) {
314	setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
315}
316