Шаблон email письма о новых записях ТК на языке пользователя

+4
99
Шаблон email письма о новых записях ТК на языке пользователя

В компоненте «Подписки» есть проблема в том, что письма приходят только на одном языке, например RU или EN.

Решение направлено на то, чтобы любой пользователь в своем профиле мог выбрать родной язык для уведомлений на email.

Обращаю внимание, что это временное, но рабочее решение. Пока не будет переработан компонент «Подписки».

Тестировалось на 2.16.1

Изображение
Изображение
Изображение

Внесены изменения в 2 системных файла:

/system/controllers/content/hooks/subscription_match_list.php

  1. <?php
  2. /**
  3.  * @property \modelContent $model
  4.  */
  5. class onContentSubscriptionMatchList extends cmsAction {
  6.  
  7. public $disallow_event_db_register = true;
  8.  
  9. public function run($subscription, $items) {
  10.  
  11. // результирующий список
  12. $match_list = [];
  13.  
  14. // тип контента
  15. $ctype = $this->model->getContentTypeByName($subscription['subject']);
  16. if (!$ctype) {
  17. return $match_list;
  18. }
  19.  
  20. // формируем id записей
  21. $item_ids = [];
  22. foreach ($items as $item) {
  23. $item_ids[] = $item['id'];
  24. }
  25.  
  26. // категория
  27. $category = [];
  28.  
  29. // фильтр по связи
  30. $relation_filter = '';
  31.  
  32. // фильтрация по набору параметров
  33. // тут может быть и фильтр наборов
  34. // и кастомный фильтр
  35. $params = [];
  36.  
  37. // Получаем поля для данного типа контента
  38. $fields = $this->model->getContentFields($ctype['name']);
  39.  
  40. // фильтры по ячейкам таблицы
  41. if (!empty($subscription['params']['filters'])) {
  42.  
  43. foreach ($subscription['params']['filters'] as $key => $filters) {
  44.  
  45. // отдельные фильтры по некторым полям
  46. // связи
  47. if ($filters['field'] === 'relation' && !empty($filters['value']['parent_ctype_id'])) {
  48.  
  49. $parent_ctype = $this->model->getContentType($filters['value']['parent_ctype_id']);
  50. if (!$parent_ctype) {
  51. continue;
  52. }
  53.  
  54. $_item = $this->model->getContentItem($parent_ctype['name'], $filters['value']['parent_item_id']);
  55.  
  56. if ($_item) {
  57. $relation_filter = "r.parent_ctype_id = {$parent_ctype['id']} AND " .
  58. "r.parent_item_id = {$_item['id']} AND " .
  59. "r.child_ctype_id = {$ctype['id']} AND " .
  60. "r.child_item_id = i.id";
  61. }
  62.  
  63. continue;
  64. }
  65. // категория
  66. if ($filters['field'] === 'category_id') {
  67.  
  68. $category = $this->model->getCategory($ctype['name'], $filters['value']);
  69.  
  70. continue;
  71. }
  72.  
  73. // проверяем наличие ячеек и заполняем фильтрацию
  74. if ($this->model->db->isFieldExists($this->model->table_prefix . $ctype['name'], $filters['field'])) {
  75. $params[] = $filters;
  76. }
  77. }
  78. }
  79.  
  80. // Получаем свойства
  81. $props = $props_fields = false;
  82. if (!empty($category['id']) && $category['id'] > 1) {
  83. $props = $this->model->getContentProps($ctype['name'], $category['id']);
  84. if ($props) {
  85. $props_fields = $this->getPropsFields($props);
  86. }
  87. }
  88.  
  89. /**
  90.   * Начинаем собирать запрос SQL
  91.   */
  92. $this->model->limit(false);
  93.  
  94. // нам нужны только записи, id которых передали
  95. $this->model->filterIn('id', $item_ids);
  96.  
  97. // категория
  98. if (!empty($category['id']) && $category['id'] > 1) {
  99.  
  100. // рекурсивность
  101. $is_recursive = true;
  102. if (array_key_exists('subscriptions_recursive_categories', $ctype['options'])) {
  103. if (!$ctype['options']['subscriptions_recursive_categories']) {
  104. $is_recursive = false;
  105. }
  106. }
  107.  
  108. $this->model->filterCategory($ctype['name'], $category, $is_recursive, !empty($ctype['options']['is_cats_multi']));
  109. }
  110.  
  111. // фильтр по связям
  112. if ($relation_filter) {
  113. $this->model->joinInner('content_relations_bind', 'r', $relation_filter);
  114. }
  115.  
  116. // фильтр по набору фильтров
  117. if ($params) {
  118. $this->model->applyDatasetFilters([
  119. 'filters' => $params
  120. ], true);
  121. }
  122.  
  123. // фильтрация по полям и свойствам
  124. if (!empty($subscription['params']['field_filters'])) {
  125.  
  126. foreach ($subscription['params']['field_filters'] as $field_name => $field_value) {
  127.  
  128. $matches = [];
  129.  
  130. // свойства или поля
  131. if (preg_match('/^p([0-9]+)$/i', $field_name, $matches)) {
  132.  
  133. // нет свойств
  134. if (!is_array($props)) {
  135. continue;
  136. }
  137.  
  138. // нет такого свойства
  139. if (!isset($props_fields[$matches[1]])) {
  140. continue;
  141. }
  142.  
  143. $this->model->filterPropValue($ctype['name'], [
  144. 'id' => $matches[1],
  145. 'handler' => $props_fields[$matches[1]]
  146. ], $field_value);
  147.  
  148. } else {
  149.  
  150. // нет такого поля
  151. if (!isset($fields[$field_name])) {
  152. continue;
  153. }
  154.  
  155. $fields[$field_name]['handler']->applyFilter($this->model, $field_value);
  156. }
  157. }
  158. }
  159.  
  160. $found_items = $this->model->getContentItems($ctype['name']);
  161.  
  162. if ($found_items) {
  163.  
  164. // Получаем список языков
  165. $languages = cmsCore::getLanguages();
  166.  
  167. foreach ($found_items as $item) {
  168. $localized_data = [
  169. 'title' => $item['title'],
  170. 'url' => href_to_abs($ctype['name'], $item['slug'] . '.html')
  171. ];
  172.  
  173. foreach ($languages as $lang_code) {
  174. $lang_title_field = 'title_' . $lang_code;
  175. if (!empty($item[$lang_title_field])) {
  176. $localized_data[$lang_title_field] = $item[$lang_title_field];
  177. }
  178. $localized_data['url_' . $lang_code] = href_to_abs($lang_code . '/' . $ctype['name'], $item['slug'] . '.html');
  179. }
  180.  
  181. $match_list[] = array_merge([
  182. 'image_src' => '',
  183. ], $localized_data);
  184.  
  185. }
  186.  
  187. }
  188.  
  189. return $match_list;
  190. }
  191.  
  192. }
  193.  

