В компоненте «Подписки» есть проблема в том, что письма приходят только на одном языке, например RU или EN.
Решение направлено на то, чтобы любой пользователь в своем профиле мог выбрать родной язык для уведомлений на email.
Обращаю внимание, что это временное, но рабочее решение. Пока не будет переработан компонент «Подписки».
Тестировалось на 2.16.1
Внесены изменения в 2 системных файла:
/system/controllers/content/hooks/subscription_match_list.php
<?php /** * @property \modelContent $model */ class onContentSubscriptionMatchList extends cmsAction { public $disallow_event_db_register = true; public function run($subscription, $items) { // результирующий список $match_list = []; // тип контента $ctype = $this->model->getContentTypeByName($subscription['subject']); if (!$ctype) { return $match_list; } // формируем id записей $item_ids = []; foreach ($items as $item) { $item_ids[] = $item['id']; } // категория $category = []; // фильтр по связи $relation_filter = ''; // фильтрация по набору параметров // тут может быть и фильтр наборов // и кастомный фильтр $params = []; // Получаем поля для данного типа контента $fields = $this->model->getContentFields($ctype['name']); // фильтры по ячейкам таблицы foreach ($subscription['params']['filters'] as $key => $filters) { // отдельные фильтры по некторым полям // связи $parent_ctype = $this->model->getContentType($filters['value']['parent_ctype_id']); if (!$parent_ctype) { continue; } $_item = $this->model->getContentItem($parent_ctype['name'], $filters['value']['parent_item_id']); if ($_item) { $relation_filter = "r.parent_ctype_id = {$parent_ctype['id']} AND " . "r.parent_item_id = {$_item['id']} AND " . "r.child_ctype_id = {$ctype['id']} AND " . "r.child_item_id = i.id"; } continue; } // категория if ($filters['field'] === 'category_id') { $category = $this->model->getCategory($ctype['name'], $filters['value']); continue; } // проверяем наличие ячеек и заполняем фильтрацию if ($this->model->db->isFieldExists($this->model->table_prefix . $ctype['name'], $filters['field'])) { $params[] = $filters; } } } // Получаем свойства $props = $props_fields = false; $props = $this->model->getContentProps($ctype['name'], $category['id']); if ($props) { $props_fields = $this->getPropsFields($props); } } /** * Начинаем собирать запрос SQL */ $this->model->limit(false); // нам нужны только записи, id которых передали $this->model->filterIn('id', $item_ids); // категория // рекурсивность $is_recursive = true; if (!$ctype['options']['subscriptions_recursive_categories']) { $is_recursive = false; } } $this->model->filterCategory($ctype['name'], $category, $is_recursive, !empty($ctype['options']['is_cats_multi'])); } // фильтр по связям if ($relation_filter) { $this->model->joinInner('content_relations_bind', 'r', $relation_filter); } // фильтр по набору фильтров if ($params) { $this->model->applyDatasetFilters([ 'filters' => $params ], true); } // фильтрация по полям и свойствам foreach ($subscription['params']['field_filters'] as $field_name => $field_value) { $matches = []; // свойства или поля // нет свойств continue; } // нет такого свойства continue; } $this->model->filterPropValue($ctype['name'], [ 'id' => $matches[1], 'handler' => $props_fields[$matches[1]] ], $field_value); } else { // нет такого поля continue; } $fields[$field_name]['handler']->applyFilter($this->model, $field_value); } } } $found_items = $this->model->getContentItems($ctype['name']); if ($found_items) { // Получаем список языков $languages = cmsCore::getLanguages(); foreach ($found_items as $item) { $localized_data = [ 'title' => $item['title'], 'url' => href_to_abs($ctype['name'], $item['slug'] . '.html') ]; foreach ($languages as $lang_code) { $lang_title_field = 'title_' . $lang_code; $localized_data[$lang_title_field] = $item[$lang_title_field]; } $localized_data['url_' . $lang_code] = href_to_abs($lang_code . '/' . $ctype['name'], $item['slug'] . '.html'); } 'image_src' => '', ], $localized_data); } } return $match_list; } }
/system/controllers/subscriptions/hooks/send_letters.php
<?php class onSubscriptionsSendLetters extends cmsAction { public $disallow_event_db_register = true; public function run($attempt, $controller_name, $subject, $items) { // получаем список для контроллера и субъекта // где есть подписчики $subscriptions_list = $this->model->filterEqual('controller', $controller_name)-> filterEqual('subject', $subject)-> filterGt('subscribers_count', 0)-> getSubscriptionsList(); // нет списка, удаляем задачу, возвратив true if (!$subscriptions_list) { return true; } $controller = cmsCore::getController($controller_name); // Опции, если есть $subject_options = $controller->runHook('subscription_options', [$subject], []); // Шаблон письма // Если задан в опциях $letter_text = $subject_options['letter_tpl']; } else { $letter_text = cmsCore::getLanguageTextFile('letters/subscribe_new_item'); } if (!$letter_text) { return false; } // Шаблон уведомления на сайте $notify_text = $subject_options['notify_text']; } else { $notify_text = LANG_SBSCR_PM_NOTIFY; } // Получаем список языков $languages = cmsCore::getLanguages(); $default_lang = cmsConfig::getInstance()->language; $content_model = cmsCore::getModel('content'); foreach ($subscriptions_list as $subscription) { // Проверяем, если это ctype if ($subscription['controller'] == 'content') { $ctype = $content_model->getContentTypeByName($subscription['subject']); // Если есть данные о типе контента // Добавляем названия для каждого языка foreach ($languages as $lang_code) { $lang_field = 'title_' . $lang_code; $subscription[$lang_field] = $ctype[$lang_field]; } } } } // получаем совпадения для подписки $match_list = $controller->runHook('subscription_match_list', [$subscription, $items], false); if (!$match_list) { continue; } // если получили совпадения, рассылаем уведомления // получаем подписчиков $subscribers = $this->model->getNotifiedUsers($subscription['id']); if (!$subscribers) { continue; } $subscribers, $match_list) = cmsEventsManager::hook('notify_subscribers', [ $subscription, $subscribers, $match_list ]); foreach ($subscribers as $user) { $notices_lang = false; if ($user['notify_options']['notices_lang'] !== $default_lang) { $notices_lang = $user['notify_options']['notices_lang']; } } $letter_text = $this->getLanguageTextFileLang('letters/subscribe_new_item', $notices_lang); $subscription_title_lang = !$notices_lang ? 'title' : 'title_'.$notices_lang; $item_title_lang = !$notices_lang ? 'title' : 'title_'.$notices_lang; $item_url_lang = !$notices_lang ? 'url' : 'url_'.$notices_lang; $list_url_lang = !$notices_lang ? '' : $notices_lang.'/'; // полный урл $list_url = rel_to_href($list_url_lang . $subscription['subject_url'], true); // ссылки на новые записи $links = []; foreach ($match_list as $m) { $links[] = '<a href="' . $m[$item_url_lang] . '">' . $m[$item_title_lang] . '</a>'; } // уведомление $this->model_messages->addNotice([$user['id']], [ ]); } $unsubscribe_url = href_to_abs('subscriptions', 'email_unsubscribe', $user['confirm_token']); $to = [ 'email' => $user['email'], 'name' => $user['nickname'], 'email_reply_to' => false, 'name_reply_to' => false, 'custom_headers' => [ 'List-Unsubscribe' => $unsubscribe_url ] ]; $data = [ 'site' => $this->cms_config->sitename, 'date' => html_date(), 'time' => html_time(), 'nickname' => $user['nickname'], 'title' => $subscription[$subscription_title_lang], 'list_url' => $list_url, 'unsubscribe_url' => $unsubscribe_url, 'subjects' => $links ]; $letter = [ 'text' => string_replace_keys_values($letter_text, $data) ]; cmsQueue::pushOn('email', [ 'controller' => 'messages', 'hook' => 'queue_send_email', 'params' => [ $to, $letter, true ] ]); } } } return true; } public static function getLanguageTextFileLang($file, $language) { $default_lang = cmsConfig::getInstance()->language; if(!$language) { $language = $default_lang; } $lang_dir = cmsConfig::get('root_path') . 'system/languages/' . $language; $lang_file = $lang_dir . '/' . $file . '.txt'; return ''; } } }
Добавлен новый файл hook
/system/controllers/subscriptions/hooks/users_profile_notices_form.php
<?php class onSubscriptionsUsersProfileNoticesForm extends cmsAction { public function run($data) { $languages = cmsCore::getLanguages(); $default_lang = cmsConfig::getInstance()->language; $fieldset_id = 0; 'title' => LANG_USERS_EDIT_PROFILE_NOTICES, 'default' => $default_lang, 'items' => $languages ))); } }