[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Mail/ -> MailTemplate.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer