В этой публикации мы расскажем о том, как среднестатистический ведущий программист ImageCMS Андрюша реализовал удобную систему e-mail-оповещений пользователей Интернет-магазина. Сам он теперь утверждает, что не программист, а фея.
В чем заключалась проблема до реализации нового функционала?
Немало огорчало, что отправка e-mail пользователям не имела централизованного места управления, ведь это создавало определенные неудобства администратору и наличие множества лишнего кода, который дублировался.
Смотрим-с:
/**
* Send email to user.
*
* @param SOrders $order
* @return bool
*/
protected function _sendMail(SOrders $order)
{
//Check setting to send message
if (ShopCore::app()->SSettings->ordersSendMessage == 'false')
return;
//Array of parameters to send
$replaceData = array(
'%userName%' => $order->getUserFullName(),
'%userEmail%' => $order->getUserEmail(),
'%userPhone%' => $order->getUserPhone(),
'%userDeliver%' => $order->getUserDeliverTo(),
'%orderId%' => $order->getId(),
'%orderKey%' => $order->getKey(),
'%orderLink%' => shop_url('cart/view/' . $order->getKey()),
);
//Use function encode for every element from $replaceData
$replaceData = array_map('encode', $replaceData);
//Get settings for sending
$fromEmail = ShopCore::app()->SSettings->ordersSenderEmail;
$shopName = ShopCore::app()->SSettings->ordersSenderName;
$theme = ShopCore::app()->SSettings->ordersMessageTheme;
//Formating message
$message = str_replace(array_keys($replaceData), $replaceData, ShopCore::app()->SSettings->ordersMessageText);
//Load CodeIgniter Email library
$this->load->library('email');
$config['mailtype'] = ShopCore::app()->SSettings->ordersMessageFormat;
//Initialize library configurations
$this->email->initialize($config);
//Sending message
$this->email->from($fromEmail, $shopName);
$this->email->to($order->getUserEmail());
$this->email->subject($theme);
$this->email->message($message);
$this->email->send();
}
protected function _sendNewMail(SOrders $order)
{
//Check setting to send message
if (ShopCore::app()->SSettings->ordersSendMessage == 'false')
return;
//Array of parameters to send
$replaceData['variables'] = array(
'%userName%' => $order->getUserFullName(),
'%userEmail%' => $order->getUserEmail(),
'%userPhone%' => $order->getUserPhone(),
'%userDeliver%' => $order->getUserDeliverTo(),
'%orderId%' => $order->getId(),
'%orderKey%' => $order->getKey(),
'%orderLink%' => shop_url('cart/view/' . $order->getKey()),
);
$replaceData['to'] = $order->getUserEmail();
//Load CodeIgniter Email library
$this->load->library('email');
//Sending message
$this->email->sendMail('toUserOrderNotification', $replaceData);
}
Что предпринял Андрюша?
Для централизации всей системы создания и отправки оповещений, Фея написал отдельный модуль. Изначально вместе с модулем идет 6 интегрированных в систему шаблонов, наиболее часто используемых в работе сайта:
- регистрация пользователя;
- восстановление пароля;
- изменение пароля;
- уведомление покупателя о совершении заказа;
- смена статуса заказа;
- уведомление о появлении.
Были применены неймспейсы, что позволяет вызывать метод с любого места:
namespace cmsemailclasses;
Главное препятствие на пути к достижению цели Андрея заключалось далеко не в количестве кода, а именно в необходимости найти все места в коде, где идет отправка e-mail, и заменить их новым методом. Наш герой не отчаивался… Фея заткнул уши группой Korn и абстрагировал обработку всей логики отправки писем пользователю и администратору в небольшой метод, что можно увидеть на следующем полотне.
Смотрим-с:
//Creatind link to check for administrator
$checkLink = site_url() . "admin/components/run/shop/orders/createPdf/" . trim($order->getId());
//Array of parameters to send
$emailData = array(
'userName' => $order->user_full_name,
'userEmail' => $order->user_email,
'userPhone' => $order->user_phone,
'userDeliver' => $order->user_deliver_to,
'orderLink' => shop_url('cart/view/' . $order->key),
'products' => $productsForEmail,
'deliveryPrice' => $deliveryPrice,
'checkLink' => $checkLink,
);
//Sending emeils
cmsemailemail::getInstance()->sendEmail($order->user_email, 'make_order', $emailData);
Так этот метод выглядит внутри:
/**
* send email
*
* @param string $send_to - recepient email
* @param string $patern_name - email patern name
* @param array $variables - variables to raplase in message:
* $variables = array('$user$' => 'UserName')
* @return bool
*/
public function sendEmail($send_to, $patern_name, $variables)
{
//loading CodeIgniter Email library
$this->load->library('email');
//Getting settings
$patern_settings = $this->cmsemail_model->getPaternSettings($patern_name);
$default_settings = $this->cmsemail_model->getSettings();
//Prepare settings into correct array for initialize library
if ($patern_settings)
{
foreach ($patern_settings as $key => $value)
{
if (!$value)
{
if ($default_settings[$key])
{
$patern_settings[$key] = $default_settings[$key];
}
}
}
}
$default_settings['type'] = strtolower($patern_settings['type']);
//Initializing library settings
$this->_set_config($patern_settings);
//Sending user email if active in options
if ($patern_settings['user_message_active'])
{
$this->from_email = $patern_settings['from_email'];
$this->from = $patern_settings['from'];
$this->send_to = $send_to;
$this->theme = $patern_settings['theme'];
$this->message = $this->replaceVariables($patern_settings['user_message'], $variables);
if (!$this->_sendEmail())
{
$this->errors[] = lang('User message doesnt send', 'cmsemail');
}
else
{
//Registering event if success
CMSFactoryEvents::create()->registerEvent(
array(
'from' => $this->from,
'from_email' => $this->from_email,
'send_to' => $this->send_to,
'theme' => $this->theme,
'message' => $this->message
), 'ParentEmail:userSend');
CMSFactoryEvents::runFactory();
}
}
//Sending administrator email if active in options
if ($patern_settings['admin_message_active'])
{
$this->from_email = $patern_settings['from_email'];
$this->from = $patern_settings['from'];
if ($patern_settings['admin_email'])
{
$this->send_to = $patern_settings['admin_email'];
}
else
{
$this->send_to = $default_settings['admin_email'];
}
$this->theme = $patern_settings['theme'];
$this->message = $this->replaceVariables($patern_settings['admin_message'], $variables);
if (!$this->_sendEmail())
{
$this->errors[] = lang('User message doesnt send', 'cmsemail');
}
else
{
//Registering event if success
CMSFactoryEvents::create()->registerEvent(
array(
'from' => $this->from,
'from_email' => $this->from_email,
'send_to' => $this->send_to,
'theme' => $this->theme,
'message' => $this->message
), 'ParentEmail:adminSend');
CMSFactoryEvents::runFactory();
}
}
//Returning status
if ($this->errors)
{
return FALSE;
}
else
{
return TRUE;
}
}
Так среднестатистический ведущий программист сделал централизацию всей системы оповещения пользователей. Кода стало меньше, он стал изящнее, управление оповещениями — проще.
Какие проблемы решает данный функционал?
Обновленная система оповещений, локализованная в едином интерфейсе, значительно упрощает работу, особенно неопытному пользователю, поскольку весь функционал собран в администраторской панели ImageCMS.
На следующем скриншоте изображена панель приборов настройки шаблонов писем, которое получает пользователь и администратор.
Пример настройки письма пользователю о сделанном заказе
Пример настройки письма администратору магазина о сделанном заказе.
Можно ли создавать свои шаблоны уведомлений?
Более опытные юзеры ImageCMS Shop могут создавать собственные шаблоны оповещений, а также интегрировать их в систему. Гибкая система настроек позволяет варьировать компоненты отправки в разных комбинациях. Каждое оповещение имеет свои отдельные настройки адреса отправки, данных об отправителе, e-mail-адресе администратора и теме письма. Также имеются стандартные настройки, и если необязательные поля не заполнены, то данные будут взяты именно оттуда.
Для еще большего удобства администратора предусмотрена проверка на сервере возможности отправки оповещения. Отправитель будет уверен в том, что получатель уведомлен о событии:
Автор: AndrCho