Spade

Mini Shell

Directory:~$ /proc/self/root/home/lmsyaran/www/joomla5/libraries/src/Mail/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ //proc/self/root/home/lmsyaran/www/joomla5/libraries/src/Mail/MailTemplate.php

<?php

/**
 * Joomla! Content Management System
 *
 * @copyright  (C) 2019 Open Source Matters, Inc.
<https://www.joomla.org>
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Mail;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Mail\Exception\MailDisabledException;
use Joomla\Database\ParameterType;
use Joomla\Filesystem\Path;
use Joomla\Registry\Registry;
use PHPMailer\PHPMailer\Exception as phpmailerException;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * Email Templating Class
 *
 * @since  4.0.0
 */
class MailTemplate
{
    /**
     * Mailer object to send the actual mail.
     *
     * @var    \Joomla\CMS\Mail\Mail
     * @since  4.0.0
     */
    protected $mailer;

    /**
     * Identifier of the mail template.
     *
     * @var    string
     * @since  4.0.0
     */
    protected $template_id;

    /**
     * Language of the mail template.
     *
     * @var    string
     */
    protected $language;

    /**
     *
     * @var    string[]
     * @since  4.0.0
     */
    protected $data = [];

    /**
     *
     * @var    string[]
     * @since  5.1.0
     */
    protected $plain_data = [];

    /**
     *
     * @var    string[]
     * @since  4.0.0
     */
    protected $attachments = [];

    /**
     * List of recipients of the email
     *
     * @var    \stdClass[]
     * @since  4.0.0
     */
    protected $recipients = [];

    /**
     * Reply To of the email
     *
     * @var    \stdClass
     * @since  4.0.0
     */
    protected $replyto;

    /**
     * Constructor for the mail templating class
     *
     * @param   string  $templateId  Id of the mail template.
     * @param   string  $language    Language of the template to use.
     * @param   Mail    $mailer      Mail object to send the mail with.
     *
     * @since   4.0.0
     */
    public function __construct($templateId, $language, Mail $mailer =
null)
    {
        $this->template_id = $templateId;
        $this->language    = $language;

        if ($mailer) {
            $this->mailer = $mailer;
        } else {
            $this->mailer = Factory::getMailer();
        }
    }

    /**
     * Add an attachment to the mail
     *
     * @param   string  $name  Filename of the attachment
     * @param   string  $file  Either a filepath or filecontent
     *
     * @return  void
     *
     * @since   4.0.0
     */
    public function addAttachment($name, $file)
    {
        $attachment          = new \stdClass();
        $attachment->name    = $name;
        $attachment->file    = $file;
        $this->attachments[] = $attachment;
    }

    /**
     * Adds recipients for this mail
     *
     * @param   string  $mail  Mail address of the recipient
     * @param   string  $name  Name of the recipient
     * @param   string  $type  How should the recipient receive the mail?
('to', 'cc', 'bcc')
     *
     * @return  void
     *
     * @since   4.0.0
     */
    public function addRecipient($mail, $name = null, $type =
'to')
    {
        $recipient          = new \stdClass();
        $recipient->mail    = $mail;
        $recipient->name    = $name ?? $mail;
        $recipient->type    = $type;
        $this->recipients[] = $recipient;
    }

    /**
     * Set reply to for this mail
     *
     * @param   string  $mail  Mail address to reply to
     * @param   string  $name  Name
     *
     * @return  void
     *
     * @since   4.0.0
     */
    public function setReplyTo($mail, $name = '')
    {
        $reply         = new \stdClass();
        $reply->mail   = $mail;
        $reply->name   = $name;
        $this->replyto = $reply;
    }

    /**
     * Add data to replace in the template
     *
     * @param   array  $data  Associative array of strings to replace
     * @param   bool   $plain Only use the data for plain-text emails.
     *
     * @return  void
     *
     * @since   4.0.0
     */
    public function addTemplateData($data, $plain = false)
    {
        if (!$plain) {
            $this->data = array_merge($this->data, $data);
        } else {
            $this->plain_data = array_merge($this->plain_data,
$data);
        }
    }

