Создание уведомлений в расширениях
- Внести изменения в services.yml, добавив сервис нового типа уведомления. Наименование сервиса должно иметь формат (начиная с phpBB 3.1.0-RC4, в более ранних версиях часть <vendor>.<extension>. не разрешалась) а его определение должно включать в себя обязательный тег
Код: Выделить всё
<vendor>.<extension>.notification.type.something
Например:Код: Выделить всё
tags: - { name: notification.type }
Код: Выделить всё
gfksx.ThanksForPosts.notification.type.thanks: class: gfksx\ThanksForPosts\notification\thanks scope: prototype # scope MUST be prototype for this to work! arguments: - @user_loader - @dbal.conn - @cache.driver - @user - @auth - @config - %core.root_path% - %core.php_ext% - %tables.notification_types% - %tables.notifications% - %tables.user_notifications% tags: - { name: notification.type }
- Создать файл нового типа уведомления. Файлы должны располагаться в папке ext/<vendor>/<ext_name>/notification.
В данном случае, файл называется thanks.php. Объявленный в файле уведомления класс расширяет базовый класс уведомлений \phpbb\notification\type\base. Пример:Файл содержит ряд свойств и функций, необходимых для создания уведомления:Код: Выделить всё
/** * Thanks for posts notifications class * This class handles notifying users when they have been thanked for a post */ class thanks extends \phpbb\notification\type\base {
- Функция, возвращающая тип уведомления, в данном случае это 'thanks' - по имени файла и класса уведомления.
Код: Выделить всё
public function get_type() { return 'thanks'; }
- Свойство, определяющее языковую переменную для создания уведомления - protected $language_key.
и сама переменная
Код: Выделить всё
protected $language_key = 'NOTIFICATION_THANKS';
Код: Выделить всё
'NOTIFICATION_THANKS' => '<strong>Благодарность</strong> от пользователя %1$s за сообщение:',
- Свойство, определяющее место настройки нового уведомления на странице настроек уведомлений в личном разделе - public static $notification_option. Используются ключи 'id', 'lang', и 'group'.
Удобство представляет использование двух последних ключей, которые имеют следующий смысл:
'group' - группа настроек, в которой будет расположена настройка нового расширения, представляет из себя ключ соответствующей имени этой группы языковой переменной. Например:значение которойКод: Выделить всё
'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS',
'lang' - непосредственно заголовок (имя) новой настройки. Например:Код: Выделить всё
'NOTIFICATION_GROUP_MISCELLANEOUS' => 'Прочие уведомления',
значение которой будетКод: Выделить всё
'lang' => 'NOTIFICATION_TYPE_THANKS',
Конечный результат:Код: Выделить всё
'NOTIFICATION_TYPE_THANKS' => 'Вас поблагодарили за сообщение',
Код: Выделить всё
public static $notification_option = array( 'lang' => 'NOTIFICATION_TYPE_THANKS', 'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS', );
- Функция, определяющая условия, при которых данное уведомление доступно. В случае, если оно доступно всегда:
Код: Выделить всё
public function is_available() { return true; }
- Функция, возвращающая идентификатор основного элемента item_id. Оно будет записано в поле item_id таблицы уведомлений в БД. Обратите внимание, что если уведомление с данным item_id уже имеется, другие уведомления с тем же Item_id добавлены не будут. Пример:
В данном случае, за основной идентификатор выбран id сообщения, за которое выдана благодарность. В общем случае, может быть выбрано любое целое значение (идентификатор любого имеющего для контекста смысл элемента, задействованного в коде, где будет обрабатываться создание уведомления).
Код: Выделить всё
/** * Get the id of the item * * @param array $thanks_data The data from the thank */ public static function get_item_id($thanks_data) { return (int) $thanks_data['post_id']; }
- Функция, возвращающая идентификатор родительского элемента, по отношению к item_id - item_parent_id. Например, идентификатор темы по отношению к идентификатору сообщения в данной теме, и т.п. Пример:
Код: Выделить всё
/** * Get the id of the parent * * @param array $thanks_data The data from the thank */ public static function get_item_parent_id($thanks_data) { return (int) $thanks_data['topic_id']; }
- Функция, отбирающая массив с идентификаторами пользователей, которым должно поступить уведомление. Массив должен быть передан функции check_user_notification_options() для формирования данных о видах уведомлений, которые должны быть направлены пользователям из данного списка. Пример:
В общем случае, не имеет значение, каким образом получен массив идентификаторов пользователей - всё зависит от конкретных обстоятельств, учитываемых в работе расширения. Например, идентификаторы могут быть отобраны по определенным условиям из базы данных.
Код: Выделить всё
/** * Find the users who want to receive notifications * * @param array $thanks_data The data from the thank * @param array $options Options for finding users for notification * * @return array */ public function find_users_for_notification($thanks_data, $options = array()) { $options = array_merge(array( 'ignore_users' => array(), ), $options); $users = array((int) $thanks_data['poster_id']); return $this->check_user_notification_options($users, $options); }
- Функция, возвращающая аватар пользователя. Пример:
В данном случае для получения идентификатора пользователя использован метод get_data(). Обратите внимание, что данный метод предназначен для получения данных, предварительно записанных в БД через метод create_insert_array() (см. ниже). Т.е. определенный необходимый для уведомления набор данных должен быть сохранен в БД (в сериализованном виде).
Код: Выделить всё
/** * Get the user's avatar */ public function get_avatar() { return $this->user_loader->get_avatar($this->get_data('user_id')); }
- Функция, создающая заголовок уведомления - например, "Получена благодарность от пользователя rxu за сообщение:", после которого может следовать заголовок сообщения, за которое получена благодарность (создание последнего будет пояснено ниже). Пример:
Обратите внимание, что здесь использовано описанное выше свойство $language_key - языковая переменная класса.
Код: Выделить всё
/** * Get the HTML formatted title of this notification * * @return string */ public function get_title() { $username = $this->user_loader->get_username($this->get_data('user_id'), 'no_profile'); return $this->user->lang($this->language_key . '_' . $this->get_data('lang_act'), $username); }
- Функция, возвращающая список идентификаторов пользователей (user_id) для последующей загрузки в класс данных указанных пользователей, необходимых для работы уведомления. Загрузка происходит при помощи класса user_loader(). Пример:
Код: Выделить всё
/** * Users needed to query before this notification can be displayed * * @return array Array of user_ids */ public function users_to_query() { $thankers = $this->get_data('thankers'); $users = array( $this->get_data('user_id'), ); if (is_array($thankers)) { foreach ($thankers as $thanker) { $users[] = $thanker['user_id']; } } return $users; }
- Функция, формирующая ссылку для перехода при клике на уведомлении. Пример:
Код: Выделить всё
/** * Get the url to this item * * @return string URL */ public function get_url() { return append_sid($this->phpbb_root_path . 'viewtopic.' . $this->php_ext, "p={$this->item_id}#p{$this->item_id}"); }
- Функция, возвращающая ссылку для использования при клике на уведомление. Использует выше описанный метод get_url(). Пример:
Код: Выделить всё
public function get_redirect_url() { return $this->get_url(); }
- Функция, определяющая шаблон email для отправки уведомления. Пример:
Код: Выделить всё
/** * Get email template * * @return string|bool */ public function get_email_template() { return '@gfksx_ThanksForPosts/user_thanks'; }
- Функция, возвращающая строку, расположенную под заголовком уведомления (например, после "Получена благодарность от пользователя rxu за сообщение:"), например, заголовок темы или сообщения. В результате получается конструкция вида Получена благодарность от пользователя rxu за сообщение: "Re: Test TFP notifications".
В данном случае "Re: Test TFP notifications" - результат работы этой функции. Пример:Код: Выделить всё
/** * Get the HTML formatted reference of the notification * * @return string */ public function get_reference() { return $this->user->lang( 'NOTIFICATION_REFERENCE', censor_text($this->get_data('post_subject')) ); }
- Функция, возвращающая массив для присвоения значений переменным шаблона email. Пример:
Об использовании шаблонов email в расширениях см. тему viewtopic.php?f=5&t=73
Код: Выделить всё
/** * Get email template variables * * @return array */ public function get_email_template_variables() { $user_data = $this->user_loader->get_user($this->get_data('poster_id')); return array( 'THANKS_SUBG' => htmlspecialchars_decode($this->user->lang['GRATITUDES']), 'USERNAME' => htmlspecialchars_decode($this->user->data['username']), 'POST_THANKS' => htmlspecialchars_decode($this->user->lang['THANKS_PM_MES_'. $this->get_data('lang_act')]), 'U_POST_THANKS' => generate_board_url() . '/viewtopic.' . $this->php_ext . "?p={$this->item_id}#p{$this->item_id}", ); }
- Функция, предназначенная для записи в БД в (в сериализованном виде) регулярно необходимых для вывода уведомления данных. перечень таких данных определяется исходя из конкретных обстоятельств, но обязательно должны записываться значения, получаемые методом get_data()/ Пример:
Код: Выделить всё
/** * Function for preparing the data for insertion in an SQL query * (The service handles insertion) * * @param array $thanks_data Data from insert_thanks * @param array $pre_create_data Data from pre_create_insert_array() * * @return array Array of data ready to be inserted into the database */ public function create_insert_array($thanks_data, $pre_create_data = array()) { $this->set_data('user_id', $thanks_data['user_id']); $this->set_data('post_id', $thanks_data['post_id']); $this->set_data('lang_act', $thanks_data['lang_act']); $this->set_data('post_subject', $thanks_data['post_subject']); return parent::create_insert_array($thanks_data, $pre_create_data); }
- Свойство в виде массива, содержащее необходимые данные для создания уведомления, в т.ч. и те, которые должны быть записаны в БД, передается во внешнем скрипте как параметр функции add_notifications(). В ланном конкретном примере - это массив $thanks_data. Пример:
Код: Выделить всё
$thanks_data = array( 'user_id' => (int) $this->user->data['user_id'], 'post_id' => $post_id, 'poster_id' => $to_id, 'topic_id' => (int) $row['topic_id'], 'forum_id' => (int) $row['forum_id'], 'thanks_time' => time(), 'username' => $this->user->data['username'], 'lang_act' => $lang_act, 'post_subject' => $row['post_subject'], );
- Функция, возвращающая тип уведомления, в данном случае это 'thanks' - по имени файла и класса уведомления.
- Обработать создание уведомления во внешнем скрипте. Пример:
Очевидно, что для этого сначала необходимо сделать инжекцию зависимости класса менеджера уведомлений.
Код: Выделить всё
$thanks_data = array( 'user_id' => (int) $this->user->data['user_id'], 'post_id' => $post_id, 'poster_id' => $to_id, 'topic_id' => (int) $row['topic_id'], 'forum_id' => (int) $row['forum_id'], 'thanks_time' => time(), 'username' => $this->user->data['username'], 'lang_act' => $lang_act, 'post_subject' => $row['post_subject'], ); $this->notification_manager->add_notifications(array( 'thanks', ), $thanks_data);
В services.yml:В конструкторе класса слушателя:Код: Выделить всё
- @notification_manager
с последующим присвоением (имя переменной может быть произвольным)Код: Выделить всё
\phpbb\notification\manager $notification_manager
Код: Выделить всё
$this->notification_manager = $notification_manager;
- ВАЖНО! В файл ext.php необходимо добавить инструкции по включению, выключению, удалению уведомлений вместе с расширением, во избежание возникновения неисправимых обычными средствами админраздела ошибок, связанных с отсутствием соответствующих сервисов для работы добавленных уведомлений. Пример можно увидеть в файле ext.php расширения Board rules.
Патч, которым в данное расширение добавлены уведомления: #1b61df0f8.