Add mail templates functionallity

This commit is contained in:
Dmitriy Simushev 2014-06-17 11:15:44 +00:00
parent d9e41240a4
commit 5193574f68
12 changed files with 601 additions and 23 deletions

View File

@ -125,6 +125,20 @@ $dbtables = array(
"translation" => "text",
),
// Contains localized mail templates
"${mysqlprefix}mailtemplate" => array(
// Artificial primary key
"templateid" => "int NOT NULL auto_increment PRIMARY KEY",
// Locale code a template belongs to
"locale" => "varchar(5) NOT NULL",
// Machine name of a template
"name" => "varchar(256) NOT NULL",
// Mail subject
"subject" => "varchar(1024) NOT NULL",
// Mail body
"body" => "text",
),
// Store chat thread messages
"${mysqlprefix}chatmessage" => array(
// Message ID.

View File

@ -329,6 +329,52 @@ function add_canned_messages($link){
}
}
function add_mail_templates($link){
global $mysqlprefix;
$localesresult = mysql_query("select distinct locale from ${mysqlprefix}mailtemplate", $link);
$existlocales = array();
for ($i = 0; $i < mysql_num_rows($localesresult); $i++) {
$existlocales[] = mysql_result($localesresult, $i, 'locale');
}
$result = array();
foreach (get_available_locales() as $locale) {
if (! in_array($locale, $existlocales)) {
$result[] = array(
'locale' => $locale,
'name' => 'user_history',
'subject' => getlocal('mail.user.history.subject', null, $locale),
'body' => getlocal('mail.user.history.body', null, $locale)
);
$result[] = array(
'locale' => $locale,
'name' => 'password_recovery',
'subject' => getlocal('restore.mailsubj', null, $locale),
'body' => getlocal('restore.mailtext', null, $locale)
);
$result[] = array(
'locale' => $locale,
'name' => 'leave_message',
'subject' => getlocal('leavemail.subject', null, $locale),
'body' => getlocal('leavemail.body', null, $locale)
);
}
}
if (count($result) > 0) {
$updatequery = "insert into ${mysqlprefix}mailtemplate (name,locale,subject,body) values ";
for ($i = 0; $i < count($result); $i++) {
if ($i > 0) {
$updatequery .= ", ";
}
$updatequery .= "('" . mysql_real_escape_string($result[$i]['name'], $link) . "', "
. "'" . mysql_real_escape_string($result[$i]['locale'], $link) . "', "
. "'" . mysql_real_escape_string($result[$i]['subject'], $link) . "', "
. "'" . mysql_real_escape_string($result[$i]['body'], $link) . "')";
}
mysql_query($updatequery, $link);
}
}
function check_status()
{
global $page, $mysqlprefix;
@ -364,6 +410,7 @@ function check_status()
}
add_canned_messages($link);
add_mail_templates($link);
check_sound();

View File