    /**
     * Render and send the mail
     *
     * @return  boolean  True on success
     *
     * @since   4.0.0
     * @throws  \Exception
     * @throws  MailDisabledException
     * @throws  phpmailerException
     */
    public function send()
    {
        $config = ComponentHelper::getParams('com_mails');

        $mail = self::getTemplate($this->template_id,
$this->language);

        // If the Mail Template was not found in the db, we cannot send an
email.
        if ($mail === null) {
            return false;
        }

        /** @var Registry $params */
        $params      = $mail->params;
        $app         = Factory::getApplication();
        $replyTo     = $app->get('replyto', '');
        $replyToName = $app->get('replytoname', '');

        if ((int) $config->get('alternative_mailconfig', 0)
=== 1 && (int) $params->get('alternative_mailconfig',
0) === 1) {
            if ($this->mailer->Mailer === 'smtp' ||
$params->get('mailer') === 'smtp') {
                $smtpauth   = ($params->get('smtpauth',
$app->get('smtpauth')) == 0) ? null : 1;
                $smtpuser   = $params->get('smtpuser',
$app->get('smtpuser'));
                $smtppass   = $params->get('smtppass',
$app->get('smtppass'));
                $smtphost   = $params->get('smtphost',
$app->get('smtphost'));
                $smtpsecure = $params->get('smtpsecure',
$app->get('smtpsecure'));
                $smtpport   = $params->get('smtpport',
$app->get('smtpport'));
                $this->mailer->useSmtp($smtpauth, $smtphost,
$smtpuser, $smtppass, $smtpsecure, $smtpport);
            }

            if ($params->get('mailer') ===
'sendmail') {
                $this->mailer->isSendmail();
            }

            $mailfrom = $params->get('mailfrom',
$app->get('mailfrom'));
            $fromname = $params->get('fromname',
$app->get('fromname'));

            if (MailHelper::isEmailAddress($mailfrom)) {
               
$this->mailer->setFrom(MailHelper::cleanLine($mailfrom),
MailHelper::cleanLine($fromname), false);
            }

            $replyTo     = $params->get('replyto', $replyTo);
            $replyToName = $params->get('replytoname',
$replyToName);
        }

        $app->triggerEvent('onMailBeforeRendering',
[$this->template_id, &$this]);

        $subject = $this->replaceTags(Text::_($mail->subject),
$this->data);
        $this->mailer->setSubject($subject);

        $mailStyle = $config->get('mail_style',
'plaintext');
        // Use the plain-text replacement data, if specified.
        $plainData = $this->plain_data ?: $this->data;
        $plainBody = $this->replaceTags(Text::_($mail->body),
$plainData);
        $htmlBody  = $this->replaceTags(Text::_($mail->htmlbody),
$this->data);

        if ($mailStyle === 'plaintext' || $mailStyle ===
'both') {
            // If the Plain template is empty try to convert the HTML
template to a Plain text
            if (!$plainBody) {
                $plainBody =
strip_tags(str_replace(['<br>', '<br />',
'<br/>'], "\n", $htmlBody));
            }

            $this->mailer->setBody($plainBody);

            // Set alt body, use $mailer->Body directly because it was
filtered by $mailer->setBody()
            if ($mailStyle === 'both') {
                $this->mailer->AltBody = $this->mailer->Body;
            }
        }

        if ($mailStyle === 'html' || $mailStyle ===
'both') {
            $this->mailer->isHtml(true);

            // If HTML body is empty try to convert the Plain template to
html
            if (!$htmlBody) {
                $htmlBody = nl2br($plainBody, false);
            }

            $htmlBody =
MailHelper::convertRelativeToAbsoluteUrls($htmlBody);

            $this->mailer->setBody($htmlBody);
        }

        if ($config->get('copy_mails') &&
$params->get('copyto')) {
           
$this->mailer->addBcc($params->get('copyto'));
        }

        foreach ($this->recipients as $recipient) {
            switch ($recipient->type) {
                case 'cc':
                    $this->mailer->addCc($recipient->mail,
$recipient->name);
                    break;
                case 'bcc':
                    $this->mailer->addBcc($recipient->mail,
$recipient->name);
                    break;
                case 'to':
                default:
                    $this->mailer->addAddress($recipient->mail,
$recipient->name);
            }
        }

        if ($this->replyto) {
            $this->mailer->addReplyTo($this->replyto->mail,
$this->replyto->name);
        } elseif ($replyTo) {
            $this->mailer->addReplyTo($replyTo, $replyToName);
        }

        if (trim($config->get('attachment_folder',
''))) {
            $folderPath = rtrim(Path::check(JPATH_ROOT . '/' .
$config->get('attachment_folder')), \DIRECTORY_SEPARATOR);

            if ($folderPath && $folderPath !==
Path::clean(JPATH_ROOT) && is_dir($folderPath)) {
                foreach ((array) json_decode($mail->attachments) as
$attachment) {
                    $filePath = Path::check($folderPath . '/' .
$attachment->file);

                    if (is_file($filePath)) {
                        $this->mailer->addAttachment($filePath,
$this->getAttachmentName($filePath, $attachment->name));
                    }
                }
            }
        }

        foreach ($this->attachments as $attachment) {
            if (is_file($attachment->file)) {
                $this->mailer->addAttachment($attachment->file,
$this->getAttachmentName($attachment->file, $attachment->name));
            } else {
               
$this->mailer->addStringAttachment($attachment->file,
$attachment->name);
            }
        }

        return $this->mailer->Send();
    }

