new group by events for extraid pandora_enterprise#9425

This commit is contained in:
Daniel Barbero 2022-09-27 15:08:09 +02:00
parent 84d9b272c3
commit 9e2c6edfeb
8 changed files with 111 additions and 65 deletions

View File

@ -90,7 +90,7 @@ $node_id = (int) get_parameter('node_id', 0);
if ($get_comments === true) { if ($get_comments === true) {
$event = get_parameter('event', false); $event = get_parameter('event', false);
$event_rep = get_parameter('event_rep', false); $event_rep = (int) get_parameter('event_rep', 0);
if ($event === false) { if ($event === false) {
return __('Failed to retrieve comments'); return __('Failed to retrieve comments');
} }
@ -98,7 +98,7 @@ if ($get_comments === true) {
$eventsGrouped = []; $eventsGrouped = [];
// Consider if the event is grouped. // Consider if the event is grouped.
$whereGrouped = '1=1'; $whereGrouped = '1=1';
if (isset($event_rep) === true && $event_rep > 0) { if ($event_rep === EVENT_GROUP_REP_EVENTS) {
// Default grouped message filtering (evento and estado). // Default grouped message filtering (evento and estado).
$whereGrouped = sprintf( $whereGrouped = sprintf(
'`evento` = "%s"', '`evento` = "%s"',
@ -119,6 +119,11 @@ if ($get_comments === true) {
(int) $event['id_agentmodule'] (int) $event['id_agentmodule']
); );
} }
} else if ($event_rep === EVENT_GROUP_REP_EXTRAIDS) {
$whereGrouped = sprintf(
'`id_extra` = "%s"',
$event['id_extra']
);
} else { } else {
$whereGrouped = sprintf('`id_evento` = %d', $event['id_evento']); $whereGrouped = sprintf('`id_evento` = %d', $event['id_evento']);
} }
@ -175,7 +180,7 @@ if ($delete_event === true) {
$filter = get_parameter('filter', []); $filter = get_parameter('filter', []);
$id_evento = (int) get_parameter('id_evento', 0); $id_evento = (int) get_parameter('id_evento', 0);
$server_id = (int) get_parameter('server_id', 0); $server_id = (int) get_parameter('server_id', 0);
$event_rep = get_parameter('event_rep', 0); $event_rep = (int) get_parameter('event_rep', 0);
try { try {
if (is_metaconsole() === true if (is_metaconsole() === true
@ -228,7 +233,7 @@ if ($validate_event === true) {
$filter = get_parameter('filter', []); $filter = get_parameter('filter', []);
$id_evento = (int) get_parameter('id_evento', 0); $id_evento = (int) get_parameter('id_evento', 0);
$server_id = (int) get_parameter('server_id', 0); $server_id = (int) get_parameter('server_id', 0);
$event_rep = get_parameter('event_rep', 0); $event_rep = (int) get_parameter('event_rep', 0);
try { try {
if (is_metaconsole() === true if (is_metaconsole() === true
@ -240,7 +245,7 @@ if ($validate_event === true) {
if ($event_rep === 0) { if ($event_rep === 0) {
// Disable group by when there're result is unique. // Disable group by when there're result is unique.
$filter['group_rep'] = 0; $filter['group_rep'] = EVENT_GROUP_REP_ALL;
} }
// Check acl. // Check acl.
@ -285,7 +290,7 @@ if ($in_process_event === true) {
$filter = get_parameter('filter', []); $filter = get_parameter('filter', []);
$id_evento = (int) get_parameter('id_evento', 0); $id_evento = (int) get_parameter('id_evento', 0);
$server_id = (int) get_parameter('server_id', 0); $server_id = (int) get_parameter('server_id', 0);
$event_rep = get_parameter('event_rep', 0); $event_rep = (int) get_parameter('event_rep', 0);
try { try {
if (is_metaconsole() === true if (is_metaconsole() === true
@ -297,7 +302,7 @@ if ($in_process_event === true) {
if ($event_rep === 0) { if ($event_rep === 0) {
// Disable group by when there're result is unique. // Disable group by when there're result is unique.
$filter['group_rep'] = 0; $filter['group_rep'] = EVENT_GROUP_REP_ALL;
} }
// Check acl. // Check acl.
@ -464,7 +469,6 @@ if ($get_filter_values) {
$event_filter = [ $event_filter = [
'status' => EVENT_NO_VALIDATED, 'status' => EVENT_NO_VALIDATED,
'event_view_hr' => $config['event_view_hr'], 'event_view_hr' => $config['event_view_hr'],
'group_rep' => 1,
'tag_with' => [], 'tag_with' => [],
'tag_without' => [], 'tag_without' => [],
'history' => false, 'history' => false,
@ -480,7 +484,7 @@ if ($get_filter_values) {
'time_to' => '', 'time_to' => '',
'severity' => '', 'severity' => '',
'event_type' => '', 'event_type' => '',
'group_rep' => 0, 'group_rep' => EVENT_GROUP_REP_ALL,
'id_group' => 0, 'id_group' => 0,
'id_group_filter' => 0, 'id_group_filter' => 0,
'group_name' => 'All', 'group_name' => 'All',
@ -2474,7 +2478,7 @@ if ($get_events_fired) {
'id_agent_module' => 0, 'id_agent_module' => 0,
'pagination' => 0, 'pagination' => 0,
'id_user_ack' => 0, 'id_user_ack' => 0,
'group_rep' => 0, 'group_rep' => EVENT_GROUP_REP_ALL,
'tag_with' => [], 'tag_with' => [],
'tag_without' => [], 'tag_without' => [],
'filter_only_alert' => -1, 'filter_only_alert' => -1,

View File

@ -45,6 +45,11 @@ define('EVENT_VALIDATE', 1);
define('EVENT_PROCESS', 2); define('EVENT_PROCESS', 2);
define('EVENT_NO_VALIDATED', 3); define('EVENT_NO_VALIDATED', 3);
// Events group by constants.
define('EVENT_GROUP_REP_ALL', 0);
define('EVENT_GROUP_REP_EVENTS', 1);
define('EVENT_GROUP_REP_AGENTS', 2);
define('EVENT_GROUP_REP_EXTRAIDS', 3);
// Agents disabled status. // Agents disabled status.
define('AGENT_ENABLED', 0); define('AGENT_ENABLED', 0);

View File

@ -11297,7 +11297,7 @@ function get_events_with_user($trash1, $trash2, $other, $returnType, $user_in_db
$id_user_ack = 0; $id_user_ack = 0;
$event_view_hr = 0; $event_view_hr = 0;
$tag = ''; $tag = '';
$group_rep = 0; $group_rep = EVENT_GROUP_REP_ALL;
$utimestamp_upper = 0; $utimestamp_upper = 0;
$utimestamp_bottom = 0; $utimestamp_bottom = 0;
$id_alert_template = -1; $id_alert_template = -1;
@ -11500,7 +11500,7 @@ function get_events_with_user($trash1, $trash2, $other, $returnType, $user_in_db
$alert_join = ' INNER JOIN talert_template_modules ON '.$table_events.'.id_alert_am=talert_template_modules.id'; $alert_join = ' INNER JOIN talert_template_modules ON '.$table_events.'.id_alert_am=talert_template_modules.id';
} }
if ($group_rep == 0) { if ($group_rep == EVENT_GROUP_REP_ALL) {
if ($filter['total']) { if ($filter['total']) {
$sql = 'SELECT COUNT(*) $sql = 'SELECT COUNT(*)
FROM '.$table_events.' FROM '.$table_events.'
@ -15953,7 +15953,7 @@ function api_set_create_event_filter($name, $thrash1, $other, $thrash3)
$id_user_ack = (in_array($other['data'][9], $users)) ? $other['data'][9] : 0; $id_user_ack = (in_array($other['data'][9], $users)) ? $other['data'][9] : 0;
$group_rep = ($other['data'][10] == 0 || $other['data'][10] == 1) ? $other['data'][10] : 0; $group_rep = ($other['data'][10] == EVENT_GROUP_REP_ALL || $other['data'][10] == EVENT_GROUP_REP_EVENTS) ? $other['data'][10] : EVENT_GROUP_REP_ALL;
$date_from = (preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $other['data'][11])) ? $other['data'][11] : '0000-00-00'; $date_from = (preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $other['data'][11])) ? $other['data'][11] : '0000-00-00';
@ -16180,7 +16180,7 @@ function api_set_update_event_filter($id_event_filter, $thrash1, $other, $thrash
break; break;
case 11: case 11:
$values['group_rep'] = ($other['data'][11] == 0 || $other['data'][11] == 1) ? $other['data'][11] : 0; $values['group_rep'] = ($other['data'][11] == EVENT_GROUP_REP_ALL || $other['data'][11] == EVENT_GROUP_REP_EVENTS) ? $other['data'][11] : EVENT_GROUP_REP_ALL;
break; break;
case 12: case 12:
@ -17549,9 +17549,11 @@ function api_set_enable_disable_discovery_task($id_task, $thrash2, $other)
} }
} }
/** /**
* Make report (PDF, CSV or XML) and send it via e-mail (this method is intended to be used by server's execution * Make report (PDF, CSV or XML) and send it via e-mail (this method is intended to be used by server's execution
* of alert actions that involve sending reports by e-mail). * of alert actions that involve sending reports by e-mail).
*
* @param [string] $server_id id server (Node) * @param [string] $server_id id server (Node)
* @param [string] $console_event_id console Id node event in tevent * @param [string] $console_event_id console Id node event in tevent
* @param [string] $trash2 don't use * @param [string] $trash2 don't use
@ -17598,15 +17600,12 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType)
$date_today = preg_split('/[\s,]+/', io_safe_output($date_today)); $date_today = preg_split('/[\s,]+/', io_safe_output($date_today));
$date_today = __($date_today[0]).' '.$date_today[1].' '.$date_today[2].' '.$date_today[3].' '.$date_today[4]; $date_today = __($date_today[0]).' '.$date_today[1].' '.$date_today[2].' '.$date_today[3].' '.$date_today[4];
if ($make_report_from_template === true) { if ($make_report_from_template === true) {
$filter['id_report'] = $id_item; $filter['id_report'] = $id_item;
$template = reports_get_report_templates( $template = reports_get_report_templates(
$filter, $filter,
[ ['description'],
'description'
],
$return_all_group, $return_all_group,
'RR' 'RR'
)[0]; )[0];
@ -17614,15 +17613,16 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType)
$description = $template['description']; $description = $template['description'];
// Report macros post-process. // Report macros post-process.
$body_email = str_replace([ $body_email = str_replace(
[
'_report_description_', '_report_description_',
'_report_generated_date_', '_report_generated_date_',
'_report_date_' '_report_date_',
], ],
[ [
$description, $description,
$date_today, $date_today,
$date_today $date_today,
], ],
$body_email $body_email
); );
@ -17636,7 +17636,7 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType)
$template_regex_agents, $template_regex_agents,
false, false,
'', '',
$email, $email,
$subject_email, $subject_email,
$body_email, $body_email,
$report_type, $report_type,
@ -17651,15 +17651,16 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType)
} }
// Report macros post-process. // Report macros post-process.
$body_email = str_replace([ $body_email = str_replace(
[
'_report_description_', '_report_description_',
'_report_generated_date_', '_report_generated_date_',
'_report_date_' '_report_date_',
], ],
[ [
$report['description'], $report['description'],
$date_today, $date_today,
$date_today $date_today,
], ],
$body_email $body_email
); );
@ -17846,4 +17847,3 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType)
returnData($returnType, $data, ';'); returnData($returnType, $data, ';');
} }
} }

View File

@ -382,14 +382,16 @@ function events_delete($id_evento, $filter=null, $history=false, $force_node=fal
} }
if (isset($filter) === false if (isset($filter) === false
|| is_array($filter) === true || is_array($filter) === false
) { ) {
$filter = ['group_rep' => 0]; $filter = ['group_rep' => EVENT_GROUP_REP_ALL];
} }
hd($filter['group_rep'], true);
switch ($filter['group_rep']) { switch ($filter['group_rep']) {
case '0': case EVENT_GROUP_REP_ALL:
case '2': case EVENT_GROUP_REP_AGENTS:
default: default:
// No groups option direct update. // No groups option direct update.
$delete_sql = sprintf( $delete_sql = sprintf(
@ -399,7 +401,8 @@ function events_delete($id_evento, $filter=null, $history=false, $force_node=fal
); );
break; break;
case '1': case EVENT_GROUP_REP_EVENTS:
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events. // Group by events.
$sql = events_get_all( $sql = events_get_all(
['te.*'], ['te.*'],
@ -418,8 +421,16 @@ function events_delete($id_evento, $filter=null, $history=false, $force_node=fal
true true
); );
$target_ids = db_get_all_rows_sql( if ((int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) {
sprintf( $sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.id_extra = tf.id_extra
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
} else {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf 'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.estado = tf.estado ON tu.estado = tf.estado
AND tu.evento = tf.evento AND tu.evento = tf.evento
@ -428,8 +439,10 @@ function events_delete($id_evento, $filter=null, $history=false, $force_node=fal
AND tf.max_id_evento = %d', AND tf.max_id_evento = %d',
$sql, $sql,
$id_evento $id_evento
) );
); }
$target_ids = db_get_all_rows_sql($sql);
// Try to avoid deadlock while updating full set. // Try to avoid deadlock while updating full set.
if ($target_ids !== false && count($target_ids) > 0) { if ($target_ids !== false && count($target_ids) > 0) {
@ -475,12 +488,12 @@ function events_update_status($id_evento, $status, $filter=null)
} }
if (isset($filter) === false || is_array($filter) === false) { if (isset($filter) === false || is_array($filter) === false) {
$filter = ['group_rep' => 0]; $filter = ['group_rep' => EVENT_GROUP_REP_ALL];
} }
switch ($filter['group_rep']) { switch ($filter['group_rep']) {
case '0': case EVENT_GROUP_REP_ALL:
case '2': case EVENT_GROUP_REP_AGENTS:
default: default:
// No groups option direct update. // No groups option direct update.
$update_sql = sprintf( $update_sql = sprintf(
@ -492,7 +505,8 @@ function events_update_status($id_evento, $status, $filter=null)
); );
break; break;
case '1': case EVENT_GROUP_REP_EVENTS:
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events. // Group by events.
$sql = events_get_all( $sql = events_get_all(
['te.*'], ['te.*'],
@ -511,8 +525,16 @@ function events_update_status($id_evento, $status, $filter=null)
true true
); );
$target_ids = db_get_all_rows_sql( if ((int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) {
sprintf( $sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.id_extra = tf.id_extra
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
} else {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf 'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.estado = tf.estado ON tu.estado = tf.estado
AND tu.evento = tf.evento AND tu.evento = tf.evento
@ -521,8 +543,10 @@ function events_update_status($id_evento, $status, $filter=null)
AND tf.max_id_evento = %d', AND tf.max_id_evento = %d',
$sql, $sql,
$id_evento $id_evento
) );
); }
$target_ids = db_get_all_rows_sql($sql);
// Try to avoid deadlock while updating full set. // Try to avoid deadlock while updating full set.
if ($target_ids !== false && count($target_ids) > 0) { if ($target_ids !== false && count($target_ids) > 0) {
@ -1363,7 +1387,10 @@ function events_get_all(
// Order. // Order.
$order_by = ''; $order_by = '';
if (isset($order, $sort_field) === true) { if (isset($order, $sort_field) === true) {
if (isset($filter['group_rep']) === true && $filter['group_rep'] == 1) { if (isset($filter['group_rep']) === true
&& $filter['group_rep'] === EVENT_GROUP_REP_EVENTS
&& $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS
) {
$order_by = events_get_sql_order('MAX('.$sort_field.')', $order); $order_by = events_get_sql_order('MAX('.$sort_field.')', $order);
} else { } else {
$order_by = events_get_sql_order($sort_field, $order); $order_by = events_get_sql_order($sort_field, $order);
@ -1397,22 +1424,22 @@ function events_get_all(
$group_by = 'GROUP BY '; $group_by = 'GROUP BY ';
$tagente_join = 'LEFT'; $tagente_join = 'LEFT';
if (isset($filter['group_rep']) === false) { if (isset($filter['group_rep']) === false) {
$filter['group_rep'] = 0; $filter['group_rep'] = EVENT_GROUP_REP_ALL;
} }
switch ($filter['group_rep']) { switch ($filter['group_rep']) {
case '0': case EVENT_GROUP_REP_ALL:
default: default:
// All events. // All events.
$group_by = ''; $group_by = '';
break; break;
case '1': case EVENT_GROUP_REP_EVENTS:
// Group by events. // Group by events.
$group_by .= 'te.evento, te.id_agente, te.id_agentmodule'; $group_by .= 'te.evento, te.id_agente, te.id_agentmodule';
break; break;
case '2': case EVENT_GROUP_REP_AGENTS:
// Group by agents. // Group by agents.
$tagente_join = 'INNER'; $tagente_join = 'INNER';
$group_by = ''; $group_by = '';
@ -1426,6 +1453,11 @@ function events_get_all(
); );
} }
break; break;
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events.
$group_by .= 'te.id_extra';
break;
} }
$tgrupo_join = 'LEFT'; $tgrupo_join = 'LEFT';
@ -1511,7 +1543,9 @@ function events_get_all(
} }
} }
if ((int) $filter['group_rep'] === 1 && $count === false) { if (($filter['group_rep'] === EVENT_GROUP_REP_EVENTS
|| $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) && $count === false
) {
$sql = sprintf( $sql = sprintf(
'SELECT %s 'SELECT %s
%s %s
@ -2880,9 +2914,9 @@ function events_get_agent(
// Group by agent. // Group by agent.
if ((bool) $show_summary_group === true) { if ((bool) $show_summary_group === true) {
$filters['group_rep'] = 1; $filters['group_rep'] = EVENT_GROUP_REP_EVENTS;
} else { } else {
$filters['group_rep'] = 2; $filters['group_rep'] = EVENT_GROUP_REP_AGENTS;
} }
$events = Event::search( $events = Event::search(
@ -5092,7 +5126,7 @@ function events_get_count_events_validated_by_user($data)
* *
* @return string SQL. * @return string SQL.
*/ */
function events_get_sql_order($sort_field='timestamp', $sort='DESC', $group_rep=0, $only_fields=false) function events_get_sql_order($sort_field='timestamp', $sort='DESC', $group_rep=EVENT_GROUP_REP_ALL, $only_fields=false)
{ {
$sort_field_translated = $sort_field; $sort_field_translated = $sort_field;
switch ($sort_field) { switch ($sort_field) {
@ -5113,7 +5147,7 @@ function events_get_sql_order($sort_field='timestamp', $sort='DESC', $group_rep=
break; break;
case 'timestamp': case 'timestamp':
$sort_field_translated = ($group_rep == 0) ? 'timestamp' : 'timestamp_last'; $sort_field_translated = ($group_rep == EVENT_GROUP_REP_ALL) ? 'timestamp' : 'timestamp_last';
break; break;
case 'user_id': case 'user_id':

View File

@ -4011,7 +4011,7 @@ function reporting_groups_nodes($content)
} }
// Grouped. // Grouped.
$filters['group_rep'] = 1; $filters['group_rep'] = EVENT_GROUP_REP_EVENTS;
$events = Event::search( $events = Event::search(
[ [

View File

@ -357,10 +357,10 @@ class Events
); );
if (isset($group_rep) === false) { if (isset($group_rep) === false) {
$group_rep = 0; $group_rep = EVENT_GROUP_REP_ALL;
} }
if ((int) $group_rep !== 0) { if ((int) $group_rep !== EVENT_GROUP_REP_ALL) {
if ($event['event_rep'] <= 1) { if ($event['event_rep'] <= 1) {
$event['event_repeated'] = '<i>'.__('No').'</i>'; $event['event_repeated'] = '<i>'.__('No').'</i>';
} else { } else {
@ -1068,7 +1068,7 @@ class Events
$filters['id_agent'] = $this->id_agent; $filters['id_agent'] = $this->id_agent;
} }
$filters['group_rep'] = 1; $filters['group_rep'] = EVENT_GROUP_REP_EVENTS;
if (isset($this->limit) === true if (isset($this->limit) === true
&& $this->limit !== -1 && $this->limit !== -1

View File

@ -84,7 +84,7 @@ ui_require_javascript_file('pandora_events');
$default_filter = [ $default_filter = [
'status' => EVENT_NO_VALIDATED, 'status' => EVENT_NO_VALIDATED,
'event_view_hr' => $config['event_view_hr'], 'event_view_hr' => $config['event_view_hr'],
'group_rep' => 1, 'group_rep' => EVENT_GROUP_REP_EVENTS,
'tag_with' => [], 'tag_with' => [],
'tag_without' => [], 'tag_without' => [],
'history' => false, 'history' => false,
@ -1626,9 +1626,10 @@ $inputs[] = $in;
// Duplicates group { events | agents }. // Duplicates group { events | agents }.
$data = html_print_select( $data = html_print_select(
[ [
0 => __('All events'), EVENT_GROUP_REP_ALL => __('All events'),
1 => __('Group events'), EVENT_GROUP_REP_EVENTS => __('Group events'),
2 => __('Group agents'), EVENT_GROUP_REP_AGENTS => __('Group agents'),
EVENT_GROUP_REP_EXTRAIDS => __('Group extra id'),
], ],
'group_rep', 'group_rep',
$group_rep, $group_rep,
@ -2227,12 +2228,14 @@ try {
$active_filters_div .= '<div>'; $active_filters_div .= '<div>';
$active_filters_div .= '<div class="label box-shadow">'.__('Duplicated').'</div>'; $active_filters_div .= '<div class="label box-shadow">'.__('Duplicated').'</div>';
$active_filters_div .= '<div id="summary_duplicates" class="content">'; $active_filters_div .= '<div id="summary_duplicates" class="content">';
if ($group_rep == 0) { if ($group_rep == EVENT_GROUP_REP_ALL) {
$active_filters_div .= __('All events.'); $active_filters_div .= __('All events.');
} else if ($group_rep == 1) { } else if ($group_rep == EVENT_GROUP_REP_EVENTS) {
$active_filters_div .= __('Group events'); $active_filters_div .= __('Group events');
} else if ($group_rep == 2) { } else if ($group_rep == EVENT_GROUP_REP_AGENTS) {
$active_filters_div .= __('Group agents.'); $active_filters_div .= __('Group agents.');
} else if ($group_rep == EVENT_GROUP_REP_EXTRAIDS) {
$active_filters_div .= __('Group extra id.');
} }
$active_filters_div .= '</div>'; $active_filters_div .= '</div>';

View File

@ -404,7 +404,7 @@ if ($access_console_node === true) {
$user_event_filter = [ $user_event_filter = [
'status' => EVENT_NO_VALIDATED, 'status' => EVENT_NO_VALIDATED,
'event_view_hr' => $config['event_view_hr'], 'event_view_hr' => $config['event_view_hr'],
'group_rep' => 1, 'group_rep' => EVENT_GROUP_REP_EVENTS,
'tag_with' => [], 'tag_with' => [],
'tag_without' => [], 'tag_without' => [],
'history' => false, 'history' => false,