[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Mail; 11 12 use Joomla\CMS\Component\ComponentHelper; 13 use Joomla\CMS\Factory; 14 use Joomla\CMS\Filesystem\File; 15 use Joomla\CMS\Filesystem\Path; 16 use Joomla\CMS\Language\Text; 17 use Joomla\CMS\Mail\Exception\MailDisabledException; 18 use Joomla\Database\ParameterType; 19 use Joomla\Registry\Registry; 20 use PHPMailer\PHPMailer\Exception as phpmailerException; 21 22 // phpcs:disable PSR1.Files.SideEffects 23 \defined('JPATH_PLATFORM') or die; 24 // phpcs:enable PSR1.Files.SideEffects 25 26 /** 27 * Email Templating Class 28 * 29 * @since 4.0.0 30 */ 31 class MailTemplate 32 { 33 /** 34 * Mailer object to send the actual mail. 35 * 36 * @var \Joomla\CMS\Mail\Mail 37 * @since 4.0.0 38 */ 39 protected $mailer; 40 41 /** 42 * Identifier of the mail template. 43 * 44 * @var string 45 * @since 4.0.0 46 */ 47 protected $template_id; 48 49 /** 50 * Language of the mail template. 51 * 52 * @var string 53 */ 54 protected $language; 55 56 /** 57 * 58 * @var string[] 59 * @since 4.0.0 60 */ 61 protected $data = array(); 62 63 /** 64 * 65 * @var string[] 66 * @since 4.0.0 67 */ 68 protected $attachments = array(); 69 70 /** 71 * List of recipients of the email 72 * 73 * @var \stdClass[] 74 * @since 4.0.0 75 */ 76 protected $recipients = array(); 77 78 /** 79 * Reply To of the email 80 * 81 * @var \stdClass 82 * @since 4.0.0 83 */ 84 protected $replyto; 85 86 /** 87 * Constructor for the mail templating class 88 * 89 * @param string $templateId Id of the mail template. 90 * @param string $language Language of the template to use. 91 * @param Mail $mailer Mail object to send the mail with. 92 * 93 * @since 4.0.0 94 */ 95 public function __construct($templateId, $language, Mail $mailer = null) 96 { 97 $this->template_id = $templateId; 98 $this->language = $language; 99 100 if ($mailer) { 101 $this->mailer = $mailer; 102 } else { 103 $this->mailer = Factory::getMailer(); 104 } 105 } 106 107 /** 108 * Add an attachment to the mail 109 * 110 * @param string $name Filename of the attachment 111 * @param string $file Either a filepath or filecontent 112 * 113 * @return void 114 * 115 * @since 4.0.0 116 */ 117 public function addAttachment($name, $file) 118 { 119 $attachment = new \stdClass(); 120 $attachment->name = $name; 121 $attachment->file = $file; 122 $this->attachments[] = $attachment; 123 } 124 125 /** 126 * Adds recipients for this mail 127 * 128 * @param string $mail Mail address of the recipient 129 * @param string $name Name of the recipient 130 * @param string $type How should the recipient receive the mail? ('to', 'cc', 'bcc') 131 * 132 * @return void 133 * 134 * @since 4.0.0 135 */ 136 public function addRecipient($mail, $name = null, $type = 'to') 137 { 138 $recipient = new \stdClass(); 139 $recipient->mail = $mail; 140 $recipient->name = $name ?? $mail; 141 $recipient->type = $type; 142 $this->recipients[] = $recipient; 143 } 144 145 /** 146 * Set reply to for this mail 147 * 148 * @param string $mail Mail address to reply to 149 * @param string $name Name 150 * 151 * @return void 152 * 153 * @since 4.0.0 154 */ 155 public function setReplyTo($mail, $name = '') 156 { 157 $reply = new \stdClass(); 158 $reply->mail = $mail; 159 $reply->name = $name; 160 $this->replyto = $reply; 161 } 162 163 /** 164 * Add data to replace in the template 165 * 166 * @param array $data Associative array of strings to replace 167 * 168 * @return void 169 * 170 * @since 4.0.0 171 */ 172 public function addTemplateData($data) 173 { 174 $this->data = array_merge($this->data, $data); 175 } 176 177 /** 178 * Render and send the mail 179 * 180 * @return boolean True on success 181 * 182 * @since 4.0.0 183 * @throws \Exception 184 * @throws MailDisabledException 185 * @throws phpmailerException 186 */ 187 public function send() 188 { 189 $config = ComponentHelper::getParams('com_mails'); 190 191 $mail = self::getTemplate($this->template_id, $this->language); 192 193 // If the Mail Template was not found in the db, we cannot send an email. 194 if ($mail === null) { 195 return false; 196 } 197 198 /** @var Registry $params */ 199 $params = $mail->params; 200 $app = Factory::getApplication(); 201 202 if ((int) $config->get('alternative_mailconfig', 0) === 1 && (int) $params->get('alternative_mailconfig', 0) === 1) { 203 if ($this->mailer->Mailer === 'smtp' || $params->get('mailer') === 'smtp') { 204 $smtpauth = ($params->get('smtpauth', $app->get('smtpauth')) == 0) ? null : 1; 205 $smtpuser = $params->get('smtpuser', $app->get('smtpuser')); 206 $smtppass = $params->get('smtppass', $app->get('smtppass')); 207 $smtphost = $params->get('smtphost', $app->get('smtphost')); 208 $smtpsecure = $params->get('smtpsecure', $app->get('smtpsecure')); 209 $smtpport = $params->get('smtpport', $app->get('smtpport')); 210 $this->mailer->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); 211 } 212 213 if ($params->get('mailer') === 'sendmail') { 214 $this->mailer->isSendmail(); 215 } 216 217 $mailfrom = $params->get('mailfrom', $app->get('mailfrom')); 218 $fromname = $params->get('fromname', $app->get('fromname')); 219 220 if (MailHelper::isEmailAddress($mailfrom)) { 221 $this->mailer->setFrom(MailHelper::cleanLine($mailfrom), MailHelper::cleanLine($fromname), false); 222 } 223 } 224 225 $app->triggerEvent('onMailBeforeRendering', array($this->template_id, &$this)); 226 227 $subject = $this->replaceTags(Text::_($mail->subject), $this->data); 228 $this->mailer->setSubject($subject); 229 230 $mailStyle = $config->get('mail_style', 'plaintext'); 231 $plainBody = $this->replaceTags(Text::_($mail->body), $this->data); 232 $htmlBody = $this->replaceTags(Text::_($mail->htmlbody), $this->data); 233 234 if ($mailStyle === 'plaintext' || $mailStyle === 'both') { 235 // If the Plain template is empty try to convert the HTML template to a Plain text 236 if (!$plainBody) { 237 $plainBody = strip_tags(str_replace(['<br>', '<br />', '<br/>'], "\n", $htmlBody)); 238 } 239 240 $this->mailer->setBody($plainBody); 241 242 // Set alt body, use $mailer->Body directly because it was filtered by $mailer->setBody() 243 if ($mailStyle === 'both') { 244 $this->mailer->AltBody = $this->mailer->Body; 245 } 246 } 247 248 if ($mailStyle === 'html' || $mailStyle === 'both') { 249 $this->mailer->isHtml(true); 250 251 // If HTML body is empty try to convert the Plain template to html 252 if (!$htmlBody) { 253 $htmlBody = nl2br($plainBody, false); 254 } 255 256 $htmlBody = MailHelper::convertRelativeToAbsoluteUrls($htmlBody); 257 258 $this->mailer->setBody($htmlBody); 259 } 260 261 if ($config->get('copy_mails') && $params->get('copyto')) { 262 $this->mailer->addBcc($params->get('copyto')); 263 } 264 265 foreach ($this->recipients as $recipient) { 266 switch ($recipient->type) { 267 case 'cc': 268 $this->mailer->addCc($recipient->mail, $recipient->name); 269 break; 270 case 'bcc': 271 $this->mailer->addBcc($recipient->mail, $recipient->name); 272 break; 273 case 'to': 274 default: 275 $this->mailer->addAddress($recipient->mail, $recipient->name); 276 } 277 } 278 279 if ($this->replyto) { 280 $this->mailer->addReplyTo($this->replyto->mail, $this->replyto->name); 281 } 282 283 if (trim($config->get('attachment_folder', ''))) { 284 $folderPath = rtrim(Path::check(JPATH_ROOT . '/' . $config->get('attachment_folder')), \DIRECTORY_SEPARATOR); 285 286 if ($folderPath && $folderPath !== Path::clean(JPATH_ROOT) && is_dir($folderPath)) { 287 foreach ((array) json_decode($mail->attachments) as $attachment) { 288 $filePath = Path::check($folderPath . '/' . $attachment->file); 289 290 if (is_file($filePath)) { 291 $this->mailer->addAttachment($filePath, $this->getAttachmentName($filePath, $attachment->name)); 292 } 293 } 294 } 295 } 296 297 foreach ($this->attachments as $attachment) { 298 if (is_file($attachment->file)) { 299 $this->mailer->addAttachment($attachment->file, $this->getAttachmentName($attachment->file, $attachment->name)); 300 } else { 301 $this->mailer->addStringAttachment($attachment->file, $attachment->name); 302 } 303 } 304 305 return $this->mailer->Send(); 306 } 307 308 /** 309 * Replace tags with their values recursively 310 * 311 * @param string $text The template to process 312 * @param array $tags An associative array to replace in the template 313 * 314 * @return string Rendered mail template 315 * 316 * @since 4.0.0 317 */ 318 protected function replaceTags($text, $tags) 319 { 320 foreach ($tags as $key => $value) { 321 if (is_array($value)) { 322 $matches = array(); 323 324 if (preg_match_all('/{' . strtoupper($key) . '}(.*?){\/' . strtoupper($key) . '}/s', $text, $matches)) { 325 foreach ($matches[0] as $i => $match) { 326 $replacement = ''; 327 328 foreach ($value as $subvalue) { 329 if (is_array($subvalue)) { 330 $replacement .= $this->replaceTags($matches[1][$i], $subvalue); 331 } 332 } 333 334 $text = str_replace($match, $replacement, $text); 335 } 336 } 337 } else { 338 $text = str_replace('{' . strtoupper($key) . '}', $value, $text); 339 } 340 } 341 342 return $text; 343 } 344 345 /** 346 * Get a specific mail template 347 * 348 * @param string $key Template identifier 349 * @param string $language Language code of the template 350 * 351 * @return object|null An object with the data of the mail, or null if the template not found in the db. 352 * 353 * @since 4.0.0 354 */ 355 public static function getTemplate($key, $language) 356 { 357 $db = Factory::getDbo(); 358 $query = $db->getQuery(true); 359 $query->select('*') 360 ->from($db->quoteName('#__mail_templates')) 361 ->where($db->quoteName('template_id') . ' = :key') 362 ->whereIn($db->quoteName('language'), ['', $language], ParameterType::STRING) 363 ->order($db->quoteName('language') . ' DESC') 364 ->bind(':key', $key); 365 $db->setQuery($query); 366 $mail = $db->loadObject(); 367 368 if ($mail) { 369 $mail->params = new Registry($mail->params); 370 } 371 372 return $mail; 373 } 374 375 /** 376 * Insert a new mail template into the system 377 * 378 * @param string $key Mail template key 379 * @param string $subject A default subject (normally a translatable string) 380 * @param string $body A default body (normally a translatable string) 381 * @param array $tags Associative array of tags to replace 382 * @param string $htmlbody A default htmlbody (normally a translatable string) 383 * 384 * @return boolean True on success, false on failure 385 * 386 * @since 4.0.0 387 */ 388 public static function createTemplate($key, $subject, $body, $tags, $htmlbody = '') 389 { 390 $db = Factory::getDbo(); 391 392 $template = new \stdClass(); 393 $template->template_id = $key; 394 $template->language = ''; 395 $template->subject = $subject; 396 $template->body = $body; 397 $template->htmlbody = $htmlbody; 398 $template->attachments = ''; 399 $params = new \stdClass(); 400 $params->tags = array($tags); 401 $template->params = json_encode($params); 402 403 return $db->insertObject('#__mail_templates', $template); 404 } 405 406 /** 407 * Update an existing mail template 408 * 409 * @param string $key Mail template key 410 * @param string $subject A default subject (normally a translatable string) 411 * @param string $body A default body (normally a translatable string) 412 * @param array $tags Associative array of tags to replace 413 * @param string $htmlbody A default htmlbody (normally a translatable string) 414 * 415 * @return boolean True on success, false on failure 416 * 417 * @since 4.0.0 418 */ 419 public static function updateTemplate($key, $subject, $body, $tags, $htmlbody = '') 420 { 421 $db = Factory::getDbo(); 422 423 $template = new \stdClass(); 424 $template->template_id = $key; 425 $template->language = ''; 426 $template->subject = $subject; 427 $template->body = $body; 428 $template->htmlbody = $htmlbody; 429 $params = new \stdClass(); 430 $params->tags = array($tags); 431 $template->params = json_encode($params); 432 433 return $db->updateObject('#__mail_templates', $template, ['template_id', 'language']); 434 } 435 436 /** 437 * Method to delete a mail template 438 * 439 * @param string $key The key of the mail template 440 * 441 * @return boolean True on success, false on failure 442 * 443 * @since 4.0.0 444 */ 445 public static function deleteTemplate($key) 446 { 447 $db = Factory::getDbo(); 448 $query = $db->getQuery(true); 449 $query->delete($db->quoteName('#__mail_templates')) 450 ->where($db->quoteName('template_id') . ' = :key') 451 ->bind(':key', $key); 452 $db->setQuery($query); 453 454 return $db->execute(); 455 } 456 457 /** 458 * Check and if necessary fix the file name of an attachment so that the attached file 459 * has the same extension as the source file, and not a different file extension 460 * 461 * @param string $file Path to the file to be attached 462 * @param string $name The file name to be used for the attachment 463 * 464 * @return string The corrected file name for the attachment 465 * 466 * @since 4.0.0 467 */ 468 protected function getAttachmentName(string $file, string $name): string 469 { 470 // If no name is given, do not process it further 471 if (!trim($name)) { 472 return ''; 473 } 474 475 // Replace any placeholders. 476 $name = $this->replaceTags($name, $this->data); 477 478 // Get the file extension. 479 $ext = File::getExt($file); 480 481 // Strip off extension from $name and append extension of $file, if any 482 return File::stripExt($name) . ($ext ? '.' . $ext : ''); 483 } 484 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |