diff --git a/src/mibew/libs/classes/Mibew/Controller/Chat/MailController.php b/src/mibew/libs/classes/Mibew/Controller/Chat/MailController.php index 306f5528..bfb12e6e 100644 --- a/src/mibew/libs/classes/Mibew/Controller/Chat/MailController.php +++ b/src/mibew/libs/classes/Mibew/Controller/Chat/MailController.php @@ -20,6 +20,7 @@ namespace Mibew\Controller\Chat; use Mibew\Http\Exception\NotFoundException; +use Mibew\Mail\Template as MailTemplate; use Mibew\Mail\Utils as MailUtils; use Mibew\Settings; use Mibew\Thread; @@ -114,23 +115,22 @@ class MailController extends AbstractController } // Load mail templates and substitute placeholders there. - $mail_template = mail_template_load('user_history', get_current_locale()); + $mail_template = MailTemplate::loadByName('user_history', get_current_locale()); if (!$mail_template) { throw new \RuntimeException('Cannot load "user_history" mail template'); } - $body = str_replace( - array('{0}', '{1}', '{2}', '{3}'), - array( + $this->sendMail(MailUtils::buildMessage( + $email, + MIBEW_MAILBOX, + $mail_template->buildSubject(), + $mail_template->buildBody(array( $thread->userName, $history, Settings::get('title'), Settings::get('hosturl'), - ), - $mail_template['body'] - ); - - $this->sendMail(MailUtils::buildMessage($email, MIBEW_MAILBOX, $mail_template['subject'], $body)); + )) + )); $page = setup_logo($group); $page['email'] = $email; diff --git a/src/mibew/libs/classes/Mibew/Controller/MailTemplateController.php b/src/mibew/libs/classes/Mibew/Controller/MailTemplateController.php index e7c0c4f0..89c9878a 100644 --- a/src/mibew/libs/classes/Mibew/Controller/MailTemplateController.php +++ b/src/mibew/libs/classes/Mibew/Controller/MailTemplateController.php @@ -19,6 +19,8 @@ namespace Mibew\Controller; +use Mibew\Http\Exception\NotFoundException; +use Mibew\Mail\Template as MailTemplate; use Symfony\Component\HttpFoundation\Request; /** @@ -84,12 +86,15 @@ class MailTemplateController extends AbstractController 'errors' => $request->attributes->get('errors', array()), ); - $template = $this->loadMailTemplate($template_name, $lang); + $template = MailTemplate::loadByName($template_name, $lang); + if (!$template) { + throw new NotFoundException('The template is not found'); + } // Use values from the request or the default ones if they are not // available. - $page['formsubject'] = $request->request->get('subject', $template['subject']); - $page['formbody'] = $request->request->get('body', $template['body']); + $page['formsubject'] = $request->request->get('subject', $template->subject); + $page['formbody'] = $request->request->get('body', $template->body); $page['formname'] = $template_name; $page['formlang'] = $lang; @@ -140,9 +145,17 @@ class MailTemplateController extends AbstractController return $this->showEditFormAction($request); } - // Save the template and redirect the operator to the page with mail - // templates list. - mail_template_save($name, $lang, $subject, $body); + // Get the instance of mail template that should be modified. + $template = MailTemplate::loadByName($name, $lang, true); + if (!$template) { + // The template cannot be loaded. Create a new one. + $template = new MailTemplate($name, $lang); + } + + $template->subject = $subject; + $template->body = $body; + $template->save(); + $redirect_to = $this->generateUrl( 'mail_templates', array( @@ -184,7 +197,7 @@ class MailTemplateController extends AbstractController */ protected function loadMailTemplate($name, $locale) { - $template = mail_template_load($name, $locale); + $template = MailTemplate::loadByName($name, $locale); if (!$template) { throw new \RuntimeException(sprintf('Cannot load "%s" mail template', $name)); diff --git a/src/mibew/libs/classes/Mibew/Controller/PasswordRecoveryController.php b/src/mibew/libs/classes/Mibew/Controller/PasswordRecoveryController.php index c46b3bb2..e20b806f 100644 --- a/src/mibew/libs/classes/Mibew/Controller/PasswordRecoveryController.php +++ b/src/mibew/libs/classes/Mibew/Controller/PasswordRecoveryController.php @@ -20,6 +20,7 @@ namespace Mibew\Controller; use Mibew\Http\Exception\BadRequestException; +use Mibew\Mail\Template as MailTemplate; use Mibew\Mail\Utils as MailUtils; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -87,18 +88,20 @@ class PasswordRecoveryController extends AbstractController ); // Load mail templates and substitute placeholders there. - $mail_template = mail_template_load('password_recovery', get_current_locale()); + $mail_template = MailTemplate::loadByName('password_recovery', get_current_locale()); if (!$mail_template) { throw new \RuntimeException('Cannot load "password_recovery" mail template'); } - $body = str_replace( - array('{0}', '{1}'), - array(get_operator_name($to_restore), $href), - $mail_template['body'] - ); - - $this->sendMail(MailUtils::buildMessage($email, $email, $mail_template['subject'], $body)); + $this->sendMail(MailUtils::buildMessage( + $email, + $email, + $mail_template->buildSubject(), + $mail_template->buildBody(array( + get_operator_name($to_restore), + $href, + )) + )); $page['isdone'] = true; return $this->render('password_recovery', $page); diff --git a/src/mibew/libs/classes/Mibew/Mail/Template.php b/src/mibew/libs/classes/Mibew/Mail/Template.php new file mode 100644 index 00000000..8f3a2f6e --- /dev/null +++ b/src/mibew/libs/classes/Mibew/Mail/Template.php @@ -0,0 +1,241 @@ +query( + "SELECT * FROM {mailtemplate} WHERE templateid = :id", + array(':id' => $id), + array('return_rows' => Database::RETURN_ONE_ROW) + ); + + // There is no template with such id in database + if (!$template_info) { + return false; + } + + return self::buildFromDbFields($template_info); + } + + /** + * Loads template by its machine name and locale. + * + * @param string $name Name of the template to load. + * @param string $locale Locale of the template to load. + * @param boolean $strict Indicates if only specified locale should be used. + * If the argument is set to false and there is no template for + * specified locale a template for default locale will be loaded. + * @return boolean|Ban Returns a Template instance or boolean false on + * failure. + */ + public static function loadByName($name, $locale, $strict = false) + { + // Try to load the template from the database. + $template_info = Database::getInstance()->query( + "SELECT * FROM {mailtemplate} WHERE name = :name AND locale = :locale", + array( + ':name' => $name, + ':locale' => $locale, + ), + array('return_rows' => Database::RETURN_ONE_ROW) + ); + + if ($template_info) { + // The template exists in the database. + return self::buildFromDbFields($template_info); + } + + if ($strict) { + // There is no appropriate template in the database and we cannot + // use one for default locale. + return false; + } + + // Try to load a template with specified name for the default locale. + if ($locale != get_default_locale()) { + return self::loadByName($name, get_default_locale()); + } + + // There is no template with specified name neither for specified locale + // nor for the default one. + return false; + } + + /** + * Class constructor. + * + * @param string $name Machine name of the template. + * @param string $locale A locale name the template belongs to. + * + * @return Template + */ + public function __construct($name, $locale) + { + // Set default values + $this->id = false; + $this->locale = $locale; + $this->name = $name; + $this->subject = ''; + $this->body = ''; + } + + /** + * Saves the template to database. + */ + public function save() + { + $db = Database::getInstance(); + + if (!$this->id) { + // This template is new. + $db->query( + ('INSERT INTO {mailtemplate} (locale, name, subject, body) ' + . 'VALUES (:locale, :name, :subject, :body)'), + array( + ':locale' => $this->locale, + ':name' => $this->name, + ':subject' => $this->subject, + ':body' => $this->body, + ) + ); + $this->id = $db->insertedId(); + } else { + // Update the existing template + $db->query( + ('UPDATE {mailtemplate} SET locale = :locale, name = :name, ' + . 'subject = :subject, body = :body WHERE templateid = :id'), + array( + ':id' => $this->id, + ':locale' => $this->locale, + ':name' => $this->name, + ':subject' => $this->subject, + ':body' => $this->body, + ) + ); + } + } + + /** + * Builds e-mail subject by replacing all placeholders with specified + * values. + * + * @param array $params List of values that should replace subject's + * placeholders. + * @return string Ready to use e-mail subject. + */ + public function buildSubject($params = array()) + { + $subject = $this->subject; + for ($i = 0; $i < count($params); $i++) { + $subject = str_replace("{" . $i . "}", $params[$i], $subject); + } + + return $subject; + } + + /** + * Builds e-mail body by replacing all placeholders with specified values. + * + * @param array $params List of values that should replace body's + * placeholders. + * @return string Ready to use e-mail body. + */ + public function buildBody($params = array()) + { + $body = $this->body; + for ($i = 0; $i < count($params); $i++) { + $body = str_replace("{" . $i . "}", $params[$i], $body); + } + + return $body; + } + + /** + * Builds and instance of Template based on fields from Database. + * + * @param array $db_fields Associative array of database fields which keys + * are fields names and the values are fields values. + * @return Template + */ + protected static function buildFromDbFields($db_fields) + { + $template = new self($db_fields['name'], $db_fields['locale']); + $template->id = $db_fields['templateid']; + $template->subject = $db_fields['subject']; + $template->body = $db_fields['body']; + + return $template; + } +} diff --git a/src/mibew/libs/classes/Mibew/Mail/Utils.php b/src/mibew/libs/classes/Mibew/Mail/Utils.php index 0b838f00..251efbe4 100644 --- a/src/mibew/libs/classes/Mibew/Mail/Utils.php +++ b/src/mibew/libs/classes/Mibew/Mail/Utils.php @@ -19,6 +19,8 @@ namespace Mibew\Mail; +use Symfony\Component\Yaml\Parser as YamlParser; + /** * Contains a set of utility methods related with emails. */ @@ -47,6 +49,45 @@ class Utils ->setBody(preg_replace("/\n/", "\r\n", $body)); } + /** + * Imports mail templates from a YAML file. + * + * @param string $locale Locale code. + * @param string $file Full path to the file that should be imported. + */ + public static function importTemplates($locale, $file) + { + // Get new mail templates + $parser = new YamlParser(); + $new_templates = $parser->parse(file_get_contents($file)); + if (empty($new_templates)) { + // Nothing to import. + return; + } + + foreach ($new_templates as $name => $template_info) { + // Validate the template + $is_valid_template = is_array($template_info) + && array_key_exists('subject', $template_info) + && array_key_exists('body', $template_info); + if (!$is_valid_template) { + throw new \RuntimeException(sprintf( + 'An invalid mail template "%s" is found in "%s".', + $name, + $file + )); + } + + if (!Template::loadByName($name, $locale, true)) { + // Import only templates that are not already in the database. + $template = new Template($name, $locale); + $template->subject = $template_info['subject']; + $template->body = $template_info['body']; + $template->save(); + } + } + } + /** * This class should not be instantiated */ diff --git a/src/mibew/libs/classes/Mibew/Maintenance/Installer.php b/src/mibew/libs/classes/Mibew/Maintenance/Installer.php index 3243011f..34736fbb 100644 --- a/src/mibew/libs/classes/Mibew/Maintenance/Installer.php +++ b/src/mibew/libs/classes/Mibew/Maintenance/Installer.php @@ -20,6 +20,7 @@ namespace Mibew\Maintenance; use Mibew\Database; +use Mibew\Mail\Utils as MailUtils; use Symfony\Component\Yaml\Parser as YamlParser; /** @@ -731,7 +732,7 @@ class Installer $mail_templates_file = MIBEW_FS_ROOT . '/locales/' . $locale . '/mail_templates.yml'; if (is_readable($mail_templates_file)) { - import_mail_templates($locale, $mail_templates_file); + MailUtils::importTemplates($locale, $mail_templates_file); } // Mark the locale as "enabled" to indicate that all its content diff --git a/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php b/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php index 6cc8d03f..69635860 100644 --- a/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php +++ b/src/mibew/libs/classes/Mibew/RequestProcessor/ThreadProcessor.php @@ -25,6 +25,7 @@ use Mibew\Authentication\AuthenticationManagerInterface; use Mibew\Http\Exception\AccessDeniedException; use Mibew\Mail\MailerFactoryAwareInterface; use Mibew\Mail\MailerFactoryInterface; +use Mibew\Mail\Template as MailTemplate; use Mibew\Mail\Utils as MailUtils; use Mibew\Settings; use Mibew\Thread; @@ -789,25 +790,18 @@ class ThreadProcessor extends ClientSideProcessor implements // Send email if ($inbox_mail) { // Prepare message to send by email - $mail_template = mail_template_load('leave_message', $message_locale); + $mail_template = MailTemplate::loadByName('leave_message', $message_locale); if (!$mail_template) { throw new \RuntimeException('Cannot load "leave_message" mail template'); } - $subject = str_replace( - '{0}', + + $subject = $mail_template->buildSubject(array($args['name'])); + $body = $mail_template->buildBody(array( $args['name'], - $mail_template['subject'] - ); - $body = str_replace( - array('{0}', '{1}', '{2}', '{3}'), - array( - $args['name'], - $email, - $message, - ($info ? $info . "\n" : "") - ), - $mail_template['body'] - ); + $email, + $message, + ($info ? $info . "\n" : ""), + )); // Send $this->getMailerFactory()->getMailer()->send( diff --git a/src/mibew/libs/common/locale.php b/src/mibew/libs/common/locale.php index a176d5bf..eb585123 100644 --- a/src/mibew/libs/common/locale.php +++ b/src/mibew/libs/common/locale.php @@ -18,6 +18,7 @@ */ use Mibew\Database; +use Mibew\Mail\Utils as MailUtils; use Symfony\Component\Translation\Loader\PoFileLoader; /** @@ -969,7 +970,7 @@ function enable_locale($locale) // files. $mail_templates_file = MIBEW_FS_ROOT . '/locales/' . $locale . '/mail_templates.yml'; if (is_readable($mail_templates_file)) { - import_mail_templates($locale, $mail_templates_file); + MailUtils::importTemplates($locale, $mail_templates_file); } } else { // The locale exists in the database. Update it. diff --git a/src/mibew/libs/init.php b/src/mibew/libs/init.php index 77938d41..424b0c4a 100644 --- a/src/mibew/libs/init.php +++ b/src/mibew/libs/init.php @@ -89,7 +89,6 @@ require_once(MIBEW_FS_ROOT . '/libs/captcha.php'); require_once(MIBEW_FS_ROOT . '/libs/chat.php'); require_once(MIBEW_FS_ROOT . '/libs/groups.php'); require_once(MIBEW_FS_ROOT . '/libs/invitation.php'); -require_once(MIBEW_FS_ROOT . '/libs/notify.php'); require_once(MIBEW_FS_ROOT . '/libs/operator.php'); require_once(MIBEW_FS_ROOT . '/libs/pagination.php'); require_once(MIBEW_FS_ROOT . '/libs/statistics.php'); diff --git a/src/mibew/libs/notify.php b/src/mibew/libs/notify.php deleted file mode 100644 index c62eb5cb..00000000 --- a/src/mibew/libs/notify.php +++ /dev/null @@ -1,161 +0,0 @@ -query( - "SELECT * FROM {mailtemplate} WHERE name = :name AND locale = :locale", - array( - ':name' => $name, - ':locale' => $locale, - ), - array( - 'return_rows' => Database::RETURN_ONE_ROW, - ) - ); - - if (!$template) { - if ($strict) { - return false; - } - - // There is no template in the database. - if ($locale == get_default_locale()) { - // The template is still not found. - $template = false; - } else { - // Try to load the template for the default locale. - $template = mail_template_load($name, get_default_locale()); - } - } - - $templates[$locale][$name] = $template; - } - - return $templates[$locale][$name]; -} - -/** - * Saves a mail template to the database. - * - * @param string $name Machine name of the template to save. - * @param string $locale Locale code the template belongs to. - * @param string $subject Localized string that is used as email subject. - * @param string $body Localized string that is used as email body. - */ -function mail_template_save($name, $locale, $subject, $body) -{ - $db = Database::getInstance(); - $template = mail_template_load($name, $locale); - - if ($template && $template['locale'] == $locale) { - // Update existing mail template - $db->query( - ("UPDATE {mailtemplate} " - . "SET subject = :subject, body = :body " - . "WHERE templateid = :id"), - array( - ':id' => $template['templateid'], - ':subject' => $subject, - ':body' => $body, - ) - ); - } else { - // Insert a new mail template - $db->query( - ("INSERT INTO {mailtemplate} (name, locale, subject, body) " - . "VALUES (:name, :locale, :subject, :body)"), - array( - ':name' => $name, - ':locale' => $locale, - ':subject' => $subject, - ':body' => $body, - ) - ); - } -} - -/** - * Import mail templates from a YAML file. - * - * @param string $locale Locale code. - * @param string $file Full path to the file that should be imported. - */ -function import_mail_templates($locale, $file) -{ - // Get new mail templates - $parser = new YamlParser(); - $new_templates = $parser->parse(file_get_contents($file)); - if (empty($new_templates)) { - // Nothing to import. - return; - } - - foreach ($new_templates as $name => $template) { - // Validate the template - $is_valid_template = is_array($template) - && array_key_exists('subject', $template) - && array_key_exists('body', $template); - if (!$is_valid_template) { - throw new \RuntimeException(sprintf( - 'An invalid mail template "%s" is found in "%s".', - $name, - $file - )); - } - - if (!mail_template_load($name, $locale, true)) { - // Import only templates that are not already in the database. - mail_template_save( - $name, - $locale, - $template['subject'], - $template['body'] - ); - } - } -}