/system/controllers/subscriptions/hooks/send_letters.php

  1. <?php
  2.  
  3. class onSubscriptionsSendLetters extends cmsAction {
  4.  
  5. public $disallow_event_db_register = true;
  6.  
  7. public function run($attempt, $controller_name, $subject, $items) {
  8.  
  9. // получаем список для контроллера и субъекта
  10. // где есть подписчики
  11. $subscriptions_list = $this->model->filterEqual('controller', $controller_name)->
  12. filterEqual('subject', $subject)->
  13. filterGt('subscribers_count', 0)->
  14. getSubscriptionsList();
  15.  
  16. // нет списка, удаляем задачу, возвратив true
  17. if (!$subscriptions_list) {
  18. return true;
  19. }
  20.  
  21. $controller = cmsCore::getController($controller_name);
  22.  
  23. // Опции, если есть
  24. $subject_options = $controller->runHook('subscription_options', [$subject], []);
  25.  
  26. // Шаблон письма
  27. // Если задан в опциях
  28. if(!empty($subject_options['letter_tpl'])){
  29. $letter_text = $subject_options['letter_tpl'];
  30. } else {
  31. $letter_text = cmsCore::getLanguageTextFile('letters/subscribe_new_item');
  32. }
  33.  
  34. if (!$letter_text) {
  35. return false;
  36. }
  37.  
  38. // Шаблон уведомления на сайте
  39. if(!empty($subject_options['notify_text'])){
  40. $notify_text = $subject_options['notify_text'];
  41. } else {
  42. $notify_text = LANG_SBSCR_PM_NOTIFY;
  43. }
  44.  
  45. // Получаем список языков
  46. $languages = cmsCore::getLanguages();
  47. $default_lang = cmsConfig::getInstance()->language;
  48.  
  49. $content_model = cmsCore::getModel('content');
  50.  
  51. foreach ($subscriptions_list as $subscription) {
  52.  
  53. // Проверяем, если это ctype
  54. if ($subscription['controller'] == 'content') {
  55. $ctype = $content_model->getContentTypeByName($subscription['subject']);
  56.  
  57. // Если есть данные о типе контента
  58. if (!empty($ctype)) {
  59. // Добавляем названия для каждого языка
  60. foreach ($languages as $lang_code) {
  61. $lang_field = 'title_' . $lang_code;
  62. if (!empty($ctype[$lang_field])) {
  63. $subscription[$lang_field] = $ctype[$lang_field];
  64. }
  65. }
  66. }
  67. }
  68.  
  69. // получаем совпадения для подписки
  70. $match_list = $controller->runHook('subscription_match_list', [$subscription, $items], false);
  71. if (!$match_list) {
  72. continue;
  73. }
  74.  
  75. // если получили совпадения, рассылаем уведомления
  76. // получаем подписчиков
  77. $subscribers = $this->model->getNotifiedUsers($subscription['id']);
  78.  
  79. if (!$subscribers) {
  80. continue;
  81. }
  82.  
  83. list($subscription,
  84. $subscribers,
  85. $match_list) = cmsEventsManager::hook('notify_subscribers', [
  86. $subscription,
  87. $subscribers,
  88. $match_list
  89. ]);
  90.  
  91. foreach ($subscribers as $user) {
  92.  
  93. $notices_lang = false;
  94.  
  95. if (!empty($user['notify_options']['notices_lang'])) {
  96. if ($user['notify_options']['notices_lang'] !== $default_lang) {
  97. $notices_lang = $user['notify_options']['notices_lang'];
  98. }
  99. }
  100.  
  101. $letter_text = $this->getLanguageTextFileLang('letters/subscribe_new_item', $notices_lang);
  102.  
  103. $subscription_title_lang = !$notices_lang ? 'title' : 'title_'.$notices_lang;
  104. $item_title_lang = !$notices_lang ? 'title' : 'title_'.$notices_lang;
  105. $item_url_lang = !$notices_lang ? 'url' : 'url_'.$notices_lang;
  106. $list_url_lang = !$notices_lang ? '' : $notices_lang.'/';
  107.  
  108. // полный урл
  109. $list_url = rel_to_href($list_url_lang . $subscription['subject_url'], true);
  110.  
  111. // ссылки на новые записи
  112. $links = [];
  113.  
  114. foreach ($match_list as $m) {
  115. $links[] = '<a href="' . $m[$item_url_lang] . '">' . $m[$item_title_lang] . '</a>';
  116. }
  117.  
  118. $links = implode(', ', $links);
  119.  
  120. // уведомление
  121. if (in_array($user['notify_options']['subscriptions'], ['pm', 'both'])) {
  122.  
  123. $this->model_messages->addNotice([$user['id']], [
  124. 'content' => sprintf($notify_text, $list_url, $subscription[$subscription_title_lang], $links)
  125. ]);
  126. }
  127.  
  128. // email
  129. if (in_array($user['notify_options']['subscriptions'], ['email', 'both'])) {
  130.  
  131. $unsubscribe_url = href_to_abs('subscriptions', 'email_unsubscribe', $user['confirm_token']);
  132.  
  133. $to = [
  134. 'email' => $user['email'],
  135. 'name' => $user['nickname'],
  136. 'email_reply_to' => false,
  137. 'name_reply_to' => false,
  138. 'custom_headers' => [
  139. 'List-Unsubscribe' => $unsubscribe_url
  140. ]
  141. ];
  142.  
  143. $data = [
  144. 'site' => $this->cms_config->sitename,
  145. 'date' => html_date(),
  146. 'time' => html_time(),
  147. 'nickname' => $user['nickname'],
  148. 'title' => $subscription[$subscription_title_lang],
  149. 'list_url' => $list_url,
  150. 'unsubscribe_url' => $unsubscribe_url,
  151. 'subjects' => $links
  152. ];
  153.  
  154. $letter = [
  155. 'text' => string_replace_keys_values($letter_text, $data)
  156. ];
  157.  
  158. cmsQueue::pushOn('email', [
  159. 'controller' => 'messages',
  160. 'hook' => 'queue_send_email',
  161. 'params' => [
  162. $to, $letter, true
  163. ]
  164. ]);
  165. }
  166. }
  167. }
  168.  
  169. return true;
  170. }
  171.  
  172. public static function getLanguageTextFileLang($file, $language) {
  173.  
  174. $default_lang = cmsConfig::getInstance()->language;
  175.  
  176. if(!$language) {
  177. $language = $default_lang;
  178. }
  179.  
  180. $lang_dir = cmsConfig::get('root_path') . 'system/languages/' . $language;
  181.  
  182. $lang_file = $lang_dir . '/' . $file . '.txt';
  183.  
  184. if (!file_exists($lang_file)) {
  185. return '';
  186. }
  187.  
  188. return file_get_contents($lang_file);
  189. }
  190.  
  191. }
  192.  