@ -110,20 +110,24 @@ class MailController extends AbstractController
$history .= message_to_text($msg);
}
$subject = getlocal('mail.user.history.subject', null, CURRENT_LOCALE, true);
$body = getlocal(
'mail.user.history.body',
// Load mail templates and substitute placeholders there.
$mail_template = mail_template_load('user_history', CURRENT_LOCALE);
if (!$mail_template) {
throw new \RuntimeException('Cannot load "user_history" mail template');
}
$body = str_replace(
array('{0}', '{1}', '{2}', '{3}'),
array(
$thread->userName,
$history,
Settings::get('title'),
Settings::get('hosturl')
Settings::get('hosturl'),
),
CURRENT_LOCALE,
true
$mail_template['body']
);
mibew_mail($email, MIBEW_MAILBOX, $subject, $body);
mibew_mail($email, MIBEW_MAILBOX, $mail_template['subject'], $body);
$page = setup_logo($group);
$page['email'] = $email;

View File

@ -0,0 +1,218 @@
<?php
/*
* Copyright 2005-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew\Controller;
use Symfony\Component\HttpFoundation\Request;
/**
* Contains actions which are related with mail templates.
*/
class MailTemplateController extends AbstractController
{
/**
* Renders list a of all mail templates which are available in the system.
*
* @param Request $request Incoming request.
* @return Rendered page content.
*/
public function indexAction(Request $request)
{
$operator = $this->getOperator();
$page = array();
// Build list of available locales
$all_locales = get_available_locales();
$locale_names = get_locale_names();
$locales_with_label = array();
foreach ($all_locales as $id) {
$locales_with_label[] = array(
'id' => $id,
'name' => (isset($locale_names[$id]) ? $locale_names[$id] : $id)
);
}
$page['locales'] = $locales_with_label;
// Get selected locale.
$lang = $this->extractLocale($request);
$page['stored'] = $request->query->has('stored');
$page['formaction'] = $this->generateUrl('mail_templates');
$page['mailTemplates'] = $this->getMailTemplatesList($lang);
$page['formlang'] = $lang;
$page['title'] = getlocal('mail_template.title');
$page['menuid'] = 'mail_templates';
$page = array_merge($page, prepare_menu($operator));
return $this->render('mail_templates', $page);
}
/**
* Builds a page with form for mail template settings.
*
* @param Request $request Incoming request.
* @return string Rendered page content.
*/
public function showEditFormAction(Request $request)
{
set_csrf_token();
$operator = $this->getOperator();
$lang = $this->extractLocale($request);
$template_name = $request->attributes->get('name');
$page = array(
// Use errors list stored in the request. We need to do so to have
// an ability to pass the request from the "submitEditForm" action.
'errors' => $request->attributes->get('errors', array()),
);
$template = $this->loadMailTemplate($template_name, $lang);
// 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['formname'] = $template_name;
$page['formlang'] = $lang;
$page['formaction'] = $this->generateUrl(
'mail_template_edit',
array('name' => $template_name)
);
$page['title'] = getlocal('mail_template.title');
$page['menuid'] = 'mail_templates';
$page = array_merge($page, prepare_menu($operator));
return $this->render('mail_template_edit', $page);
}
/**
* Processes submitting of the form which is generated in
* {@link \Mibew\Controller\MailTemplateController::showFormAction()}
* method.
*
* @param Request $request Incoming request.
* @return string Rendered page content.
*/
public function submitEditFormAction(Request $request)
{
csrf_check_token($request);
$name = $request->attributes->get('name');
$lang = $this->extractLocale($request);
$errors = array();
$subject = $request->request->get('subject');
if (!$subject) {
$errors[] = no_field('form.field.mail_template_subject');
}
$body = $request->request->get('body');
if (!$body) {
$errors[] = no_field('form.field.mail_template_body');
}
if (count($errors) != 0) {
// On or more errors took place. We cannot continue the saving
// process. Just attach errors to the request and rerender the edit
// form.
$request->attributes->set('errors', $errors);
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);
$redirect_to = $this->generateUrl(
'mail_templates',
array(
'lang' => $lang,
'stored' => true,
)
);
return $this->redirect($redirect_to);
}
/**
* Builds list of mail templates.
*
* @param string $locale Locale code which will be used for templates
* loading.
* @return array List of mail templates available in the system.
*/
protected function getMailTemplatesList($locale)
{
return array(
$this->loadMailTemplate('user_history', $locale),
$this->loadMailTemplate('password_recovery', $locale),
$this->loadMailTemplate('leave_message', $locale),
);
}
/**
* Loads mail template.
*
* It's just a wrapper for {@link mail_template_load()} function which
* throws an exception if a template cannot be loaded.
*
* @param string $name Machine name of the template
* @param string $locale Locale code which should be used for template
* loading.
* @return array Mail template.
* @throws \RuntimeException If the template cannot be loaded.
*/
protected function loadMailTemplate($name, $locale)
{
$template = mail_template_load($name, $locale);
if (!$template) {
throw new \RuntimeException(sprintf('Cannot load "%s" mail template', $name));
}
return $template;
}
/**
* Extracts locale code from the request.
*
* @param Request $request
* @return string Locale code for the selected locale.
*/
protected function extractLocale(Request $request)
{
$lang = $request->isMethod('POST')
? $request->request->get('lang')
: $request->query->get('lang');
$all_locales = get_available_locales();
$correct_locale = !empty($lang)
&& preg_match("/^[\w-]{2,5}$/", $lang)
&& in_array($lang, $all_locales);
if (!$correct_locale) {
$lang = in_array(CURRENT_LOCALE, $all_locales)
? CURRENT_LOCALE
: $all_locales[0];
}
return $lang;
}
}

View File

@ -90,15 +90,20 @@ class PasswordRecoveryController extends AbstractController
),
UrlGeneratorInterface::ABSOLUTE_URL
);
mibew_mail(
$email,
$email,
getlocal('restore.mailsubj'),
getlocal(
'restore.mailtext',
array(get_operator_name($to_restore), $href)
)
// Load mail templates and substitute placeholders there.
$mail_template = mail_template_load('password_recovery', 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']
);
mibew_mail($email, $email, $mail_template['subject'], $body);
$page['isdone'] = true;
return $this->render('password_recovery', $page);

View File

@ -644,20 +644,24 @@ class ThreadProcessor extends ClientSideProcessor
// Send email
if ($inbox_mail) {
// Prepare message to send by email
$subject = getlocal(
"leavemail.subject",
array($args['name']),
$message_locale
$mail_template = mail_template_load('leave_message', $message_locale);
if (!$mail_template) {
throw new \RuntimeException('Cannot load "leave_message" mail template');
}
$subject = str_replace(
'{0}',
$args['name'],
$mail_template['subject']
);
$body = getlocal(
"leavemail.body",
$body = str_replace(
array('{0}', '{1}', '{2}', '{3}'),
array(
$args['name'],
$email,
$message,
$info ? $info . "\n" : ""
($info ? $info . "\n" : "")
),
$message_locale
$mail_template['body']
);
// Send

View File

@ -15,6 +15,8 @@
* limitations under the License.
*/
use Mibew\Database;
function mibew_mail($to_addr, $reply_to, $subject, $body)
{
$headers = "From: " . MIBEW_MAILBOX . "\r\n"
@ -38,3 +40,96 @@ function mibew_mail($to_addr, $reply_to, $subject, $body)
@ini_set('sendmail_from', $old_from);
}
}
/**
* Loads an email template.
*
* @param string $name Machine name of the template.
* @param string $locale Locale code for the mail template.
* @return array|boolean Associative array with localized mail template data. If
* the template with specified locale is not found a template for default
* locale will be loaded. If the last one does not found too boolean FALSE
* will be returned.
* Mail template array contains the following keys:
* - templateid: int, internale id of the template. It should not be used
* directly.
* - name: string, machine name of the template.
* - locale: string, locale code the templates belongs to.
* - title: string, localized human-readable mail template title.
* - subject: string, localized value which will be used as subject field in
* an email.
* - body: string, localized value which will be used as body in an email.
*/
function mail_template_load($name, $locale)
{
static $templates = array();
if (!isset($templates[$locale][$name])) {
// Try to load the template from the database.
$template = 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) {
// There is no template in the database.
if ($locale == DEFAULT_LOCALE) {
// The template is still not found.
$template = false;
} else {
// Try to load the template for the default locale.
$template = $this->loadMailTemplate($name, 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,
)
);
}
}

View File

@ -343,6 +343,34 @@ logout:
_controller: Mibew\Controller\LogoutController::logoutAction
_access_check: Mibew\AccessControl\Check\LoggedInCheck
## Mail templates
mail_template_edit:
path: /operator/mail-template/{name}/edit
defaults:
_controller: Mibew\Controller\MailTemplateController::showEditFormAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
methods: [GET]
requirements:
name: "[A-Za-z0-9_]+"
mail_template_edit_save:
path: /operator/mail-template/{name}/edit
defaults:
_controller: Mibew\Controller\MailTemplateController::submitEditFormAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
methods: [POST]
requirements:
name: "[A-Za-z0-9_]+"
mail_templates:
path: /operator/mail-template
defaults:
_controller: Mibew\Controller\MailTemplateController::indexAction
_access_check: Mibew\AccessControl\Check\PermissionsCheck
_access_permissions: [CAN_ADMINISTRATE]
## Operators
operator_add:
path: /operator/operator/add

View File

@ -338,6 +338,10 @@ msgid "form.field.mail.description"
msgstr "For notifications and password retrieval."
msgid "form.field.mail"
msgstr "E-mail"
msgid "form.field.mail_template_body"
msgstr "Mail body"
msgid "form.field.mail_template_subject"
msgstr "Mail subject"
msgid "form.field.message"
msgstr "Message"
msgid "form.field.name"
@ -460,6 +464,24 @@ msgid "localedirection"
msgstr "ltr"
msgid "localeid"
msgstr "English (en)"
msgid "mail_template.actions"
msgstr "Modify"
msgid "mail_template.actions.edit"
msgstr "edit"
msgid "mail_template.body"
msgstr "Mail body"
msgid "mail_template.intro"
msgstr "On this page you can edit mail templates which are used in the system."
msgid "mail_template.locale"
msgstr "For language:"
msgid "mail_template.name"
msgstr "Machine name"
msgid "mail_template.saved"
msgstr "Changes saved"
msgid "mail_template.subject"
msgstr "Mail subject"
msgid "mail_template.title"
msgstr "Mail templates"
msgid "mail.user.history.body"
msgstr "Hello {0}!\n\nYour chat history: \n\n{1}\n--- \nRegards,\n{2} and Mibew\n{3}"
msgid "mail.user.history.subject"
@ -488,6 +510,8 @@ msgid "menu.locale.content"
msgstr "Change locale."
msgid "menu.locale"
msgstr "Language"
msgid "menu.mail_templates"
msgstr "Mail templates"
msgid "menu.main"
msgstr "Main"
msgid "menu.operator"

View File

@ -34,6 +34,7 @@
<li{{#ifEqual menuid "settings"}} class="active"{{/ifEqual}}><a href="{{mibewRoot}}/operator/settings">{{l10n "leftMenu.client_settings"}}</a></li>
<li{{#ifEqual menuid "styles"}} class="active"{{/ifEqual}}><a href="{{mibewRoot}}/operator/style/page/preview">{{l10n "menu.styles"}}</a></li>
<li{{#ifEqual menuid "translation"}} class="active"{{/ifEqual}}><a href="{{mibewRoot}}/operator/translation">{{l10n "menu.translate"}}</a></li>
<li{{#ifEqual menuid "mail_templates"}} class="active"{{/ifEqual}}><a href="{{mibewRoot}}/operator/mail-template">{{l10n "menu.mail_templates"}}</a></li>
<li{{#ifEqual menuid "updates"}} class="active"{{/ifEqual}}><a href="{{mibewRoot}}/operator/updates">{{l10n "menu.updates"}}</a></li>
{{/if}}
{{#if currentopid}}

View File

@ -0,0 +1,60 @@
{{#extends "_layout"}}
{{#override "menu"}}{{> _menu}}{{/override}}
{{#override "content"}}
{{l10n "mail_template.intro"}}
<br />
<br />
{{> _errors}}
<form name="mail_template" method="post" action="{{formaction}}">
{{csrfTokenInput}}
<input type="hidden" name="lang" value="{{formlang}}" />
<div>
<div class="mform">
<div class="formtop">
<div class="formtopi"></div>
</div>
<div class="forminner">
<div class="fieldForm">
<div class="field">
<label for="subject" class="flabel">{{l10n "form.field.mail_template_subject"}}<span class="required">*</span></label>
<div class="fvalue">
<input id="subject" type="text" name="subject" size="40" value="{{formsubject}}" class="formauth" />
</div>
<br clear="all"/>
</div>
<div class="field">
<label for="body" class="flabel">{{l10n "form.field.mail_template_body"}}<span class="required">*</span></label>
<div class="fvaluenodesc">
<textarea id="body" name="body" cols="20" rows="5" class="wide">{{formbody}}</textarea>
</div>
<br clear="all"/>
</div>
<div class="fbutton">
<input type="submit" name="save" class="submit-bg-button save-button" value="{{l10n "button.save"}}"/>
</div>
</div>
</div>
<div class="formbottom">
<div class="formbottomi"></div>
</div>
</div>
</div>
<div class="asterisk">
{{l10n "common.asterisk_explanation"}}
</div>
</form>
{{/override}}
{{/extends}}

View File

@ -0,0 +1,78 @@
{{#extends "_layout"}}
{{#override "menu"}}{{> _menu}}{{/override}}
{{#override "content"}}
{{l10n "mail_template.intro"}}
<br />
<br />
{{#if stored}}
<div id="formmessage">{{l10n "mail_template.saved"}}</div>
{{/if}}
{{> _errors}}
<form name="mail_templates" method="get" action="{{formaction}}">
<div>
{{> _tabs}}
<div class="mform">
<div class="formtop">
<div class="formtopi"></div>
</div>
<div class="forminner">
<div class="packedFormField">
{{l10n "mail_template.locale"}}<br/>
<select name="lang" onchange="this.form.submit();">
{{#each locales}}
<option value="{{id}}"{{#ifEqual id ../formlang}} selected="selected"{{/ifEqual}}>{{name}}</option>
{{/each}}
</select>
</div>
<br clear="all"/>
</div>
<div class="formbottom">
<div class="formbottomi"></div>
</div>
</div>
</div>
</form>
<table class="translate">
<thead>
<tr class="header">
<th>{{l10n "mail_template.name"}}</th>
<th>{{l10n "mail_template.subject"}}</th>
<th>{{l10n "mail_template.body"}}</th>
<th>{{l10n "mail_template.actions"}}</th>
</tr>
</thead>
<tbody>
{{#each mailTemplates}}
<tr>
<td>
{{name}}
</td>
<td>
{{subject}}
</td>
<td>
{{body}}
</td>
<td>
<a href="{{../mibewRoot}}/operator/mail-template/{{name}}/edit?lang={{../formlang}}">{{l10n "mail_template.actions.edit"}}</a>
</td>
</tr>
{{/each}}
</tbody>
</table>
{{/override}}
{{/extends}}