2019-01-30 11:56:47 +01:00
< ? php
/**
2019-01-30 13:29:46 +01:00
* Library . Notification system auxiliary functions .
2019-01-30 11:56:47 +01:00
*
2019-01-30 13:29:46 +01:00
* @ category Library
2019-01-30 11:56:47 +01:00
* @ package Pandora FMS
* @ subpackage Community
* @ version 1.0 . 0
* @ license See below
*
* ______ ___ _______ _______ ________
2023-06-08 12:42:10 +02:00
* | __ \ .-----.--.--.--| |.-----.----.-----. | ___ | | | __ |
* | __ /| _ | | _ || _ | _ | _ | | ___ | | __ |
2019-01-30 11:56:47 +01:00
* | ___ | | ___ . _ | __ | __ | _____ || _____ | __ | | ___ . _ | | ___ | | __ | _ | __ | _______ |
*
* ============================================================================
2023-06-08 11:53:13 +02:00
* Copyright ( c ) 2005 - 2023 Pandora FMS
2023-06-08 13:19:01 +02:00
* Please see https :// pandorafms . com / community / for full contribution list
2019-01-30 11:56:47 +01:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* ============================================================================
*/
2019-02-11 13:35:36 +01:00
require_once $config [ 'homedir' ] . '/include/functions_messages.php' ;
2019-01-31 20:11:43 +01:00
define ( 'NOTIFICATIONS_POSTPONE_FOREVER' , - 1 );
2019-01-30 11:56:47 +01:00
2019-02-06 12:51:02 +01:00
2019-01-30 11:56:47 +01:00
/**
* Retrieves source ID for given source .
*
* @ param string $source Source .
*
* @ return integer source ' s id .
*/
function get_notification_source_id ( string $source )
{
if ( empty ( $source ) === true ) {
return false ;
}
return db_get_value_sql (
2019-02-08 10:32:04 +01:00
sprintf (
' SELECT id
FROM `tnotification_source`
WHERE lower ( `description` ) = lower ( " %s " ) ' ,
$source
)
2019-01-30 11:56:47 +01:00
);
}
2019-01-30 13:29:46 +01:00
2019-02-06 12:51:02 +01:00
2019-01-30 13:29:46 +01:00
/**
* Retrieve all targets for given message .
*
* @ param integer $id_message Message id .
*
* @ return array of users and groups target of this message .
*/
function get_notification_targets ( int $id_message )
{
$targets = [
'users' => [],
'groups' => [],
];
if ( empty ( $id_message )) {
return $targets ;
}
$ret = db_get_all_rows_sql (
sprintf (
' SELECT id_user
FROM tnotification_user nu
WHERE nu . id_mensaje = % d ' ,
$id_message
)
);
if ( is_array ( $ret )) {
foreach ( $ret as $row ) {
2022-06-16 13:02:49 +02:00
array_push ( $targets [ 'users' ], get_user_fullname ( $row [ 'id_user' ]));
2019-01-30 13:29:46 +01:00
}
}
2019-01-30 17:33:31 +01:00
$ret = db_get_all_rows_sql (
2019-01-30 13:29:46 +01:00
sprintf (
2019-01-30 17:33:31 +01:00
' SELECT COALESCE ( tg . nombre , ng . id_group ) as " id_group "
2019-01-30 13:29:46 +01:00
FROM tnotification_group ng
2019-01-30 17:33:31 +01:00
LEFT JOIN tgrupo tg
ON tg . id_grupo = ng . id_group
2019-01-30 13:29:46 +01:00
WHERE ng . id_mensaje = % d ' ,
$id_message
)
);
if ( is_array ( $ret )) {
foreach ( $ret as $row ) {
2019-01-30 17:33:31 +01:00
if ( $row [ 'id_group' ] == '0' ) {
$row [ 'id_group' ] = '<b>' . __ ( 'All' ) . '</b>' ;
}
2019-01-30 13:29:46 +01:00
array_push ( $targets [ 'groups' ], $row [ 'id_group' ]);
}
}
return $targets ;
}
2019-01-30 17:33:31 +01:00
2021-02-19 13:36:29 +01:00
/**
* Return subtypes .
*
* @ param string | null $source Source filter or all .
*
* @ return array
*/
function notifications_get_subtypes ( ? string $source = null )
{
$subtypes = [
'System status' => [
'NOTIF.LICENSE.LIMITED' ,
'NOTIF.FILES.ATTACHMENT' ,
'NOTIF.FILES.DATAIN' ,
'NOTIF.FILES.DATAIN.BADXML' ,
'NOTIF.PHP.SAFE_MODE' ,
'NOTIF.PHP.INPUT_TIME' ,
'NOTIF.PHP.EXECUTION_TIME' ,
'NOTIF.PHP.UPLOAD_MAX_FILESIZE' ,
'NOTIF.PHP.MEMORY_LIMIT' ,
'NOTIF.PHP.DISABLE_FUNCTIONS' ,
2022-12-20 12:23:18 +01:00
'NOTIF.PHP.CHROMIUM' ,
2021-02-19 13:36:29 +01:00
'NOTIF.PHP.VERSION' ,
2023-07-03 09:18:30 +02:00
'NOTIF.PHP.VERSION.SUPPORT' ,
2021-02-19 13:36:29 +01:00
'NOTIF.HISTORYDB' ,
2021-11-04 16:28:15 +01:00
'NOTIF.PANDORADB' ,
'NOTIF.PANDORADB.HISTORICAL' ,
2021-02-19 13:36:29 +01:00
'NOTIF.HISTORYDB.MR' ,
'NOTIF.EXT.ELASTICSEARCH' ,
'NOTIF.METACONSOLE.DB_CONNECTION' ,
'NOTIF.DOWNTIME' ,
'NOTIF.UPDATEMANAGER.REGISTRATION' ,
2023-07-27 19:58:06 +02:00
'NOTIF.API.ACCESS' ,
2021-02-19 13:36:29 +01:00
'NOTIF.MISC.EVENTSTORMPROTECTION' ,
'NOTIF.MISC.DEVELOPBYPASS' ,
'NOTIF.MISC.FONTPATH' ,
'NOTIF.SECURITY.DEFAULT_PASSWORD' ,
'NOTIF.UPDATEMANAGER.OPENSETUP' ,
'NOTIF.UPDATEMANAGER.UPDATE' ,
'NOTIF.UPDATEMANAGER.MINOR' ,
'NOTIF.UPDATEMANAGER.MESSAGES' ,
'NOTIF.CRON.CONFIGURED' ,
'NOTIF.ALLOWOVERRIDE.MESSAGE' ,
'NOTIF.HAMASTER.MESSAGE' ,
'NOTIF.SERVER.STATUS' ,
2021-02-19 13:57:39 +01:00
'NOTIF.SERVER.QUEUE' ,
2021-02-19 13:36:29 +01:00
'NOTIF.SERVER.MASTER' ,
2023-02-06 10:37:01 +01:00
'NOTIF.ACCESSSTASTICS.PERFORMANCE' ,
2023-02-06 15:22:39 +01:00
'NOTIF.VARIABLES.PERFORMANCE' ,
2021-02-19 13:36:29 +01:00
],
];
if ( $source === null ) {
return $subtypes ;
}
if ( isset ( $subtypes [ $source ]) === true ) {
return $subtypes [ $source ];
}
return [];
}
2019-01-30 17:33:31 +01:00
/**
* Check if current user has grants to read this notification
*
* @ param integer $id_message Target message .
*
* @ return boolean true , read available . False if not .
*/
function check_notification_readable ( int $id_message )
{
global $config ;
if ( empty ( $id_message )) {
return false ;
}
2019-02-11 15:28:38 +01:00
// Using distinct to avoid double response on group messages read by user.
2019-01-30 17:33:31 +01:00
$sql = sprintf (
2019-02-11 15:28:38 +01:00
' SELECT DISTINCT tm .* , utimestamp_read > 0 as " read "
FROM tmensajes tm
2019-01-30 17:33:31 +01:00
LEFT JOIN tnotification_user nu
ON tm . id_mensaje = nu . id_mensaje
2019-02-11 15:28:38 +01:00
AND nu . id_user = " %s "
2019-01-30 17:33:31 +01:00
AND tm . id_mensaje =% d
LEFT JOIN ( tnotification_group ng
INNER JOIN tusuario_perfil up
ON ng . id_group = up . id_grupo
AND up . id_grupo = ng . id_group
) ON tm . id_mensaje = ng . id_mensaje
WHERE utimestamp_erased is null
2019-02-18 14:18:58 +01:00
AND ( nu . id_user = " %s " OR up . id_usuario = " %s " OR ng . id_group = 0 ) ' ,
2019-02-11 15:28:38 +01:00
$config [ 'id_user' ],
2019-01-30 17:33:31 +01:00
$id_message ,
$config [ 'id_user' ],
$config [ 'id_user' ]
);
return ( bool ) db_get_value_sql ( $sql );
}
2019-01-31 15:16:56 +01:00
2019-02-06 12:51:02 +01:00
2019-02-12 13:29:43 +01:00
/**
* Returns the target users and groups assigned to be notified on
* desired source .
*
2021-02-19 13:36:29 +01:00
* @ param integer $id_source Source identificator .
* @ param string | null $subtype Subtype identification .
2019-02-12 13:29:43 +01:00
*
* @ return array [ users ] and [ groups ] with the targets .
*/
2022-06-16 13:02:49 +02:00
function get_notification_source_targets (
int $id_source ,
? string $subtype = null
) {
2019-02-12 13:29:43 +01:00
$ret = [];
2021-02-19 13:57:39 +01:00
$filter = '' ;
2021-02-19 13:36:29 +01:00
if ( $subtype !== null ) {
2021-02-19 13:57:39 +01:00
$matches = [];
if ( preg_match ( '/(.*)\.\d+$/' , $subtype , $matches ) > 0 ) {
$subtype = $matches [ 1 ];
}
2021-02-19 13:36:29 +01:00
$filter = sprintf (
2021-04-20 13:19:19 +02:00
' AND (ns.`subtype_blacklist` IS NULL OR ns.`subtype_blacklist` NOT LIKE "%%%s%%") ' ,
2021-02-19 13:36:29 +01:00
$subtype
);
}
2019-02-12 13:29:43 +01:00
$users = db_get_all_rows_sql (
sprintf (
' SELECT
id_user ,
IF ( ns . user_editable = 1 , nsu . also_mail , ns . also_mail ) AS also_mail
FROM tnotification_source_user nsu
INNER JOIN tnotification_source ns
ON ns . id = nsu . id_source
2021-02-19 13:57:39 +01:00
% s
2019-02-12 13:29:43 +01:00
WHERE ns . id = % d
AND (( ns . enabled is NULL OR ns . enabled != 0 )
2021-02-19 13:57:39 +01:00
OR ( nsu . enabled is NULL OR nsu . enabled != 0 )) ' ,
$filter ,
$id_source
2019-02-12 13:29:43 +01:00
)
);
if ( $users !== false ) {
$i = 0 ;
foreach ( $users as $user ) {
$ret [ 'users' ][ $i ][ 'id_user' ] = $user [ 'id_user' ];
$ret [ 'users' ][ $i ++ ][ 'also_mail' ] = $user [ 'also_mail' ];
}
}
$groups = db_get_all_rows_sql (
sprintf (
' SELECT id_group , ns . also_mail
FROM tnotification_source_group nsg
INNER JOIN tnotification_source ns
ON ns . id = nsg . id_source
2021-02-19 13:57:39 +01:00
% s
2019-02-12 13:29:43 +01:00
WHERE ns . id = % d
2021-02-19 13:57:39 +01:00
AND ( ns . enabled is NULL OR ns . enabled != 0 ) ' ,
$filter ,
$id_source
2019-02-12 13:29:43 +01:00
)
);
if ( $groups !== false ) {
$i = 0 ;
foreach ( $groups as $group ) {
$ret [ 'groups' ][ $i ][ 'id_group' ] = $group [ 'id_group' ];
$ret [ 'groups' ][ $i ++ ][ 'also_mail' ] = $group [ 'also_mail' ];
}
}
return $ret ;
}
2019-01-31 19:13:51 +01:00
/**
* Return all info from tnotification_source
*
2019-02-07 12:57:51 +01:00
* @ param array $filter Filter to table tnotification_source .
*
2019-01-31 19:13:51 +01:00
* @ return array with sources info
*/
2019-02-07 12:22:50 +01:00
function notifications_get_all_sources ( $filter = [])
2019-02-06 12:51:02 +01:00
{
2019-02-07 12:22:50 +01:00
return db_get_all_rows_filter ( 'tnotification_source' , $filter );
2019-01-31 19:13:51 +01:00
}
2019-02-06 12:51:02 +01:00
2019-02-01 13:53:22 +01:00
/**
* Return the user sources to be inserted into a select
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source database identificator .
2019-02-01 13:53:22 +01:00
*
* @ return array with the user id in keys and user id in value too
*/
2019-02-06 12:51:02 +01:00
function notifications_get_user_sources_for_select ( $source_id )
2019-02-06 18:20:26 +01:00
{
$users = notifications_get_user_sources (
[ 'id_source' => $source_id ],
[ 'id_user' ]
);
return index_array ( $users , 'id_user' , 'id_user' );
}
/**
* Get the user sources
*
* @ param array $filter Filter of sql query .
* @ param array $fields Fields to get of query .
*
* @ return array Array with user sources data .
*/
function notifications_get_user_sources ( $filter = [], $fields = [])
2019-02-06 12:51:02 +01:00
{
2019-02-01 13:46:58 +01:00
$users = db_get_all_rows_filter (
'tnotification_source_user' ,
2019-02-06 18:20:26 +01:00
$filter ,
$fields
2019-02-01 13:46:58 +01:00
);
2019-02-06 18:20:26 +01:00
// If fails or no one is selected, return empty array.
2019-02-06 12:51:02 +01:00
if ( $users === false ) {
return [];
}
2019-02-01 13:46:58 +01:00
2019-02-06 18:20:26 +01:00
return $users ;
2019-02-01 13:46:58 +01:00
}
2019-02-01 13:53:22 +01:00
/**
* Return the groups sources to be inserted into a select
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source database identificator .
2019-02-01 13:53:22 +01:00
*
* @ return array with the group id in keys and group name in value
*/
2019-02-06 12:51:02 +01:00
function notifications_get_group_sources_for_select ( $source_id )
{
$groups = notifications_get_group_sources (
[ 'id_source' => $source_id ],
[ 'id_group' ]
2019-02-05 13:36:16 +01:00
);
return index_array ( $groups , 'id_group' , 'name' );
}
2019-02-06 12:51:02 +01:00
2019-02-05 13:36:16 +01:00
/**
* Get the group sources
*
* @ param array $filter Filter of sql query .
2019-02-07 12:57:51 +01:00
* @ param array $fields Fields retrieved .
*
* @ return array With the group info
2019-02-05 13:36:16 +01:00
*/
2019-02-06 12:51:02 +01:00
function notifications_get_group_sources ( $filter = [], $fields = [])
{
2019-02-05 13:36:16 +01:00
// Get only the tnotifications_source_group fields in addition to group name.
2019-02-06 12:51:02 +01:00
if ( empty ( $fields )) {
$fields [] = 'tnsg.*' ;
}
$fields = array_map (
function ( $field ) {
if ( ! preg_match ( '/^tnsg./' , $field )) {
2019-02-08 10:32:04 +01:00
$field = 'tnsg.' . $field ;
2019-02-06 12:51:02 +01:00
}
return $field ;
},
$fields
);
2019-02-05 13:36:16 +01:00
// Get groups.
2019-02-01 14:48:52 +01:00
$groups = db_get_all_rows_filter (
2019-02-01 13:46:58 +01:00
' tnotification_source_group tnsg
2019-02-01 14:48:52 +01:00
LEFT JOIN tgrupo tg ON tnsg . id_group = tg . id_grupo ' ,
2019-02-05 13:36:16 +01:00
$filter ,
2019-02-06 12:51:02 +01:00
array_merge ( $fields , [ 'IFNULL(tg.nombre, "All") AS name' ])
2019-02-01 13:46:58 +01:00
);
2019-02-05 13:36:16 +01:00
2019-02-08 10:32:04 +01:00
// If fails or no one is selected, return empty array.
2019-02-06 12:51:02 +01:00
if ( $groups === false ) {
return [];
}
2019-02-05 13:36:16 +01:00
return $groups ;
2019-02-01 13:46:58 +01:00
}
2019-02-06 12:51:02 +01:00
2019-02-04 10:41:35 +01:00
/**
* Delete a set of groups from notification source
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
* @ param array $groups Id of groups to be deleted .
2019-02-04 10:41:35 +01:00
*
2019-02-06 12:51:02 +01:00
* @ return boolean True if success . False otherwise .
2019-02-04 10:41:35 +01:00
*/
2019-02-06 12:51:02 +01:00
function notifications_remove_group_from_source ( $source_id , $groups )
{
2019-02-08 10:32:04 +01:00
// Source id is mandatory.
2019-02-06 12:51:02 +01:00
if ( ! isset ( $source_id )) {
return false ;
}
2019-02-04 10:41:35 +01:00
2019-02-08 10:32:04 +01:00
// Delete from database.
2019-02-06 12:51:02 +01:00
return db_process_sql_delete (
2019-02-04 10:41:35 +01:00
'tnotification_source_group' ,
2019-02-06 12:51:02 +01:00
[
'id_group' => $groups ,
'id_source' => $source_id ,
]
2019-02-04 10:41:35 +01:00
) !== false ;
}
2019-02-06 12:51:02 +01:00
2019-02-05 18:14:10 +01:00
/**
* Delete a set of users from notification source
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
* @ param array $users Id of users to be deleted .
2019-02-05 18:14:10 +01:00
*
2019-02-06 12:51:02 +01:00
* @ return boolean True if success . False otherwise .
2019-02-05 18:14:10 +01:00
*/
2019-02-06 12:51:02 +01:00
function notifications_remove_users_from_source ( $source_id , $users )
{
2019-02-08 10:32:04 +01:00
// Source id is mandatory.
2019-02-06 12:51:02 +01:00
if ( ! isset ( $source_id )) {
return false ;
}
2019-02-05 18:14:10 +01:00
2019-02-08 10:32:04 +01:00
// Delete from database.
2019-02-06 12:51:02 +01:00
return db_process_sql_delete (
2019-02-05 18:14:10 +01:00
'tnotification_source_user' ,
2019-02-06 12:51:02 +01:00
[
'id_user' => $users ,
'id_source' => $source_id ,
]
2019-02-05 18:14:10 +01:00
) !== false ;
}
2019-02-06 12:51:02 +01:00
2019-02-04 10:41:35 +01:00
/**
* Insert a set of groups to notification source
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
* @ param array $groups Id of groups to be deleted .
2019-02-04 10:41:35 +01:00
*
2019-02-06 12:51:02 +01:00
* @ return boolean True if success . False otherwise .
2019-02-04 10:41:35 +01:00
*/
2019-02-06 12:51:02 +01:00
function notifications_add_group_to_source ( $source_id , $groups )
{
2019-02-07 17:53:09 +01:00
// Source id is mandatory.
2019-02-06 12:51:02 +01:00
if ( ! isset ( $source_id )) {
return false ;
}
2019-02-04 10:41:35 +01:00
2019-02-07 17:53:09 +01:00
// Insert into database all groups passed.
2019-02-04 10:41:35 +01:00
$res = true ;
foreach ( $groups as $group ) {
2019-02-07 18:04:14 +01:00
if ( ! isset ( $group )) {
continue ;
}
2019-02-06 12:51:02 +01:00
2022-06-16 13:02:49 +02:00
$res = $res &&
db_process_sql_insert (
2019-02-04 10:41:35 +01:00
'tnotification_source_group' ,
2019-02-06 12:51:02 +01:00
[
'id_group' => $group ,
'id_source' => $source_id ,
]
) !== false ;
2019-02-04 10:41:35 +01:00
}
2019-02-06 12:51:02 +01:00
2019-02-04 10:41:35 +01:00
return $res ;
}
2019-02-06 12:51:02 +01:00
2019-02-05 17:40:44 +01:00
/**
* Insert a set of users to notification source
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
* @ param array $users Id of users to be deleted .
2019-02-05 17:40:44 +01:00
*
2019-02-06 12:51:02 +01:00
* @ return boolean True if success . False otherwise .
2019-02-05 17:40:44 +01:00
*/
2019-02-06 12:51:02 +01:00
function notifications_add_users_to_source ( $source_id , $users )
{
2019-02-08 10:32:04 +01:00
// Source id is mandatory.
2019-02-06 12:51:02 +01:00
if ( ! isset ( $source_id )) {
return false ;
}
2019-02-05 17:40:44 +01:00
2019-02-08 10:32:04 +01:00
// Insert into database all groups passed.
2019-02-05 17:40:44 +01:00
$res = true ;
2019-02-06 18:20:26 +01:00
$also_mail = db_get_value (
'also_mail' ,
'tnotification_source' ,
'id' ,
$source_id
);
2019-02-05 17:40:44 +01:00
foreach ( $users as $user ) {
2019-02-06 12:51:02 +01:00
if ( empty ( $user )) {
continue ;
}
2022-06-16 13:02:49 +02:00
$res = $res &&
db_process_sql_insert (
2019-02-05 17:40:44 +01:00
'tnotification_source_user' ,
2019-02-06 12:51:02 +01:00
[
'id_user' => $user ,
'id_source' => $source_id ,
2019-02-06 18:20:26 +01:00
'enabled' => 1 ,
'also_mail' => ( int ) $also_mail ,
2019-02-06 12:51:02 +01:00
]
) !== false ;
2019-02-05 17:40:44 +01:00
}
2019-02-06 12:51:02 +01:00
2019-02-05 17:40:44 +01:00
return $res ;
}
2019-02-06 12:51:02 +01:00
2019-02-05 13:36:16 +01:00
/**
* Get the groups that not own to a source and , for that reason , they can be
* added to the source .
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
*
2019-02-05 13:36:16 +01:00
* @ return array Indexed by id group all selectable groups .
*/
2019-02-06 12:51:02 +01:00
function notifications_get_group_source_not_configured ( $source_id )
{
2019-02-05 13:36:16 +01:00
$groups_selected = notifications_get_group_sources_for_select ( $source_id );
2022-06-16 13:02:49 +02:00
$all_groups = users_get_groups_for_select (
false ,
'AR' ,
false ,
true ,
$groups_selected
);
2019-02-05 13:36:16 +01:00
return array_diff ( $all_groups , $groups_selected );
}
2019-02-06 12:51:02 +01:00
2019-02-05 13:36:16 +01:00
/**
* Get the users that not own to a source and , for that reason , they can be
* added to the source .
*
2019-02-07 12:57:51 +01:00
* @ param integer $source_id Source id .
*
2019-02-05 13:36:16 +01:00
* @ return array Indexed by id user , all selectable users .
*/
2019-02-06 12:51:02 +01:00
function notifications_get_user_source_not_configured ( $source_id )
{
2022-06-16 13:02:49 +02:00
$users_selected = array_keys (
notifications_get_user_sources_for_select ( $source_id )
2019-02-05 13:36:16 +01:00
);
2022-06-16 13:02:49 +02:00
$users = get_users ( 'id_user' , [ '!id_user' => $users_selected ], [ 'id_user' ]);
2019-02-05 13:36:16 +01:00
return index_array ( $users , 'id_user' , 'id_user' );
}
2019-02-06 12:51:02 +01:00
2019-02-07 12:57:51 +01:00
/**
* Build a data struct to handle the value of a label
*
* @ param mixed $status Status value .
* @ param mixed $enabled Enabled value .
*
* @ return array with status ( 1 | 0 ) and enabled ( 1 | 0 )
*/
2019-02-06 18:20:26 +01:00
function notifications_build_user_enable_return ( $status , $enabled )
{
return [
2022-06-16 13:02:49 +02:00
'status' => ( bool ) $status === true ? 1 : 0 ,
'enabled' => ( bool ) $enabled === true ? 1 : 0 ,
2019-02-06 18:20:26 +01:00
];
}
2019-02-07 12:57:51 +01:00
/**
* Get user label ( enabled , also_mail ... ) status .
*
* @ param integer $source Id of notification source .
* @ param string $user User id .
* @ param string $label Label id ( enabled , also_email ... ) .
*
* @ return array Return of notifications_build_user_enable_return .
*/
2019-02-06 18:20:26 +01:00
function notifications_get_user_label_status ( $source , $user , $label )
{
// If not enabled, it cannot be modificable.
2019-02-18 17:08:23 +01:00
if ( ! $source [ 'enabled' ]) {
2019-02-06 18:20:26 +01:00
return notifications_build_user_enable_return ( false , false );
}
// See at first for direct reference.
$user_source = notifications_get_user_sources (
[
'id_source' => $source [ 'id' ],
'id_user' => $user ,
]
);
if ( ! empty ( $user_source )) {
return notifications_build_user_enable_return (
isset ( $user_source [ 0 ][ $label ]) ? $user_source [ 0 ][ $label ] : false ,
$source [ 'user_editable' ]
);
}
$common_groups = array_intersect (
array_keys ( users_get_groups ( $user )),
2022-06-16 13:02:49 +02:00
array_keys ( notifications_get_group_sources_for_select ( $source [ 'id' ]))
2019-02-06 18:20:26 +01:00
);
2023-09-07 14:16:36 +02:00
// Clean default common groups error for mesagges.
if ( $common_groups [ 0 ] === 0 ) {
unset ( $common_groups [ 0 ]);
}
2019-02-06 18:20:26 +01:00
// No group found, return no permissions.
$value = empty ( $common_groups ) ? false : $source [ $label ];
2022-06-16 13:02:49 +02:00
return notifications_build_user_enable_return ( $value , false );
2019-02-06 18:20:26 +01:00
}
2019-02-07 12:57:51 +01:00
/**
* Set the status to a single label on config of users notifications .
*
* @ param integer $source Id of notification source .
* @ param string $user User id .
* @ param string $label Label id ( enabled , also_email ... ) .
* @ param mixed $value Numeric value : 1 or 0.
*
* @ return boolean True if success .
*/
function notifications_set_user_label_status ( $source , $user , $label , $value )
{
2023-09-04 12:50:23 +02:00
global $config ;
2023-11-10 10:03:13 +01:00
$user_info = get_user_info ( $config [ 'id_user' ]);
if (( bool ) $user_info [ 'is_admin' ] === false && $config [ 'id_user' ] !== $user ) {
2023-09-04 12:50:23 +02:00
return false ;
}
2019-02-07 12:22:50 +01:00
$source_info = notifications_get_all_sources ([ 'id' => $source ]);
2023-09-04 12:50:23 +02:00
2019-02-07 12:22:50 +01:00
if ( ! isset ( $source_info [ 0 ])
|| ! $source_info [ 0 ][ 'enabled' ]
|| ! $source_info [ 0 ][ 'user_editable' ]
) {
return false ;
}
return ( bool ) db_process_sql_update (
'tnotification_source_user' ,
[ $label => $value ],
[
'id_user' => $user ,
'id_source' => $source ,
]
);
2019-02-11 13:05:31 +01:00
}
/**
* Get the counters of notification . Usefull to print the header notification
* ball .
*
* @ return array With the fields :
* 'notifications' => Total new notifications ,
* 'last_id' => Id of last read value . Usefull to make comparisons .
*/
function notifications_get_counters ()
{
$num_notifications = 0 ;
$last_id = 0 ;
2022-06-16 13:02:49 +02:00
$last_message = messages_get_overview ( 'timestamp' , 'DESC' , false , false , 1 );
2019-02-11 13:05:31 +01:00
if ( ! empty ( $last_message )) {
$num_notifications = messages_get_count ();
$last_id = $last_message [ 0 ][ 'id_mensaje' ];
}
2019-02-07 12:22:50 +01:00
2019-02-11 13:05:31 +01:00
return [
'notifications' => $num_notifications ,
'last_id' => $last_id ,
];
2019-02-07 12:22:50 +01:00
}
2019-02-06 18:20:26 +01:00
2019-02-08 14:23:05 +01:00
// /////////////////////////////////////////////////////////////////////////////
// UI FUNCTIONS
// /////////////////////////////////////////////////////////////////////////////
2019-01-31 15:16:56 +01:00
/**
2019-02-07 12:57:51 +01:00
* Print the notification ball to see unread messages .
2019-01-31 15:16:56 +01:00
*
2019-02-11 13:05:31 +01:00
* @ param integer $num_notifications Number of messages shown
* in notification ball .
* @ param integer $last_id Id of last message shown
* in the notification ball .
*
2019-02-07 12:57:51 +01:00
* @ return string with HTML code of notification ball .
2019-01-31 15:16:56 +01:00
*/
2019-02-11 13:05:31 +01:00
function notifications_print_ball ( $num_notifications , $last_id )
2019-02-06 12:51:02 +01:00
{
2019-02-12 16:25:59 +01:00
$no_notifications = ( int ) $num_notifications === 0 ;
2022-06-16 13:02:49 +02:00
$class_status = $no_notifications
? 'notification-ball-no-messages'
: 'notification-ball-new-messages' ;
2019-02-08 10:32:04 +01:00
return sprintf (
2019-02-08 14:23:05 +01:00
' < div
2019-02-12 16:25:59 +01:00
% s
2019-02-08 14:23:05 +01:00
class = " notification-ball %s "
id = " notification-ball-header "
2019-02-11 13:05:31 +01:00
last_id = " %s "
2019-02-08 14:23:05 +01:00
>
2019-02-08 10:32:04 +01:00
% s
</ div > ' ,
2022-06-16 13:02:49 +02:00
$no_notifications ? '' : 'onclick="addNotifications(event)"' ,
2019-02-08 10:32:04 +01:00
$class_status ,
2019-02-11 13:05:31 +01:00
$last_id ,
2019-02-08 10:32:04 +01:00
$num_notifications
);
2019-01-31 15:16:56 +01:00
}
2019-01-31 19:13:51 +01:00
2019-02-06 12:51:02 +01:00
2019-01-31 19:13:51 +01:00
/**
* Print notification configuration global
*
2019-02-07 12:57:51 +01:00
* @ param array $source Notification source data .
2019-01-31 19:13:51 +01:00
*
* @ return string with HTML of source configuration
*/
2019-02-06 12:51:02 +01:00
function notifications_print_global_source_configuration ( $source )
{
2019-02-07 17:53:09 +01:00
// Get some values to generate the title.
2019-02-06 12:51:02 +01:00
$switch_values = [
2019-02-07 18:04:14 +01:00
'name' => 'enable-' . $source [ 'id' ],
2019-02-06 12:51:02 +01:00
'value' => $source [ 'enabled' ],
2019-02-07 17:53:09 +01:00
'id' => 'nt-' . $source [ 'id' ] . '-enabled' ,
'class' => 'elem-clickable' ,
2019-02-06 12:51:02 +01:00
];
2019-02-01 14:48:52 +01:00
2019-02-08 10:32:04 +01:00
// Search if group all is set and handle that situation.
2019-02-01 14:48:52 +01:00
$source_groups = notifications_get_group_sources_for_select ( $source [ 'id' ]);
2019-02-06 12:51:02 +01:00
$is_group_all = isset ( $source_groups [ '0' ]);
if ( $is_group_all ) {
unset ( $source_groups [ '0' ]);
}
2019-02-01 14:48:52 +01:00
2019-02-08 10:32:04 +01:00
// Generate the title.
2023-09-07 12:46:39 +02:00
$html_title = '<h2 style="margin-bottom: auto;">' . $source [ 'description' ] . '</h2>' ;
$html_title .= " <div class='global-config-notification-title'> " ;
2019-02-06 12:51:02 +01:00
$html_title .= html_print_switch ( $switch_values );
2023-09-07 12:46:39 +02:00
$html_title .= '<h2>' . __ ( 'Enable user configuration' ) . '</h2>' ;
2019-02-06 12:51:02 +01:00
$html_title .= '</div>' ;
2019-01-31 19:13:51 +01:00
2019-02-08 10:32:04 +01:00
// Generate the html for title.
2019-02-01 13:46:58 +01:00
$html_selectors = " <div class='global-config-notification-selectors'> " ;
2019-02-12 15:36:41 +01:00
$html_selectors .= notifications_print_source_select_box (
notifications_get_user_sources_for_select ( $source [ 'id' ]),
'users' ,
$source [ 'id' ]
);
$html_selectors .= notifications_print_source_select_box (
$source_groups ,
'groups' ,
$source [ 'id' ]
);
2019-02-06 12:51:02 +01:00
$html_selectors .= '</div>' ;
2019-01-31 20:11:43 +01:00
2021-02-19 13:36:29 +01:00
$html_checkboxes = '' ;
$blacklist = json_decode ( $source [ 'subtype_blacklist' ], 1 );
if ( json_last_error () !== JSON_ERROR_NONE ) {
$blacklist = [];
}
if ( $source [ 'description' ] === io_safe_input ( 'System status' )) {
$system_subtypes = notifications_get_subtypes ( 'System status' );
foreach ( $system_subtypes as $type ) {
$html_checkboxes .= html_print_input (
[
'input_class' => 'flex flex-row w290px margin-soft' ,
'label' => $type ,
'name' => 'check-' . $type ,
'type' => 'switch' ,
'id' => 'nt-' . $source [ 'id' ] . '.' . $type . '-subtype' ,
'class' => 'elem-clickable' ,
2022-06-16 13:02:49 +02:00
'value' => isset ( $blacklist [ $type ]) === false ,
2021-02-19 13:36:29 +01:00
'return' => true ,
]
);
}
$html_checkboxes = ui_print_toggle (
[
'content' => $html_checkboxes ,
'name' => __ ( 'Subtype customization' ),
'hidden_default' => false ,
'return' => true ,
'toggle_class' => '' ,
'container_class' => 'flex flex-row flex-start w100p' ,
'main_class' => '' ,
'clean' => true ,
]
);
}
2019-02-08 10:32:04 +01:00
// Return all html.
2021-02-19 13:36:29 +01:00
return $html_title . $html_selectors . $html_checkboxes ;
2019-02-01 13:46:58 +01:00
}
2019-02-06 12:51:02 +01:00
2019-02-01 13:53:22 +01:00
/**
* Print select boxes of notified users or groups
*
2019-02-12 15:36:41 +01:00
* @ param array $info_selec All info required for build the selector .
* @ param string $id One of users | groups .
* @ param string $source_id Id of source .
2019-02-01 13:53:22 +01:00
*
* @ return string HTML with the generated selector
*/
2022-06-16 13:02:49 +02:00
function notifications_print_source_select_box ( $info_selec , $id , $source_id )
{
$title = $id === 'users' ? __ ( 'Notified users' ) : __ ( 'Notified groups' );
$add_title = $id === 'users' ? __ ( 'Add users' ) : __ ( 'Add groups' );
$delete_title = $id === 'users' ? __ ( 'Delete users' ) : __ ( 'Delete groups' );
2019-02-01 13:46:58 +01:00
2019-02-08 10:32:04 +01:00
// Generate the HTML.
2019-02-08 11:39:17 +01:00
return sprintf (
"
< div class = 'global-config-notification-single-selector' >
< div >
2020-07-13 13:00:47 +02:00
< h5 >% s </ h5 >
2019-02-08 11:39:17 +01:00
% s
</ div >
< div class = 'global-notifications-icons' >
% s
% s
</ div >
</ div >
" ,
$title ,
// Put a true if empty sources to avoid to sow the 'None' value.
html_print_select (
empty ( $info_selec ) ? true : $info_selec ,
'multi-' . $id . '-' . $source_id . '[]' ,
0 ,
false ,
'' ,
'' ,
true ,
2019-02-12 15:36:41 +01:00
true
2019-02-08 11:39:17 +01:00
),
html_print_image (
2023-03-09 23:31:40 +01:00
'images/fail@svg.svg' ,
2019-02-08 11:39:17 +01:00
true ,
[
2023-03-09 23:31:40 +01:00
'style' => 'width: 14px;rotate: 45deg' ,
2019-02-08 11:39:17 +01:00
'title' => $add_title ,
2023-03-09 23:31:40 +01:00
'class' => 'main_menu_icon invert_filter' ,
2022-06-16 13:02:49 +02:00
'onclick' => sprintf ( " add_source_dialog('%s', '%s') " , $id , $source_id ),
2019-02-08 11:39:17 +01:00
]
),
html_print_image (
2023-03-09 23:31:40 +01:00
'images/delete.svg' ,
2019-02-08 11:39:17 +01:00
true ,
[
2023-03-09 23:31:40 +01:00
'style' => 'width: 14px' ,
2019-02-08 11:39:17 +01:00
'title' => $delete_title ,
2023-03-09 23:31:40 +01:00
'class' => 'main_menu_icon invert_filter' ,
2019-02-08 11:39:17 +01:00
'onclick' => sprintf (
" remove_source_elements('%s', '%s') " ,
$id ,
$source_id
),
]
)
);
2019-01-31 19:13:51 +01:00
}
2019-02-05 13:36:16 +01:00
2019-02-06 12:51:02 +01:00
2019-02-05 13:36:16 +01:00
/**
* Print the select with right and left arrows to select new sources
* ( groups or users ) .
*
2019-02-07 12:57:51 +01:00
* @ param array $info_selec Array with source info .
* @ param string $users One of users | groups .
* @ param source $source_id Source id .
*
2019-02-05 13:36:16 +01:00
* @ return string HTML with the select code .
*/
2019-02-06 12:51:02 +01:00
function notifications_print_two_ways_select ( $info_selec , $users , $source_id )
{
2019-02-08 11:39:17 +01:00
return sprintf (
"
< div class = 'global_config_notifications_dialog_add' >
% s
< div class = 'global_config_notifications_two_ways_form_arrows' >
% s
% s
</ div >
% s
</ div >
% s
" ,
html_print_select (
empty ( $info_selec ) ? true : $info_selec ,
'all-multi-' . $users . '-' . $source_id . '[]' ,
0 ,
false ,
'' ,
'' ,
true ,
true ,
true ,
''
),
html_print_image (
2023-03-09 23:31:40 +01:00
'images/arrow@svg.svg' ,
2019-02-08 11:39:17 +01:00
true ,
[
'title' => __ ( 'Add elements' ),
2023-05-16 12:19:20 +02:00
'style' => 'rotate: 180deg' ,
2019-02-08 11:39:17 +01:00
'onclick' => sprintf (
" notifications_modify_two_ways_element('%s', '%s', 'add') " ,
$users ,
$source_id
),
2023-03-09 23:31:40 +01:00
'class' => 'main_menu_icon invert_filter' ,
2019-02-08 11:39:17 +01:00
]
),
html_print_image (
2023-03-09 23:31:40 +01:00
'images/arrow@svg.svg' ,
2019-02-08 11:39:17 +01:00
true ,
[
'title' => __ ( 'Remove elements' ),
2023-03-09 23:31:40 +01:00
'style' => 'rotate: 0' ,
2019-02-08 11:39:17 +01:00
'onclick' => sprintf (
" notifications_modify_two_ways_element('%s', '%s', 'remove') " ,
$users ,
$source_id
),
2023-03-09 23:31:40 +01:00
'class' => 'main_menu_icon invert_filter' ,
2019-02-08 11:39:17 +01:00
]
),
html_print_select (
true ,
'selected-multi-' . $users . '-' . $source_id . '[]' ,
0 ,
false ,
'' ,
'' ,
true ,
true ,
true ,
''
),
html_print_button (
__ ( 'Add' ),
'Add' ,
false ,
2023-05-16 12:19:20 +02:00
'notifications_add_source_element_to_database("' . $users . '",' . $source_id . ')' ,
2019-02-08 11:39:17 +01:00
" class='sub add' " ,
true
)
);
2019-02-05 13:36:16 +01:00
}
2019-02-06 18:20:26 +01:00
2019-02-07 12:57:51 +01:00
/**
* Print a label status represented by a switch
*
* @ param integer $source Source id .
* @ param string $user User id .
* @ param string $label Label ( enabled , also_mail ... ) .
*
* @ return string With HTML code
*/
2019-02-06 18:20:26 +01:00
function notifications_print_user_switch ( $source , $user , $label )
{
$status = notifications_get_user_label_status ( $source , $user , $label );
2020-04-02 10:37:59 +02:00
$switch = html_print_switch (
2019-02-06 18:20:26 +01:00
[
'name' => $label ,
'value' => $status [ 'status' ],
'disabled' => ! $status [ 'enabled' ],
2019-02-07 12:22:50 +01:00
'class' => 'notifications-user-label_individual' ,
'id' => 'notifications-user-' . $source [ 'id' ] . '-label-' . $label ,
2019-02-06 18:20:26 +01:00
]
);
2020-04-02 10:37:59 +02:00
$data = [
'disabled' => ! $status [ 'enabled' ],
'switch' => $switch ,
];
return $data ;
2019-02-06 18:20:26 +01:00
}
2019-02-08 14:23:05 +01:00
2023-07-04 13:33:29 +02:00
/**
* Generates an HTML of notification filter types .
*
* @ return string HTML filter notification .
*/
function notification_filter ()
{
$types_list [] = 'All' ;
2023-08-21 10:59:29 +02:00
$notification_types = db_get_all_rows_sql ( 'SELECT DISTINCT tm.subtype FROM tmensajes as tm INNER JOIN tnotification_user as tnu ON tm.id_mensaje = tnu.id_mensaje WHERE tnu.utimestamp_read IS NULL' );
2023-07-04 13:33:29 +02:00
if ( $notification_types !== false ) {
foreach ( $notification_types as $notification_type ) {
$type = explode ( '.' , $notification_type [ 'subtype' ])[ 1 ];
$types_list [] = $type ;
}
}
2023-08-21 10:59:29 +02:00
$types_list = array_unique ( $types_list );
2023-07-04 13:33:29 +02:00
$notification_filter = " <ul id='menu-filter_notification'> " ;
$notification_filter .= " <li>
< input type = 'checkbox' name = 'filter_menu' id = 'filter_menu' >
< label for = 'filter_menu' id = 'filter_menu_label' > " .__('Filter').'</label>';
$notification_filter .= " <ul class='sublevel-filter_notification'> " ;
foreach ( $types_list as $type ) {
if ( $type === 'All' ) {
$checked = 'checked' ;
} else {
$checked = '' ;
}
switch ( $type ) {
case 'HISTORYDB' :
$type_name = 'HISTORY DB' ;
break ;
case 'PANDORADB' :
$type_name = 'PANDORA DB' ;
break ;
case 'UPDATEMANAGER' :
$type_name = 'UPDATE MANAGER' ;
break ;
case 'ALLOWOVERRIDE' :
$type_name = 'ALLOW OVERRIDE' ;
break ;
2023-08-21 13:11:57 +02:00
case 'DISCOVERYTASK' :
2023-08-21 10:59:29 +02:00
$type_name = 'DISCOVERY TASK' ;
break ;
2023-07-04 13:33:29 +02:00
default :
$type_name = $type ;
break ;
}
$notification_filter .= " <li><div class='item-filter'>
< input type = 'checkbox'
class = 'checkbox_filter_notifications'
value = " . $type . "
name = 'filter_".$type."'
" . $checked . "
id = 'filter_".$type."' >
< label for = 'filter_".$type."' > " . $type_name .'</label>
</ div >
</ li > ' ;
}
$notification_filter .= " <li><div class='item-filter'> " ;
$notification_filter .= html_print_div (
[
'class' => 'action-buttons w100p' ,
'content' => html_print_submit_button (
__ ( 'Filter' ),
'btn_submit' ,
false ,
[
'class' => 'mini sub filter' ,
'icon' => 'search mini' ,
'onClick' => 'filter_notification()' ,
],
true
),
],
true
);
$notification_filter .= ' </ div >
</ li > ' ;
$notification_filter .= '</ul>' ;
$notification_filter .= '</li>' ;
$notification_filter .= '</ul>' ;
return $notification_filter ;
}
2019-02-08 14:23:05 +01:00
/**
* Generates the dropdown notifications menu .
*
* @ return string HTML with dropdown menu .
*/
function notifications_print_dropdown ()
{
$mess = messages_get_overview ( 'status' , 'DESC' , false , true );
if ( $mess === false ) {
$mess = [];
}
2023-07-03 09:18:30 +02:00
$notification_menu = html_print_menu_button (
[
'href' => 'javascript:' ,
'class' => 'notification_menu_actions' ,
'text' => __ ( 'Mark all as read' ),
'onClick' => 'mark_all_notification_as_read()' ,
],
true
);
2023-07-04 13:33:29 +02:00
$notification_filter = notification_filter ();
2023-07-03 09:18:30 +02:00
2019-02-08 14:23:05 +01:00
return sprintf (
2019-02-12 16:25:59 +01:00
" <div id='notification-wrapper'>
2019-02-13 12:44:30 +01:00
< div id = 'notification-wrapper-inner' >
2023-07-04 13:33:29 +02:00
< div class = 'notificaion_menu_container' >
< div class = 'menu_tab filter_notification' >% s </ div >
< div class = 'menu_tab notification_menu' >% s </ div >
</ div >
2019-02-13 12:44:30 +01:00
% s
2019-02-08 18:53:28 +01:00
</ div >
2019-02-13 12:44:30 +01:00
</ div >
< div
id = 'notification-wrapper-shadow'
onclick = 'notifications_hide()'
>
2019-02-12 16:25:59 +01:00
</ div >
" ,
2023-07-04 13:33:29 +02:00
$notification_filter ,
2023-07-03 09:18:30 +02:00
$notification_menu ,
2019-02-08 14:23:05 +01:00
array_reduce (
$mess ,
function ( $carry , $message ) {
return $carry . notifications_print_dropdown_element ( $message );
},
''
)
);
}
/**
* Print a single notification box
*
* @ param array $message_info Info of printed message .
*
* @ return string HTML code of single message
*/
function notifications_print_dropdown_element ( $message_info )
{
2019-05-14 23:49:01 +02:00
$action = '' ;
switch ( $message_info [ 'description' ]) {
case 'Official communication' :
$action = 'show_modal(this.id);' ;
$target = '' ;
2019-05-21 08:29:59 +02:00
$body_preview = __ ( 'Click here to get more information' );
2019-05-14 23:49:01 +02:00
break ;
default :
$action = '' ;
$target = '_blank' ;
$body_preview = strip_tags (
io_safe_output ( $message_info [ 'mensaje' ]),
'<br><pre>'
);
break ;
}
2021-03-18 11:00:34 +01:00
$split_subject = explode ( ' ' , io_safe_output ( $message_info [ 'subject' ]));
$is_image = false ;
$img = '' ;
foreach ( $split_subject as $item ) {
if ( $is_image ) {
if ( preg_match ( '/src/' , $item )) {
$img .= $item . ' >' ;
$is_image = false ;
}
}
if ( preg_match ( '/img/' , $item )) {
$img = '<img ' ;
$is_image = true ;
}
}
if ( $img !== '' ) {
$message_info [ 'subject' ] = io_safe_input ( $img );
}
2023-07-04 13:33:29 +02:00
$type = explode ( '.' , $message_info [ 'subtype' ])[ 1 ];
2023-08-21 08:25:53 +02:00
2023-06-22 15:30:55 +02:00
if ( strlen ( $body_preview ) >= 170 ) {
$body_preview = substr ( $body_preview , 0 , 150 );
$body_preview .= __ ( '. Read More...' );
}
2019-02-08 14:23:05 +01:00
return sprintf (
2019-02-13 11:09:15 +01:00
" <a
2019-02-12 16:46:21 +01:00
class = 'notification-item'
2019-05-14 23:49:01 +02:00
onclick = '%s'
2019-02-12 16:46:21 +01:00
id = 'notification-item-id-%s'
2023-07-04 13:33:29 +02:00
value = '%s'
2019-02-13 11:09:15 +01:00
href = '%s'
2019-05-14 23:49:01 +02:00
target = '%s'
2019-02-12 16:46:21 +01:00
>
2019-02-13 16:40:37 +01:00
% s
2019-02-08 14:23:05 +01:00
< div class = 'notification-info' >
< h4 class = 'notification-title' >
% s
</ h4 >
< p class = 'notification-subtitle' >
% s
</ p >
</ div >
2019-02-13 11:09:15 +01:00
</ a > " ,
2023-07-03 09:18:30 +02:00
$action . '; click_on_notification_toast(event)' ,
2019-02-12 16:46:21 +01:00
$message_info [ 'id_mensaje' ],
2023-07-04 13:33:29 +02:00
$type ,
2019-02-13 11:09:15 +01:00
messages_get_url ( $message_info [ 'id_mensaje' ]),
2019-05-14 23:49:01 +02:00
$target ,
2023-04-18 16:51:19 +02:00
html_print_image ( 'images/info.svg' , true , [ 'style' => 'height: 40px;margin-left: -20px;margin-top: -40px;' ]),
2019-03-06 18:00:28 +01:00
io_safe_output ( $message_info [ 'subject' ]),
2019-05-14 23:49:01 +02:00
$body_preview
2019-02-08 14:23:05 +01:00
);
}