Добавлен новый файл hook

/system/controllers/subscriptions/hooks/users_profile_notices_form.php

  1. <?php
  2.  
  3. class onSubscriptionsUsersProfileNoticesForm extends cmsAction {
  4.  
  5. public function run($data) {
  6.  
  7. list($form, $profile, $options) = $data;
  8.  
  9. $languages = cmsCore::getLanguages();
  10. $languages = array_combine($languages, $languages);
  11.  
  12. $default_lang = cmsConfig::getInstance()->language;
  13.  
  14. $fieldset_id = 0;
  15.  
  16. $form->addField($fieldset_id, new fieldList('notices_lang', array(
  17. 'title' => LANG_USERS_EDIT_PROFILE_NOTICES,
  18. 'default' => $default_lang,
  19. 'items' => $languages
  20. )));
  21.  
  22. return array($form, $profile, $options);
  23.  
  24. }
  25.  
  26. }
  27.  
Нет комментариев. Ваш будет первым!

Еще от автора

Новогодние скидки 20 _ 24% на дополнения!
Встречайте Новый год с выгодой! Скидка 24% на плагины — ваш идеальный шанс украсить праздничный сезон дополнительными возможностями.
Аудиоплеер для контента
Аудиоплеер позволяет проигрывать аудиофайлы в списке записей типа контента, а также в самой записи -Фиксация плеера при прокрутке страницы -загрузка и
Платные Группы (Сообщества)
Компонент позволяет вступать в Группы(Сообщества) на платной основе и на определенный период времени Варианты применения: 1.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.