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