    /**
     * Replace tags with their values recursively
     *
     * @param   string  $text  The template to process
     * @param   array   $tags  An associative array to replace in the
template
     *
     * @return  string  Rendered mail template
     *
     * @since   4.0.0
     */
    protected function replaceTags($text, $tags)
    {
        foreach ($tags as $key => $value) {
            // If the value is NULL, replace with an empty string. NULL
itself throws notices
            if (\is_null($value)) {
                $value = '';
            }

            if (\is_array($value)) {
                $matches = [];
                $pregKey = preg_quote(strtoupper($key), '/');

                if (preg_match_all('/{' . $pregKey .
'}(.*?){\/' . $pregKey . '}/s', $text, $matches)) {
                    foreach ($matches[0] as $i => $match) {
                        $replacement = '';

                        foreach ($value as $name => $subvalue) {
                            if (\is_array($subvalue) && $name ==
$matches[1][$i]) {
                                $replacement .= implode("\n",
$subvalue);
                            } elseif (\is_array($subvalue)) {
                                $replacement .=
$this->replaceTags($matches[1][$i], $subvalue);
                            } elseif (\is_string($subvalue) &&
$name == $matches[1][$i]) {
                                $replacement .= $subvalue;
                            }
                        }

                        $text = str_replace($match, $replacement, $text);
                    }
                }
            } else {
                $text = str_replace('{' . strtoupper($key) .
'}', $value, $text);
            }
        }

        return $text;
    }

    /**
     * Get a specific mail template
     *
     * @param   string  $key       Template identifier
     * @param   string  $language  Language code of the template
     *
     * @return  object|null  An object with the data of the mail, or null
if the template not found in the db.
     *
     * @since   4.0.0
     */
    public static function getTemplate($key, $language)
    {
        $db    = Factory::getDbo();
        $query = $db->getQuery(true);
        $query->select('*')
            ->from($db->quoteName('#__mail_templates'))
            ->where($db->quoteName('template_id') . '
= :key')
            ->whereIn($db->quoteName('language'),
['', $language], ParameterType::STRING)
            ->order($db->quoteName('language') . '
DESC')
            ->bind(':key', $key);
        $db->setQuery($query);
        $mail = $db->loadObject();

        if ($mail) {
            $mail->params = new Registry($mail->params);
        }

        return $mail;
    }

    /**
     * Insert a new mail template into the system
     *
     * @param   string  $key       Mail template key
     * @param   string  $subject   A default subject (normally a
translatable string)
     * @param   string  $body      A default body (normally a translatable
string)
     * @param   array   $tags      Associative array of tags to replace
     * @param   string  $htmlbody  A default htmlbody (normally a
translatable string)
     *
     * @return  boolean  True on success, false on failure
     *
     * @since   4.0.0
     */
    public static function createTemplate($key, $subject, $body, $tags,
$htmlbody = '')
    {
        $db = Factory::getDbo();

        $template              = new \stdClass();
        $template->template_id = $key;
        $template->language    = '';
        $template->subject     = $subject;
        $template->body        = $body;
        $template->htmlbody    = $htmlbody;
        $template->extension   = explode('.', $key, 2)[0] ??
'';
        $template->attachments = '';
        $params                = new \stdClass();
        $params->tags          = (array) $tags;
        $template->params      = json_encode($params);

        return $db->insertObject('#__mail_templates',
$template);
    }

    /**
     * Update an existing mail template
     *
     * @param   string  $key       Mail template key
     * @param   string  $subject   A default subject (normally a
translatable string)
     * @param   string  $body      A default body (normally a translatable
string)
     * @param   array   $tags      Associative array of tags to replace
     * @param   string  $htmlbody  A default htmlbody (normally a
translatable string)
     *
     * @return  boolean  True on success, false on failure
     *
     * @since   4.0.0
     */
    public static function updateTemplate($key, $subject, $body, $tags,
$htmlbody = '')
    {
        $db = Factory::getDbo();

        $template              = new \stdClass();
        $template->template_id = $key;
        $template->language    = '';
        $template->subject     = $subject;
        $template->body        = $body;
        $template->htmlbody    = $htmlbody;
        $params                = new \stdClass();
        $params->tags          = (array) $tags;
        $template->params      = json_encode($params);

        return $db->updateObject('#__mail_templates',
$template, ['template_id', 'language']);
    }

    /**
     * Method to delete a mail template
     *
     * @param   string  $key  The key of the mail template
     *
     * @return  boolean  True on success, false on failure
     *
     * @since   4.0.0
     */
    public static function deleteTemplate($key)
    {
        $db    = Factory::getDbo();
        $query = $db->getQuery(true);
        $query->delete($db->quoteName('#__mail_templates'))
            ->where($db->quoteName('template_id') . '
= :key')
            ->bind(':key', $key);
        $db->setQuery($query);

        return $db->execute();
    }

    /**
     * Check and if necessary fix the file name of an attachment so that
the attached file
     * has the same extension as the source file, and not a different file
extension
     *
     * @param   string  $file  Path to the file to be attached
     * @param   string  $name  The file name to be used for the attachment
     *
     * @return  string  The corrected file name for the attachment
     *
     * @since   4.0.0
     */
    protected function getAttachmentName(string $file, string $name):
string
    {
        // If no name is given, do not process it further
        if (!trim($name)) {
            return '';
        }

        // Replace any placeholders.
        $name = $this->replaceTags($name, $this->data);

        // Get the file extension.
        $ext = File::getExt($file);

        // Strip off extension from $name and append extension of $file, if
any
        return File::stripExt($name) . ($ext ? '.' . $ext :
'');
    }
}